@amos.com/react-amos-js 0.10.6 → 0.11.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
@@ -15,8 +15,8 @@ npm install @amos.com/react-amos-js @amos.com/node
15
15
  ## What it gives you
16
16
 
17
17
  - React components for the iframe payment method forms: `AmosCreditCardPaymentMethodForm`, `AmosBankAccountPaymentMethodForm`, `AmosGooglePayButton`, `AmosApplePayButton`.
18
- - React-flavoured iframe message helpers that accept a React `ref`: `validateForm({ iframeRef })`, `confirmPaymentIntent({ iframeRef, token })`, `confirmSetupIntent({ iframeRef, token })`, `resetForm({ iframeRef })`.
19
- - Re-exports of the `@amos.com/amos-js` helpers and types that come up in client code: `createMessage`, `decodeJwt`, `getEmbedOrigin`, `formatGooglePayPaymentData`, `resetForm`, `ConfirmationResult`, `ConfirmationIncompleteReason`, `FormattedGooglePayPaymentData`, `Appearance`, `Message`, etc.
18
+ - React-flavoured iframe message helpers that accept a React `ref`: `validateForm({ iframeRef })`, `confirmPayment({ iframeRef, token })`, `confirmSetup({ iframeRef, token })`, `resetForm({ iframeRef })`.
19
+ - Re-exports of the `@amos.com/amos-js` helpers and types that come up in client code: `createMessage`, `decodeJwt`, `getEmbedOrigin`, `formatGooglePayPaymentData`, `resetForm`, `ConfirmResult`, `FormattedGooglePayPaymentData`, `Appearance`, `Message`, etc.
20
20
 
21
21
  > **Note:** `@amos.com/react-amos-js` is the client-side half of the Amos integration. For end-to-end payment processing you also need `@amos.com/node` on your server (creating payment intents, handling webhooks, etc.). The same `@amos.com/node` package is listed as a peer dependency so you can import its OpenAPI types in client-side TypeScript code.
22
22
 
@@ -39,12 +39,12 @@ The render token configures the iframe's allowed origin(s), allowed payment meth
39
39
  The following flow is for credit card and bank account payment method types only.
40
40
 
41
41
  1. **Set up prerequisites**: create a `renderToken` (safe for client), and keep `apiKey` and `accountId` server-side only.
42
- 2. **Render your checkout UI** with one of the payment method components (e.g. `AmosCreditCardPaymentMethodForm`) along with the required `onResult` prop. Card and bank forms show a field-shaped skeleton immediately (sized from `appearance`, `additionalFields`, and `billingAddressRequirement`); Google Pay and Apple Pay paint a button-shaped skeleton in the parent document on first render so the 48px slot is reserved before the iframe loads.
42
+ 2. **Render your checkout UI** with one of the payment method components (e.g. `AmosCreditCardPaymentMethodForm`). Card and bank forms show a field-shaped skeleton immediately (sized from `appearance`, `additionalFields`, and `billingAddressRequirement`); Google Pay and Apple Pay paint a button-shaped skeleton in the parent document on first render so the 48px slot is reserved before the iframe loads.
43
43
  3. **User clicks "Pay now" button**: call `validateForm({ iframeRef })`, which returns `Promise<true>` if the embedded form is valid and `Promise<false>` otherwise.
44
44
  4. **Create payment intent on your server**: use your server-side Amos client to call `POST /payment_intents`. You may also associate this payment intent with a new or existing customer via `POST /customers`. This must be server-side because it uses your private API key.
45
45
  5. **Return the payment intent token to the browser**: your backend responds with the embed token (`components["schemas"]["EmbedToken"]`) needed for confirmation.
46
- 6. **Confirm the payment intent from the client**: call `confirmPaymentIntent({ iframeRef, token })` to continue the payment flow.
47
- 7. **Handle UX**: show the user a "processing" state when the "Pay now" button is clicked, and handle `onResult`. Do not treat `onResult` as settlement proof — verify payment success on your backend via webhooks. Recoverable field errors are shown in the iframe (`status: "incomplete"` with `reason`: `"field_errors"` or `"validation_failed"`).
46
+ 6. **Confirm the payment intent from the client**: `await confirmPayment({ iframeRef, token })`.
47
+ 7. **Handle UX**: show the user a "processing" state while awaiting `confirmPayment`. Do not treat `{ status: "succeeded" }` as settlement proof — verify payment success on your backend via webhooks. Recoverable field errors stay in the iframe; `confirmPayment` still resolves `{ status: "failed" }`.
48
48
 
49
49
  ### Google Pay & Apple Pay
50
50
 
@@ -52,17 +52,17 @@ Google Pay and Apple Pay are forms of express checkout. Their buttons are altern
52
52
 
53
53
  The key differences between the express and non-express payment flows are:
54
54
 
55
- - The express payment method components accept a prop called `onInitiatePaymentIntentRequest` which will be called when you should create the payment intent on your server.
55
+ - The express payment method components accept `onConfirm`. Create a payment intent, then `await confirmPayment(token)`.
56
56
  - You do not call `validateForm` in an express flow.
57
- - You do not call `confirmPaymentIntent` in an express flow (this is done after `onInitiatePaymentIntentRequest` returns a token).
57
+ - You call `confirmPayment` inside `onConfirm` (the SDK no longer auto-confirms).
58
58
 
59
59
  ## Understanding the flow for creating and confirming setup intents
60
60
 
61
61
  Setup intents are used to save payment methods for future use (e.g. recurring payments, subscriptions) without charging the customer immediately. The flow is identical to a payment intent, except:
62
62
 
63
63
  - On the server, call `POST /setup_intents` instead of `POST /payment_intents`.
64
- - On the client, call `confirmSetupIntent({ iframeRef, token })` instead of `confirmPaymentIntent({ iframeRef, token })`.
65
- - The same `onResult` callback is used; succeeded setup intents arrive as `{ status: "succeeded", intent: "setup", setupIntent }`.
64
+ - On the client, `await confirmSetup({ iframeRef, token })` instead of `confirmPayment({ iframeRef, token })`.
65
+ - Both resolve `{ status: "succeeded" | "failed" }`.
66
66
 
67
67
  The same `AmosCreditCardPaymentMethodForm` / `AmosBankAccountPaymentMethodForm` components support both payment intents and setup intents — they are differentiated by which confirmation function you call. For bank setup, pass `intent="setup"` so Connect / Plaid is always shown (no merchant ACH threshold lookup).
68
68
 
@@ -75,8 +75,8 @@ Why this matters:
75
75
  - The payment method UI is rendered inside Amos-hosted iframes, so sensitive input fields are not part of your DOM.
76
76
  - Raw payment details are submitted from the iframe directly to Amos-controlled infrastructure.
77
77
  - Your backend only creates payment intents (or setup intents) and returns a short-lived token used to continue the iframe flow.
78
- - `confirmPaymentIntent` / `confirmSetupIntent` sends the token back to the iframe to complete confirmation; it does not pass full payment method payloads through your app server.
79
- - In express flows (Google Pay / Apple Pay), the iframe component handles payment data exchange and only asks your server to create a payment intent token.
78
+ - `confirmPayment` / `confirmSetup` send the token back to the iframe to complete confirmation; they do not pass full payment method payloads through your app server.
79
+ - In express flows (Google Pay / Apple Pay), the iframe handles payment data exchange and calls `onConfirm` so your server can create a payment intent token, then you `await confirmPayment(token)`.
80
80
 
81
81
  In short, your app orchestrates the payment flow, while sensitive payment data stays within Amos-controlled components and APIs.
82
82
 
@@ -94,10 +94,6 @@ Card and bank components accept an optional `appearance` prop that controls the
94
94
  "--radius": "0.25rem",
95
95
  },
96
96
  }}
97
- onResult={(result) => {
98
- if (result.status === "failed") setError(result.errorMessage);
99
- if (result.status === "incomplete") setError(null);
100
- }}
101
97
  />
102
98
  ```
103
99
 
@@ -167,7 +163,7 @@ Radio groups (e.g. account type) always use an above-style group label regardles
167
163
  import { useRef, useState } from "react";
168
164
  import {
169
165
  AmosCreditCardPaymentMethodForm,
170
- confirmPaymentIntent,
166
+ confirmPayment,
171
167
  validateForm,
172
168
  } from "@amos.com/react-amos-js";
173
169
  import type { components } from "@amos.com/node";
@@ -212,7 +208,10 @@ function CheckoutForm() {
212
208
  }
213
209
 
214
210
  const { token } = await response.json();
215
- confirmPaymentIntent({ iframeRef, token });
211
+ const result = await confirmPayment({ iframeRef, token });
212
+ if (result.status !== "succeeded") {
213
+ setError("Payment failed. Please try again.");
214
+ }
216
215
  } catch (error) {
217
216
  setError(error instanceof Error ? error.message : "Unknown error");
218
217
  } finally {
@@ -227,16 +226,6 @@ function CheckoutForm() {
227
226
  renderToken="the-render-token-that-you-created-on-dashboard.amos.com"
228
227
  additionalFields={{ cardholderName: true }}
229
228
  onValidityChange={({ isValid }) => setIsValid(isValid)}
230
- onResult={(result) => {
231
- // Unlock UI. Verify settlement on your backend via webhooks.
232
- if (result.status === "succeeded") {
233
- console.log("Confirm returned:", result);
234
- } else if (result.status === "failed") {
235
- console.error("Confirm failed:", result.errorMessage);
236
- } else if (result.status === "incomplete") {
237
- console.log("Recoverable:", result.reason);
238
- }
239
- }}
240
229
  />
241
230
  {error ? <p>{error}</p> : null}
242
231
  <button type="submit" disabled={!isValid || isProcessing}>
@@ -254,7 +243,7 @@ import { useState } from "react";
254
243
  import {
255
244
  AmosApplePayButton,
256
245
  AmosGooglePayButton,
257
- type ConfirmationResult,
246
+ type ConfirmResult,
258
247
  } from "@amos.com/react-amos-js";
259
248
  import type { components } from "@amos.com/node";
260
249
 
@@ -283,13 +272,28 @@ async function createPaymentIntentToken({
283
272
  function CheckoutWallets({ renderToken }: { renderToken: string }) {
284
273
  const [error, setError] = useState<string | null>(null);
285
274
 
286
- function handleResult(result: ConfirmationResult) {
287
- if (result.status === "succeeded") {
288
- console.log("Confirm returned:", result);
289
- } else if (result.status === "failed") {
290
- setError(result.errorMessage);
291
- } else if (result.status === "incomplete") {
292
- console.log("Recoverable:", result.reason);
275
+ async function handleConfirm({
276
+ paymentIntentCreateAttributes,
277
+ customerCreateAttributes,
278
+ confirmPayment,
279
+ }: {
280
+ paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
281
+ customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
282
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
283
+ }): Promise<ConfirmResult> {
284
+ try {
285
+ const token = await createPaymentIntentToken({
286
+ paymentIntentCreateAttributes,
287
+ customerCreateAttributes,
288
+ });
289
+ const result = await confirmPayment(token);
290
+ if (result.status === "failed") {
291
+ setError("Payment failed. Please try again.");
292
+ }
293
+ return result;
294
+ } catch (error) {
295
+ setError(error instanceof Error ? error.message : "Unknown error");
296
+ return { status: "failed" };
293
297
  }
294
298
  }
295
299
 
@@ -301,8 +305,7 @@ function CheckoutWallets({ renderToken }: { renderToken: string }) {
301
305
  renderToken={renderToken}
302
306
  amount="50.00"
303
307
  merchantName="Example Store"
304
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
305
- onResult={handleResult}
308
+ onConfirm={handleConfirm}
306
309
  />
307
310
  </div>
308
311
  <div style={{ flex: "1 1 0", minWidth: 0 }}>
@@ -310,8 +313,7 @@ function CheckoutWallets({ renderToken }: { renderToken: string }) {
310
313
  renderToken={renderToken}
311
314
  amount="50.00"
312
315
  merchantName="Example Store"
313
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
314
- onResult={handleResult}
316
+ onConfirm={handleConfirm}
315
317
  />
316
318
  </div>
317
319
  </div>
@@ -321,7 +323,7 @@ function CheckoutWallets({ renderToken }: { renderToken: string }) {
321
323
  }
322
324
  ```
323
325
 
324
- Do not call `validateForm` or `confirmPaymentIntent` — return the embed token from `onInitiatePaymentIntentRequest` and the SDK confirms. Size the mount slot; omitted `buttonProps` keep paint defaults and fill the iframe.
326
+ Do not call `validateForm` from the host in an express flow — create a payment intent inside `onConfirm`, then `await confirmPayment(token)`. Size the mount slot; omitted `buttonProps` keep paint defaults and fill the iframe.
325
327
 
326
328
  On Safari, Apple Pay uses the native payment sheet. On other browsers, Apple's QR handoff opens in a popup (`pay.apple.com`); while that popup is open, the SDK shows a waiting overlay with **Cancel payment**.
327
329
 
@@ -335,8 +337,7 @@ Optional visuals:
335
337
  height="48px"
336
338
  buttonProps={{ buttonType: "donate", buttonBorderType: "no_border" }}
337
339
  iframeProps={{ style: { borderRadius: "8px" } }}
338
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
339
- onResult={handleResult}
340
+ onConfirm={handleConfirm}
340
341
  />
341
342
 
342
343
  <AmosApplePayButton
@@ -346,8 +347,7 @@ Optional visuals:
346
347
  height="48px"
347
348
  buttonProps={{ type: "donate" }}
348
349
  iframeProps={{ style: { borderRadius: "8px" } }}
349
- onInitiatePaymentIntentRequest={createPaymentIntentToken}
350
- onResult={handleResult}
350
+ onConfirm={handleConfirm}
351
351
  />
352
352
  ```
353
353
 
@@ -357,7 +357,7 @@ Optional visuals:
357
357
  import { useRef, useState } from "react";
358
358
  import {
359
359
  AmosCreditCardPaymentMethodForm,
360
- confirmSetupIntent,
360
+ confirmSetup,
361
361
  validateForm,
362
362
  } from "@amos.com/react-amos-js";
363
363
 
@@ -393,7 +393,10 @@ function SavePaymentMethodForm() {
393
393
  }
394
394
 
395
395
  const { token } = await response.json();
396
- confirmSetupIntent({ iframeRef, token });
396
+ const result = await confirmSetup({ iframeRef, token });
397
+ if (result.status !== "succeeded") {
398
+ setError("Failed to save the payment method.");
399
+ }
397
400
  } catch (error) {
398
401
  setError(error instanceof Error ? error.message : "Unknown error");
399
402
  } finally {
@@ -406,15 +409,6 @@ function SavePaymentMethodForm() {
406
409
  <AmosCreditCardPaymentMethodForm
407
410
  ref={iframeRef}
408
411
  renderToken="the-render-token-that-you-created-on-dashboard.amos.com"
409
- onResult={(result) => {
410
- if (result.status === "succeeded") {
411
- console.log("Confirm returned:", result);
412
- } else if (result.status === "failed") {
413
- console.error("Confirm failed:", result.errorMessage);
414
- } else if (result.status === "incomplete") {
415
- console.log("Recoverable:", result.reason);
416
- }
417
- }}
418
412
  />
419
413
  {error ? <p>{error}</p> : null}
420
414
  <button type="submit" disabled={isProcessing}>
@@ -437,18 +431,18 @@ Validates the embedded card/bank iframe form before payment confirmation.
437
431
 
438
432
  **Returns:** `Promise<boolean>` (resolves to `false` after 5 seconds if the iframe does not respond).
439
433
 
440
- ### `confirmPaymentIntent({ iframeRef, token })`
434
+ ### `confirmPayment({ iframeRef, token })`
441
435
 
442
- Confirms a payment intent in the embedded iframe flow.
436
+ Confirms a payment intent in the embedded iframe flow. Resolves `{ status: "succeeded" }` or `{ status: "failed" }`.
443
437
 
444
438
  **Parameters:**
445
439
 
446
440
  - `iframeRef` (`React.RefObject<HTMLIFrameElement | null> | undefined`, required)
447
441
  - `token` (typed as `Pick<components["schemas"]["EmbedToken"], "token">` — the embed JWT string returned by your server)
448
442
 
449
- **Returns:** `void`
443
+ **Returns:** `Promise<ConfirmResult>`
450
444
 
451
- ### `confirmSetupIntent({ iframeRef, token })`
445
+ ### `confirmSetup({ iframeRef, token })`
452
446
 
453
447
  Confirms a setup intent in the embedded iframe flow. Use this when saving a payment method for future use.
454
448
 
@@ -457,11 +451,11 @@ Confirms a setup intent in the embedded iframe flow. Use this when saving a paym
457
451
  - `iframeRef` (`React.RefObject<HTMLIFrameElement | null> | undefined`, required)
458
452
  - `token` (same `Pick<components["schemas"]["EmbedToken"], "token">` embed JWT string as for payment confirmation)
459
453
 
460
- **Returns:** `void`
454
+ **Returns:** `Promise<ConfirmResult>`
461
455
 
462
456
  ### `resetForm({ iframeRef })`
463
457
 
464
- Clears all field values and API errors in the embedded card/bank iframe form. Call after `onResult` when the customer wants to try again (for example, after a successful payment when starting a new one).
458
+ Clears all field values and API errors in the embedded card/bank iframe form. Call after a failed confirm when the customer wants to try again (for example, after a successful payment when starting a new one).
465
459
 
466
460
  **Parameters:**
467
461
 
@@ -476,7 +470,6 @@ Renders the secure credit card iframe form. A field-shaped skeleton is shown imm
476
470
  **Required props:**
477
471
 
478
472
  - `renderToken` (`string`)
479
- - `onResult` (`(result: ConfirmationResult) => void`) — required. Called when the interactive confirmation attempt finishes (`succeeded`, `failed`, or `incomplete` with `reason`). Not settlement proof; verify via webhooks.
480
473
 
481
474
  **Optional props:**
482
475
 
@@ -495,7 +488,7 @@ Renders the secure bank account iframe form. A field-shaped skeleton is shown im
495
488
 
496
489
  When the charge meets the merchant’s ACH verification threshold, the SDK hides the routing/account iframe and renders a **Connect bank account** button in the parent page. The button follows the same outline/focus defaults as Amos UI (`--ring`, `--border`, `--radius`, `--input-height`, …): it inherits those CSS variables from the host page when present, and `appearance.themeVariables` overrides them the same way as the iframe. Clicking it asks the iframe to mint a Plaid Link token, then opens [Plaid Link](https://plaid.com/docs/link/web/). Hosts do not proxy Pay API (`GET /merchants`, `POST /plaid_link_tokens`); embed does that with `PAY_API_KEY`. Do not put Plaid secrets in the browser.
497
490
 
498
- **Required props:** same as `AmosCreditCardPaymentMethodForm` — `renderToken`, `onResult` — plus:
491
+ **Required props:** same as `AmosCreditCardPaymentMethodForm` — `renderToken` — plus:
499
492
 
500
493
  - `amount` (`string`, major-currency decimal, e.g. `"50.00"`, defaults to `"0"`) — same format as Google Pay / Apple Pay. Compared to the threshold the iframe fetches (cents). Pass `"0"` (the default) on open-amount forms until the customer enters a charge — 0 is typically under the threshold, so Connect stays hidden. Pass a new `amount` when the customer changes the charge.
501
494
  - `intent` (`"payment" | "setup"`, defaults to `"payment"`) — `"setup"` always shows Connect / Plaid (no merchant ACH threshold lookup), unless the render token disables verification. Use this when saving a bank account for later charges.
@@ -508,7 +501,6 @@ Compare locally once the iframe posts `ACH_THRESHOLD`: Plaid when `requireVerifi
508
501
  <AmosBankAccountPaymentMethodForm
509
502
  renderToken={renderToken}
510
503
  amount="50.00" // defaults to "0" (manual form until the charge meets the threshold)
511
- onResult={onResult}
512
504
  />
513
505
  ```
514
506
 
@@ -518,11 +510,10 @@ Setup (always Connect, no merchant lookup):
518
510
  <AmosBankAccountPaymentMethodForm
519
511
  renderToken={renderToken}
520
512
  intent="setup"
521
- onResult={onResult}
522
513
  />
523
514
  ```
524
515
 
525
- `validateForm` / `confirmPaymentIntent` / `confirmSetupIntent` stay iframe-based. When Plaid succeeded, confirm sends `payment_method.plaid` (`public_token`, `account_id`) and does not require typed account numbers.
516
+ `validateForm` / `confirmPayment` / `confirmSetup` stay iframe-based. When Plaid succeeded, confirm sends `payment_method.plaid` (`public_token`, `account_id`) and does not require typed account numbers.
526
517
 
527
518
  **CSP:** the parent page must allow Plaid’s script and frames, for example `script-src https://cdn.plaid.com` and `frame-src https://cdn.plaid.com https://*.plaid.com`. Amos never loads `PLAID_SECRET` / `PLAID_CLIENT_ID` in the SDK or embed iframe.
528
519
 
@@ -537,9 +528,7 @@ Renders the secure Google Pay iframe button (express checkout flow). A button-sh
537
528
  - `renderToken` (`string`)
538
529
  - `amount` (`string`) — major-currency decimal string shown in the wallet sheet (e.g. `"50.00"` for $50.00). The iframe converts this to cents in `paymentIntentCreateAttributes.amount`.
539
530
  - `merchantName` (`string`)
540
- - `onInitiatePaymentIntentRequest` (callback receiving `{ paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"]; customerCreateAttributes: components["schemas"]["CreateCustomerInput"] }`, returns `Promise<components["schemas"]["EmbedToken"]["token"]>` — the embed JWT string for confirmation)
541
-
542
- - `onResult` (`(result: ConfirmationResult) => void`) — required. Called when the interactive confirmation attempt finishes (`succeeded`, `failed`, or `incomplete` with `reason`). Not settlement proof; verify via webhooks.
531
+ - `onConfirm` (callback receiving `{ paymentIntentCreateAttributes, customerCreateAttributes, confirmPayment }`. Create a payment intent, then `return confirmPayment(token)` — `Promise<ConfirmResult>`)
543
532
 
544
533
  **Optional props:**
545
534
 
@@ -595,14 +584,14 @@ Re-exports of the same advanced helpers exposed by `@amos.com/amos-js`. Most int
595
584
 
596
585
  ### Exported types
597
586
 
598
- `@amos.com/react-amos-js` re-exports everything from `@amos.com/amos-js`, including `ConfirmationResult`, `ConfirmationIncompleteReason`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, `FormattedGooglePayPaymentData`, `Message`, `Appearance`, `ThemeVariable`, and the per-form `*Options` / `*Controller` types. For OpenAPI schema types (e.g. `PaymentIntent`, `CreatePaymentIntentInput`), import `components` from `@amos.com/node`.
587
+ `@amos.com/react-amos-js` re-exports everything from `@amos.com/amos-js`, including `ConfirmResult`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, `FormattedGooglePayPaymentData`, `Message`, `Appearance`, `ThemeVariable`, and the per-form `*Options` / `*Controller` types. For OpenAPI schema types (e.g. `PaymentIntent`, `CreatePaymentIntentInput`), import `components` from `@amos.com/node`.
599
588
 
600
589
  ## Notes and potential gotchas
601
590
 
602
- - **`ref` / `iframeRef`**: for card and bank forms, pass `ref={iframeRef}` to the form component. The same `iframeRef` must be used when calling `validateForm`, `confirmPaymentIntent`, `confirmSetupIntent`, or `resetForm`. The component forwards the ref to the inner iframe.
603
- - **`onResult` is not settlement proof**: `onResult` tells you when to stop waiting (e.g. dismiss a spinner). Verify payment or setup success on your backend via webhooks. On `status: "incomplete"`, unlock your UI — the customer can fix fields in the iframe and retry. Use `result.reason` (`"field_errors"` or `"validation_failed"`) to distinguish recoverable states.
604
- - **Same components for payment vs setup intents**: `AmosCreditCardPaymentMethodForm` and `AmosBankAccountPaymentMethodForm` support both payment intents and setup intents. The flow differs only by which server call you make and which confirmation function you use (`confirmPaymentIntent` vs `confirmSetupIntent`). Handle both payment and setup outcomes via `onResult`.
605
- - **Amount format**: for `AmosGooglePayButton`, `AmosApplePayButton`, and `AmosBankAccountPaymentMethodForm`, `amount` is a major-currency decimal string (e.g. `"50.00"` for $50.00). For `components["schemas"]["CreatePaymentIntentInput"]` on the server (card/bank create, and the object the wallet iframe sends to `onInitiatePaymentIntentRequest`), `amount` is a number in cents (e.g. `5000`).
591
+ - **`ref` / `iframeRef`**: for card and bank forms, pass `ref={iframeRef}` to the form component. The same `iframeRef` must be used when calling `validateForm`, `confirmPayment`, `confirmSetup`, or `resetForm`. The component forwards the ref to the inner iframe.
592
+ - **`confirmPayment` / `confirmSetup` are not settlement proof**: `{ status: "succeeded" }` means authorization succeeded (capture may still finish asynchronously). Verify payment or setup success on your backend via webhooks. Recoverable field errors stay in the iframe; the Promise still resolves `{ status: "failed" }`.
593
+ - **Same components for payment vs setup intents**: `AmosCreditCardPaymentMethodForm` and `AmosBankAccountPaymentMethodForm` support both payment intents and setup intents. The flow differs only by which server call you make and which confirmation function you use (`confirmPayment` vs `confirmSetup`).
594
+ - **Amount format**: for `AmosGooglePayButton`, `AmosApplePayButton`, and `AmosBankAccountPaymentMethodForm`, `amount` is a major-currency decimal string (e.g. `"50.00"` for $50.00). For `components["schemas"]["CreatePaymentIntentInput"]` on the server (card/bank create, and the object the wallet iframe sends to `onConfirm`), `amount` is a number in cents (e.g. `5000`).
606
595
  - **Plaid Link (ACH verification)**: load `cdn.plaid.com` from the **parent** document (see CSP on `AmosBankAccountPaymentMethodForm`). Merchants do not proxy Pay API; the bank iframe fetches the ACH threshold for payment intents and mints link tokens. Setup intents skip the merchant lookup and always require Plaid unless the render token disables verification. Confirm still goes through the bank iframe so Amos can attach `plaid` to the payment method.
607
596
  - **Apple Pay waiting overlay**: on browsers where Apple's QR handoff opens in a popup (non-Safari), `AmosApplePayButton` shows a fixed full-viewport overlay on the host page until payment completes, the popup closes, or the user clicks **Cancel payment**. Avoid stacking other fixed UI above it.
608
597
  - **Going framework-free**: if you need to use Amos outside of React (vanilla JS, another framework, etc.), use [`@amos.com/amos-js`](../amos-js) directly.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /// <reference types="googlepay" />
2
- import { Appearance, ApplePayButtonElementProps, BillingAddressRequirement, ConfirmationResult, CreditCardAdditionalFields, GooglePayButtonElementProps } from '@amos.com/amos-js';
2
+ import { Appearance, ApplePayButtonElementProps, BillingAddressRequirement, ConfirmResult, CreditCardAdditionalFields, GooglePayButtonElementProps } from '@amos.com/amos-js';
3
3
  import { components } from '@amos.com/node';
4
4
  import { ComponentProps, Ref, RefObject } from 'react';
5
5
  export * from '@amos.com/amos-js';
@@ -20,9 +20,9 @@ export declare function validateForm({ iframeRef, }: {
20
20
  * Pass the embed JWT (`token`) returned by your server's
21
21
  * `POST /payment_intents` call.
22
22
  */
23
- export declare function confirmPaymentIntent({ iframeRef, token, }: {
23
+ export declare function confirmPayment({ iframeRef, token, }: {
24
24
  iframeRef: IframeRef;
25
- } & Pick<components["schemas"]["EmbedToken"], "token">): void;
25
+ } & Pick<components["schemas"]["EmbedToken"], "token">): Promise<ConfirmResult>;
26
26
  /**
27
27
  * Confirm a setup intent in the embedded iframe flow. Use this when
28
28
  * saving a payment method for future use.
@@ -30,12 +30,12 @@ export declare function confirmPaymentIntent({ iframeRef, token, }: {
30
30
  * Pass the embed JWT (`token`) returned by your server's
31
31
  * `POST /setup_intents` call.
32
32
  */
33
- export declare function confirmSetupIntent({ iframeRef, token, }: {
33
+ export declare function confirmSetup({ iframeRef, token, }: {
34
34
  iframeRef: IframeRef;
35
- } & Pick<components["schemas"]["EmbedToken"], "token">): void;
35
+ } & Pick<components["schemas"]["EmbedToken"], "token">): Promise<ConfirmResult>;
36
36
  /**
37
37
  * Clear all field values and API errors in the embedded card/bank iframe
38
- * form. Call after `onResult` when the customer wants to try again.
38
+ * form. Call after a failed confirm when the customer wants to try again.
39
39
  */
40
40
  export declare function resetForm({ iframeRef }: {
41
41
  iframeRef: IframeRef;
@@ -45,7 +45,6 @@ type IframePassthroughProps = Omit<ComponentProps<"iframe">, "src" | "title" | "
45
45
  type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
46
46
  renderToken: string;
47
47
  appearance?: Appearance;
48
- onResult: (result: ConfirmationResult) => void;
49
48
  /**
50
49
  * Called when form validity changes. `isValid` is true when all
51
50
  * required fields are present and valid. Does not include PCI data.
@@ -64,11 +63,10 @@ type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
64
63
  additionalFields?: CreditCardAdditionalFields;
65
64
  billingAddressRequirement?: BillingAddressRequirement;
66
65
  };
67
- export declare function AmosCreditCardPaymentMethodForm({ ref, renderToken, appearance, onResult, onValidityChange, onCardBrandChanged, additionalFields, billingAddressRequirement, style, ...rest }: AmosCreditCardPaymentMethodFormProps): import("react").JSX.Element;
66
+ export declare function AmosCreditCardPaymentMethodForm({ ref, renderToken, appearance, onValidityChange, onCardBrandChanged, additionalFields, billingAddressRequirement, style, ...rest }: AmosCreditCardPaymentMethodFormProps): import("react").JSX.Element;
68
67
  type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
69
68
  renderToken: string;
70
69
  appearance?: Appearance;
71
- onResult: (result: ConfirmationResult) => void;
72
70
  /**
73
71
  * Called when form validity changes. `isValid` is true when all
74
72
  * required fields are present and valid, or when Plaid Link has
@@ -101,7 +99,7 @@ type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
101
99
  */
102
100
  intent?: "payment" | "setup";
103
101
  };
104
- export declare function AmosBankAccountPaymentMethodForm({ ref, renderToken, appearance, onResult, onValidityChange, billingAddressRequirement, amount, intent, style, ...rest }: AmosBankAccountPaymentMethodFormProps): import("react").JSX.Element;
102
+ export declare function AmosBankAccountPaymentMethodForm({ ref, renderToken, appearance, onValidityChange, billingAddressRequirement, amount, intent, style, ...rest }: AmosBankAccountPaymentMethodFormProps): import("react").JSX.Element;
105
103
  type AmosGooglePayButtonProps = {
106
104
  ref?: ForwardedIframeRef;
107
105
  renderToken: string;
@@ -126,18 +124,22 @@ type AmosGooglePayButtonProps = {
126
124
  buttonProps?: GooglePayButtonElementProps;
127
125
  /** Props applied to the host-page `<iframe>` element. */
128
126
  iframeProps?: IframePassthroughProps;
129
- onInitiatePaymentIntentRequest: ({ paymentIntentCreateAttributes, customerCreateAttributes, }: {
127
+ /**
128
+ * Called when the buyer authorizes in the Google Pay sheet. Create a
129
+ * payment intent on your server, then `await confirmPayment(token)`.
130
+ */
131
+ onConfirm: ({ paymentIntentCreateAttributes, customerCreateAttributes, confirmPayment, }: {
130
132
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
131
133
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
132
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
133
- onResult: (result: ConfirmationResult) => void;
134
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
135
+ }) => Promise<ConfirmResult>;
134
136
  };
135
137
  /**
136
138
  * Renders the secure Google Pay iframe button. A button-shaped
137
139
  * skeleton is painted in the parent document on first render (including
138
140
  * SSR) so the slot height is reserved before the iframe loads.
139
141
  */
140
- export declare function AmosGooglePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onInitiatePaymentIntentRequest, onResult, }: AmosGooglePayButtonProps): import("react").JSX.Element;
142
+ export declare function AmosGooglePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onConfirm, }: AmosGooglePayButtonProps): import("react").JSX.Element;
141
143
  type AmosApplePayButtonProps = {
142
144
  ref?: ForwardedIframeRef;
143
145
  renderToken: string;
@@ -162,15 +164,19 @@ type AmosApplePayButtonProps = {
162
164
  buttonProps?: ApplePayButtonElementProps;
163
165
  /** Props applied to the host-page `<iframe>` element. */
164
166
  iframeProps?: IframePassthroughProps;
165
- onInitiatePaymentIntentRequest: ({ paymentIntentCreateAttributes, customerCreateAttributes, }: {
167
+ /**
168
+ * Called when the buyer authorizes in the Apple Pay sheet. Create a
169
+ * payment intent on your server, then `await confirmPayment(token)`.
170
+ */
171
+ onConfirm: ({ paymentIntentCreateAttributes, customerCreateAttributes, confirmPayment, }: {
166
172
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
167
173
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
168
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
169
- onResult: (result: ConfirmationResult) => void;
174
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
175
+ }) => Promise<ConfirmResult>;
170
176
  };
171
177
  /**
172
178
  * Renders the secure Apple Pay iframe button. A button-shaped
173
179
  * skeleton is painted in the parent document on first render (including
174
180
  * SSR) so the slot height is reserved before the iframe loads.
175
181
  */
176
- export declare function AmosApplePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onInitiatePaymentIntentRequest, onResult, }: AmosApplePayButtonProps): import("react").JSX.Element;
182
+ export declare function AmosApplePayButton({ ref, renderToken, amount, merchantName, height, buttonProps, iframeProps, onConfirm, }: AmosApplePayButtonProps): import("react").JSX.Element;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@amos.com/amos-js"),t=require("react"),n=require("react/jsx-runtime");function r(e){return e?e.current??null:null}function i({iframeRef:t}){return(0,e.validateForm)({iframe:r(t)})}function a({iframeRef:t,token:n}){(0,e.confirmPaymentIntent)({iframe:r(t),token:n})}function o({iframeRef:t,token:n}){(0,e.confirmSetupIntent)({iframe:r(t),token:n})}function s({iframeRef:t}){(0,e.resetForm)({iframe:r(t)})}function c(e,t){typeof e==`function`?e(t):e&&(e.current=t)}function l(e,{style:t,className:n,id:r,...i}){n!=null&&(e.className=n),r!=null&&(e.id=r),Object.assign(e.style,t);for(let[t,n]of Object.entries(i))n!=null&&(t in e?Reflect.set(e,t,n):e.setAttribute(t,String(n)))}function u({containerRef:e,iframeRef:n,mount:r,options:i,remountDeps:a,iframePassthrough:o,updateDeps:s}){let u=(0,t.useRef)(null);(0,t.useLayoutEffect)(()=>{let t=e.current;if(!t)return;let a=r(t,i);return u.current=a,c(n,a.iframe),l(a.iframe,o),()=>{a.destroy(),u.current=null,c(n,null)}},[...a]),(0,t.useEffect)(()=>{u.current?.update(i)},[...s]),(0,t.useEffect)(()=>{let e=u.current?.iframe;e&&l(e,o)})}var d=`oklch(0.97 0 0)`;function f({height:r,borderRadius:i,containerRef:a}){return(0,t.useLayoutEffect)(()=>{(0,e.ensureSkeletonStyles)()},[]),(0,n.jsxs)(`div`,{style:{boxSizing:`border-box`,position:`relative`,width:`100%`,height:r,minHeight:r,overflow:`hidden`},children:[(0,n.jsx)(`div`,{className:`amos-js-form-skeleton-input amos-js-wallet-skeleton`,style:{position:`absolute`,inset:0,height:r,borderRadius:i,background:d,pointerEvents:`none`,zIndex:0},"aria-hidden":!0}),(0,n.jsx)(`div`,{ref:a,style:{position:`absolute`,inset:0,zIndex:1,width:`100%`,height:`100%`}})]})}function p({ref:r,renderToken:i,appearance:a,onResult:o,onValidityChange:s,onCardBrandChanged:c,additionalFields:l={cardholderName:!1},billingAddressRequirement:d=`country`,style:f,...p}){let m=(0,t.useRef)(null);return u({containerRef:m,iframeRef:r,mount:e.mountAmosCreditCardPaymentMethodForm,options:{renderToken:i,appearance:a,additionalFields:l,billingAddressRequirement:d,onResult:o,onValidityChange:s,onCardBrandChanged:c},remountDeps:[i,l.cardholderName,d],iframePassthrough:{style:f,...p},updateDeps:[a,l,d,o,s,c]}),(0,n.jsx)(`div`,{ref:m})}function m({ref:r,renderToken:i,appearance:a,onResult:o,onValidityChange:s,billingAddressRequirement:c=`country`,amount:l=`0`,intent:d=`payment`,style:f,...p}){let m=(0,t.useRef)(null);return u({containerRef:m,iframeRef:r,mount:e.mountAmosBankAccountPaymentMethodForm,options:{renderToken:i,appearance:a,billingAddressRequirement:c,amount:l,intent:d,onResult:o,onValidityChange:s},remountDeps:[i,c,d],iframePassthrough:{style:f,...p},updateDeps:[a,c,l,d,o,s]}),(0,n.jsx)(`div`,{ref:m})}function h({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onInitiatePaymentIntentRequest:d,onResult:p}){let m=(0,t.useRef)(null),h=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return u({containerRef:m,iframeRef:r,mount:e.mountAmosGooglePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onInitiatePaymentIntentRequest:d,onResult:p},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,d,p]}),(0,n.jsx)(f,{height:s,borderRadius:h,containerRef:m})}function g({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onInitiatePaymentIntentRequest:d,onResult:p}){let m=(0,t.useRef)(null),h=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return u({containerRef:m,iframeRef:r,mount:e.mountAmosApplePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onInitiatePaymentIntentRequest:d,onResult:p},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,d,p]}),(0,n.jsx)(f,{height:s,borderRadius:h,containerRef:m})}exports.AmosApplePayButton=g,exports.AmosBankAccountPaymentMethodForm=m,exports.AmosCreditCardPaymentMethodForm=p,exports.AmosGooglePayButton=h,exports.confirmPaymentIntent=a,exports.confirmSetupIntent=o,exports.resetForm=s,exports.validateForm=i,Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@amos.com/amos-js"),t=require("react"),n=require("react/jsx-runtime");function r(e){return e?e.current??null:null}function i({iframeRef:t}){return(0,e.validateForm)({iframe:r(t)})}function a({iframeRef:t,token:n}){return(0,e.confirmPayment)({iframe:r(t),token:n})}function o({iframeRef:t,token:n}){return(0,e.confirmSetup)({iframe:r(t),token:n})}function s({iframeRef:t}){(0,e.resetForm)({iframe:r(t)})}function c(e,t){typeof e==`function`?e(t):e&&(e.current=t)}function l(e,{style:t,className:n,id:r,...i}){n!=null&&(e.className=n),r!=null&&(e.id=r),Object.assign(e.style,t);for(let[t,n]of Object.entries(i))n!=null&&(t in e?Reflect.set(e,t,n):e.setAttribute(t,String(n)))}function u({containerRef:e,iframeRef:n,mount:r,options:i,remountDeps:a,iframePassthrough:o,updateDeps:s}){let u=(0,t.useRef)(null);(0,t.useLayoutEffect)(()=>{let t=e.current;if(!t)return;let a=r(t,i);return u.current=a,c(n,a.iframe),l(a.iframe,o),()=>{a.destroy(),u.current=null,c(n,null)}},[...a]),(0,t.useEffect)(()=>{u.current?.update(i)},[...s]),(0,t.useEffect)(()=>{let e=u.current?.iframe;e&&l(e,o)})}var d=`oklch(0.97 0 0)`;function f({height:r,borderRadius:i,containerRef:a}){return(0,t.useLayoutEffect)(()=>{(0,e.ensureSkeletonStyles)()},[]),(0,n.jsxs)(`div`,{style:{boxSizing:`border-box`,position:`relative`,width:`100%`,height:r,minHeight:r,overflow:`hidden`},children:[(0,n.jsx)(`div`,{className:`amos-js-form-skeleton-input amos-js-wallet-skeleton`,style:{position:`absolute`,inset:0,height:r,borderRadius:i,background:d,pointerEvents:`none`,zIndex:0},"aria-hidden":!0}),(0,n.jsx)(`div`,{ref:a,style:{position:`absolute`,inset:0,zIndex:1,width:`100%`,height:`100%`}})]})}function p({ref:r,renderToken:i,appearance:a,onValidityChange:o,onCardBrandChanged:s,additionalFields:c={cardholderName:!1},billingAddressRequirement:l=`country`,style:d,...f}){let p=(0,t.useRef)(null);return u({containerRef:p,iframeRef:r,mount:e.mountAmosCreditCardPaymentMethodForm,options:{renderToken:i,appearance:a,additionalFields:c,billingAddressRequirement:l,onValidityChange:o,onCardBrandChanged:s},remountDeps:[i,c.cardholderName,l],iframePassthrough:{style:d,...f},updateDeps:[a,c,l,o,s]}),(0,n.jsx)(`div`,{ref:p})}function m({ref:r,renderToken:i,appearance:a,onValidityChange:o,billingAddressRequirement:s=`country`,amount:c=`0`,intent:l=`payment`,style:d,...f}){let p=(0,t.useRef)(null);return u({containerRef:p,iframeRef:r,mount:e.mountAmosBankAccountPaymentMethodForm,options:{renderToken:i,appearance:a,billingAddressRequirement:s,amount:c,intent:l,onValidityChange:o},remountDeps:[i,s,l],iframePassthrough:{style:d,...f},updateDeps:[a,s,c,l,o]}),(0,n.jsx)(`div`,{ref:p})}function h({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onConfirm:d}){let p=(0,t.useRef)(null),m=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return u({containerRef:p,iframeRef:r,mount:e.mountAmosGooglePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onConfirm:d},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,d]}),(0,n.jsx)(f,{height:s,borderRadius:m,containerRef:p})}function g({ref:r,renderToken:i,amount:a,merchantName:o,height:s=`48px`,buttonProps:c,iframeProps:l,onConfirm:d}){let p=(0,t.useRef)(null),m=(0,e.resolveWalletButtonSkeletonBorderRadius)({iframeStyle:l?.style,buttonProps:c});return u({containerRef:p,iframeRef:r,mount:e.mountAmosApplePayButton,options:{renderToken:i,amount:a,merchantName:o,height:s,buttonProps:c,onConfirm:d},remountDeps:[i],iframePassthrough:l??{},updateDeps:[a,o,s,c,d]}),(0,n.jsx)(f,{height:s,borderRadius:m,containerRef:p})}exports.AmosApplePayButton=g,exports.AmosBankAccountPaymentMethodForm=m,exports.AmosCreditCardPaymentMethodForm=p,exports.AmosGooglePayButton=h,exports.confirmPayment=a,exports.confirmSetup=o,exports.resetForm=s,exports.validateForm=i,Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { confirmPaymentIntent as e, confirmSetupIntent as t, ensureSkeletonStyles as n, mountAmosApplePayButton as r, mountAmosBankAccountPaymentMethodForm as i, mountAmosCreditCardPaymentMethodForm as a, mountAmosGooglePayButton as o, resetForm as s, resolveWalletButtonSkeletonBorderRadius as c, validateForm as l } from "@amos.com/amos-js";
1
+ import { confirmPayment as e, confirmSetup as t, ensureSkeletonStyles as n, mountAmosApplePayButton as r, mountAmosBankAccountPaymentMethodForm as i, mountAmosCreditCardPaymentMethodForm as a, mountAmosGooglePayButton as o, resetForm as s, resolveWalletButtonSkeletonBorderRadius as c, validateForm as l } from "@amos.com/amos-js";
2
2
  import { useEffect as u, useLayoutEffect as d, useRef as f } from "react";
3
3
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
4
4
  export * from "@amos.com/amos-js";
@@ -10,13 +10,13 @@ function g({ iframeRef: e }) {
10
10
  return l({ iframe: h(e) });
11
11
  }
12
12
  function _({ iframeRef: t, token: n }) {
13
- e({
13
+ return e({
14
14
  iframe: h(t),
15
15
  token: n
16
16
  });
17
17
  }
18
18
  function v({ iframeRef: e, token: n }) {
19
- t({
19
+ return t({
20
20
  iframe: h(e),
21
21
  token: n
22
22
  });
@@ -84,81 +84,77 @@ function w({ height: e, borderRadius: t, containerRef: r }) {
84
84
  })]
85
85
  });
86
86
  }
87
- function T({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChange: i, onCardBrandChanged: o, additionalFields: s = { cardholderName: !1 }, billingAddressRequirement: c = "country", style: l, ...u }) {
88
- let d = f(null);
87
+ function T({ ref: e, renderToken: t, appearance: n, onValidityChange: r, onCardBrandChanged: i, additionalFields: o = { cardholderName: !1 }, billingAddressRequirement: s = "country", style: c, ...l }) {
88
+ let u = f(null);
89
89
  return S({
90
- containerRef: d,
90
+ containerRef: u,
91
91
  iframeRef: e,
92
92
  mount: a,
93
93
  options: {
94
94
  renderToken: t,
95
95
  appearance: n,
96
- additionalFields: s,
97
- billingAddressRequirement: c,
98
- onResult: r,
99
- onValidityChange: i,
100
- onCardBrandChanged: o
96
+ additionalFields: o,
97
+ billingAddressRequirement: s,
98
+ onValidityChange: r,
99
+ onCardBrandChanged: i
101
100
  },
102
101
  remountDeps: [
103
102
  t,
104
- s.cardholderName,
105
- c
103
+ o.cardholderName,
104
+ s
106
105
  ],
107
106
  iframePassthrough: {
108
- style: l,
109
- ...u
107
+ style: c,
108
+ ...l
110
109
  },
111
110
  updateDeps: [
112
111
  n,
112
+ o,
113
113
  s,
114
- c,
115
114
  r,
116
- i,
117
- o
115
+ i
118
116
  ]
119
- }), /* @__PURE__ */ p("div", { ref: d });
117
+ }), /* @__PURE__ */ p("div", { ref: u });
120
118
  }
121
- function E({ ref: e, renderToken: t, appearance: n, onResult: r, onValidityChange: a, billingAddressRequirement: o = "country", amount: s = "0", intent: c = "payment", style: l, ...u }) {
122
- let d = f(null);
119
+ function E({ ref: e, renderToken: t, appearance: n, onValidityChange: r, billingAddressRequirement: a = "country", amount: o = "0", intent: s = "payment", style: c, ...l }) {
120
+ let u = f(null);
123
121
  return S({
124
- containerRef: d,
122
+ containerRef: u,
125
123
  iframeRef: e,
126
124
  mount: i,
127
125
  options: {
128
126
  renderToken: t,
129
127
  appearance: n,
130
- billingAddressRequirement: o,
131
- amount: s,
132
- intent: c,
133
- onResult: r,
134
- onValidityChange: a
128
+ billingAddressRequirement: a,
129
+ amount: o,
130
+ intent: s,
131
+ onValidityChange: r
135
132
  },
136
133
  remountDeps: [
137
134
  t,
138
- o,
139
- c
135
+ a,
136
+ s
140
137
  ],
141
138
  iframePassthrough: {
142
- style: l,
143
- ...u
139
+ style: c,
140
+ ...l
144
141
  },
145
142
  updateDeps: [
146
143
  n,
144
+ a,
147
145
  o,
148
146
  s,
149
- c,
150
- r,
151
- a
147
+ r
152
148
  ]
153
- }), /* @__PURE__ */ p("div", { ref: d });
149
+ }), /* @__PURE__ */ p("div", { ref: u });
154
150
  }
155
- function D({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48px", buttonProps: a, iframeProps: s, onInitiatePaymentIntentRequest: l, onResult: u }) {
156
- let d = f(null), m = c({
151
+ function D({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48px", buttonProps: a, iframeProps: s, onConfirm: l }) {
152
+ let u = f(null), d = c({
157
153
  iframeStyle: s?.style,
158
154
  buttonProps: a
159
155
  });
160
156
  return S({
161
- containerRef: d,
157
+ containerRef: u,
162
158
  iframeRef: e,
163
159
  mount: o,
164
160
  options: {
@@ -167,8 +163,7 @@ function D({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48
167
163
  merchantName: r,
168
164
  height: i,
169
165
  buttonProps: a,
170
- onInitiatePaymentIntentRequest: l,
171
- onResult: u
166
+ onConfirm: l
172
167
  },
173
168
  remountDeps: [t],
174
169
  iframePassthrough: s ?? {},
@@ -177,22 +172,21 @@ function D({ ref: e, renderToken: t, amount: n, merchantName: r, height: i = "48
177
172
  r,
178
173
  i,
179
174
  a,
180
- l,
181
- u
175
+ l
182
176
  ]
183
177
  }), /* @__PURE__ */ p(w, {
184
178
  height: i,
185
- borderRadius: m,
186
- containerRef: d
179
+ borderRadius: d,
180
+ containerRef: u
187
181
  });
188
182
  }
189
- function O({ ref: e, renderToken: t, amount: n, merchantName: i, height: a = "48px", buttonProps: o, iframeProps: s, onInitiatePaymentIntentRequest: l, onResult: u }) {
190
- let d = f(null), m = c({
183
+ function O({ ref: e, renderToken: t, amount: n, merchantName: i, height: a = "48px", buttonProps: o, iframeProps: s, onConfirm: l }) {
184
+ let u = f(null), d = c({
191
185
  iframeStyle: s?.style,
192
186
  buttonProps: o
193
187
  });
194
188
  return S({
195
- containerRef: d,
189
+ containerRef: u,
196
190
  iframeRef: e,
197
191
  mount: r,
198
192
  options: {
@@ -201,8 +195,7 @@ function O({ ref: e, renderToken: t, amount: n, merchantName: i, height: a = "48
201
195
  merchantName: i,
202
196
  height: a,
203
197
  buttonProps: o,
204
- onInitiatePaymentIntentRequest: l,
205
- onResult: u
198
+ onConfirm: l
206
199
  },
207
200
  remountDeps: [t],
208
201
  iframePassthrough: s ?? {},
@@ -211,14 +204,13 @@ function O({ ref: e, renderToken: t, amount: n, merchantName: i, height: a = "48
211
204
  i,
212
205
  a,
213
206
  o,
214
- l,
215
- u
207
+ l
216
208
  ]
217
209
  }), /* @__PURE__ */ p(w, {
218
210
  height: a,
219
- borderRadius: m,
220
- containerRef: d
211
+ borderRadius: d,
212
+ containerRef: u
221
213
  });
222
214
  }
223
215
  //#endregion
224
- export { O as AmosApplePayButton, E as AmosBankAccountPaymentMethodForm, T as AmosCreditCardPaymentMethodForm, D as AmosGooglePayButton, _ as confirmPaymentIntent, v as confirmSetupIntent, y as resetForm, g as validateForm };
216
+ export { O as AmosApplePayButton, E as AmosBankAccountPaymentMethodForm, T as AmosCreditCardPaymentMethodForm, D as AmosGooglePayButton, _ as confirmPayment, v as confirmSetup, y as resetForm, g as validateForm };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amos.com/react-amos-js",
3
- "version": "0.10.6",
3
+ "version": "0.11.2",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,22 +37,22 @@
37
37
  "license": "MIT",
38
38
  "description": "React SDK for embedding Amos payment methods via iframes. Wraps @amos.com/amos-js.",
39
39
  "devDependencies": {
40
- "@amos.com/node": "0.1.50",
41
- "@biomejs/biome": "2.5.7",
40
+ "@amos.com/node": "0.1.53",
41
+ "@biomejs/biome": "2.5.10",
42
42
  "@changesets/cli": "2.31.1",
43
- "@types/node": "26.1.2",
43
+ "@types/node": "26.3.0",
44
44
  "@types/react": "19.2.18",
45
45
  "@typescript/typescript6": "6.0.2",
46
46
  "typescript": "7.0.2",
47
- "vite": "8.2.0",
47
+ "vite": "8.2.2",
48
48
  "vite-plugin-dts": "5.0.3"
49
49
  },
50
50
  "dependencies": {
51
- "@amos.com/amos-js": "0.10.6",
52
- "@types/googlepay": "0.7.11"
51
+ "@amos.com/amos-js": "0.11.3",
52
+ "@types/googlepay": "0.7.12"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "react": "^17 || ^18 || ^19",
56
- "@amos.com/node": ">=0.1.50"
56
+ "@amos.com/node": ">=0.1.53"
57
57
  }
58
58
  }
package/src/index.tsx CHANGED
@@ -3,12 +3,12 @@
3
3
  import {
4
4
  type Appearance,
5
5
  type ApplePayButtonElementProps,
6
- confirmPaymentIntent as amosConfirmPaymentIntent,
7
- confirmSetupIntent as amosConfirmSetupIntent,
6
+ confirmPayment as amosConfirmPayment,
7
+ confirmSetup as amosConfirmSetup,
8
8
  resetForm as amosResetForm,
9
9
  validateForm as amosValidateForm,
10
10
  type BillingAddressRequirement,
11
- type ConfirmationResult,
11
+ type ConfirmResult,
12
12
  type CreditCardAdditionalFields,
13
13
  ensureSkeletonStyles,
14
14
  type GooglePayButtonElementProps,
@@ -60,13 +60,16 @@ export function validateForm({
60
60
  * Pass the embed JWT (`token`) returned by your server's
61
61
  * `POST /payment_intents` call.
62
62
  */
63
- export function confirmPaymentIntent({
63
+ export function confirmPayment({
64
64
  iframeRef,
65
65
  token,
66
66
  }: {
67
67
  iframeRef: IframeRef;
68
- } & Pick<components["schemas"]["EmbedToken"], "token">): void {
69
- amosConfirmPaymentIntent({ iframe: resolveIframe(iframeRef), token });
68
+ } & Pick<
69
+ components["schemas"]["EmbedToken"],
70
+ "token"
71
+ >): Promise<ConfirmResult> {
72
+ return amosConfirmPayment({ iframe: resolveIframe(iframeRef), token });
70
73
  }
71
74
 
72
75
  /**
@@ -76,18 +79,21 @@ export function confirmPaymentIntent({
76
79
  * Pass the embed JWT (`token`) returned by your server's
77
80
  * `POST /setup_intents` call.
78
81
  */
79
- export function confirmSetupIntent({
82
+ export function confirmSetup({
80
83
  iframeRef,
81
84
  token,
82
85
  }: {
83
86
  iframeRef: IframeRef;
84
- } & Pick<components["schemas"]["EmbedToken"], "token">): void {
85
- amosConfirmSetupIntent({ iframe: resolveIframe(iframeRef), token });
87
+ } & Pick<
88
+ components["schemas"]["EmbedToken"],
89
+ "token"
90
+ >): Promise<ConfirmResult> {
91
+ return amosConfirmSetup({ iframe: resolveIframe(iframeRef), token });
86
92
  }
87
93
 
88
94
  /**
89
95
  * Clear all field values and API errors in the embedded card/bank iframe
90
- * form. Call after `onResult` when the customer wants to try again.
96
+ * form. Call after a failed confirm when the customer wants to try again.
91
97
  */
92
98
  export function resetForm({ iframeRef }: { iframeRef: IframeRef }): void {
93
99
  amosResetForm({ iframe: resolveIframe(iframeRef) });
@@ -247,7 +253,6 @@ function WalletButtonSlot({
247
253
  type AmosCreditCardPaymentMethodFormProps = IframePassthroughProps & {
248
254
  renderToken: string;
249
255
  appearance?: Appearance;
250
- onResult: (result: ConfirmationResult) => void;
251
256
  /**
252
257
  * Called when form validity changes. `isValid` is true when all
253
258
  * required fields are present and valid. Does not include PCI data.
@@ -276,7 +281,6 @@ export function AmosCreditCardPaymentMethodForm({
276
281
  ref,
277
282
  renderToken,
278
283
  appearance,
279
- onResult,
280
284
  onValidityChange,
281
285
  onCardBrandChanged,
282
286
  additionalFields = { cardholderName: false },
@@ -295,7 +299,6 @@ export function AmosCreditCardPaymentMethodForm({
295
299
  appearance,
296
300
  additionalFields,
297
301
  billingAddressRequirement,
298
- onResult,
299
302
  onValidityChange,
300
303
  onCardBrandChanged,
301
304
  },
@@ -309,7 +312,6 @@ export function AmosCreditCardPaymentMethodForm({
309
312
  appearance,
310
313
  additionalFields,
311
314
  billingAddressRequirement,
312
- onResult,
313
315
  onValidityChange,
314
316
  onCardBrandChanged,
315
317
  ],
@@ -321,7 +323,6 @@ export function AmosCreditCardPaymentMethodForm({
321
323
  type AmosBankAccountPaymentMethodFormProps = IframePassthroughProps & {
322
324
  renderToken: string;
323
325
  appearance?: Appearance;
324
- onResult: (result: ConfirmationResult) => void;
325
326
  /**
326
327
  * Called when form validity changes. `isValid` is true when all
327
328
  * required fields are present and valid, or when Plaid Link has
@@ -357,7 +358,6 @@ export function AmosBankAccountPaymentMethodForm({
357
358
  ref,
358
359
  renderToken,
359
360
  appearance,
360
- onResult,
361
361
  onValidityChange,
362
362
  billingAddressRequirement = "country",
363
363
  amount = "0",
@@ -377,7 +377,6 @@ export function AmosBankAccountPaymentMethodForm({
377
377
  billingAddressRequirement,
378
378
  amount,
379
379
  intent,
380
- onResult,
381
380
  onValidityChange,
382
381
  },
383
382
  remountDeps: [renderToken, billingAddressRequirement, intent],
@@ -387,7 +386,6 @@ export function AmosBankAccountPaymentMethodForm({
387
386
  billingAddressRequirement,
388
387
  amount,
389
388
  intent,
390
- onResult,
391
389
  onValidityChange,
392
390
  ],
393
391
  });
@@ -419,14 +417,19 @@ type AmosGooglePayButtonProps = {
419
417
  buttonProps?: GooglePayButtonElementProps;
420
418
  /** Props applied to the host-page `<iframe>` element. */
421
419
  iframeProps?: IframePassthroughProps;
422
- onInitiatePaymentIntentRequest: ({
420
+ /**
421
+ * Called when the buyer authorizes in the Google Pay sheet. Create a
422
+ * payment intent on your server, then `await confirmPayment(token)`.
423
+ */
424
+ onConfirm: ({
423
425
  paymentIntentCreateAttributes,
424
426
  customerCreateAttributes,
427
+ confirmPayment,
425
428
  }: {
426
429
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
427
430
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
428
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
429
- onResult: (result: ConfirmationResult) => void;
431
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
432
+ }) => Promise<ConfirmResult>;
430
433
  };
431
434
 
432
435
  /**
@@ -442,8 +445,7 @@ export function AmosGooglePayButton({
442
445
  height = "48px",
443
446
  buttonProps,
444
447
  iframeProps,
445
- onInitiatePaymentIntentRequest,
446
- onResult,
448
+ onConfirm,
447
449
  }: AmosGooglePayButtonProps) {
448
450
  const containerRef = useRef<HTMLDivElement | null>(null);
449
451
  const borderRadius = resolveWalletButtonSkeletonBorderRadius({
@@ -461,19 +463,11 @@ export function AmosGooglePayButton({
461
463
  merchantName,
462
464
  height,
463
465
  buttonProps,
464
- onInitiatePaymentIntentRequest,
465
- onResult,
466
+ onConfirm,
466
467
  },
467
468
  remountDeps: [renderToken],
468
469
  iframePassthrough: iframeProps ?? {},
469
- updateDeps: [
470
- amount,
471
- merchantName,
472
- height,
473
- buttonProps,
474
- onInitiatePaymentIntentRequest,
475
- onResult,
476
- ],
470
+ updateDeps: [amount, merchantName, height, buttonProps, onConfirm],
477
471
  });
478
472
 
479
473
  return (
@@ -509,14 +503,19 @@ type AmosApplePayButtonProps = {
509
503
  buttonProps?: ApplePayButtonElementProps;
510
504
  /** Props applied to the host-page `<iframe>` element. */
511
505
  iframeProps?: IframePassthroughProps;
512
- onInitiatePaymentIntentRequest: ({
506
+ /**
507
+ * Called when the buyer authorizes in the Apple Pay sheet. Create a
508
+ * payment intent on your server, then `await confirmPayment(token)`.
509
+ */
510
+ onConfirm: ({
513
511
  paymentIntentCreateAttributes,
514
512
  customerCreateAttributes,
513
+ confirmPayment,
515
514
  }: {
516
515
  paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
517
516
  customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
518
- }) => Promise<components["schemas"]["EmbedToken"]["token"]>;
519
- onResult: (result: ConfirmationResult) => void;
517
+ confirmPayment: (token: string) => Promise<ConfirmResult>;
518
+ }) => Promise<ConfirmResult>;
520
519
  };
521
520
 
522
521
  /**
@@ -532,8 +531,7 @@ export function AmosApplePayButton({
532
531
  height = "48px",
533
532
  buttonProps,
534
533
  iframeProps,
535
- onInitiatePaymentIntentRequest,
536
- onResult,
534
+ onConfirm,
537
535
  }: AmosApplePayButtonProps) {
538
536
  const containerRef = useRef<HTMLDivElement | null>(null);
539
537
  const borderRadius = resolveWalletButtonSkeletonBorderRadius({
@@ -551,19 +549,11 @@ export function AmosApplePayButton({
551
549
  merchantName,
552
550
  height,
553
551
  buttonProps,
554
- onInitiatePaymentIntentRequest,
555
- onResult,
552
+ onConfirm,
556
553
  },
557
554
  remountDeps: [renderToken],
558
555
  iframePassthrough: iframeProps ?? {},
559
- updateDeps: [
560
- amount,
561
- merchantName,
562
- height,
563
- buttonProps,
564
- onInitiatePaymentIntentRequest,
565
- onResult,
566
- ],
556
+ updateDeps: [amount, merchantName, height, buttonProps, onConfirm],
567
557
  });
568
558
 
569
559
  return (