@amos.com/amos-js 0.9.16 → 0.9.18

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.
@@ -68,6 +68,13 @@ export declare function updateMerchantName({ iframe, merchantName, }: {
68
68
  export declare function validateForm({ iframe }: {
69
69
  iframe: Iframe;
70
70
  }): Promise<boolean>;
71
+ /**
72
+ * Ask the bank iframe to mint a Plaid Link token (`POST /plaid_link_tokens`
73
+ * on embed). Resolves with `link_token`, or rejects on error / timeout.
74
+ */
75
+ export declare function requestPlaidLinkToken({ iframe, }: {
76
+ iframe: Iframe;
77
+ }): Promise<string>;
71
78
  /**
72
79
  * Clear all field values and API errors in the embedded credit-card or
73
80
  * bank-account iframe form.
package/dist/mount.d.ts CHANGED
@@ -40,6 +40,14 @@ export type AmosPaymentMethodFormMountController = PaymentMethodFormController &
40
40
  */
41
41
  iframe: HTMLIFrameElement;
42
42
  };
43
+ /**
44
+ * Controller returned by {@link mountAmosBankAccountPaymentMethodForm}.
45
+ * `update()` also accepts `amount` (major-currency decimal string) when
46
+ * the charge changes.
47
+ */
48
+ export type AmosBankAccountPaymentMethodFormMountController = Omit<AmosPaymentMethodFormMountController, "update"> & {
49
+ update: (patch: Partial<AmosBankAccountPaymentMethodFormOptions>) => void;
50
+ };
43
51
  /**
44
52
  * Mount the secure credit-card payment method form into a container
45
53
  * element. Returns a controller exposing the underlying iframe, an
@@ -70,20 +78,32 @@ export type AmosBankAccountPaymentMethodFormOptions = PaymentMethodFormListenerO
70
78
  * @default "country"
71
79
  */
72
80
  billingAddressRequirement?: BillingAddressRequirement;
81
+ /**
82
+ * Charge amount as a major-currency decimal string (e.g. `"50.00"`
83
+ * for $50.00), the same format as Google Pay / Apple Pay. Compared
84
+ * to the merchant ACH threshold fetched by the iframe. Omit for
85
+ * setup intents or when the charge is unknown — if a threshold is
86
+ * set, Plaid is required.
87
+ */
88
+ amount?: string;
73
89
  };
74
90
  /**
75
91
  * Mount the secure bank-account payment method form into a container
76
92
  * element. Returns a controller exposing the underlying iframe, an
77
93
  * `update()` method, and a `destroy()` method.
78
94
  *
79
- * A field-shaped skeleton is shown immediately and replaced by the
80
- * iframe once appearance is applied.
95
+ * When the iframe reports an ACH threshold and `amount` meets it (or
96
+ * `amount` is omitted), a Connect bank button is rendered in the parent
97
+ * document and Plaid Link is opened on click. The button uses the same
98
+ * `appearance.themeVariables` as the iframe (and inherits host-page
99
+ * tokens when those variables are unset). Otherwise a field-shaped
100
+ * skeleton is shown and replaced by the iframe once appearance is applied.
81
101
  *
82
102
  * Use the returned `controller.iframe` when calling
83
103
  * {@link validateForm}, {@link confirmPaymentIntent}, or
84
104
  * {@link confirmSetupIntent}.
85
105
  */
86
- export declare function mountAmosBankAccountPaymentMethodForm(container: Container, options: AmosBankAccountPaymentMethodFormOptions): AmosPaymentMethodFormMountController;
106
+ export declare function mountAmosBankAccountPaymentMethodForm(container: Container, options: AmosBankAccountPaymentMethodFormOptions): AmosBankAccountPaymentMethodFormMountController;
87
107
  /**
88
108
  * Options accepted by {@link mountAmosGooglePayButton}.
89
109
  */
@@ -116,6 +136,9 @@ export type AmosGooglePayButtonMountController = GooglePayButtonController & {
116
136
  * Mount the secure Google Pay button (express checkout) into a
117
137
  * container element. Returns a controller exposing the underlying
118
138
  * iframe, an `update()` method, and a `destroy()` method.
139
+ *
140
+ * A button-shaped skeleton is shown immediately and replaced by the
141
+ * iframe once appearance is applied.
119
142
  */
120
143
  export declare function mountAmosGooglePayButton(container: Container, options: AmosGooglePayButtonOptions): AmosGooglePayButtonMountController;
121
144
  /**
@@ -150,6 +173,9 @@ export type AmosApplePayButtonMountController = ApplePayButtonController & {
150
173
  * Mount the secure Apple Pay button (express checkout) into a
151
174
  * container element. Returns a controller exposing the underlying
152
175
  * iframe, an `update()` method, and a `destroy()` method.
176
+ *
177
+ * A button-shaped skeleton is shown immediately and replaced by the
178
+ * iframe once appearance is applied.
153
179
  */
154
180
  export declare function mountAmosApplePayButton(container: Container, options: AmosApplePayButtonOptions): AmosApplePayButtonMountController;
155
181
  export {};
@@ -0,0 +1,21 @@
1
+ import { PaymentMethodFormListenerOptions } from './payment-method-form';
2
+ export type PlaidBankUiOptions = {
3
+ amount?: string;
4
+ appearance?: PaymentMethodFormListenerOptions["appearance"];
5
+ onValidityChange?: PaymentMethodFormListenerOptions["onValidityChange"];
6
+ };
7
+ /**
8
+ * Parent-page Connect bank UI. Outline/ghost controls match `@amos/ui`
9
+ * (including `:focus-visible` `--ring`). Unset theme variables inherit
10
+ * from the host document, then fall back to {@link ThemeVariable}
11
+ * defaults; `appearance.themeVariables` overrides with the same replace
12
+ * model as the iframe.
13
+ */
14
+ export declare function attachPlaidBankUi({ host, iframe, options, }: {
15
+ host: HTMLElement;
16
+ iframe: HTMLIFrameElement;
17
+ options: PlaidBankUiOptions;
18
+ }): {
19
+ update: (patch: Partial<PlaidBankUiOptions>) => void;
20
+ destroy: () => void;
21
+ };
@@ -0,0 +1,12 @@
1
+ import { PlaidCredentials } from './plaid';
2
+ type BankPlaidSession = {
3
+ requiresVerification: boolean;
4
+ plaid?: PlaidCredentials;
5
+ /** Drop linked Plaid credentials and restore the Connect button. */
6
+ clearLinked?: () => void;
7
+ };
8
+ export declare function setBankPlaidSession(iframe: HTMLIFrameElement, session: BankPlaidSession): void;
9
+ export declare function getBankPlaidSession(iframe: HTMLIFrameElement | null | undefined): BankPlaidSession | undefined;
10
+ export declare function clearBankPlaidSession(iframe: HTMLIFrameElement | null | undefined): void;
11
+ export declare function getBankPlaidCredentials(iframe: HTMLIFrameElement | null | undefined): PlaidCredentials | undefined;
12
+ export {};
@@ -0,0 +1,82 @@
1
+ import { components } from '@amos.com/node';
2
+ export type PlaidCredentials = components["schemas"]["PlaidCredentialsInput"];
3
+ export type PlaidLinkAccount = {
4
+ id?: string;
5
+ mask?: string;
6
+ name?: string;
7
+ subtype?: string | null;
8
+ type?: string;
9
+ };
10
+ export type PlaidLinkOnSuccessMetadata = {
11
+ institution?: {
12
+ name?: string;
13
+ } | null;
14
+ accounts?: Array<PlaidLinkAccount>;
15
+ account?: PlaidLinkAccount;
16
+ account_id?: string;
17
+ };
18
+ type PlaidLinkHandler = {
19
+ open: () => void;
20
+ exit: (options?: {
21
+ force?: boolean;
22
+ }) => void;
23
+ destroy: () => void;
24
+ };
25
+ type PlaidCreateConfig = {
26
+ token: string;
27
+ onSuccess: (publicToken: string, metadata: PlaidLinkOnSuccessMetadata) => void;
28
+ onExit?: (error: {
29
+ error_code?: string;
30
+ error_message?: string;
31
+ } | null, metadata: unknown) => void;
32
+ };
33
+ declare global {
34
+ interface Window {
35
+ Plaid?: {
36
+ create: (config: PlaidCreateConfig) => PlaidLinkHandler;
37
+ };
38
+ }
39
+ }
40
+ /**
41
+ * Whether the bank form should show Plaid Link instead of routing/account
42
+ * fields.
43
+ *
44
+ * - No `achThreshold`: always manual ACH (backward compatible).
45
+ * - `amount` omitted: Plaid (setup / unknown future charge).
46
+ * - Otherwise: Plaid when `amount >= achThreshold`.
47
+ *
48
+ * `amount` and `achThreshold` are integer minor units (cents).
49
+ */
50
+ export declare function requiresAchVerification({ amount, achThreshold, }: {
51
+ amount?: number;
52
+ achThreshold?: number;
53
+ }): boolean;
54
+ /**
55
+ * Convert a major-currency decimal string (e.g. `"50.00"`) to integer
56
+ * cents. Empty / invalid values are omitted.
57
+ */
58
+ export declare function majorAmountToMinorUnits(amount?: string): number | undefined;
59
+ export declare function plaidAccountIdFromMetadata(metadata: PlaidLinkOnSuccessMetadata): string | undefined;
60
+ export declare function linkedBankLabelFromMetadata(metadata: PlaidLinkOnSuccessMetadata): {
61
+ bankName: string;
62
+ last4: string;
63
+ };
64
+ export declare function loadPlaidScript(): Promise<void>;
65
+ export type OpenPlaidLinkInput = {
66
+ token: string;
67
+ onSuccess: (publicToken: string, metadata: PlaidLinkOnSuccessMetadata) => void;
68
+ onExit?: (error: {
69
+ error_code?: string;
70
+ } | null) => void;
71
+ /**
72
+ * When aborted (e.g. the bank form was unmounted), skip opening Link
73
+ * and destroy the handler if it was already created.
74
+ */
75
+ signal?: AbortSignal;
76
+ };
77
+ /**
78
+ * Load Plaid Link (if needed) and open it with the given `link_token`.
79
+ * Returns a destroy function for the Link handler.
80
+ */
81
+ export declare function openPlaidLink({ token, onSuccess, onExit, signal, }: OpenPlaidLinkInput): Promise<() => void>;
82
+ export {};
package/dist/types.d.ts CHANGED
@@ -185,10 +185,16 @@ export type Message = {
185
185
  } | ({
186
186
  /** Parent → embed: confirm a payment intent with an embed token. */
187
187
  type: "CONFIRM_PAYMENT_INTENT";
188
- } & Pick<components["schemas"]["PaymentIntent"], "id"> & Pick<components["schemas"]["EmbedToken"], "token">) | ({
188
+ } & Pick<components["schemas"]["PaymentIntent"], "id"> & Pick<components["schemas"]["EmbedToken"], "token"> & {
189
+ /** Present when ACH verification completed via Plaid Link in the parent. */
190
+ plaid?: components["schemas"]["PlaidCredentialsInput"];
191
+ }) | ({
189
192
  /** Parent → embed: confirm a setup intent with an embed token. */
190
193
  type: "CONFIRM_SETUP_INTENT";
191
- } & Pick<components["schemas"]["SetupIntent"], "id"> & Pick<components["schemas"]["EmbedToken"], "token">) | {
194
+ } & Pick<components["schemas"]["SetupIntent"], "id"> & Pick<components["schemas"]["EmbedToken"], "token"> & {
195
+ /** Present when ACH verification completed via Plaid Link in the parent. */
196
+ plaid?: components["schemas"]["PlaidCredentialsInput"];
197
+ }) | {
192
198
  /**
193
199
  * Embed → parent: the interactive confirmation flow finished.
194
200
  * Parent → embed: express-checkout initiation failed on the host.
@@ -220,6 +226,26 @@ export type Message = {
220
226
  */
221
227
  type: "FORM_VALIDITY_CHANGE";
222
228
  isValid: boolean;
229
+ } | {
230
+ /**
231
+ * Embed → parent: merchant ACH verification threshold for this
232
+ * render token. `achThreshold` is cents, or `null` when the
233
+ * merchant has no threshold (manual ACH). `requireVerification`
234
+ * is true when the fetch failed in production (fail closed).
235
+ */
236
+ type: "ACH_THRESHOLD";
237
+ achThreshold?: number | null;
238
+ requireVerification?: boolean;
239
+ } | {
240
+ /** Parent → embed: mint a Plaid Link token for Connect. */
241
+ type: "CREATE_PLAID_LINK_TOKEN";
242
+ requestId: string;
243
+ } | {
244
+ /** Embed → parent: minted Plaid Link token, or `error`. */
245
+ type: "PLAID_LINK_TOKEN";
246
+ requestId: string;
247
+ link_token?: string;
248
+ error?: string;
223
249
  };
224
250
  /**
225
251
  * Identity helper that brands an object as a typed `Message`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amos.com/amos-js",
3
- "version": "0.9.16",
3
+ "version": "0.9.18",
4
4
  "main": "dist/index.js",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,7 @@ const SKELETON_THEME_DEFAULTS: Record<string, string> = {
16
16
  "--label-font-size": "0.875rem",
17
17
  };
18
18
 
19
- const SKELETON_STYLES = `
19
+ export const SKELETON_STYLES = `
20
20
  .amos-js-form-skeleton {
21
21
  box-sizing: border-box;
22
22
  container-type: inline-size;
@@ -71,6 +71,10 @@ const SKELETON_STYLES = `
71
71
  gap: var(--control-gap);
72
72
  }
73
73
  }
74
+ .amos-js-wallet-skeleton {
75
+ flex: none;
76
+ width: 100%;
77
+ }
74
78
  @keyframes amos-js-skeleton-pulse {
75
79
  50% { opacity: 0.5; }
76
80
  }
@@ -81,7 +85,7 @@ const SKELETON_STYLES = `
81
85
  }
82
86
  `;
83
87
 
84
- function ensureSkeletonStyles(): void {
88
+ export function ensureSkeletonStyles(): void {
85
89
  if (document.getElementById(STYLE_ID)) {
86
90
  return;
87
91
  }
@@ -242,3 +246,74 @@ export function createPaymentMethodFormSkeleton(
242
246
  update: render,
243
247
  };
244
248
  }
249
+
250
+ export type WalletButtonSkeletonOptions = {
251
+ /** Painted height of the wallet button slot (CSS length). */
252
+ height: string;
253
+ /** Corner radius matching the iframe / native button. */
254
+ borderRadius?: string;
255
+ };
256
+
257
+ export type WalletButtonSkeleton = {
258
+ element: HTMLElement;
259
+ update: (options: WalletButtonSkeletonOptions) => void;
260
+ };
261
+
262
+ /**
263
+ * Host-page placeholder for Google Pay / Apple Pay: a pulsing bar at
264
+ * the button's height. Shown immediately while the iframe loads, then
265
+ * removed when appearance is ready.
266
+ */
267
+ export function createWalletButtonSkeleton(
268
+ options: WalletButtonSkeletonOptions,
269
+ ): WalletButtonSkeleton {
270
+ ensureSkeletonStyles();
271
+ const element = div("amos-js-form-skeleton-input amos-js-wallet-skeleton");
272
+ element.setAttribute("aria-hidden", "true");
273
+
274
+ function render(next: WalletButtonSkeletonOptions): void {
275
+ applyTheme(element, undefined);
276
+ element.style.height = next.height;
277
+ element.style.borderRadius = next.borderRadius ?? "4px";
278
+ }
279
+
280
+ render(options);
281
+
282
+ return {
283
+ element,
284
+ update: render,
285
+ };
286
+ }
287
+
288
+ function cssLength(value: unknown): string | undefined {
289
+ if (typeof value === "number" && Number.isFinite(value)) {
290
+ return `${value}px`;
291
+ }
292
+ if (typeof value === "string" && value.trim() !== "") {
293
+ return value.trim();
294
+ }
295
+ return undefined;
296
+ }
297
+
298
+ /**
299
+ * Corner radius for a wallet-button skeleton. Prefers host iframe
300
+ * chrome, then native Google / Apple button radius, then 4px.
301
+ */
302
+ export function resolveWalletButtonSkeletonBorderRadius({
303
+ iframeStyle,
304
+ buttonProps,
305
+ }: {
306
+ iframeStyle?: { borderRadius?: string | number };
307
+ buttonProps?: {
308
+ buttonRadius?: number;
309
+ style?: Record<string, string | number | undefined>;
310
+ };
311
+ }): string {
312
+ return (
313
+ cssLength(iframeStyle?.borderRadius) ??
314
+ cssLength(buttonProps?.buttonRadius) ??
315
+ cssLength(buttonProps?.style?.["borderRadius"]) ??
316
+ cssLength(buttonProps?.style?.["--apple-pay-button-border-radius"]) ??
317
+ "4px"
318
+ );
319
+ }
package/src/index.ts CHANGED
@@ -9,7 +9,20 @@ export {
9
9
  getApplePayButtonInitialHeight,
10
10
  getApplePayButtonSrc,
11
11
  } from "./apple-pay";
12
-
12
+ export type {
13
+ PaymentMethodFormSkeleton,
14
+ PaymentMethodFormSkeletonKind,
15
+ PaymentMethodFormSkeletonOptions,
16
+ WalletButtonSkeleton,
17
+ WalletButtonSkeletonOptions,
18
+ } from "./form-skeleton";
19
+ export {
20
+ createPaymentMethodFormSkeleton,
21
+ createWalletButtonSkeleton,
22
+ ensureSkeletonStyles,
23
+ resolveWalletButtonSkeletonBorderRadius,
24
+ SKELETON_STYLES,
25
+ } from "./form-skeleton";
13
26
  export type {
14
27
  FormattedGooglePayPaymentData,
15
28
  GooglePayButtonController,
@@ -21,7 +34,6 @@ export {
21
34
  getGooglePayButtonInitialHeight,
22
35
  getGooglePayButtonSrc,
23
36
  } from "./google-pay";
24
-
25
37
  export { decodeJwt, getEmbedOrigin } from "./jwt";
26
38
 
27
39
  export {
@@ -40,6 +52,7 @@ export {
40
52
  export type {
41
53
  AmosApplePayButtonMountController,
42
54
  AmosApplePayButtonOptions,
55
+ AmosBankAccountPaymentMethodFormMountController,
43
56
  AmosBankAccountPaymentMethodFormOptions,
44
57
  AmosCreditCardPaymentMethodFormOptions,
45
58
  AmosGooglePayButtonMountController,
@@ -65,6 +78,18 @@ export {
65
78
  getCreditCardFormInitialHeight,
66
79
  getCreditCardFormSrc,
67
80
  } from "./payment-method-form";
81
+ export type {
82
+ OpenPlaidLinkInput,
83
+ PlaidCredentials,
84
+ PlaidLinkOnSuccessMetadata,
85
+ } from "./plaid";
86
+ export {
87
+ linkedBankLabelFromMetadata,
88
+ loadPlaidScript,
89
+ openPlaidLink,
90
+ plaidAccountIdFromMetadata,
91
+ requiresAchVerification,
92
+ } from "./plaid";
68
93
  export type {
69
94
  Appearance,
70
95
  AppearanceLabels,
package/src/messaging.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { components } from "@amos.com/node";
2
2
  import { decodeJwt } from "./jwt";
3
+ import { getBankPlaidSession } from "./plaid-session";
3
4
  import {
4
5
  type Appearance,
5
6
  type ApplePayButtonElementProps,
@@ -163,6 +164,11 @@ export function updateMerchantName({
163
164
  * `false` if the iframe does not respond within 5 seconds.
164
165
  */
165
166
  export function validateForm({ iframe }: { iframe: Iframe }): Promise<boolean> {
167
+ const session = getBankPlaidSession(iframe);
168
+ if (session?.requiresVerification) {
169
+ return Promise.resolve(Boolean(session.plaid));
170
+ }
171
+
166
172
  const requestId = crypto.randomUUID();
167
173
 
168
174
  return new Promise((resolve) => {
@@ -193,11 +199,71 @@ export function validateForm({ iframe }: { iframe: Iframe }): Promise<boolean> {
193
199
  });
194
200
  }
195
201
 
202
+ const PLAID_LINK_TOKEN_TIMEOUT_MS = 10_000;
203
+
204
+ /**
205
+ * Ask the bank iframe to mint a Plaid Link token (`POST /plaid_link_tokens`
206
+ * on embed). Resolves with `link_token`, or rejects on error / timeout.
207
+ */
208
+ export function requestPlaidLinkToken({
209
+ iframe,
210
+ }: {
211
+ iframe: Iframe;
212
+ }): Promise<string> {
213
+ const requestId = crypto.randomUUID();
214
+
215
+ return new Promise((resolve, reject) => {
216
+ if (!iframe?.contentWindow) {
217
+ reject(new Error("Bank form is not ready."));
218
+ return;
219
+ }
220
+
221
+ const contentWindow = iframe.contentWindow;
222
+ contentWindow.postMessage(
223
+ createMessage({ type: "CREATE_PLAID_LINK_TOKEN", requestId }),
224
+ getIframeTargetOrigin(iframe),
225
+ );
226
+
227
+ const timeoutId = setTimeout(() => {
228
+ window.removeEventListener("message", handleMessage);
229
+ reject(new Error("Timed out waiting for Plaid Link token."));
230
+ }, PLAID_LINK_TOKEN_TIMEOUT_MS);
231
+
232
+ function handleMessage(event: MessageEvent<Message>) {
233
+ if (event.source !== contentWindow) {
234
+ return;
235
+ }
236
+ if (
237
+ event.data.type !== "PLAID_LINK_TOKEN" ||
238
+ event.data.requestId !== requestId
239
+ ) {
240
+ return;
241
+ }
242
+ window.removeEventListener("message", handleMessage);
243
+ clearTimeout(timeoutId);
244
+ if (event.data.link_token) {
245
+ resolve(event.data.link_token);
246
+ return;
247
+ }
248
+ reject(
249
+ new Error(event.data.error ?? "Could not create Plaid Link token."),
250
+ );
251
+ }
252
+
253
+ window.addEventListener("message", handleMessage);
254
+ });
255
+ }
256
+
196
257
  /**
197
258
  * Clear all field values and API errors in the embedded credit-card or
198
259
  * bank-account iframe form.
199
260
  */
200
261
  export function resetForm({ iframe }: { iframe: Iframe }): void {
262
+ getBankPlaidSession(iframe)?.clearLinked?.();
263
+ resetIframeFields(iframe);
264
+ }
265
+
266
+ function resetIframeFields(iframe: Iframe): void {
201
267
  if (!iframe?.contentWindow) {
202
268
  return;
203
269
  }
@@ -208,6 +274,35 @@ export function resetForm({ iframe }: { iframe: Iframe }): void {
208
274
  );
209
275
  }
210
276
 
277
+ function postConfirmIntent({
278
+ iframe,
279
+ type,
280
+ token,
281
+ id,
282
+ }: {
283
+ iframe: HTMLIFrameElement;
284
+ type: "CONFIRM_PAYMENT_INTENT" | "CONFIRM_SETUP_INTENT";
285
+ token: string | undefined;
286
+ id: string | undefined;
287
+ }): void {
288
+ const session = getBankPlaidSession(iframe);
289
+ const plaid = session?.plaid;
290
+ // Plaid mode: do not confirm leftover routing/account numbers.
291
+ if (session?.requiresVerification && !plaid) {
292
+ resetIframeFields(iframe);
293
+ }
294
+
295
+ iframe.contentWindow?.postMessage(
296
+ createMessage({
297
+ type,
298
+ token,
299
+ id,
300
+ ...(plaid ? { plaid } : {}),
301
+ }),
302
+ getIframeTargetOrigin(iframe),
303
+ );
304
+ }
305
+
211
306
  /**
212
307
  * Confirm a payment intent in the embedded iframe flow.
213
308
  *
@@ -227,14 +322,12 @@ export function confirmPaymentIntent({
227
322
 
228
323
  const { payment_intent_id: id }: components["schemas"]["EmbedTokenJwt"] =
229
324
  decodeJwt(token).payload;
230
- iframe.contentWindow.postMessage(
231
- createMessage({
232
- type: "CONFIRM_PAYMENT_INTENT",
233
- token,
234
- id: id ?? undefined,
235
- }),
236
- getIframeTargetOrigin(iframe),
237
- );
325
+ postConfirmIntent({
326
+ iframe,
327
+ type: "CONFIRM_PAYMENT_INTENT",
328
+ token,
329
+ id: id ?? undefined,
330
+ });
238
331
  }
239
332
 
240
333
  /**
@@ -256,14 +349,12 @@ export function confirmSetupIntent({
256
349
 
257
350
  const { setup_intent_id: id }: components["schemas"]["EmbedTokenJwt"] =
258
351
  decodeJwt(token).payload;
259
- iframe.contentWindow.postMessage(
260
- createMessage({
261
- type: "CONFIRM_SETUP_INTENT",
262
- token,
263
- id: id ?? undefined,
264
- }),
265
- getIframeTargetOrigin(iframe),
266
- );
352
+ postConfirmIntent({
353
+ iframe,
354
+ type: "CONFIRM_SETUP_INTENT",
355
+ token,
356
+ id: id ?? undefined,
357
+ });
267
358
  }
268
359
 
269
360
  /**