FloPayFloPay
Guides

Automatic Payment Buttons

Render one-click saved-payment buttons that create or reuse an auto checkout session and keep FloPay's shared processing modal on the page.

Automatic Payment Buttons

FloPayAutomaticPaymentButton turns FloPay's backend-driven auto checkout mode into a client component you can place anywhere in your UI. It is designed for upsells, add-ons, renewals, and other saved-payment journeys where you want a single button instead of a full checkout form.

The button keeps the user on the current page while still giving you FloPay's shared processing, success, and decline modal states.

When To Use It

Use FloPayAutomaticPaymentButton when you want to:

  • trigger a saved-payment purchase from a success page or account area
  • pass the same session-creation data you would normally post to your backend
  • reuse an existing sessionId created elsewhere
  • style the button with the same theme system as the embedded buttons layout
  • receive explicit onClick, onSuccess, onError, and onDecline events

Basic Example

app/success/UpsellButton.tsx
'use client';

import { FloPayAutomaticPaymentButton } from '@flopay/react';

export function UpsellButton() {
  return (
    <FloPayAutomaticPaymentButton
      clientId="client_123"
      currency="USD"
      account={{
        userId: 'user_123',
        email: 'customer@example.com',
        firstName: 'Jane',
        lastName: 'Doe',
      }}
      products={[{ code: 'upsell_ai_pack' }]}
      successUrl={`${window.location.origin}/success`}
      cancelUrl={`${window.location.origin}/success`}
      theme="bold-dark"
      onClick={() => {
        console.log('automatic payment button clicked');
      }}
      onSuccess={({ result, sessionId }) => {
        console.log('payment succeeded', result.status, sessionId);
      }}
      onError={(error) => {
        console.error(error.message);
      }}
      onDecline={(decline) => {
        console.log('payment declined', decline.code);
      }}
    >
      Purchase Item
    </FloPayAutomaticPaymentButton>
  );
}

Session Sources

You can render the button from either input shape:

  • sessionId (plus its nonce) when your backend already created the checkout session
  • inline session data via createSession
  • direct convenience props for inline creation: clientId, currency, products, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata

The component always forces checkoutMode="auto" under the hood, so it uses the saved payment method attached to the session.

The backend resolves the customer's latest vaulted payment method (getLatestByUserId) and rebinds the session's gateway when the saved PM lives on a different provider than routing originally picked. You no longer pass paymentMethodId or checkoutMethod from the client — the backend orchestrates gateway selection and tokenizedData shape per provider ({ id: vaultToken } for Stripe, { userPaymentMethodId: uuid } for PayPal).

Reuse An Existing Session

Pass the session's nonce alongside sessionId. Your backend returns it on the create response (see Checkout Session Token); the SDK forwards it as the x-checkout-session-token header on the session read and /process. Without it, post-#640 backends reject both with 401 "Missing checkout session token.".

<FloPayAutomaticPaymentButton
  sessionId="sess_abc123"
  nonce="nonce_abc123"
  onSuccess={() => window.location.reload()}
>
  Purchase Item
</FloPayAutomaticPaymentButton>

On the inline-creation path (createSession or the convenience props) you do not pass a nonce — the SDK mints it from the create response and threads it through every continuation call, including the fallback FloPayCheckout modal that opens when the charge needs extra authentication.

Create The Session Inline

<FloPayAutomaticPaymentButton
  createSession={{
    clientId: 'client_123',
    currency: 'USD',
    account: {
      userId: 'user_123',
      email: 'customer@example.com',
    },
    products: [{ code: 'upsell_ai_pack' }],
    successUrl: `${window.location.origin}/success`,
    cancelUrl: `${window.location.origin}/success`,
  }}
>
  Purchase Item
</FloPayAutomaticPaymentButton>

Do not pass both sessionId and inline session-creation props at the same time.

Styling And Slot Content

The button shares the same theme system as FloPayCheckout. One theme value styles the button and the fallback FloPayCheckout modal that opens when the saved-payment charge needs user interaction:

  • theme accepts any ThemeId ('classic' | 'modern-light' | 'modern-dark' | 'bold-light' | 'bold-dark' | 'glass-light' | 'glass-dark')
  • appearance and buttonsStyles are still available as per-field overrides on top of the theme bundle
  • children render inside the button, so you can treat them as the button slot content
<FloPayAutomaticPaymentButton
  sessionId="sess_abc123"
  theme="bold-dark"
  buttonsStyles={{
    cardButtonFontSize: '1rem',
  }}
>
  <span style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
    <strong>Add AI Supercharger Pack</strong>
    <span style={{ opacity: 0.72 }}>$0.80 today</span>
  </span>
</FloPayAutomaticPaymentButton>

If children are omitted, the default embedded button content is rendered for you. See the Theming guide for the resolution precedence (appearance > buttonsStyles > theme > legacy buttonsTheme > defaults).

Events

PropPurpose
onClickFires when the button is pressed, before the automatic payment flow begins
onSuccessFires after the success modal state completes; includes the payment result and resolved session details
onErrorFires when the automatic payment flow fails with a FloPayError
onDeclineFires when FloPay can classify the failure as a decline or cancellation event

FloPayAutomaticPaymentButton also extends the standard React button props, so disabled, className, aria-*, and similar attributes work as expected.

Authentication And Redirect Handling

Automatic Payment Buttons do not hard-fail when extra authentication is needed:

  • when the saved payment method can complete immediately, the button shows the shared processing and success modal states
  • when the payment provider returns a redirect-capable auth flow such as 3DS or PayPal, the backend resumes and captures the result end-to-end — there is no longer a client-side payment_intent_client_secret URL-param watcher or sessionStorage handshake to wire up
  • when FloPay returns authentication_required without a direct redirect token, the button opens an inline FloPayCheckout modal on the same page so the user can finish authentication without navigating away; that fallback modal inherits the same theme you passed to the button

This makes the component a better fit for upsells than raw backend-only auto mode.

See Also

On this page