@flopay/react 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,13 +53,13 @@ function CheckoutPage() {
53
53
  }
54
54
  ```
55
55
 
56
- `FloPayCheckout` automatically fetches the session, initializes the correct payment provider, and renders a `SplitCardForm` with card fields, Apple Pay, Google Pay, and PayPal. Customer data (email, userId, name) is injected from the session.
56
+ `FloPayCheckout` automatically fetches the session, initializes the correct payment providers, and renders a `SplitCardForm` with the hosted vault card widget plus the session's supported wallets, APMs, and PayPal. Customer data (email, userId, name) is injected from the session.
57
57
 
58
58
  #### Checkout Modes
59
59
 
60
60
  `FloPayCheckout` supports three checkout modes matching the billing API's `checkoutMode` field:
61
61
 
62
- - **`full`** (default) — Shows the full payment form with card fields + wallet buttons.
62
+ - **`full`** (default) — Shows the hosted card widget plus supported non-card methods.
63
63
  - **`confirm`** — Hides the payment form and shows a "Confirm Purchase" button. Uses a saved payment method on the backend.
64
64
  - **`auto`** — Auto-submits with a saved payment method after the session loads. Falls back to `full` mode on failure.
65
65
 
@@ -187,6 +187,13 @@ the entire integration change — no SDK redeploy or consumer code update is
187
187
  required. Wallets only render on supported devices regardless of dashboard
188
188
  state (Apple Pay on Safari/macOS/iOS, Google Pay on Chrome).
189
189
 
190
+ > **Bundler note:** the vendored APM brand logos ship as sibling `.svg` assets
191
+ > under `dist/payment-logos/`, referenced with `new URL('./…', import.meta.url)`
192
+ > so their bytes stay out of the JS bundle (a card-only checkout ships none of
193
+ > them). Your bundler must support asset URLs — Vite, webpack 5, Rollup, Next,
194
+ > and esbuild all do out of the box. Card-only and vault checkouts never render
195
+ > a method tile, so they never request a logo.
196
+
190
197
  In `layout="buttons"`, the **Credit / Debit Card** button always opens the
191
198
  inline card form. External wallets and PayPal keep their own lifecycle:
192
199
  buyer cancellation silently returns to the payment-method chooser with all
@@ -204,7 +211,7 @@ two gateway-level props:
204
211
  ```tsx
205
212
  <FloPayCheckout
206
213
  sessionId="sess_abc123"
207
- showStripe={true} // default: true — card + ECE + PaymentElement
214
+ showStripe={true} // default: true — Stripe wallets/APMs only
208
215
  showPayPal={true} // default: true — DirectPayPal when gateway present,
209
216
  // Stripe-rendered PayPal otherwise
210
217
  onComplete={handleSuccess}
@@ -227,7 +234,7 @@ legacy props will be removed in `2.0`.
227
234
 
228
235
  #### Theming
229
236
 
230
- `FloPayCheckout`, `FloPayAutomaticPaymentButton`, and `SplitCardForm` accept a single `theme` prop that maps to a coherent `{appearance, buttonsLayout}` bundle in `@flopay/shared`'s `THEMES` map. One value styles the Stripe-side appearance, the React-rendered wrapper, the submit button, the inputs, and — for `FloPayAutomaticPaymentButton` — the fallback modal that opens when a saved-payment charge can't complete silently.
237
+ `FloPayCheckout`, `FloPayAutomaticPaymentButton`, and `SplitCardForm` accept a single `theme` prop that maps to a coherent `{appearance, buttonsLayout}` bundle in `@flopay/shared`'s `THEMES` map. One value styles non-card Stripe Elements, the React-rendered wrapper and AVS inputs, the hosted vault widget, and — for `FloPayAutomaticPaymentButton` — the fallback modal that opens when a saved-payment charge can't complete silently.
231
238
 
232
239
  | `theme` | Aesthetic |
233
240
  |---|---|
@@ -373,87 +380,9 @@ When you use `onBeforeButtonClick` with `createSession`, any returned `InlineSes
373
380
 
374
381
  ### Advanced: Manual Provider Setup
375
382
 
376
- For full control over initialization:
377
-
378
- ```tsx
379
- import { loadFloPay } from '@flopay/js';
380
- import { FloPayProvider, CheckoutForm } from '@flopay/react';
381
-
382
- const floPayPromise = loadFloPay('pk_test_...');
383
-
384
- function CheckoutPage() {
385
- return (
386
- <FloPayProvider
387
- flopay={floPayPromise}
388
- options={{
389
- amount: 2999,
390
- currency: 'usd',
391
- }}
392
- >
393
- <CheckoutForm
394
- sessionId="session_uuid"
395
- nonce={sessionNonce}
396
- email="user@example.com"
397
- userId="user_1"
398
- onComplete={(result) => {
399
- if (result.status === 'succeeded') {
400
- window.location.href = '/success';
401
- }
402
- }}
403
- onError={(err) => console.error(err)}
404
- />
405
- </FloPayProvider>
406
- );
407
- }
408
- ```
409
-
410
- `CheckoutForm` handles the full payment lifecycle by default:
411
-
412
- 1. Validate elements via `submitElements()`
413
- 2. Tokenize card via `createPaymentMethod()` -> `pm_xxx`
414
- 3. Create PaymentIntent via billing API
415
- 4. Confirm card payment (handles 3D Secure)
416
- 5. Submit tokenized body to `POST /v1/checkouts/sessions/<id>/process`
417
- 6. If backend returns `3ds_required`, re-confirm with new client secret
418
- 7. Resume wallet payments after redirect (PayPal)
419
-
420
- Pass `nonce` (the session-bound checkout token returned by session creation —
421
- `CheckoutSessionResult.nonce`, or `session.clientSecret` once the session is
422
- loaded). The SDK forwards it as `x-checkout-session-token` on every
423
- continuation call. Post-#640 backends (`TeamFloPay/backend#640`) 401 when the
424
- header is missing. `FloPayCheckout` already plumbs the prop automatically.
425
-
426
- ### Override Mode (Custom Backend)
427
-
428
- Pass `onTokenizedBody` to handle backend submission yourself:
429
-
430
- ```tsx
431
- <CheckoutForm
432
- sessionId="session_uuid"
433
- billingApiUrl="https://billing.example.com"
434
- email="user@example.com"
435
- onTokenizedBody={(body) => {
436
- // body = {
437
- // id: 'pm_xxx',
438
- // type: 'card',
439
- // threeDSecureActionResultTokenId: 'pi_xxx',
440
- // originalPaymentMethodId: 'pm_xxx',
441
- // }
442
- myCustomProcessPayment(body);
443
- }}
444
- />
445
- ```
446
-
447
- > **Vault card path — `onTokenizedBody` does not fire.** When the session uses the
448
- > [vault PCI card form](#vault-pci-card-form), the backend-served widget owns the
449
- > whole charge (tokenize → PaymentIntent → 3DS → result), so there is no
450
- > client-side tokenization step to override. Use `onComplete` / `onDecline` /
451
- > `onError` instead — the SDK relays the widget's terminal outcome to them. The
452
- > legacy Stripe path's `onTokenizedBody` is unchanged.
453
-
454
- ### SplitCardForm (Split Card Fields + PayPal)
455
-
456
- `SplitCardForm` renders separate CardNumber, CardExpiry, and CardCVC fields with an integrated PayPal button. It matches the existing checkout/StripeCardForm layout.
383
+ Use `SplitCardForm` when you need to compose the provider and session yourself.
384
+ Card checkout still requires the backend-hosted vault block; Stripe remains
385
+ limited to wallets/APMs and saved-payment authentication.
457
386
 
458
387
  ```tsx
459
388
  import { FloPayProvider, SplitCardForm } from '@flopay/react';
@@ -473,12 +402,13 @@ function CheckoutPage() {
473
402
  <SplitCardForm
474
403
  sessionId="session_uuid"
475
404
  nonce={sessionNonce}
405
+ session={session}
476
406
  billingApiUrl="https://billing.example.com"
477
407
  email="user@example.com"
478
408
  userId="user_1"
479
- totalAmount={29.99} // dollars (for PayPal Elements config)
409
+ totalAmount={2999} // cents
480
410
  currency="usd"
481
- showPayPal={true} // default: true
411
+ enabledPaymentMethods={session.gateways?.stripe?.enabledPaymentMethods}
482
412
  onComplete={(result) => {
483
413
  if (result.status === 'succeeded') {
484
414
  window.location.href = '/success';
@@ -493,26 +423,33 @@ function CheckoutPage() {
493
423
  }
494
424
  ```
495
425
 
496
- The `SplitCardForm` layout:
497
- 1. Wallet buttons — Apple Pay + Google Pay (via ExpressCheckoutElement in the main Elements instance)
498
- 2. PayPal button (via ExpressCheckoutElement in a separate Elements instance)
499
- 3. "or pay with card" divider
500
- 4. Card Number input
501
- 5. Card Expiry + CVC side by side
502
- 6. Full Name input
503
- 7. Submit button
426
+ The resulting surfaces are:
427
+
428
+ 1. Wallet buttons and supported APM tiles from the session gateway capability.
429
+ 2. Direct or Stripe-hosted PayPal, selected from the session gateways.
430
+ 3. The hosted vault widget for card-capable sessions.
431
+
432
+ Wallets, APMs, and PayPal create intents through
433
+ `POST /v1/checkouts/sessions/{id}/intents`. The discriminated request separates
434
+ provider, payment-method category/type/id, and intent kind. Direct-card intent
435
+ requests are unsupported. Client-observed non-card failures use the
436
+ nonce-protected session decline endpoint and contain no payment tokens,
437
+ provider object IDs, card data, credentials, or PII.
438
+
439
+ If a card-capable backend omits the vault block, card checkout stays hidden.
440
+ Advertised non-card methods remain usable; if none remain,
441
+ `onError` receives `UnsupportedBackendVaultCapability`.
504
442
 
505
443
  #### AVS postcode validation
506
444
 
507
445
  When AVS collection is enabled (`enableAVS`) and the postcode field is shown,
508
446
  `SplitCardForm` validates the postcode **format against the live selected
509
- country before the card is captured**, on both the Stripe and vault card paths.
447
+ country before the hosted vault captures the card**.
510
448
  It reuses `@flopay/shared`'s country-aware
511
449
  [postcode helpers](../shared/README.md#postal-code-helpers) (the same
512
450
  `validator` rules the billing API applies), so client and server agree.
513
451
 
514
- - **Supported country + malformed postcode** → the submit is blocked (the vault
515
- widget's submit button is gated; the Stripe path returns before tokenizing)
452
+ - **Supported country + malformed postcode** → the vault widget's submit is blocked
516
453
  and an inline, country-specific message shows the expected format
517
454
  (e.g. *"Enter a valid ZIP Code (e.g. 12345 or 12345-6789)"*). On the vault
518
455
  path the inline message appears once the field is blurred, since the disabled
@@ -553,17 +490,18 @@ best-effort **in parallel** with the widget's charge:
553
490
 
554
491
  When the billing API returns a hosted vault card form on the session
555
492
  (`session.vault`), the card path renders a **backend-served, self-contained
556
- hosted vault widget** (`VaultCardFields`) instead of Stripe's embedded card
557
- elements (TeamFloPay/backend#823, Model A). The backend embeds this block for
558
- any SDK that advertises `x-flo-sdk-version >= 1.3.0`, so it is fully
493
+ hosted vault widget** (`VaultCardFields`) (TeamFloPay/backend#823, Model A).
494
+ Every card-capable session is
495
+ expected to include this block without SDK-version dispatch. It is fully
559
496
  **server-driven** — there is no consumer prop to toggle it. The widget owns the
560
497
  card fields, its own submit button, card tokenization, the PaymentIntent (created
561
498
  **and** confirmed server-side), **3DS**, and the result, so **no Stripe.js runs
562
499
  on the card path** and PAN / CVC never enter the SDK runtime. Wallets / PayPal /
563
500
  APMs render exactly as before.
564
501
 
565
- Because the widget owns the form, on the vault path `SplitCardForm` hides its own
566
- card fields, cardholder-name input, AVS fields, and submit button. The flow is:
502
+ Because the widget owns the form, `SplitCardForm` exposes no SDK card-entry or
503
+ card-submit controls. Host-collected AVS fields remain outside the PCI
504
+ widget and gate its submit. The flow is:
567
505
 
568
506
  ```text
569
507
  session includes a hosted vault card form (session.vault)
@@ -572,9 +510,8 @@ session includes a hosted vault card form (session.vault)
572
510
  → widget postMessages its outcome → SDK fires onComplete / onDecline / onError
573
511
  ```
574
512
 
575
- - The widget HTML comes from the embedded `session.vault.html` (SDKs ≥ 1.3.0 send
576
- `X-Flo-SDK-Version`, so the backend embeds it on create-session) or, if absent,
577
- from `POST /v1/checkouts/sessions/{id}/vault/capture`.
513
+ - The widget HTML normally comes from embedded `session.vault.html`; the explicit
514
+ recovery/retry path is `POST /v1/checkouts/sessions/{id}/vault/capture`.
578
515
  - **Returning customers** with a card on file (`session.providerPaymentMethodId`)
579
516
  are charged by the backend's auto-checkout cascade.
580
517
  - **3DS** is handled inside the widget — there is no client-side `confirmCardPayment`.
@@ -584,9 +521,10 @@ session includes a hosted vault card form (session.vault)
584
521
 
585
522
  > **Backend dependencies:** the hosted widget must emit the `flopay-vault`
586
523
  > `postMessage` outcome the SDK listens for (otherwise it falls back to its own
587
- > success redirect), handle the 3DS step internally, and own AVS for the vault
588
- > path (the SDK no longer collects it inline; account-level address set at
589
- > session-create still flows to the backend). Because the widget is injected
524
+ > success redirect), handle the 3DS step internally, and use the session account
525
+ > snapshot for AVS. The SDK collects and validates those address fields outside
526
+ > the PCI widget and persists them through the session account endpoint; the
527
+ > widget owns only sensitive card-data capture. Because the widget is injected
590
528
  > **same-window**, every terminal outcome must be bound to the session id, and —
591
529
  > to fully defend against same-window forgery — the backend should mint a
592
530
  > per-session `messageToken` on the vault block and echo it in each
@@ -598,12 +536,35 @@ session includes a hosted vault card form (session.vault)
598
536
  The SDK supports two PayPal paths, selected per-session based on what the billing API advertises under `gateways.*`:
599
537
 
600
538
  - **Direct PayPal** (preferred where available — works inside Facebook, Instagram, and other in-app browsers): when the session exposes `gateways.paypal.publishableKey`, the SDK renders PayPal via the official PayPal JS SDK using `<DirectPayPalButton>`. The PayPal client ID and `environment` (`'sandbox'`/`'live'`) come directly from the backend.
601
- - **Stripe-rendered PayPal fallback** (legacy): when only `gateways.stripe` is configured, PayPal renders through Stripe's `ExpressCheckoutElement` in its own Elements wrapper. This path can't render in Facebook/Instagram in-app browsers.
539
+ - **Stripe-rendered PayPal**: when only `gateways.stripe` is configured, PayPal renders through Stripe's `ExpressCheckoutElement` in its own Elements wrapper. This path can't render in Facebook/Instagram in-app browsers.
602
540
 
603
541
  Renderer selection is mutually exclusive per session — direct PayPal takes priority over Stripe-rendered PayPal. Consumer props such as `showPayPal` continue to gate visibility on the client side.
604
542
 
605
543
  **PayPal-only sessions:** When the backend advertises only `gateways.paypal` (no `gateways.stripe`), `FloPayCheckout` skips Stripe Elements entirely and renders `<DirectPayPalButton>` as the sole payment surface. Sessions that advertise no supported gateway at all throw a `validation_error` explaining the expected shape.
606
544
 
545
+ **Direct PayPal initialization recovery:** PayPal's own cross-window bridge owns
546
+ its 10-second `postMessage init()` acknowledgement deadline; FloPay does not
547
+ change that upstream timeout. If the exact acknowledgement timeout is reported,
548
+ or if `Buttons.render()` is still unsettled after 11 seconds, the SDK hides
549
+ Direct PayPal, waits one second, and makes exactly one background render retry.
550
+ The retry uses a fresh render generation, and callbacks or promise settlements
551
+ from the superseded generation are ignored.
552
+
553
+ In a mixed checkout, card, wallets, APMs, and any other eligible methods remain
554
+ interactive throughout recovery. If both Direct PayPal attempts fail, PayPal
555
+ stays hidden for that component configuration; the SDK emits one sanitized
556
+ console diagnostic and calls neither `onError` nor `onDecline`. Deterministic
557
+ configuration failures and `isEligible() === false` are not automatically
558
+ retried.
559
+
560
+ In a PayPal-only checkout, `FloPayCheckout` shows an accessible retrying status
561
+ instead of a blank surface. After automatic recovery is exhausted, it shows safe
562
+ generic unavailable copy and a **Retry PayPal** button. `onError` fires once with
563
+ a `FloPayError` whose `type` is `api_error` and whose stable `code` is
564
+ `paypal_init_timeout`; `onDecline` does not fire and the raw provider message is
565
+ never rendered. Manual retry reuses the current checkout session and performs
566
+ one fresh render attempt without adding another automatic retry.
567
+
607
568
  The SDK exposes the relevant pieces in three ways:
608
569
 
609
570
  - **`SplitCardForm`** / **`FloPayCheckout`**: pick the renderer automatically based on `gateways.*`. No additional configuration needed.
@@ -615,7 +576,7 @@ The SDK exposes the relevant pieces in three ways:
615
576
  - **`PayPalButton`** (standalone): Must be rendered inside its own `FloPayProvider`:
616
577
 
617
578
  ```tsx
618
- {/* Card fields provider */}
579
+ {/* Main checkout provider */}
619
580
  <FloPayProvider flopay={flopay} options={{ amount, currency }}>
620
581
  <SplitCardForm ... />
621
582
  </FloPayProvider>
@@ -631,31 +592,30 @@ The SDK exposes the relevant pieces in three ways:
631
592
  </FloPayProvider>
632
593
  ```
633
594
 
634
- ### Using Individual Elements
595
+ ### Using Individual Non-card Elements
635
596
 
636
597
  ```tsx
637
- import { FloPayProvider, PaymentElement, CardElement, useFloPay } from '@flopay/react';
598
+ import { AddressElement, PaymentElement } from '@flopay/react';
638
599
 
639
600
  function CustomForm() {
640
- const flopay = useFloPay();
641
-
642
- const handleSubmit = async () => {
643
- if (!flopay) return;
644
- const { error } = await flopay.submitElements();
645
- if (error) return console.error(error);
646
- const { paymentMethodId } = await flopay.createPaymentMethod();
647
- // Use paymentMethodId...
648
- };
649
-
650
601
  return (
651
602
  <div>
652
- <PaymentElement options={{ layout: 'tabs' }} />
653
- <button onClick={handleSubmit}>Pay</button>
603
+ <PaymentElement
604
+ options={{
605
+ layout: 'tabs',
606
+ paymentMethodTypes: ['cashapp', 'ideal'],
607
+ }}
608
+ />
609
+ <AddressElement />
654
610
  </div>
655
611
  );
656
612
  }
657
613
  ```
658
614
 
615
+ These elements support wallet/APM and address collection. `PaymentElement`
616
+ requires a non-empty `paymentMethodTypes` allowlist and rejects `card`; use the
617
+ hosted vault checkout surface for card payments.
618
+
659
619
  ### Using Hooks
660
620
 
661
621
  ```tsx
@@ -678,15 +638,12 @@ function PaymentStatus() {
678
638
  | Component | Description |
679
639
  |-----------|-------------|
680
640
  | `FloPayProvider` | Context provider. Accepts `flopay` (instance or promise), `options?`, and `children`. Creates the elements group automatically. |
681
- | `CheckoutForm` | Drop-in form with unified PaymentElement. Self-contained by default, or override with `onTokenizedBody`. Supports `ref` for imperative `handleNextAction()`. |
682
- | `SplitCardForm` | Split card form (CardNumber + CardExpiry + CardCvc + Full Name). Integrates PayPal via separate Elements instance. Renders the [vault PCI card form](#vault-pci-card-form) when the session includes a hosted vault card form (`session.vault`). Supports `ref` for imperative `handleNextAction()`. |
641
+ | `FloPayCheckout` | Recommended self-contained session checkout. Resolves gateways, mounts hosted-vault cards, and preserves wallets/APMs/PayPal/saved-payment flows. |
642
+ | `SplitCardForm` | Advanced checkout surface combining hosted-vault cards with wallets, APMs, and PayPal. Supports `ref` for imperative next-action handling. |
683
643
  | `VaultCardFields` | Hosted vault PCI card fields. Used internally by `SplitCardForm` on the vault path; consumes a `CardCaptureAdapter` from `useFloPay().cardCapture()`. |
684
644
  | `PayPalButton` | Standalone PayPal button. Requires its own `FloPayProvider` with `paymentMethodCreation` set to something other than `'manual'`. |
685
- | `PaymentElement` | Unified payment element (cards, wallets, etc.) |
686
- | `CardElement` | Combined card input |
687
- | `CardNumberElement` | Card number field |
688
- | `CardExpiryElement` | Card expiry field |
689
- | `CardCvcElement` | Card CVC field |
645
+ | `DirectPayPalButton` | Standalone direct PayPal order/subscription button using the session-scoped intent contract. |
646
+ | `PaymentElement` | Provider element for an explicitly declared non-card `paymentMethodTypes` allowlist. |
690
647
  | `AddressElement` | Address input element |
691
648
 
692
649
  ### Hooks
@@ -704,9 +661,9 @@ function PaymentStatus() {
704
661
  | `flopay` | `Promise<FloPay> \| FloPay` | SDK instance or promise from `loadFloPay()` |
705
662
  | `options.locale` | `string?` | Locale |
706
663
  | `options.appearance` | `FloPayAppearance?` | Theme appearance |
707
- | `options.clientSecret` | `string?` | PaymentIntent client secret (if intent already exists) |
708
- | `options.amount` | `number?` | Amount in cents (used when no `clientSecret`) |
709
- | `options.currency` | `string?` | ISO 4217 currency code (used when no `clientSecret`) |
664
+ | `options.clientSecret` | `string?` | Existing non-card PaymentIntent or SetupIntent secret; the SDK verifies the provider intent against `PaymentElement`'s explicit wallet/APM allowlist before mounting and rejects card or undeclared methods. Card checkout uses the hosted vault. |
665
+ | `options.amount` | `number?` | Amount in cents for deferred non-card Elements without a `clientSecret` |
666
+ | `options.currency` | `string?` | ISO 4217 currency code for deferred non-card Elements without a `clientSecret` |
710
667
  | `options.paymentMethodCreation` | `'manual' \| 'auto'` | How payment methods are created |
711
668
 
712
669
  ### Privacy-safe operational telemetry
@@ -727,38 +684,19 @@ No endpoint, custom tag, user context, message, stack, or metadata can be
727
684
  configured. See [`docs/TELEMETRY.md`](../../docs/TELEMETRY.md) for the complete
728
685
  privacy and retention contract.
729
686
 
730
- ### CheckoutFormProps
731
-
732
- | Prop | Type | Description |
733
- |------|------|-------------|
734
- | `sessionId` | `string` | Checkout session UUID |
735
- | `billingApiUrl` | `string` | Billing API base URL |
736
- | `email` | `string?` | User email |
737
- | `userId` | `string?` | User ID |
738
- | `onComplete` | `(result: PaymentResult) => void` | Success callback |
739
- | `onError` | `(error: FloPayError) => void` | Error callback |
740
- | `onTokenizedBody` | `(body: TokenizedBody) => void` | Override: handle backend submission yourself |
741
- | `layout` | `'tabs' \| 'accordion' \| 'auto'` | PaymentElement layout (default: `'auto'`) |
742
- | `submitLabel` | `string` | Button text (default: `'Pay'`) |
743
- | `showAddress` | `boolean \| 'billing' \| 'shipping'` | Show address element (default: `false`) |
744
- | `className` | `string?` | CSS class for form wrapper |
745
- | `children` | `ReactNode?` | Custom submit button |
746
- | `firstName` | `string?` | Billing first name |
747
- | `lastName` | `string?` | Billing last name |
748
- | `chv` | `string?` | Checkout version for A/B tracking |
749
- | `isProcessing` | `boolean?` | External processing state |
750
- | `error` | `string?` | External error message |
751
- | `onErrorChange` | `(error: string \| null) => void` | Error state change callback |
752
-
753
687
  ### SplitCardFormProps
754
688
 
755
- Shares most props with `CheckoutFormProps`, plus:
689
+ Key payment-surface props include:
756
690
 
757
691
  | Prop | Type | Description |
758
692
  |------|------|-------------|
759
- | `showStripe` | `boolean` | Show the whole Stripe surface (card + ECE + PaymentElement). Default: `true`. Setting `showStripe={false}` together with `showPayPal={false}` (or no PayPal gateway) emits a `FloPayError({ type: 'validation_error' })` via `onError`. |
693
+ | `sessionId` | `string` | Checkout session UUID. |
694
+ | `nonce` | `string` | Session-bound token forwarded on intent, decline, account, and process calls. |
695
+ | `session` | `CheckoutSession?` | Session capability data, including the hosted `vault` block and gateways. |
696
+ | `billingApiUrl` | `string` | Billing API base URL. |
697
+ | `showStripe` | `boolean` | Show Stripe-backed wallets/APMs. Card checkout is controlled by the session vault capability. |
760
698
  | `showPayPal` | `boolean` | Show PayPal. Renderer chosen by `gateways.paypal` presence (DirectPayPal JS SDK when present; Stripe-rendered PayPal otherwise). Default: `true`. |
761
- | `enabledPaymentMethods` | `string[]?` | Per-session list of Stripe method type identifiers (`apple_pay`, `google_pay`, `cashapp`, `klarna`, `link`, `amazon_pay`, `sepa_debit`, `affirm`, `ideal`, …). Normally threaded automatically from `gateways.stripe.enabledPaymentMethods` by `FloPayCheckout`. The SDK partitions it into the ExpressCheckoutElement big-button row (intersected with `STRIPE_EXPRESS_METHODS`) and the accordion PaymentElement region (everything else; `card` is always dropped because the split fields render the card path). |
699
+ | `enabledPaymentMethods` | `string[]?` | Per-session list of Stripe method type identifiers (`apple_pay`, `google_pay`, `cashapp`, `klarna`, `link`, `amazon_pay`, `sepa_debit`, `affirm`, `ideal`, …). Normally threaded automatically from `gateways.stripe.enabledPaymentMethods` by `FloPayCheckout`. The SDK partitions it into the ExpressCheckoutElement big-button row (intersected with `STRIPE_EXPRESS_METHODS`) and the accordion PaymentElement region; `card` is always dropped because the hosted vault owns that path. |
762
700
  | `showApplePay` | `boolean` | *Deprecated.* Apple Pay availability is dashboard-controlled at Stripe and surfaces through `enabledPaymentMethods`. Emits a one-time `console.warn` when supplied alongside `enabledPaymentMethods` and is otherwise ignored. Removed in `2.0`. |
763
701
  | `showGooglePay` | `boolean` | *Deprecated.* See `showApplePay`. |
764
702
  | `directPaypal` | `{ clientId: string; environment?: GatewayEnvironment }?` | *Deprecated input on `FloPayCheckout`* — auto-resolved from `gateways.paypal` on the session response. Still accepted on `SplitCardForm` for advanced consumers wiring providers manually. |
@@ -766,7 +704,7 @@ Shares most props with `CheckoutFormProps`, plus:
766
704
  | `currency` | `string` | Currency code for PayPal / wallet config (default: `'usd'`) |
767
705
  | `onFirstNameChange` | `(value: string) => void` | First name change callback |
768
706
  | `onLastNameChange` | `(value: string) => void` | Last name change callback |
769
- | `submitLabel` | `string` | Button text (default: `'CONFIRM PAYMENT'`) |
707
+ | `onComplete` / `onDecline` / `onError` | callbacks | Observable checkout outcomes. |
770
708
 
771
709
  ### ElementComponentProps (shared by all element components)
772
710
 
@@ -787,10 +725,7 @@ Shares most props with `CheckoutFormProps`, plus:
787
725
  | Type | Description |
788
726
  |------|-------------|
789
727
  | `FloPayProviderProps` | Props for `FloPayProvider` |
790
- | `CheckoutFormProps` | Props for `CheckoutForm` |
791
- | `CheckoutFormRef` | Ref type: `{ handleNextAction(clientSecret) }` |
792
728
  | `SplitCardFormProps` | Props for `SplitCardForm` |
793
- | `SplitCardFormRef` | Ref type: `{ handleNextAction(clientSecret) }` |
794
729
  | `PayPalButtonProps` | Props for `PayPalButton` |
795
730
  | `ElementComponentProps` | Shared props for all element components |
796
731
  | `CheckoutState` | `{ session, loading, error }` |