@flopay/js 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
@@ -24,43 +24,35 @@ const flopay = await loadFloPay('pk_test_...', {
24
24
  });
25
25
  ```
26
26
 
27
- `loadFloPay` caches the instance -- calling it again with the same key returns the cached `FloPay` instance. The optional second argument accepts a `FloPayConfig` with `billingApiUrl`, `locale`, `appearance`, and `telemetry`; set `telemetry: false` to opt out of privacy-safe operational telemetry.
27
+ `loadFloPay` caches by publishable key and behavior-affecting options. Concurrent
28
+ calls with the same key and options share one in-flight provider initialization
29
+ and resolve to the same `FloPay` instance. A failed initialization is evicted so
30
+ a later call can retry. The optional second argument accepts
31
+ `Omit<FloPayConfig, 'publishableKey'>`, including `billingApiUrl`, `locale`,
32
+ `appearance`, and `telemetry`; set `telemetry: false` to opt out of privacy-safe
33
+ operational telemetry.
28
34
 
29
- ### Create and Mount Elements
35
+ ### Create and Mount Non-card Elements
30
36
 
31
37
  ```ts
32
38
  const elements = flopay.elements({
33
39
  amount: 2999, // in cents
34
40
  currency: 'usd',
41
+ paymentMethodTypes: ['cashapp', 'ideal'],
35
42
  });
36
43
 
37
- const cardElement = await elements.create('card');
38
- cardElement.mount(document.getElementById('card-container')!);
44
+ const paymentElement = await elements.create('payment');
45
+ paymentElement.mount(document.getElementById('payment-container')!);
39
46
  ```
40
47
 
41
- ### Tokenize and Confirm Payment
42
-
43
- ```ts
44
- // 1. Validate elements
45
- const { error: submitError } = await flopay.submitElements();
46
- if (submitError) throw submitError;
47
-
48
- // 2. Tokenize card into a PaymentMethod
49
- const { paymentMethodId, error } = await flopay.createPaymentMethod();
50
- if (error || !paymentMethodId) throw error;
51
-
52
- // 3. Confirm card payment with a client secret from your server
53
- const result = await flopay.confirmCardPayment({
54
- clientSecret: 'pi_xxx_secret_yyy',
55
- paymentMethodId,
56
- });
57
-
58
- if (result.error) {
59
- console.error(result.error.message);
60
- } else {
61
- console.log('Payment status:', result.status);
62
- }
63
- ```
48
+ `paymentMethodTypes` is required for `payment` elements and must contain at
49
+ least one wallet/APM method. Any `card` entry is removed; a missing or empty
50
+ non-card allowlist throws `FloPayError('validation_error')`. When Elements are
51
+ initialized with a `clientSecret`, the provider intent is verified against the
52
+ explicit non-card allowlist before mounting; the allowlist remains required and
53
+ any extra provider method is rejected. Use
54
+ `@flopay/react`'s `FloPayCheckout` or `SplitCardForm` for card checkout; both
55
+ mount the backend-hosted vault widget supplied in the session's `vault` block.
64
56
 
65
57
  ### PayPal Payment
66
58
 
@@ -68,6 +60,7 @@ if (result.error) {
68
60
  const result = await flopay.confirmPayPalPayment({
69
61
  billingApiUrl: 'https://billing.example.com',
70
62
  sessionId: 'session_uuid',
63
+ nonce: sessionNonce,
71
64
  email: 'user@example.com',
72
65
  returnUrl: window.location.href,
73
66
  });
@@ -113,15 +106,28 @@ const session = await api.getUnifiedCheckoutSession('session_uuid', sessionNonce
113
106
  // session.data.session.clientSecret carries the same nonce so downstream
114
107
  // code can re-use it.
115
108
 
116
- // Create a PaymentIntent nonce becomes the `x-checkout-session-token`
117
- // header automatically.
118
- const intentResponse = await api.createPaymentIntent(
109
+ // Create an Apple Pay intent. Direct-card requests are not part of this union.
110
+ const intent = await api.createSessionIntent(
119
111
  'session_uuid',
120
- 'user@example.com',
121
- 'pm_xxx',
122
- { nonce: sessionNonce },
112
+ sessionNonce,
113
+ {
114
+ provider: 'stripe',
115
+ paymentMethodCategory: 'wallet',
116
+ paymentMethodType: 'apple_pay',
117
+ paymentMethodId: 'pm_xxx',
118
+ intentKind: 'payment',
119
+ },
123
120
  );
124
121
 
122
+ // Report a client-observed non-card decline using a provider classification
123
+ // code only. Messages, identifiers, card data, credentials, and PII are rejected.
124
+ await api.reportSessionIntentDecline('session_uuid', sessionNonce, {
125
+ provider: 'stripe',
126
+ paymentMethodCategory: 'wallet',
127
+ paymentMethodType: 'apple_pay',
128
+ providerDeclineReason: 'payment_failed',
129
+ });
130
+
125
131
  // Process a tokenized payment. `nonce` is required: the SDK throws a
126
132
  // `FloPayError` with code `MissingCheckoutSessionToken` when it is missing,
127
133
  // and otherwise POSTs to `/v1/checkouts/sessions/<id>/process` with the
@@ -267,12 +273,12 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
267
273
 
268
274
  | Export | Description |
269
275
  |--------|-------------|
270
- | `loadFloPay(publishableKey, options?)` | Initializes the SDK. Returns a `Promise<FloPay>`. Caches by key. |
271
- | `FloPay` | Main SDK class. Methods: `elements()`, `submitElements()`, `createPaymentMethod()`, `confirmCardPayment()`, `cardCapture()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
276
+ | `loadFloPay(publishableKey, options?)` | Initializes the SDK. Returns a `Promise<FloPay>`. Shares successful and in-flight work by key; failed work remains retryable. |
277
+ | `FloPay` | Main SDK class. Methods: `elements()`, `submitElements()`, `cardCapture()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
272
278
  | `FloPayElements` | Element group manager. Methods: `create(type, options?)`, `getElement(type)`, `submit()`, `destroy()` |
273
279
  | `StripeAdapter` | `PaymentProviderAdapter` implementation for Stripe |
274
280
  | `PciVaultCardCapture` | `CardCaptureAdapter` implementation that injects the backend-served hosted vault card widget. See [Vault card capture](#vault-card-capture). |
275
- | `PaymentAPI` | Billing API client. Methods: `getCheckoutSession()`, `getVaultCapture()`, `getUnifiedCheckoutSession()`, `processPayment()`, `waitForCheckoutSessionCompletion()`, `createPaymentIntent()`, `createSetupIntent()`, `getPaymentsByEmail()`, `destroy()` |
281
+ | `PaymentAPI` | Billing API client. Includes session retrieval/creation, vault recovery, `/process`, `createSessionIntent()`, `reportSessionIntentDecline()`, completion polling, and saved-payment lookup. |
276
282
  | `createCheckoutSession(options)` | Creates a checkout session and redirects. Returns `CheckoutSessionResult`. |
277
283
  | `createCheckoutSessionWithRetries(options)` | Same as above with automatic retries (default 3, exponential backoff). |
278
284
 
@@ -282,12 +288,10 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
282
288
  |--------|---------|-------------|
283
289
  | `elements(options?)` | `FloPayElements` | Creates a new elements group. Destroys previous group. |
284
290
  | `submitElements()` | `Promise<{ error? }>` | Validates all mounted elements |
285
- | `createPaymentMethod()` | `Promise<CreatePaymentMethodResult>` | Tokenizes card fields into a `pm_xxx` ID. Auto-detects split fields vs unified PaymentElement. |
286
- | `confirmCardPayment(params)` | `Promise<ConfirmCardPaymentResult>` | Confirms with `clientSecret` + `paymentMethodId`. Handles 3DS. |
287
291
  | `cardCapture(options?)` | `CardCaptureAdapter` | Creates a hosted vault card-widget adapter (`PciVaultCardCapture`). See [Vault card capture](#vault-card-capture). |
288
- | `confirmPayment(params)` | `Promise<PaymentResult>` | Confirms using mounted elements + `clientSecret` |
289
- | `confirmPayPalPayment(params)` | `Promise<ConfirmCardPaymentResult>` | Full PayPal flow: create PM -> create intent -> confirm/redirect |
290
- | `resumePayPalPayment()` | `Promise<ConfirmCardPaymentResult \| null>` | Resumes after PayPal redirect. Returns `null` if no PayPal params in URL. |
292
+ | `confirmPayment(params)` | `Promise<PaymentResult>` | Confirms a mounted wallet/APM using `clientSecret`, `paymentMethodCategory`, and `paymentMethodType`; rejects `card`. |
293
+ | `confirmPayPalPayment(params)` | `Promise<PayPalPaymentResult>` | Stripe-hosted PayPal flow through the nonce-protected session intent contract, followed by confirmation/redirect. |
294
+ | `resumePayPalPayment()` | `Promise<PayPalPaymentResult \| null>` | Resumes after PayPal redirect. Returns `null` if no PayPal params in URL. |
291
295
  | `retrieveSession(sessionId, billingApiUrl?)` | `Promise<CheckoutSession>` | Retrieves a checkout session by ID via `GET /v1/checkouts/sessions/{id}`. Uses `billingApiUrl` from config or the optional second argument. |
292
296
  | `retrieveUnifiedSession(sessionId, billingApiUrl?)` | `Promise<NormalizedCheckoutSession>` | Retrieves and normalizes a checkout session, including provider-specific data (Stripe `clientSecret`/`publishableKey`, etc.). |
293
297
  | `getRawProvider()` | `unknown` | Returns the raw underlying provider instance (e.g. Stripe object) |
@@ -295,26 +299,22 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
295
299
 
296
300
  ### Supported Element Types
297
301
 
298
- - `payment` -- Unified PaymentElement (cards, wallets, etc.)
299
- - `card` -- Combined card input (number + expiry + CVC)
300
- - `cardNumber` -- Card number field (for split card forms)
301
- - `cardExpiry` -- Card expiry field
302
- - `cardCvc` -- Card CVC field
302
+ - `payment` -- Provider PaymentElement for supported non-card methods
303
303
  - `address` -- Address input element
304
304
 
305
305
  ### Vault card capture
306
306
 
307
307
  `flopay.cardCapture()` returns a `CardCaptureAdapter` that injects a
308
- **backend-served, self-contained hosted vault widget** in place of provider-owned
309
- (Stripe) card fields (TeamFloPay/backend#823, Model A). The widget owns the PCI
308
+ **backend-served, self-contained hosted vault widget**
309
+ (TeamFloPay/backend#823, Model A). The widget owns the PCI
310
310
  card fields, its own submit button, card tokenization, the PaymentIntent (created
311
311
  **and** confirmed server-side), **3DS**, and the result — so **no Stripe.js runs
312
312
  on the card path** and PAN / CVC never enter the SDK runtime. The SDK's only job
313
313
  is to inject the widget HTML and relay its terminal `postMessage` outcome.
314
314
 
315
315
  ```ts
316
- // 1. Obtain the vault capture block — embedded on the create-session response
317
- // (session.vault) for SDKs ≥ 1.3.0, or fetched explicitly. The first
316
+ // 1. Obtain the vault capture block — normally embedded on every card-capable
317
+ // create/read response, or fetched through the explicit recovery route. The first
318
318
  // argument is the checkout session id (`getVaultCapture(checkoutSessionId, nonce?)`):
319
319
  const { html, messageToken, expectedOrigin } =
320
320
  await new PaymentAPI(billingApiUrl).getVaultCapture(checkoutSessionId, nonce);
@@ -338,7 +338,7 @@ adapter rejects terminal `complete` / `decline` outcomes that are not bound to
338
338
  the mounted `sessionId`, that mismatch the mounted `messageToken` (when one was
339
339
  supplied), or that arrive from a non-matching `expectedOrigin` (when set).
340
340
 
341
- > Backend contract: TeamFloPay/backend#823. The SDK declares
342
- > `X-Flo-SDK-Version: 1.3.0` (`FLO_SDK_VERSION_HEADER`) on `POST /v1/checkouts/sessions`
343
- > so the backend embeds the `vault` block; otherwise it fetches the widget via
344
- > `PaymentAPI.getVaultCapture()` (`POST /v1/checkouts/sessions/{id}/vault/capture`).
341
+ > Backend contract: TeamFloPay/backend#823. Card-capable session create/read
342
+ > responses include the `vault` block without SDK-version dispatch.
343
+ > `PaymentAPI.getVaultCapture()` keeps
344
+ > `POST /v1/checkouts/sessions/{id}/vault/capture` available for recovery/retry.