@flopay/react 1.4.1 → 1.4.3

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
 
@@ -211,7 +211,7 @@ two gateway-level props:
211
211
  ```tsx
212
212
  <FloPayCheckout
213
213
  sessionId="sess_abc123"
214
- showStripe={true} // default: true — card + ECE + PaymentElement
214
+ showStripe={true} // default: true — Stripe wallets/APMs only
215
215
  showPayPal={true} // default: true — DirectPayPal when gateway present,
216
216
  // Stripe-rendered PayPal otherwise
217
217
  onComplete={handleSuccess}
@@ -234,7 +234,7 @@ legacy props will be removed in `2.0`.
234
234
 
235
235
  #### Theming
236
236
 
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 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.
238
238
 
239
239
  | `theme` | Aesthetic |
240
240
  |---|---|
@@ -280,6 +280,11 @@ Switch from the default form layout to stacked payment buttons with an expandabl
280
280
  />
281
281
  ```
282
282
 
283
+ `layout` can be changed at runtime. Switching a mounted `FloPayCheckout` from
284
+ the default layout to `"buttons"` keeps the resolved checkout session and its
285
+ gateway capabilities, so the **Credit / Debit Card** choice remains available
286
+ without recreating the session.
287
+
283
288
  > **Deprecated**: the legacy `buttonsTheme` prop (`'default'` / `'minimal'` / `'rounded'` / `'dark'`) still works but new code should use `theme` so the same value drives both the buttons-layout wrapper and the auto-payment fallback. See [ButtonsLayoutStyles reference](https://docs.flopay.com/api-reference/react/flopay-checkout#buttonslayoutstyles-reference) for the underlying override fields.
284
289
 
285
290
  #### Button Hooks
@@ -380,87 +385,9 @@ When you use `onBeforeButtonClick` with `createSession`, any returned `InlineSes
380
385
 
381
386
  ### Advanced: Manual Provider Setup
382
387
 
383
- For full control over initialization:
384
-
385
- ```tsx
386
- import { loadFloPay } from '@flopay/js';
387
- import { FloPayProvider, CheckoutForm } from '@flopay/react';
388
-
389
- const floPayPromise = loadFloPay('pk_test_...');
390
-
391
- function CheckoutPage() {
392
- return (
393
- <FloPayProvider
394
- flopay={floPayPromise}
395
- options={{
396
- amount: 2999,
397
- currency: 'usd',
398
- }}
399
- >
400
- <CheckoutForm
401
- sessionId="session_uuid"
402
- nonce={sessionNonce}
403
- email="user@example.com"
404
- userId="user_1"
405
- onComplete={(result) => {
406
- if (result.status === 'succeeded') {
407
- window.location.href = '/success';
408
- }
409
- }}
410
- onError={(err) => console.error(err)}
411
- />
412
- </FloPayProvider>
413
- );
414
- }
415
- ```
416
-
417
- `CheckoutForm` handles the full payment lifecycle by default:
418
-
419
- 1. Validate elements via `submitElements()`
420
- 2. Tokenize card via `createPaymentMethod()` -> `pm_xxx`
421
- 3. Create PaymentIntent via billing API
422
- 4. Confirm card payment (handles 3D Secure)
423
- 5. Submit tokenized body to `POST /v1/checkouts/sessions/<id>/process`
424
- 6. If backend returns `3ds_required`, re-confirm with new client secret
425
- 7. Resume wallet payments after redirect (PayPal)
426
-
427
- Pass `nonce` (the session-bound checkout token returned by session creation —
428
- `CheckoutSessionResult.nonce`, or `session.clientSecret` once the session is
429
- loaded). The SDK forwards it as `x-checkout-session-token` on every
430
- continuation call. Post-#640 backends (`TeamFloPay/backend#640`) 401 when the
431
- header is missing. `FloPayCheckout` already plumbs the prop automatically.
432
-
433
- ### Override Mode (Custom Backend)
434
-
435
- Pass `onTokenizedBody` to handle backend submission yourself:
436
-
437
- ```tsx
438
- <CheckoutForm
439
- sessionId="session_uuid"
440
- billingApiUrl="https://billing.example.com"
441
- email="user@example.com"
442
- onTokenizedBody={(body) => {
443
- // body = {
444
- // id: 'pm_xxx',
445
- // type: 'card',
446
- // threeDSecureActionResultTokenId: 'pi_xxx',
447
- // originalPaymentMethodId: 'pm_xxx',
448
- // }
449
- myCustomProcessPayment(body);
450
- }}
451
- />
452
- ```
453
-
454
- > **Vault card path — `onTokenizedBody` does not fire.** When the session uses the
455
- > [vault PCI card form](#vault-pci-card-form), the backend-served widget owns the
456
- > whole charge (tokenize → PaymentIntent → 3DS → result), so there is no
457
- > client-side tokenization step to override. Use `onComplete` / `onDecline` /
458
- > `onError` instead — the SDK relays the widget's terminal outcome to them. The
459
- > legacy Stripe path's `onTokenizedBody` is unchanged.
460
-
461
- ### SplitCardForm (Split Card Fields + PayPal)
462
-
463
- `SplitCardForm` renders separate CardNumber, CardExpiry, and CardCVC fields with an integrated PayPal button. It matches the existing checkout/StripeCardForm layout.
388
+ Use `SplitCardForm` when you need to compose the provider and session yourself.
389
+ Card checkout still requires the backend-hosted vault block; Stripe remains
390
+ limited to wallets/APMs and saved-payment authentication.
464
391
 
465
392
  ```tsx
466
393
  import { FloPayProvider, SplitCardForm } from '@flopay/react';
@@ -480,12 +407,13 @@ function CheckoutPage() {
480
407
  <SplitCardForm
481
408
  sessionId="session_uuid"
482
409
  nonce={sessionNonce}
410
+ session={session}
483
411
  billingApiUrl="https://billing.example.com"
484
412
  email="user@example.com"
485
413
  userId="user_1"
486
- totalAmount={29.99} // dollars (for PayPal Elements config)
414
+ totalAmount={2999} // cents
487
415
  currency="usd"
488
- showPayPal={true} // default: true
416
+ enabledPaymentMethods={session.gateways?.stripe?.enabledPaymentMethods}
489
417
  onComplete={(result) => {
490
418
  if (result.status === 'succeeded') {
491
419
  window.location.href = '/success';
@@ -500,26 +428,33 @@ function CheckoutPage() {
500
428
  }
501
429
  ```
502
430
 
503
- The `SplitCardForm` layout:
504
- 1. Wallet buttons — Apple Pay + Google Pay (via ExpressCheckoutElement in the main Elements instance)
505
- 2. PayPal button (via ExpressCheckoutElement in a separate Elements instance)
506
- 3. "or pay with card" divider
507
- 4. Card Number input
508
- 5. Card Expiry + CVC side by side
509
- 6. Full Name input
510
- 7. Submit button
431
+ The resulting surfaces are:
432
+
433
+ 1. Wallet buttons and supported APM tiles from the session gateway capability.
434
+ 2. Direct or Stripe-hosted PayPal, selected from the session gateways.
435
+ 3. The hosted vault widget for card-capable sessions.
436
+
437
+ Wallets, APMs, and PayPal create intents through
438
+ `POST /v1/checkouts/sessions/{id}/intents`. The discriminated request separates
439
+ provider, payment-method category/type/id, and intent kind. Direct-card intent
440
+ requests are unsupported. Client-observed non-card failures use the
441
+ nonce-protected session decline endpoint and contain no payment tokens,
442
+ provider object IDs, card data, credentials, or PII.
443
+
444
+ If a card-capable backend omits the vault block, card checkout stays hidden.
445
+ Advertised non-card methods remain usable; if none remain,
446
+ `onError` receives `UnsupportedBackendVaultCapability`.
511
447
 
512
448
  #### AVS postcode validation
513
449
 
514
450
  When AVS collection is enabled (`enableAVS`) and the postcode field is shown,
515
451
  `SplitCardForm` validates the postcode **format against the live selected
516
- country before the card is captured**, on both the Stripe and vault card paths.
452
+ country before the hosted vault captures the card**.
517
453
  It reuses `@flopay/shared`'s country-aware
518
454
  [postcode helpers](../shared/README.md#postal-code-helpers) (the same
519
455
  `validator` rules the billing API applies), so client and server agree.
520
456
 
521
- - **Supported country + malformed postcode** → the submit is blocked (the vault
522
- widget's submit button is gated; the Stripe path returns before tokenizing)
457
+ - **Supported country + malformed postcode** → the vault widget's submit is blocked
523
458
  and an inline, country-specific message shows the expected format
524
459
  (e.g. *"Enter a valid ZIP Code (e.g. 12345 or 12345-6789)"*). On the vault
525
460
  path the inline message appears once the field is blurred, since the disabled
@@ -560,17 +495,18 @@ best-effort **in parallel** with the widget's charge:
560
495
 
561
496
  When the billing API returns a hosted vault card form on the session
562
497
  (`session.vault`), the card path renders a **backend-served, self-contained
563
- hosted vault widget** (`VaultCardFields`) instead of Stripe's embedded card
564
- elements (TeamFloPay/backend#823, Model A). The backend embeds this block for
565
- any SDK that advertises `x-flo-sdk-version >= 1.3.0`, so it is fully
498
+ hosted vault widget** (`VaultCardFields`) (TeamFloPay/backend#823, Model A).
499
+ Every card-capable session is
500
+ expected to include this block without SDK-version dispatch. It is fully
566
501
  **server-driven** — there is no consumer prop to toggle it. The widget owns the
567
502
  card fields, its own submit button, card tokenization, the PaymentIntent (created
568
503
  **and** confirmed server-side), **3DS**, and the result, so **no Stripe.js runs
569
504
  on the card path** and PAN / CVC never enter the SDK runtime. Wallets / PayPal /
570
505
  APMs render exactly as before.
571
506
 
572
- Because the widget owns the form, on the vault path `SplitCardForm` hides its own
573
- card fields, cardholder-name input, AVS fields, and submit button. The flow is:
507
+ Because the widget owns the form, `SplitCardForm` exposes no SDK card-entry or
508
+ card-submit controls. Host-collected AVS fields remain outside the PCI
509
+ widget and gate its submit. The flow is:
574
510
 
575
511
  ```text
576
512
  session includes a hosted vault card form (session.vault)
@@ -579,9 +515,8 @@ session includes a hosted vault card form (session.vault)
579
515
  → widget postMessages its outcome → SDK fires onComplete / onDecline / onError
580
516
  ```
581
517
 
582
- - The widget HTML comes from the embedded `session.vault.html` (SDKs ≥ 1.3.0 send
583
- `X-Flo-SDK-Version`, so the backend embeds it on create-session) or, if absent,
584
- from `POST /v1/checkouts/sessions/{id}/vault/capture`.
518
+ - The widget HTML normally comes from embedded `session.vault.html`; the explicit
519
+ recovery/retry path is `POST /v1/checkouts/sessions/{id}/vault/capture`.
585
520
  - **Returning customers** with a card on file (`session.providerPaymentMethodId`)
586
521
  are charged by the backend's auto-checkout cascade.
587
522
  - **3DS** is handled inside the widget — there is no client-side `confirmCardPayment`.
@@ -591,9 +526,10 @@ session includes a hosted vault card form (session.vault)
591
526
 
592
527
  > **Backend dependencies:** the hosted widget must emit the `flopay-vault`
593
528
  > `postMessage` outcome the SDK listens for (otherwise it falls back to its own
594
- > success redirect), handle the 3DS step internally, and own AVS for the vault
595
- > path (the SDK no longer collects it inline; account-level address set at
596
- > session-create still flows to the backend). Because the widget is injected
529
+ > success redirect), handle the 3DS step internally, and use the session account
530
+ > snapshot for AVS. The SDK collects and validates those address fields outside
531
+ > the PCI widget and persists them through the session account endpoint; the
532
+ > widget owns only sensitive card-data capture. Because the widget is injected
597
533
  > **same-window**, every terminal outcome must be bound to the session id, and —
598
534
  > to fully defend against same-window forgery — the backend should mint a
599
535
  > per-session `messageToken` on the vault block and echo it in each
@@ -605,12 +541,35 @@ session includes a hosted vault card form (session.vault)
605
541
  The SDK supports two PayPal paths, selected per-session based on what the billing API advertises under `gateways.*`:
606
542
 
607
543
  - **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.
608
- - **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.
544
+ - **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.
609
545
 
610
546
  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.
611
547
 
612
548
  **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.
613
549
 
550
+ **Direct PayPal initialization recovery:** PayPal's own cross-window bridge owns
551
+ its 10-second `postMessage init()` acknowledgement deadline; FloPay does not
552
+ change that upstream timeout. If the exact acknowledgement timeout is reported,
553
+ or if `Buttons.render()` is still unsettled after 11 seconds, the SDK hides
554
+ Direct PayPal, waits one second, and makes exactly one background render retry.
555
+ The retry uses a fresh render generation, and callbacks or promise settlements
556
+ from the superseded generation are ignored.
557
+
558
+ In a mixed checkout, card, wallets, APMs, and any other eligible methods remain
559
+ interactive throughout recovery. If both Direct PayPal attempts fail, PayPal
560
+ stays hidden for that component configuration; the SDK emits one sanitized
561
+ console diagnostic and calls neither `onError` nor `onDecline`. Deterministic
562
+ configuration failures and `isEligible() === false` are not automatically
563
+ retried.
564
+
565
+ In a PayPal-only checkout, `FloPayCheckout` shows an accessible retrying status
566
+ instead of a blank surface. After automatic recovery is exhausted, it shows safe
567
+ generic unavailable copy and a **Retry PayPal** button. `onError` fires once with
568
+ a `FloPayError` whose `type` is `api_error` and whose stable `code` is
569
+ `paypal_init_timeout`; `onDecline` does not fire and the raw provider message is
570
+ never rendered. Manual retry reuses the current checkout session and performs
571
+ one fresh render attempt without adding another automatic retry.
572
+
614
573
  The SDK exposes the relevant pieces in three ways:
615
574
 
616
575
  - **`SplitCardForm`** / **`FloPayCheckout`**: pick the renderer automatically based on `gateways.*`. No additional configuration needed.
@@ -622,7 +581,7 @@ The SDK exposes the relevant pieces in three ways:
622
581
  - **`PayPalButton`** (standalone): Must be rendered inside its own `FloPayProvider`:
623
582
 
624
583
  ```tsx
625
- {/* Card fields provider */}
584
+ {/* Main checkout provider */}
626
585
  <FloPayProvider flopay={flopay} options={{ amount, currency }}>
627
586
  <SplitCardForm ... />
628
587
  </FloPayProvider>
@@ -638,31 +597,30 @@ The SDK exposes the relevant pieces in three ways:
638
597
  </FloPayProvider>
639
598
  ```
640
599
 
641
- ### Using Individual Elements
600
+ ### Using Individual Non-card Elements
642
601
 
643
602
  ```tsx
644
- import { FloPayProvider, PaymentElement, CardElement, useFloPay } from '@flopay/react';
603
+ import { AddressElement, PaymentElement } from '@flopay/react';
645
604
 
646
605
  function CustomForm() {
647
- const flopay = useFloPay();
648
-
649
- const handleSubmit = async () => {
650
- if (!flopay) return;
651
- const { error } = await flopay.submitElements();
652
- if (error) return console.error(error);
653
- const { paymentMethodId } = await flopay.createPaymentMethod();
654
- // Use paymentMethodId...
655
- };
656
-
657
606
  return (
658
607
  <div>
659
- <PaymentElement options={{ layout: 'tabs' }} />
660
- <button onClick={handleSubmit}>Pay</button>
608
+ <PaymentElement
609
+ options={{
610
+ layout: 'tabs',
611
+ paymentMethodTypes: ['cashapp', 'ideal'],
612
+ }}
613
+ />
614
+ <AddressElement />
661
615
  </div>
662
616
  );
663
617
  }
664
618
  ```
665
619
 
620
+ These elements support wallet/APM and address collection. `PaymentElement`
621
+ requires a non-empty `paymentMethodTypes` allowlist and rejects `card`; use the
622
+ hosted vault checkout surface for card payments.
623
+
666
624
  ### Using Hooks
667
625
 
668
626
  ```tsx
@@ -685,15 +643,12 @@ function PaymentStatus() {
685
643
  | Component | Description |
686
644
  |-----------|-------------|
687
645
  | `FloPayProvider` | Context provider. Accepts `flopay` (instance or promise), `options?`, and `children`. Creates the elements group automatically. |
688
- | `CheckoutForm` | Drop-in form with unified PaymentElement. Self-contained by default, or override with `onTokenizedBody`. Supports `ref` for imperative `handleNextAction()`. |
689
- | `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()`. |
646
+ | `FloPayCheckout` | Recommended self-contained session checkout. Resolves gateways, mounts hosted-vault cards, and preserves wallets/APMs/PayPal/saved-payment flows. |
647
+ | `SplitCardForm` | Advanced checkout surface combining hosted-vault cards with wallets, APMs, and PayPal. Supports `ref` for imperative next-action handling. |
690
648
  | `VaultCardFields` | Hosted vault PCI card fields. Used internally by `SplitCardForm` on the vault path; consumes a `CardCaptureAdapter` from `useFloPay().cardCapture()`. |
691
649
  | `PayPalButton` | Standalone PayPal button. Requires its own `FloPayProvider` with `paymentMethodCreation` set to something other than `'manual'`. |
692
- | `PaymentElement` | Unified payment element (cards, wallets, etc.) |
693
- | `CardElement` | Combined card input |
694
- | `CardNumberElement` | Card number field |
695
- | `CardExpiryElement` | Card expiry field |
696
- | `CardCvcElement` | Card CVC field |
650
+ | `DirectPayPalButton` | Standalone direct PayPal order/subscription button using the session-scoped intent contract. |
651
+ | `PaymentElement` | Provider element for an explicitly declared non-card `paymentMethodTypes` allowlist. |
697
652
  | `AddressElement` | Address input element |
698
653
 
699
654
  ### Hooks
@@ -711,9 +666,9 @@ function PaymentStatus() {
711
666
  | `flopay` | `Promise<FloPay> \| FloPay` | SDK instance or promise from `loadFloPay()` |
712
667
  | `options.locale` | `string?` | Locale |
713
668
  | `options.appearance` | `FloPayAppearance?` | Theme appearance |
714
- | `options.clientSecret` | `string?` | PaymentIntent client secret (if intent already exists) |
715
- | `options.amount` | `number?` | Amount in cents (used when no `clientSecret`) |
716
- | `options.currency` | `string?` | ISO 4217 currency code (used when no `clientSecret`) |
669
+ | `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. |
670
+ | `options.amount` | `number?` | Amount in cents for deferred non-card Elements without a `clientSecret` |
671
+ | `options.currency` | `string?` | ISO 4217 currency code for deferred non-card Elements without a `clientSecret` |
717
672
  | `options.paymentMethodCreation` | `'manual' \| 'auto'` | How payment methods are created |
718
673
 
719
674
  ### Privacy-safe operational telemetry
@@ -734,38 +689,19 @@ No endpoint, custom tag, user context, message, stack, or metadata can be
734
689
  configured. See [`docs/TELEMETRY.md`](../../docs/TELEMETRY.md) for the complete
735
690
  privacy and retention contract.
736
691
 
737
- ### CheckoutFormProps
738
-
739
- | Prop | Type | Description |
740
- |------|------|-------------|
741
- | `sessionId` | `string` | Checkout session UUID |
742
- | `billingApiUrl` | `string` | Billing API base URL |
743
- | `email` | `string?` | User email |
744
- | `userId` | `string?` | User ID |
745
- | `onComplete` | `(result: PaymentResult) => void` | Success callback |
746
- | `onError` | `(error: FloPayError) => void` | Error callback |
747
- | `onTokenizedBody` | `(body: TokenizedBody) => void` | Override: handle backend submission yourself |
748
- | `layout` | `'tabs' \| 'accordion' \| 'auto'` | PaymentElement layout (default: `'auto'`) |
749
- | `submitLabel` | `string` | Button text (default: `'Pay'`) |
750
- | `showAddress` | `boolean \| 'billing' \| 'shipping'` | Show address element (default: `false`) |
751
- | `className` | `string?` | CSS class for form wrapper |
752
- | `children` | `ReactNode?` | Custom submit button |
753
- | `firstName` | `string?` | Billing first name |
754
- | `lastName` | `string?` | Billing last name |
755
- | `chv` | `string?` | Checkout version for A/B tracking |
756
- | `isProcessing` | `boolean?` | External processing state |
757
- | `error` | `string?` | External error message |
758
- | `onErrorChange` | `(error: string \| null) => void` | Error state change callback |
759
-
760
692
  ### SplitCardFormProps
761
693
 
762
- Shares most props with `CheckoutFormProps`, plus:
694
+ Key payment-surface props include:
763
695
 
764
696
  | Prop | Type | Description |
765
697
  |------|------|-------------|
766
- | `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`. |
698
+ | `sessionId` | `string` | Checkout session UUID. |
699
+ | `nonce` | `string` | Session-bound token forwarded on intent, decline, account, and process calls. |
700
+ | `session` | `CheckoutSession?` | Session capability data, including the hosted `vault` block and gateways. |
701
+ | `billingApiUrl` | `string` | Billing API base URL. |
702
+ | `showStripe` | `boolean` | Show Stripe-backed wallets/APMs. Card checkout is controlled by the session vault capability. |
767
703
  | `showPayPal` | `boolean` | Show PayPal. Renderer chosen by `gateways.paypal` presence (DirectPayPal JS SDK when present; Stripe-rendered PayPal otherwise). Default: `true`. |
768
- | `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). |
704
+ | `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. |
769
705
  | `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`. |
770
706
  | `showGooglePay` | `boolean` | *Deprecated.* See `showApplePay`. |
771
707
  | `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. |
@@ -773,7 +709,7 @@ Shares most props with `CheckoutFormProps`, plus:
773
709
  | `currency` | `string` | Currency code for PayPal / wallet config (default: `'usd'`) |
774
710
  | `onFirstNameChange` | `(value: string) => void` | First name change callback |
775
711
  | `onLastNameChange` | `(value: string) => void` | Last name change callback |
776
- | `submitLabel` | `string` | Button text (default: `'CONFIRM PAYMENT'`) |
712
+ | `onComplete` / `onDecline` / `onError` | callbacks | Observable checkout outcomes. |
777
713
 
778
714
  ### ElementComponentProps (shared by all element components)
779
715
 
@@ -794,10 +730,7 @@ Shares most props with `CheckoutFormProps`, plus:
794
730
  | Type | Description |
795
731
  |------|-------------|
796
732
  | `FloPayProviderProps` | Props for `FloPayProvider` |
797
- | `CheckoutFormProps` | Props for `CheckoutForm` |
798
- | `CheckoutFormRef` | Ref type: `{ handleNextAction(clientSecret) }` |
799
733
  | `SplitCardFormProps` | Props for `SplitCardForm` |
800
- | `SplitCardFormRef` | Ref type: `{ handleNextAction(clientSecret) }` |
801
734
  | `PayPalButtonProps` | Props for `PayPalButton` |
802
735
  | `ElementComponentProps` | Shared props for all element components |
803
736
  | `CheckoutState` | `{ session, loading, error }` |