@amos.com/amos-js 0.9.15 → 0.9.16

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
@@ -101,7 +101,7 @@ The following flow is for credit card and bank account payment method types only
101
101
  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.
102
102
  5. **Return the payment intent token to the browser**: your backend responds with the embed token (`components["schemas"]["EmbedToken"]`) needed for confirmation.
103
103
  6. **Confirm the payment intent from the client**: call `confirmPaymentIntent({ iframe: form.iframe, token })` in the browser to continue the payment flow.
104
- 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"`).
104
+ 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"`).
105
105
 
106
106
  ### Google Pay & Apple Pay
107
107
 
@@ -114,44 +114,56 @@ The key differences between the express and non-express payment flows are:
114
114
  - You do not call `confirmPaymentIntent` in an express flow (this is done after `onInitiatePaymentIntentRequest` returns a token).
115
115
 
116
116
  ```ts
117
- import { mountAmosGooglePayButton } from "@amos.com/amos-js";
118
-
119
- const button = mountAmosGooglePayButton(
120
- document.querySelector("#google-pay")!,
121
- {
122
- renderToken: "the-render-token-created-on-dashboard.amos.com",
123
- amount: "5000", // $50.00 in cents, as a string
124
- merchantName: "your-user-facing-merchant-name",
125
- onInitiatePaymentIntentRequest: async ({
126
- paymentIntentCreateAttributes,
127
- customerCreateAttributes,
128
- }) => {
129
- const response = await fetch("/api/payment-intents", {
130
- method: "POST",
131
- headers: { "Content-Type": "application/json" },
132
- body: JSON.stringify({
133
- customer: customerCreateAttributes,
134
- paymentIntent: paymentIntentCreateAttributes,
135
- }),
136
- });
137
- const { token } = await response.json();
138
- return token;
139
- },
140
- onResult: (result) => {
141
- if (result.status === "succeeded") {
142
- console.log("Google Pay confirm returned:", result);
143
- } else if (result.status === "failed") {
144
- console.error("Google Pay failed:", result.errorMessage);
145
- }
146
- },
117
+ import {
118
+ mountAmosApplePayButton,
119
+ mountAmosGooglePayButton,
120
+ type ConfirmationResult,
121
+ } from "@amos.com/amos-js";
122
+ import type { components } from "@amos.com/node";
123
+
124
+ async function createPaymentIntentToken({
125
+ paymentIntentCreateAttributes,
126
+ customerCreateAttributes,
127
+ }: {
128
+ paymentIntentCreateAttributes: components["schemas"]["CreatePaymentIntentInput"];
129
+ customerCreateAttributes: components["schemas"]["CreateCustomerInput"];
130
+ }): Promise<string> {
131
+ const response = await fetch("/api/payment-intents", {
132
+ method: "POST",
133
+ headers: { "Content-Type": "application/json" },
134
+ body: JSON.stringify({
135
+ customer: customerCreateAttributes,
136
+ paymentIntent: paymentIntentCreateAttributes,
137
+ }),
138
+ });
139
+ const { token } = (await response.json()) as { token: string };
140
+ return token;
141
+ }
142
+
143
+ const shared = {
144
+ renderToken: "the-render-token-created-on-dashboard.amos.com",
145
+ amount: "50.00",
146
+ merchantName: "Example Store",
147
+ onInitiatePaymentIntentRequest: createPaymentIntentToken,
148
+ onResult: (result: ConfirmationResult) => {
149
+ if (result.status === "succeeded") {
150
+ console.log("Confirm returned:", result);
151
+ } else if (result.status === "failed") {
152
+ console.error("Confirm failed:", result.errorMessage);
153
+ }
147
154
  },
148
- );
155
+ };
149
156
 
150
- // Updating amount/merchant name later just works:
151
- button.update({ amount: "7500" });
157
+ const googlePay = mountAmosGooglePayButton("#google-pay", shared);
158
+ const applePay = mountAmosApplePayButton("#apple-pay", shared);
159
+
160
+ googlePay.update({ amount: "75.00" });
161
+ applePay.update({ amount: "75.00" });
152
162
  ```
153
163
 
154
- Apple Pay uses the same express-checkout flow and options — swap `mountAmosGooglePayButton` for `mountAmosApplePayButton`. When Apple Pay Code opens in a separate window, the SDK shows a host-page waiting overlay and tears it down when the session ends.
164
+ 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.
165
+
166
+ 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**.
155
167
 
156
168
  ## Understanding the flow for creating and confirming setup intents
157
169
 
@@ -288,7 +300,7 @@ Mount the secure Google Pay button (express checkout) into a container element.
288
300
  **Required `options`:**
289
301
 
290
302
  - `renderToken` (`string`)
291
- - `amount` (`string`)
303
+ - `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`.
292
304
  - `merchantName` (`string`)
293
305
  - `onInitiatePaymentIntentRequest` (`({ paymentIntentCreateAttributes, customerCreateAttributes }) => Promise<components["schemas"]["EmbedToken"]["token"]>`)
294
306
 
@@ -339,6 +351,8 @@ button.update({
339
351
  });
340
352
  ```
341
353
 
354
+ Only Amos domains need Apple merchant registration. The button and `ApplePaySession` run inside the Amos embed iframe. On Safari, the native payment sheet is used. On other browsers, Apple's QR handoff opens in a popup (`pay.apple.com`); while that popup is open, the SDK automatically shows a full-viewport waiting overlay on the host page with instructions and a **Cancel payment** button. You do not need to implement popup or overlay handling yourself.
355
+
342
356
  ### `validateForm({ iframe })`
343
357
 
344
358
  Validates the embedded card/bank iframe form. Returns `Promise<boolean>` (resolves to `false` after 5 seconds if the iframe does not respond).
@@ -375,13 +389,15 @@ Advanced helpers exposed for integrators that need to construct or inspect the m
375
389
 
376
390
  ### Exported types
377
391
 
378
- `Message`, `Appearance`, `ThemeVariable`, `FormattedGooglePayPaymentData`, `PaymentMethodFormValidityChangeEvent`, plus the per-form `*Options` and `*Controller` types. For OpenAPI schema types, import `components` from `@amos.com/node`.
392
+ `ConfirmationResult`, `ConfirmationIncompleteReason`, `Message`, `Appearance`, `ThemeVariable`, `FormattedGooglePayPaymentData`, `PaymentMethodFormValidityChangeEvent`, plus the per-form `*Options` and `*Controller` types. For OpenAPI schema types, import `components` from `@amos.com/node`.
379
393
 
380
394
  ## Notes and potential gotchas
381
395
 
382
396
  - **`iframe` argument**: every messaging helper (`validateForm`, `confirmPaymentIntent`, `confirmSetupIntent`, `resetForm`) accepts the `iframe` element directly. With the mount helpers, use `controller.iframe`.
397
+ - **`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.
383
398
  - **Same components for payment vs setup intents**: `mountAmosCreditCardPaymentMethodForm` and `mountAmosBankAccountPaymentMethodForm` support both payment intents and setup intents. The flow differs only by which server call you make and which confirmation function you use. Handle both outcomes via `onResult`.
384
- - **Amount format**: for `mountAmosGooglePayButton` and `mountAmosApplePayButton`, `amount` is a string (e.g. `"5000"` for $50.00). For `components["schemas"]["CreatePaymentIntentInput"]` on the server, `amount` is a number in cents (e.g. `5000`).
399
+ - **Amount format**: for `mountAmosGooglePayButton` and `mountAmosApplePayButton`, `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`).
400
+ - **Apple Pay waiting overlay**: on browsers where Apple's QR handoff opens in a popup (non-Safari), `mountAmosApplePayButton` 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.
385
401
  - **Browser-only**: the mount and messaging helpers require `window` and the DOM. They are not safe to call during server-side rendering — call them from client-side code only (for example, inside a `useEffect`-like hook in your framework of choice).
386
402
 
387
403
  ---
@@ -12,7 +12,11 @@ export declare function getApplePayButtonInitialHeight(): string;
12
12
  * Options accepted by {@link attachApplePayButtonListeners}.
13
13
  */
14
14
  export type ApplePayButtonListenerOptions = {
15
- /** The amount of the payment, in the same format passed in props. */
15
+ /**
16
+ * Major-currency decimal string shown in the Apple Pay sheet
17
+ * (e.g. `"50.00"` for $50.00). Converted to cents in
18
+ * `paymentIntentCreateAttributes.amount`.
19
+ */
16
20
  amount: string;
17
21
  /** A user-visible merchant name. */
18
22
  merchantName: string;
@@ -12,7 +12,11 @@ export declare function getGooglePayButtonInitialHeight(): string;
12
12
  * Options accepted by {@link attachGooglePayButtonListeners}.
13
13
  */
14
14
  export type GooglePayButtonListenerOptions = {
15
- /** The amount of the payment, in the same format passed in props. */
15
+ /**
16
+ * Major-currency decimal string shown in the Google Pay sheet
17
+ * (e.g. `"50.00"` for $50.00). Converted to cents in
18
+ * `paymentIntentCreateAttributes.amount`.
19
+ */
16
20
  amount: string;
17
21
  /** A user-visible merchant name. */
18
22
  merchantName: string;
@@ -43,7 +43,8 @@ export declare function updateGooglePayButton({ iframe, props, height, }: {
43
43
  height?: string;
44
44
  }): void;
45
45
  /**
46
- * Push the express-checkout amount into the embedded Google Pay iframe.
46
+ * Push the express-checkout amount into the embedded wallet iframe.
47
+ * `amount` is a major-currency decimal string (e.g. `"50.00"` for $50.00).
47
48
  */
48
49
  export declare function updateAmount({ iframe, amount, }: {
49
50
  iframe: Iframe;
package/dist/types.d.ts CHANGED
@@ -145,7 +145,10 @@ export type Message = {
145
145
  type: "UPDATE_HEIGHT";
146
146
  height: string;
147
147
  } | {
148
- /** Parent → embed: express-checkout amount changed. */
148
+ /**
149
+ * Parent → embed: express-checkout amount changed. Major-currency
150
+ * decimal string (e.g. `"50.00"` for $50.00).
151
+ */
149
152
  type: "UPDATE_AMOUNT";
150
153
  amount: string;
151
154
  } | {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amos.com/amos-js",
3
- "version": "0.9.15",
3
+ "version": "0.9.16",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
package/src/apple-pay.ts CHANGED
@@ -38,7 +38,11 @@ export function getApplePayButtonInitialHeight(): string {
38
38
  * Options accepted by {@link attachApplePayButtonListeners}.
39
39
  */
40
40
  export type ApplePayButtonListenerOptions = {
41
- /** The amount of the payment, in the same format passed in props. */
41
+ /**
42
+ * Major-currency decimal string shown in the Apple Pay sheet
43
+ * (e.g. `"50.00"` for $50.00). Converted to cents in
44
+ * `paymentIntentCreateAttributes.amount`.
45
+ */
42
46
  amount: string;
43
47
  /** A user-visible merchant name. */
44
48
  merchantName: string;
package/src/google-pay.ts CHANGED
@@ -34,7 +34,11 @@ export function getGooglePayButtonInitialHeight(): string {
34
34
  * Options accepted by {@link attachGooglePayButtonListeners}.
35
35
  */
36
36
  export type GooglePayButtonListenerOptions = {
37
- /** The amount of the payment, in the same format passed in props. */
37
+ /**
38
+ * Major-currency decimal string shown in the Google Pay sheet
39
+ * (e.g. `"50.00"` for $50.00). Converted to cents in
40
+ * `paymentIntentCreateAttributes.amount`.
41
+ */
38
42
  amount: string;
39
43
  /** A user-visible merchant name. */
40
44
  merchantName: string;
package/src/messaging.ts CHANGED
@@ -114,7 +114,8 @@ export function updateGooglePayButton({
114
114
  }
115
115
 
116
116
  /**
117
- * Push the express-checkout amount into the embedded Google Pay iframe.
117
+ * Push the express-checkout amount into the embedded wallet iframe.
118
+ * `amount` is a major-currency decimal string (e.g. `"50.00"` for $50.00).
118
119
  */
119
120
  export function updateAmount({
120
121
  iframe,
package/src/types.ts CHANGED
@@ -406,7 +406,10 @@ export type Message =
406
406
  height: string;
407
407
  }
408
408
  | {
409
- /** Parent → embed: express-checkout amount changed. */
409
+ /**
410
+ * Parent → embed: express-checkout amount changed. Major-currency
411
+ * decimal string (e.g. `"50.00"` for $50.00).
412
+ */
410
413
  type: "UPDATE_AMOUNT";
411
414
  amount: string;
412
415
  }