FloPayFloPay
API Reference@flopay/react

SplitCardForm

Split card checkout form with separate card number, expiry, CVC fields, name input, and optional PayPal button.

SplitCardForm

Split card checkout form that renders individual card fields (CardNumber, CardExpiry, CardCVC), a full name input, and an optional PayPal button. Matches the checkout/StripeCardForm layout.

const SplitCardForm: React.ForwardRefExoticComponent<
  SplitCardFormProps & React.RefAttributes<SplitCardFormRef>
>

Props

NameTypeRequiredDefaultDescription
sessionIdstringYes--Checkout session ID (UUID from billing API).
billingApiUrlstringYes--Billing API base URL.
emailstringNo--User's email (required for creating payment intents).
userIdstringNo--User ID (required for processing payments).
onComplete(result: PaymentResult) => voidNo--Called when payment completes successfully.
onError(error: FloPayError) => voidNo--Called when a payment error occurs.
onDecline(decline: DeclineEvent) => voidNo--Called when a payment is declined, authentication fails, PayPal is cancelled, or a wallet sheet is dismissed.
onTokenizedBody(tokenizedBody: TokenizedBody) => voidNo--Override: delegates backend submission to the caller.
firstNamestringNo--First name for billing.
lastNamestringNo--Last name for billing.
chvstringNo--Checkout version for A/B tracking.
submitLabelstringNo'CONFIRM PAYMENT'Label for the submit button.
classNamestringNo--Additional CSS class for the form wrapper.
childrenReact.ReactNodeNo--Custom children (overrides default submit button).
isProcessingbooleanNo--External processing state.
errorstring | nullNo--External error message.
onErrorChange(error: string | null) => voidNo--Called when internal error state changes.
onFullNameChange(value: string) => voidNo--Callback when the full cardholder name input changes.
onFirstNameChange(value: string) => voidNo--Callback when first name changes (parsed from full name input).
onLastNameChange(value: string) => voidNo--Callback when last name changes (parsed from full name input).
showStripebooleanNotrueRender the Stripe gateway. When false, the entire Stripe panel is hidden — card fields, Apple Pay, Google Pay, and every other Stripe-enabled payment method. When true (default), each method enabled on the connected Stripe account renders dynamically. See Stripe payment methods.
showPayPalbooleanNotrueRender the PayPal gateway above card fields. When false, both the direct PayPal and PayPal via Stripe paths are hidden.
layout'default' | 'buttons'No'default'Layout mode. 'buttons' shows payment method buttons with an expandable card form.
themeThemeIdNo--Single-prop theming. Styles both the Stripe-side appearance and the React-rendered wrapper, submit, and inputs from one value. Available across FloPayCheckout, FloPayAutomaticPaymentButton, and SplitCardForm.
appearanceFloPayAppearanceNo--Stripe-side appearance overrides (palette + nested-element rules). Wins over a theme bundle's appearance. When supplied without buttonsStyles, the wrapper, submit, title, input, and font styling derive from appearance.variables.
buttonsStylesButtonsLayoutStylesNo--Per-field style overrides merged on top of the resolved theme bundle. Painted regardless of layout="default" or layout="buttons".
buttonsThemeButtonsLayoutThemeNo--Deprecated. Legacy preset ('default' | 'minimal' | 'rounded' | 'dark') still resolved via resolveButtonsLayoutTheme() for back-compat. Prefer theme.
cardButtonContentReact.ReactNodeNo--Replaces the default content inside the card button when layout="buttons".
cardBackButtonContentReact.ReactNodeNo--Replaces the default "Go back" label in the expanded card form when layout="buttons". Pass '' to remove the text and keep only the icon.
cardTitleContentReact.ReactNodeNo--Replaces the default "Secure card checkout" title. Pass '' to remove the title text entirely.
onButtonClick(method: CheckoutButtonMethod) => voidNo--Called when a payment method button is clicked. Fires on the initial click for 'card' (buttons layout), 'paypal', 'apple_pay', 'google_pay' — before PayPal redirect or wallet authorization. Cancelled if onBeforeButtonClick returns false.
onBeforeButtonClick(event: BeforeButtonClickEvent) => void | false | InlineSessionPatch | Promise<...>No--Card only. Runs before the "Credit / Debit Card" button continues in layout="buttons". Returning false cancels the click.
enableAVSboolean | AVSFieldConfigNofalseEnable AVS. true → country + postal code (legacy default). An AVSFieldConfig object enables per-field, per-country control of country, postal code, street address, city, and state. See AVS guide.
avsLayout'row' | 'column'No'row'Layout for the country / postal code pair. Address line, city, and state always render on their own rows.
countrystringNo'US'Pre-filled country code (ISO 3166-1 alpha-2). Typically from a partner GEO/IP lookup.
zipstringNoPre-filled ZIP/postal code.
citystringNoPre-filled city. Typically from a partner GEO/IP lookup.
statestringNoPre-filled state/province. Typically from a partner GEO/IP lookup.
addressLine1stringNoPre-filled street address (line 1).
addressLine2stringNoPre-filled apt/suite/unit (line 2).
onCountryChange(country: string) => voidNoCallback when country changes.
onZipChange(zip: string) => voidNoCallback when ZIP/postal code changes.
totalAmountnumberNo0Total amount in cents (used for wallet/PayPal Elements config).
currencystringNo'usd'Currency code (used for PayPal Elements config).
debugbooleanNofalseRender diagnostic panels showing resolved payment methods and the Direct PayPal button lifecycle. Forwarded to each DirectPayPalButton render site. Intended for local development — leave off in production.

SplitCardFormRef

Methods exposed via ref for external 3DS handling.

MethodSignatureDescription
handleNextAction(clientSecret: string) => Promise<void>Trigger 3DS authentication with the given client secret.

Default Layout

The default layout renders all payment methods and card fields together:

  1. Wallet buttons (Apple Pay / Google Pay)
  2. PayPal button
  3. "or pay with card" divider
  4. Card Number field
  5. Card Expiry + CVC fields (side by side)
  6. Full Name input
  7. Error display
  8. Submit button

Buttons Layout

When layout="buttons", payment methods are shown as stacked buttons:

  1. PayPal button
  2. Wallet buttons (Apple Pay / Google Pay)
  3. "Credit / Debit Card" button

Clicking the card button expands into the card form with a configurable back button label and title. PayPal and wallet buttons stay mounted (no re-render) and are hidden via CSS.

onBeforeButtonClick is credit card only. It runs only for the "Credit / Debit Card" button in layout="buttons". It does not run for PayPal, Apple Pay, or Google Pay.

<SplitCardForm
  sessionId={sessionId}
  billingApiUrl="https://api.flopay.com"
  email={email}
  layout="buttons"
  theme="modern-light"
/>

You can replace the default card button body with any React content:

<SplitCardForm
  sessionId={sessionId}
  billingApiUrl="https://api.flopay.com"
  email={email}
  layout="buttons"
  cardButtonContent={
    <div style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
      <span style={{ fontWeight: 700 }}>Pay by card</span>
      <span style={{ marginLeft: 'auto', opacity: 0.7 }}>Secure</span>
    </div>
  }
/>

You can also replace or remove the header text in the expanded card form:

<SplitCardForm
  sessionId={sessionId}
  billingApiUrl="https://api.flopay.com"
  email={email}
  layout="buttons"
  cardBackButtonContent=""
  cardTitleContent="Enter card details"
/>

See FloPayCheckout — Layout Modes for theme presets and custom styling options.

Button Hooks

<SplitCardForm
  sessionId={sessionId}
  billingApiUrl="https://api.flopay.com"
  email={email}
  layout="buttons"
  onBeforeButtonClick={async ({ method }) => {
    if (method !== 'card') return;

    const confirmed = await confirmCardCheckoutDetails();
    if (!confirmed) return false;
  }}
  onButtonClick={(method) => {
    console.log('clicked:', method);
  }}
  onDecline={(decline) => {
    console.log('declined:', decline);
  }}
/>

onBeforeButtonClick only runs for the buttons-layout credit card button. Throwing routes the error through onError.

Example

<FloPayProvider
  flopay={flopayPromise}
  options={{ amount: 4999, currency: 'usd', paymentMethodCreation: 'manual' }}
>
  <SplitCardForm
    sessionId="uuid-xxx"
    billingApiUrl="https://api.example.com"
    email="user@example.com"
    userId="user_1"
    totalAmount={49.99}
    currency="usd"
    onComplete={(result) => router.push('/success')}
    onFirstNameChange={setFirstName}
    onLastNameChange={setLastName}
  />
</FloPayProvider>

On this page