v1.3.0 - Backend-orchestrated vault PCI card widget #
The card path now renders a backend-served, self-contained hosted vault widget that owns tokenization, the charge, and 3DS — gateway agnostic for cards. Also ships first-class Modern/Bold/Glass theme bundles and hides unsupported in-app-browser wallet rows.
19 Jun 2026
FloPay SDK v1.3.0 moves card collection onto the vault PCI card form. When a checkout session advertises a pcivault
gateway, the backend returns a self-contained hosted widget that owns the PCI card fields, its own submit button, card tokenization, PaymentIntent creation and confirmation, 3DS, and the result. The SDK injects that widget and relays its terminal outcome - this becomes gateway agnostic for cards and the backend handles the routing/cascading. Stripe stays only for non-card methods (Wallets and APMs).
What changed — vault PCI card form
@flopay/react'sSplitCardFormrenders a backend-served hosted vault widget (via the rewrittenVaultCardFields) instead of Stripe's embedded card elements whenever the session advertises apcivaultgateway. On the vault path it hides its own card fields, cardholder-name input, AVS fields, and submit button — the widget owns them.@flopay/js'sPciVaultCardCaptureis now a thin widget injector.flopay.cardCapture({ sessionId })returns aCardCaptureAdapterwhosemount(container, { html })injects the server HTML (re-executing its bundled script) and whoseon('ready' | 'complete' | 'decline' | 'error', …)relays the widget's terminalwindow.postMessage({ source: 'flopay-vault', … }) to the host checkout. The SDK creates no PaymentIntent and runs no 3DS.SplitCardFormrelays the widget's outcome toonComplete/onDecline/onError, and obtains the widget HTML from the embeddedsession.vault.html(when present) or by fetchingPOST /v1/checkouts/sessions/{id}/vault/capture.- The SDK declares
X-Flo-SDK-Version: 1.3.0onPOST /v1/checkouts/sessions(newFLO_SDK_VERSION_HEADER) so the backend embeds thevaultblock in the create-session response for SDKs ≥ 1.3.0. - New / changed types in
@flopay/shared:VaultCaptureBlock,CardCaptureOutcomeEvent,VaultCaptureResultMessage, a redefinedCardCaptureEventType('ready' | 'complete' | 'decline' | 'error') andCardCaptureMountOptions({ html }), andCheckoutSession.vault.PaymentAPIaddsgetVaultCapture()and threads the embeddedvaultblock onto the created session.
Why it matters
- Card data is routed through Flo's PCI vault rather than Stripe's hosted card form, decoupling the card path from any single downstream processor while keeping PCI scope off the SDK and the consumer page.
- The backend orchestrates the charge and 3DS, so the SDK no longer ships or depends on Stripe.js for cards. Stripe is confined to wallets / PayPal / APMs.
Developer notes
- The vault path is capability-gated on the
pcivaultsession gateway, so existing (non-vault) card checkout is unchanged. - On the vault path,
onTokenizedBodydoes not fire — useonComplete/onDecline/onError. The legacy Stripe path'sonTokenizedBodyis unchanged. - Backend dependencies this SDK relies on: the hosted widget must (a) emit the
flopay-vaultpostMessageoutcome the SDK listens for (otherwise it falls back to its own success redirect), (b) handle theACTION_REQUIRED3DS step internally, and (c) own AVS for the vault path (the SDK no longer collects it inline; account-level address set at session-create still flows to the backend). - Bump all
@flopay/*packages together to1.3.0(@flopay/js,@flopay/react,@flopay/node,@flopay/shared).