@flopay/js 1.2.7 → 1.3.0

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
@@ -199,10 +199,11 @@ try {
199
199
  | Export | Description |
200
200
  |--------|-------------|
201
201
  | `loadFloPay(publishableKey, options?)` | Initializes the SDK. Returns a `Promise<FloPay>`. Caches by key. |
202
- | `FloPay` | Main SDK class. Methods: `elements()`, `submitElements()`, `createPaymentMethod()`, `confirmCardPayment()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
202
+ | `FloPay` | Main SDK class. Methods: `elements()`, `submitElements()`, `createPaymentMethod()`, `confirmCardPayment()`, `cardCapture()`, `confirmPayment()`, `confirmPayPalPayment()`, `resumePayPalPayment()`, `retrieveSession()`, `retrieveUnifiedSession()`, `getRawProvider()`, `destroy()` |
203
203
  | `FloPayElements` | Element group manager. Methods: `create(type, options?)`, `getElement(type)`, `submit()`, `destroy()` |
204
204
  | `StripeAdapter` | `PaymentProviderAdapter` implementation for Stripe |
205
- | `PaymentAPI` | Billing API client. Methods: `getCheckoutSession()`, `getUnifiedCheckoutSession()`, `processPayment()`, `waitForCheckoutSessionCompletion()`, `createPaymentIntent()`, `createSetupIntent()`, `getPaymentsByEmail()` |
205
+ | `PciVaultCardCapture` | `CardCaptureAdapter` implementation that injects the backend-served hosted vault card widget. See [Vault card capture](#vault-card-capture). |
206
+ | `PaymentAPI` | Billing API client. Methods: `getCheckoutSession()`, `getVaultCapture()`, `getUnifiedCheckoutSession()`, `processPayment()`, `waitForCheckoutSessionCompletion()`, `createPaymentIntent()`, `createSetupIntent()`, `getPaymentsByEmail()` |
206
207
  | `createCheckoutSession(options)` | Creates a checkout session and redirects. Returns `CheckoutSessionResult`. |
207
208
  | `createCheckoutSessionWithRetries(options)` | Same as above with automatic retries (default 3, exponential backoff). |
208
209
 
@@ -214,6 +215,7 @@ try {
214
215
  | `submitElements()` | `Promise<{ error? }>` | Validates all mounted elements |
215
216
  | `createPaymentMethod()` | `Promise<CreatePaymentMethodResult>` | Tokenizes card fields into a `pm_xxx` ID. Auto-detects split fields vs unified PaymentElement. |
216
217
  | `confirmCardPayment(params)` | `Promise<ConfirmCardPaymentResult>` | Confirms with `clientSecret` + `paymentMethodId`. Handles 3DS. |
218
+ | `cardCapture(options?)` | `CardCaptureAdapter` | Creates a hosted vault card-widget adapter (`PciVaultCardCapture`). See [Vault card capture](#vault-card-capture). |
217
219
  | `confirmPayment(params)` | `Promise<PaymentResult>` | Confirms using mounted elements + `clientSecret` |
218
220
  | `confirmPayPalPayment(params)` | `Promise<ConfirmCardPaymentResult>` | Full PayPal flow: create PM -> create intent -> confirm/redirect |
219
221
  | `resumePayPalPayment()` | `Promise<ConfirmCardPaymentResult \| null>` | Resumes after PayPal redirect. Returns `null` if no PayPal params in URL. |
@@ -230,3 +232,44 @@ try {
230
232
  - `cardExpiry` -- Card expiry field
231
233
  - `cardCvc` -- Card CVC field
232
234
  - `address` -- Address input element
235
+
236
+ ### Vault card capture
237
+
238
+ `flopay.cardCapture()` returns a `CardCaptureAdapter` that injects a
239
+ **backend-served, self-contained hosted vault widget** in place of provider-owned
240
+ (Stripe) card fields (TeamFloPay/backend#823, Model A). The widget owns the PCI
241
+ card fields, its own submit button, card tokenization, the PaymentIntent (created
242
+ **and** confirmed server-side), **3DS**, and the result — so **no Stripe.js runs
243
+ on the card path** and PAN / CVC never enter the SDK runtime. The SDK's only job
244
+ is to inject the widget HTML and relay its terminal `postMessage` outcome.
245
+
246
+ ```ts
247
+ // 1. Obtain the vault capture block — embedded on the create-session response
248
+ // (session.vault) for SDKs ≥ 1.3.0, or fetched explicitly. The first
249
+ // argument is the checkout session id (`getVaultCapture(checkoutSessionId, nonce?)`):
250
+ const { html, messageToken, expectedOrigin } =
251
+ await new PaymentAPI(billingApiUrl).getVaultCapture(checkoutSessionId, nonce);
252
+
253
+ // 2. Inject it and relay the widget's outcome.
254
+ const capture = flopay.cardCapture({ sessionId: checkoutSessionId });
255
+ capture.on('complete', (e) => onComplete({ status: 'succeeded', paymentIntentId: e.intentId }));
256
+ capture.on('decline', (e) => onDecline(e.declineReason, e.message));
257
+ capture.on('error', (e) => onError(e.message));
258
+ // Pass the block's `messageToken` / `expectedOrigin` so the adapter can
259
+ // authenticate the widget's terminal postMessage (both optional).
260
+ await capture.mount(container, { html, messageToken, expectedOrigin });
261
+ ```
262
+
263
+ `CardCaptureAdapter` methods: `mount(container, { html, messageToken?, expectedOrigin? })`,
264
+ `on(event, handler)` (`'ready' | 'complete' | 'decline' | 'error'`), `unmount()`.
265
+ Outcome events arrive via a `window.postMessage` from the widget shaped
266
+ `{ source: 'flopay-vault', type, sessionId, messageToken?, intentId?, declineReason?, message? }`.
267
+ The widget is injected **same-window**, so `source` alone is forgeable: the
268
+ adapter rejects terminal `complete` / `decline` outcomes that are not bound to
269
+ the mounted `sessionId`, that mismatch the mounted `messageToken` (when one was
270
+ supplied), or that arrive from a non-matching `expectedOrigin` (when set).
271
+
272
+ > Backend contract: TeamFloPay/backend#823. The SDK declares
273
+ > `X-Flo-SDK-Version: 1.3.0` (`FLO_SDK_VERSION_HEADER`) on `POST /v1/checkouts/sessions`
274
+ > so the backend embeds the `vault` block; otherwise it fetches the widget via
275
+ > `PaymentAPI.getVaultCapture()` (`POST /v1/checkouts/sessions/{id}/vault/capture`).