FloPayFloPay
GatewaysStripe

PayPal via Stripe (Fallback)

The Stripe-rendered PayPal path. Used when a client has not provisioned a direct PayPal gateway.

PayPal via Stripe

This page covers the Stripe-rendered PayPal fallback — PayPal mounted through Stripe's ExpressCheckoutElement. It is the path FloPay uses when the checkout session response does not include a gateways.paypal entry.

Looking for the primary PayPal flow? See the Direct PayPal guide. Direct PayPal is required for checkouts opened inside Facebook, Meta, and Instagram in-app browsers, where the Stripe-rendered PayPal flow does not work reliably. For an overview of when each path is used, see the PayPal overview.

When This Path Is Used

The SDK picks the PayPal path from the checkout session's gateways map:

  • gateways.paypal is present → direct PayPal renders.
  • gateways.paypal is null or missing → the Stripe-rendered PayPal button described on this page renders, using gateways.stripe.publishableKey.

PayPal never renders twice. The two paths are mutually exclusive per session.

Architecture

PayPal in this path has a specific Stripe Elements requirement: it needs its own Stripe Elements instance without paymentMethodCreation: 'manual'. Card tokenization needs paymentMethodCreation: 'manual'. Those two requirements are mutually exclusive on the same <Elements> instance, so FloPay mounts two Elements groups side by side.

The simplest way to offer the Stripe-rendered PayPal flow is through FloPayCheckout, which fetches the session, picks the PayPal path from the gateways map, and handles the dual-Elements architecture automatically:

<FloPayCheckout
  sessionId="sess_abc123"
  onComplete={handleComplete}
/>

Under the hood, FloPayCheckout renders a SplitCardForm that creates two Elements instances:

  1. Card Elements -- with paymentMethodCreation: 'manual' for card tokenization
  2. PayPal Elements -- a separate Stripe <Elements> wrapper without paymentMethodCreation for the ExpressCheckoutElement

The amount and currency for the PayPal Elements instance are read from the session automatically — no extra props required.

Need full control over provider setup? See the SplitCardForm reference for the lower-level API that lets you mount SplitCardForm inside your own FloPayProvider.

PayPal Payment Flow

The Stripe-rendered PayPal flow differs from the card flow:

  1. User clicks the PayPal button (rendered by ExpressCheckoutElement)
  2. Stripe opens the PayPal approval window
  3. The confirmPayPalPayment method on the FloPay instance is called:
    • Creates a payment intent via the billing API
    • Confirms the PayPal payment with Stripe
    • Handles any redirect if needed
  4. On return from PayPal redirect, resumePayPalPayment picks up the flow
  5. Payment is processed via the billing API
// This is handled internally by SplitCardForm, shown for reference:
const result = await flopay.confirmPayPalPayment({
  billingApiUrl: 'https://billing.example.com',
  sessionId: 'sess_abc123',
  email: 'user@example.com',
  returnUrl: window.location.href,
});

Wallet Resume Across Redirects

PayPal payments may redirect the user away from your site and back. FloPayCheckout (and the underlying SplitCardForm / CheckoutForm components) persist payment state to localStorage under the key flopay_wallet_resume before the redirect, then automatically resume the flow when the user returns.

Why Separate Elements?

Stripe's ExpressCheckoutElement (which renders PayPal, Apple Pay, Google Pay) requires an Elements instance configured with mode, amount, and currency. Card-based flows that use paymentMethodCreation: 'manual' are incompatible with this configuration. SplitCardForm solves this by mounting the PayPal button in its own <Elements> wrapper while keeping card fields in the parent provider's context.

In-App Browser Limitation

The Stripe-rendered PayPal path does not work reliably inside Facebook, Meta, and Instagram in-app browsers. The PayPal popup either fails to open or fails to return to the originating tab. Clients running paid social funnels (Meta Ads, Instagram Ads) should provision a direct PayPal gateway so the SDK switches to the direct PayPal path automatically for those buyers.

Migration

Existing clients that use only the Stripe-rendered PayPal flow stay on this path with no action required. Opting into direct PayPal is a per-gateway provisioning step (see Setup). Once a provider_type=paypal gateway record exists for a client, FloPay starts populating gateways.paypal on that client's sessions and the SDK switches automatically.

On this page