Payments (Stripe)

This app uses Stripe for card payments (web + native) and native wallets (Apple Pay / Google Pay) in the Capacitor app.

Entry points in the app

  • Stripe is initialized at the app root with CapacitorStripeProvider in client/src/App.js.
  • Card payments use Stripe Elements (PaymentElement) in:
    • client/src/components/fight/summary/StripeForm.js
    • client/src/components/reservations/ReservationStripeCardSection.js
  • Native wallets are handled in:
    • client/src/utils/nativeStripeWallet.js

Stripe publishable key selection

Stripe keys are chosen based on environment and platform:

  • Helper: client/src/utils/env.js (getStripePublishableKey)
  • Some flows also select keys locally (for example client/src/components/fight/summary/PaymentStep.js)

Expected env vars:

  • REACT_APP_STRIPE_LIVE_KEY
  • REACT_APP_STRIPE_TEST_KEY

Apple Pay / Google Pay (native)

Wallet selection:

  • iOS native → Apple Pay
  • Android native → Google Pay

Availability checks:

  • Apple Pay: Stripe.isApplePayAvailable()
  • Google Pay: Stripe.isGooglePayAvailable()

Apple Pay merchant id:

  • REACT_APP_APPLE_MERCHANT_ID is required for Apple Pay flows
  • Example expected format: merchant.link.getfoodfight

How payments complete (high level)

Common pattern:

  1. Client calls backend to create a Stripe PaymentIntent (returns client_secret)
  2. Client confirms payment with Stripe
  3. Client sends the resulting payment_intent.id to the backend to complete the business action

Examples:

  • Fight flow: Payment is confirmed and the payment intent id is stored in StartFight context
  • Reservation flow: after payment confirm, the app calls createUserReservation(..., paymentIntentId)

Testing checklist

  • Web card payment:
    • ensure the page renders Stripe Elements and confirmPayment completes
  • iOS Apple Pay:
    • requires native build (Capacitor) and REACT_APP_APPLE_MERCHANT_ID set
    • Stripe.isApplePayAvailable() must succeed
  • Android Google Pay:
    • requires native build (Capacitor)
    • Stripe.isGooglePayAvailable() must succeed