@flopay/js 1.4.1 → 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
@@ -32,41 +32,27 @@ a later call can retry. The optional second argument accepts
32
32
  `appearance`, and `telemetry`; set `telemetry: false` to opt out of privacy-safe
33
33
  operational telemetry.
34
34
 
35
- ### Create and Mount Elements
35
+ ### Create and Mount Non-card Elements
36
36
 
37
37
  ```ts
38
38
  const elements = flopay.elements({
39
39
  amount: 2999, // in cents
40
40
  currency: 'usd',
41
+ paymentMethodTypes: ['cashapp', 'ideal'],
41
42
  });
42
43
 
43
- const cardElement = await elements.create('card');
44
- cardElement.mount(document.getElementById('card-container')!);
44
+ const paymentElement = await elements.create('payment');
45
+ paymentElement.mount(document.getElementById('payment-container')!);
45
46
  ```
46
47
 
47
- ### Tokenize and Confirm Payment
48
-
49
- ```ts
50
- // 1. Validate elements
51
- const { error: submitError } = await flopay.submitElements();
52
- if (submitError) throw submitError;
53
-
54
- // 2. Tokenize card into a PaymentMethod
55
- const { paymentMethodId, error } = await flopay.createPaymentMethod();
56
- if (error || !paymentMethodId) throw error;
57
-
58
- // 3. Confirm card payment with a client secret from your server
59
- const result = await flopay.confirmCardPayment({
60
- clientSecret: 'pi_xxx_secret_yyy',
61
- paymentMethodId,
62
- });
63
-
64
- if (result.error) {
65
- console.error(result.error.message);
66
- } else {
67
- console.log('Payment status:', result.status);
68
- }
69
- ```
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.
70
56
 
71
57
  ### PayPal Payment
72
58
 
@@ -74,6 +60,7 @@ if (result.error) {
74
60
  const result = await flopay.confirmPayPalPayment({
75
61
  billingApiUrl: 'https://billing.example.com',
76
62
  sessionId: 'session_uuid',
63
+ nonce: sessionNonce,
77
64
  email: 'user@example.com',
78
65
  returnUrl: window.location.href,
79
66
  });
@@ -119,15 +106,28 @@ const session = await api.getUnifiedCheckoutSession('session_uuid', sessionNonce
119
106
  // session.data.session.clientSecret carries the same nonce so downstream
120
107
  // code can re-use it.
121
108
 
122
- // Create a PaymentIntent nonce becomes the `x-checkout-session-token`
123
- // header automatically.
124
- 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(
125
111
  'session_uuid',
126
- 'user@example.com',
127
- 'pm_xxx',
128
- { nonce: sessionNonce },
112
+ sessionNonce,
113
+ {
114
+ provider: 'stripe',
115
+ paymentMethodCategory: 'wallet',
116
+ paymentMethodType: 'apple_pay',
117
+ paymentMethodId: 'pm_xxx',
118
+ intentKind: 'payment',
119
+ },
129
120
  );
130
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
+
131
131
  // Process a tokenized payment. `nonce` is required: the SDK throws a
132
132
  // `FloPayError` with code `MissingCheckoutSessionToken` when it is missing,
133
133
  // and otherwise POSTs to `/v1/checkouts/sessions/<id>/process` with the
@@ -274,11 +274,11 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
274
274
  | Export | Description |
275
275
  |--------|-------------|
276
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()`, `createPaymentMethod()`, `confirmCardPayment()`, `cardCapture()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
277
+ | `FloPay` | Main SDK class. Methods: `elements()`, `submitElements()`, `cardCapture()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
278
278
  | `FloPayElements` | Element group manager. Methods: `create(type, options?)`, `getElement(type)`, `submit()`, `destroy()` |
279
279
  | `StripeAdapter` | `PaymentProviderAdapter` implementation for Stripe |
280
280
  | `PciVaultCardCapture` | `CardCaptureAdapter` implementation that injects the backend-served hosted vault card widget. See [Vault card capture](#vault-card-capture). |
281
- | `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. |
282
282
  | `createCheckoutSession(options)` | Creates a checkout session and redirects. Returns `CheckoutSessionResult`. |
283
283
  | `createCheckoutSessionWithRetries(options)` | Same as above with automatic retries (default 3, exponential backoff). |
284
284
 
@@ -288,12 +288,10 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
288
288
  |--------|---------|-------------|
289
289
  | `elements(options?)` | `FloPayElements` | Creates a new elements group. Destroys previous group. |
290
290
  | `submitElements()` | `Promise<{ error? }>` | Validates all mounted elements |
291
- | `createPaymentMethod()` | `Promise<CreatePaymentMethodResult>` | Tokenizes card fields into a `pm_xxx` ID. Auto-detects split fields vs unified PaymentElement. |
292
- | `confirmCardPayment(params)` | `Promise<ConfirmCardPaymentResult>` | Confirms with `clientSecret` + `paymentMethodId`. Handles 3DS. |
293
291
  | `cardCapture(options?)` | `CardCaptureAdapter` | Creates a hosted vault card-widget adapter (`PciVaultCardCapture`). See [Vault card capture](#vault-card-capture). |
294
- | `confirmPayment(params)` | `Promise<PaymentResult>` | Confirms using mounted elements + `clientSecret` |
295
- | `confirmPayPalPayment(params)` | `Promise<ConfirmCardPaymentResult>` | Full PayPal flow: create PM -> create intent -> confirm/redirect |
296
- | `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. |
297
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. |
298
296
  | `retrieveUnifiedSession(sessionId, billingApiUrl?)` | `Promise<NormalizedCheckoutSession>` | Retrieves and normalizes a checkout session, including provider-specific data (Stripe `clientSecret`/`publishableKey`, etc.). |
299
297
  | `getRawProvider()` | `unknown` | Returns the raw underlying provider instance (e.g. Stripe object) |
@@ -301,26 +299,22 @@ The same default-on behavior and boolean opt-out apply to direct `FloPay`,
301
299
 
302
300
  ### Supported Element Types
303
301
 
304
- - `payment` -- Unified PaymentElement (cards, wallets, etc.)
305
- - `card` -- Combined card input (number + expiry + CVC)
306
- - `cardNumber` -- Card number field (for split card forms)
307
- - `cardExpiry` -- Card expiry field
308
- - `cardCvc` -- Card CVC field
302
+ - `payment` -- Provider PaymentElement for supported non-card methods
309
303
  - `address` -- Address input element
310
304
 
311
305
  ### Vault card capture
312
306
 
313
307
  `flopay.cardCapture()` returns a `CardCaptureAdapter` that injects a
314
- **backend-served, self-contained hosted vault widget** in place of provider-owned
315
- (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
316
310
  card fields, its own submit button, card tokenization, the PaymentIntent (created
317
311
  **and** confirmed server-side), **3DS**, and the result — so **no Stripe.js runs
318
312
  on the card path** and PAN / CVC never enter the SDK runtime. The SDK's only job
319
313
  is to inject the widget HTML and relay its terminal `postMessage` outcome.
320
314
 
321
315
  ```ts
322
- // 1. Obtain the vault capture block — embedded on the create-session response
323
- // (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
324
318
  // argument is the checkout session id (`getVaultCapture(checkoutSessionId, nonce?)`):
325
319
  const { html, messageToken, expectedOrigin } =
326
320
  await new PaymentAPI(billingApiUrl).getVaultCapture(checkoutSessionId, nonce);
@@ -344,7 +338,7 @@ adapter rejects terminal `complete` / `decline` outcomes that are not bound to
344
338
  the mounted `sessionId`, that mismatch the mounted `messageToken` (when one was
345
339
  supplied), or that arrive from a non-matching `expectedOrigin` (when set).
346
340
 
347
- > Backend contract: TeamFloPay/backend#823. The SDK declares
348
- > `X-Flo-SDK-Version: 1.3.0` (`FLO_SDK_VERSION_HEADER`) on `POST /v1/checkouts/sessions`
349
- > so the backend embeds the `vault` block; otherwise it fetches the widget via
350
- > `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.