@flopay/react 1.4.19 → 1.4.21

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
@@ -83,6 +83,52 @@ function CheckoutPage() {
83
83
 
84
84
  The mode can also be set on the session itself via the billing API's `checkoutMode` field. The `checkoutMode` prop overrides the session value.
85
85
 
86
+ ### Secure saved-card setup
87
+
88
+ Use `FloPayCardSetup` to let a customer add or verify a card without creating a
89
+ purchase or charge. Your trusted server must first call the
90
+ merchant-authenticated card-setup endpoint and pass only its opaque `sessionId`
91
+ and bound `nonce` to the browser. Never send Client Basic credentials, OAuth
92
+ tokens, or a customer identifier to this component.
93
+
94
+ ```tsx
95
+ import { FloPayCardSetup } from '@flopay/react';
96
+
97
+ function AddCard({ sessionId, nonce }: { sessionId: string; nonce: string }) {
98
+ return (
99
+ <FloPayCardSetup
100
+ sessionId={sessionId}
101
+ nonce={nonce}
102
+ onComplete={({ paymentMethod }) => {
103
+ // Display-only when supplied. Re-list from the server if absent during
104
+ // a mixed-version backend rollout.
105
+ console.log(paymentMethod?.brand, paymentMethod?.lastFour);
106
+ }}
107
+ onDecline={({ message }) => showCardError(message)}
108
+ onValidation={(message) => showCardValidation(message)}
109
+ onError={(error) => {
110
+ if (error.retryable) showRetry();
111
+ }}
112
+ onCancel={() => closeAddCard()}
113
+ />
114
+ );
115
+ }
116
+ ```
117
+
118
+ The component reads and validates the setup session before injecting FloPay's
119
+ hosted PCI card widget. It refuses purchase sessions, zero-amount non-setup
120
+ sessions, non-zero setup sessions, and setup sessions containing products. Bank
121
+ authentication is shown through the existing hosted challenge and does not
122
+ count as success while pending. Completion fires only after verification says
123
+ the card is usable; decline, validation, retryable technical failure, and
124
+ unmount cancellation remain separate outcomes.
125
+
126
+ Saved-card listing, setup-session creation, and deletion remain authenticated
127
+ merchant REST calls. Replacement is composition: complete setup for the new
128
+ card, then ask your server to delete the old card. `FloPayCardSetup` deliberately
129
+ has no customer-id, merchant-credential, list, delete, purchase, or Stripe
130
+ Elements prop.
131
+
86
132
  #### Expired Sessions
87
133
 
88
134
  When `FloPayCheckout` or `FloPayAutomaticPaymentButton` loads a checkout session whose `status` is `expired`, the component calls `onError` with a `FloPayError` so your app can route the customer into a recovery flow.
@@ -356,6 +402,41 @@ Skip the backend API route — create the session directly in the component:
356
402
 
357
403
  The component POSTs to the billing API, gets the full session back, and renders the form — zero backend code needed.
358
404
 
405
+ #### Authorisation-only checkout
406
+
407
+ Set `captureMethod: 'manual'` in the same `createSession` draft for an eligible
408
+ item-only card checkout:
409
+
410
+ ```tsx
411
+ <FloPayCheckout
412
+ createSession={{
413
+ clientId: 'your-client-id',
414
+ captureMethod: 'manual',
415
+ currency: 'EUR',
416
+ items: [{ code: 'order_123', totalAmount: 29.99 }],
417
+ account: { userId: 'user_1', email: 'user@example.com' },
418
+ successUrl: '/success',
419
+ cancelUrl: '/cancel',
420
+ }}
421
+ onComplete={(result) => {
422
+ if (result.status === 'authorized') {
423
+ saveAuthorisation({
424
+ paymentId: result.paymentId,
425
+ sessionId: result.sessionId,
426
+ expiresAt: result.authorizationExpiresAt,
427
+ });
428
+ }
429
+ }}
430
+ onSessionCompleted={(successUrl) => router.push(successUrl)}
431
+ />
432
+ ```
433
+
434
+ The component still releases the buyer to the success experience, but its
435
+ overlay says `PAYMENT AUTHORISED`. `authorized` means funds are held, not paid.
436
+ Capture remains a merchant-authenticated REST operation and is never available
437
+ to browser code. Manual capture is rejected for subscription carts. See the
438
+ repository's [pre-authorisation guide](../../docs/PREAUTHORIZATION.md).
439
+
359
440
  That create POST sends a stable `Idempotency-Key` header automatically whenever a
360
441
  secure RNG is available. `FloPayCheckout` resolves the key once per logical
361
442
  checkout, stores it with the inline-session cache in `sessionStorage`, and reuses
@@ -714,6 +795,7 @@ function PaymentStatus() {
714
795
  |-----------|-------------|
715
796
  | `FloPayProvider` | Context provider. Accepts `flopay` (instance or promise), `options?`, and `children`. Creates the elements group automatically. |
716
797
  | `FloPayCheckout` | Recommended self-contained session checkout. Resolves gateways, mounts hosted-vault cards, and preserves wallets/APMs/PayPal/saved-payment flows. |
798
+ | `FloPayCardSetup` | Browser-only no-charge card verification for a merchant-server-created setup session. Requires `sessionId` + `nonce`; reports ready, verified completion, decline, validation, retryable technical error, and cancellation outcomes. |
717
799
  | `SplitCardForm` | Advanced checkout surface combining hosted-vault cards with wallets, APMs, and PayPal. Supports `ref` for imperative next-action handling. |
718
800
  | `VaultCardFields` | Hosted vault PCI card fields. Used internally by `SplitCardForm` on the vault path; consumes a `CardCaptureAdapter` from `useFloPay().cardCapture()`. |
719
801
  | `PayPalButton` | Standalone PayPal button. Requires its own `FloPayProvider` with `paymentMethodCreation` set to something other than `'manual'`. |
@@ -741,6 +823,24 @@ function PaymentStatus() {
741
823
  | `options.currency` | `string?` | ISO 4217 currency code for deferred non-card Elements without a `clientSecret` |
742
824
  | `options.paymentMethodCreation` | `'manual' \| 'auto'` | How payment methods are created |
743
825
 
826
+ ### FloPayCardSetupProps
827
+
828
+ | Prop | Type | Description |
829
+ |------|------|-------------|
830
+ | `sessionId` | `string` | Opaque id returned by the merchant-authenticated setup-session endpoint. |
831
+ | `nonce` | `string` | Required session-bound read/capture token. |
832
+ | `billingApiUrl` | `string?` | Billing API base URL; defaults through normal FloPay environment resolution. |
833
+ | `telemetry` | `boolean?` | Privacy-safe operational telemetry; set `false` to opt out. |
834
+ | `theme` | `VaultCardThemeColors?` | Hosted widget colors. |
835
+ | `containerStyle` | `React.CSSProperties?` | Inline styles for the hosted-widget container. |
836
+ | `loading` | `React.ReactNode?` | Content shown while the session and hosted widget load. |
837
+ | `onReady` | `() => void` | Hosted widget is mounted and accepting input. |
838
+ | `onComplete` | `(event: FloPayCardSetupCompleteEvent) => void` | Verified usable card. Includes `sessionId` and optional display-only `paymentMethod`; never amount, charge, or payment-success data. |
839
+ | `onDecline` | `(event: FloPayCardSetupDeclineEvent) => void` | Terminal card-verification decline. |
840
+ | `onValidation` | `(message: string \| null) => void` | Live hosted-field validation; not a technical error. |
841
+ | `onError` | `(error: FloPayCardSetupError) => void` | Validation/technical failure with stable `code` and explicit `retryable`. |
842
+ | `onCancel` | `(event: FloPayCardSetupCancelEvent) => void` | Fires once when the component unmounts before a terminal outcome. |
843
+
744
844
  ### Privacy-safe operational telemetry
745
845
 
746
846
  `FloPayCheckout` emits the same closed Flo-owned lifecycle/error/performance
@@ -854,6 +954,11 @@ endpoint when a buyer enters the card path.
854
954
  | Type | Description |
855
955
  |------|-------------|
856
956
  | `FloPayProviderProps` | Props for `FloPayProvider` |
957
+ | `FloPayCardSetupProps` | Props for `FloPayCardSetup` |
958
+ | `FloPayCardSetupCompleteEvent` | Verified setup completion with optional display-only `paymentMethod` |
959
+ | `FloPayCardSetupDeclineEvent` | Terminal card-verification decline |
960
+ | `FloPayCardSetupCancelEvent` | Unmount-before-terminal cancellation |
961
+ | `FloPayCardSetupError` | Structured setup failure with stable `code` and `retryable` classification |
857
962
  | `SplitCardFormProps` | Props for `SplitCardForm` |
858
963
  | `PayPalButtonProps` | Props for `PayPalButton` |
859
964
  | `ElementComponentProps` | Shared props for all element components |