diff --git a/backend/app/api/v1/payments.py b/backend/app/api/v1/payments.py index 0dfefe4..64f779f 100644 --- a/backend/app/api/v1/payments.py +++ b/backend/app/api/v1/payments.py @@ -190,7 +190,8 @@ async def process_square_payment( source_id=payment_request.source_id, idempotency_key=payment_request.idempotency_key, reference_id=reference_id, - note=payment_request.note or f"Membership payment for {tier.name} - {current_user.email}" + note=payment_request.note or f"Membership payment for {tier.name} - {current_user.email}", + billing_details=payment_request.billing_details ) if not square_result.get('success'): diff --git a/backend/app/schemas/schemas.py b/backend/app/schemas/schemas.py index 983ea24..a90dba5 100644 --- a/backend/app/schemas/schemas.py +++ b/backend/app/schemas/schemas.py @@ -171,6 +171,7 @@ class SquarePaymentRequest(BaseModel): amount: float = Field(..., gt=0, description="Payment amount in GBP") idempotency_key: Optional[str] = Field(None, description="Unique key to prevent duplicate payments") note: Optional[str] = Field(None, description="Optional payment note") + billing_details: Optional[dict] = Field(None, description="Billing address and cardholder name for AVS") class SquarePaymentResponse(BaseModel): diff --git a/backend/app/services/square_service.py b/backend/app/services/square_service.py index 7e4f44f..c30f5c6 100644 --- a/backend/app/services/square_service.py +++ b/backend/app/services/square_service.py @@ -35,7 +35,8 @@ class SquareService: idempotency_key: Optional[str] = None, customer_id: Optional[str] = None, reference_id: Optional[str] = None, - note: Optional[str] = None + note: Optional[str] = None, + billing_details: Optional[Dict] = None ) -> Dict: """ Create a payment using Square @@ -47,6 +48,7 @@ class SquareService: customer_id: Optional Square customer ID reference_id: Optional reference ID for internal tracking note: Optional note about the payment + billing_details: Optional billing address and cardholder name for AVS Returns: Dict with payment result including payment_id, status, and details @@ -60,19 +62,49 @@ class SquareService: # For GBP, this is pence amount_in_pence = int(amount_money * 100) - # Create payment - pass parameters directly as keyword arguments - result = self.client.payments.create( - source_id=source_id, - idempotency_key=idempotency_key, - amount_money={ + # Build payment parameters + payment_params = { + 'source_id': source_id, + 'idempotency_key': idempotency_key, + 'amount_money': { 'amount': amount_in_pence, 'currency': 'GBP' }, - location_id=self.location_id, - customer_id=customer_id if customer_id else None, - reference_id=reference_id if reference_id else None, - note=note if note else None - ) + 'location_id': self.location_id + } + + # Add billing address for AVS if provided + if billing_details: + # Add buyer email if available + if billing_details.get('email'): + payment_params['buyer_email_address'] = billing_details.get('email') + + # Build billing address for AVS + billing_address = {} + if billing_details.get('address_line_1'): + billing_address['address_line_1'] = billing_details.get('address_line_1') + if billing_details.get('address_line_2'): + billing_address['address_line_2'] = billing_details.get('address_line_2') + if billing_details.get('city'): + billing_address['locality'] = billing_details.get('city') + if billing_details.get('postal_code'): + billing_address['postal_code'] = billing_details.get('postal_code') + if billing_details.get('country'): + billing_address['country'] = billing_details.get('country') + + if billing_address: + payment_params['billing_address'] = billing_address + + # Add optional parameters + if customer_id: + payment_params['customer_id'] = customer_id + if reference_id: + payment_params['reference_id'] = reference_id + if note: + payment_params['note'] = note + + # Create payment - pass parameters directly as keyword arguments + result = self.client.payments.create(**payment_params) if result.errors: # Payment failed - extract user-friendly error messages diff --git a/frontend/index.html b/frontend/index.html index cdc0723..074fc49 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,8 +4,7 @@
Amount: £{amount.toFixed(2)}
Date: {formatDate(selectedEventForRSVP.event_date)}
+ {selectedEventForRSVP.event_time && ( +Time: {selectedEventForRSVP.event_time}
+ )} + {selectedEventForRSVP.location && ( +Location: {selectedEventForRSVP.location}
+ )} +| Name | +RSVP | +Date | +|
|---|---|---|---|
| + {rsvpUser ? `${rsvpUser.first_name} ${rsvpUser.last_name}` : `User #${rsvp.user_id}`} + | ++ {rsvpUser?.email || 'N/A'} + | ++ + {rsvp.status === 'attending' ? 'ATTENDING' : + rsvp.status === 'maybe' ? 'MAYBE' : + 'NOT ATTENDING'} + + | ++ {rsvp.created_at ? formatDate(rsvp.created_at) : 'N/A'} + | +
No RSVPs yet for this event.
+ )} +