@amos.com/amos-js 0.9.18 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +3 -0
- package/dist/payment-method-form.d.ts +8 -1
- package/dist/types.d.ts +20 -0
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/payment-method-form.ts +12 -0
- package/src/types.ts +29 -0
package/README.md
CHANGED
|
@@ -281,6 +281,7 @@ Mount the secure credit-card payment method form into a container element (an `H
|
|
|
281
281
|
- `billingAddressRequirement` (`"country" | "full"`, defaults to `"country"`) — how much billing address the iframe collects. `country` collects country / region and, for CA / PR / GB / US, a postal code (labeled ZIP for the United States). `full` shows a full street address form with Smarty autocomplete.
|
|
282
282
|
|
|
283
283
|
- `onValidityChange` (`(event: { isValid: boolean }) => void`) — called when form validity changes. `isValid` is true when all required fields are present and valid. Does not include PCI data. Use this to enable or disable your checkout button.
|
|
284
|
+
- `onCardBrandChanged` (`(event: { brand: CardBrand | null }) => void`) — called when the detected card brand changes. `brand` is `"visa"`, `"mastercard"`, `"amex"`, `"discover"`, `"diners"`, or `"jcb"`, or `null` when the field is empty or the number does not match a known brand. Does not include PCI data. Credit-card form only.
|
|
284
285
|
- `onHeightChange`, `onAppearanceReady` (advanced — override the default iframe styling logic). The skeleton is removed and the iframe faded in when `onAppearanceReady` fires.
|
|
285
286
|
|
|
286
287
|
**Returns** `AmosPaymentMethodFormMountController`:
|
|
@@ -415,7 +416,7 @@ Advanced helpers exposed for integrators that need to construct or inspect the m
|
|
|
415
416
|
|
|
416
417
|
### Exported types
|
|
417
418
|
|
|
418
|
-
`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`.
|
|
419
|
+
`ConfirmationResult`, `ConfirmationIncompleteReason`, `Message`, `Appearance`, `ThemeVariable`, `FormattedGooglePayPaymentData`, `PaymentMethodFormValidityChangeEvent`, `CardBrand`, `PaymentMethodFormCardBrandChangeEvent`, plus the per-form `*Options` and `*Controller` types. For OpenAPI schema types, import `components` from `@amos.com/node`.
|
|
419
420
|
|
|
420
421
|
## Notes and potential gotchas
|
|
421
422
|
|
package/dist/index.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export type { BillingAddressRequirement, CreditCardAdditionalFields, PaymentMeth
|
|
|
13
13
|
export { attachPaymentMethodFormListeners, getBankAccountFormInitialHeight, getBankAccountFormSrc, getCreditCardFormInitialHeight, getCreditCardFormSrc, } from './payment-method-form';
|
|
14
14
|
export type { OpenPlaidLinkInput, PlaidCredentials, PlaidLinkOnSuccessMetadata, } from './plaid';
|
|
15
15
|
export { linkedBankLabelFromMetadata, loadPlaidScript, openPlaidLink, plaidAccountIdFromMetadata, requiresAchVerification, } from './plaid';
|
|
16
|
-
export type { Appearance, AppearanceLabels, ApplePayButtonElementProps, ConfirmationIncompleteReason, ConfirmationResult, GooglePayButtonElementProps, Message, PaymentMethodFormValidityChangeEvent, ThemeVariable, } from './types';
|
|
16
|
+
export type { Appearance, AppearanceLabels, ApplePayButtonElementProps, CardBrand, ConfirmationIncompleteReason, ConfirmationResult, GooglePayButtonElementProps, Message, PaymentMethodFormCardBrandChangeEvent, PaymentMethodFormValidityChangeEvent, ThemeVariable, } from './types';
|
|
17
17
|
export { createMessage } from './types';
|
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`data-a
|
|
|
65
65
|
animation: none;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
`;function A(){if(document.getElementById(k))return;let e=document.createElement(`style`);e.id=k,e.textContent=ne,document.head.appendChild(e)}function j(e,t){for(let[t,n]of Object.entries(te))e.style.setProperty(t,n);let n=t?.themeVariables;if(n)for(let[t,r]of Object.entries(n))typeof r==`string`&&r.trim()!==``&&e.style.setProperty(t,r.trim())}function M(e,t){let n=document.createElement(`div`);if(n.className=e,t)for(let e of t)n.appendChild(e);return n}function N(e,t){let n=M(`amos-js-form-skeleton-field`);t!==void 0&&(n.style.flexGrow=String(t)),e===`above`&&n.appendChild(M(`amos-js-form-skeleton-label`));let r=M(`amos-js-form-skeleton-input`);return e===`floating`&&r.classList.add(`amos-js-form-skeleton-input-floating`),n.appendChild(r),n}function P(e,t){return M(t?`amos-js-form-skeleton-row-stack`:`amos-js-form-skeleton-row`,e)}function re({labels:e,requirement:t,wrapCountryZip:n}){return t===`full`?[N(e),N(e),P([N(e,1.4),N(e,.7),N(e,.8)],!1),N(e)]:[P([N(e),N(e)],n)]}function ie(e){let t=e.appearance?.labels??`above`,n=e.billingAddressRequirement??`country`;if(e.kind===`card`){let r=[N(t),P([N(t),N(t)],!1)];return e.additionalFields?.cardholderName&&r.push(N(t)),r.push(...re({labels:t,requirement:n,wrapCountryZip:!1})),r}return[N(t),P([N(t),N(t)],!0),N(t),P([N(`above`),N(`above`)],!0),...re({labels:t,requirement:n,wrapCountryZip:!0})]}function ae(e){A();let t=M(`amos-js-form-skeleton`);t.setAttribute(`aria-hidden`,`true`);function n(e){j(t,e.appearance),t.replaceChildren(...ie(e))}return n(e),{element:t,update:n}}function F(e){A();let t=M(`amos-js-form-skeleton-input amos-js-wallet-skeleton`);t.setAttribute(`aria-hidden`,`true`);function n(e){j(t,void 0),t.style.height=e.height,t.style.borderRadius=e.borderRadius??`4px`}return n(e),{element:t,update:n}}function I(e){if(typeof e==`number`&&Number.isFinite(e))return`${e}px`;if(typeof e==`string`&&e.trim()!==``)return e.trim()}function L({iframeStyle:e,buttonProps:t}){return I(e?.borderRadius)??I(t?.buttonRadius)??I(t?.style?.borderRadius)??I(t?.style?.[`--apple-pay-button-border-radius`])??`4px`}function R(e){return`${i(e)}/iframe/google-pay?token=${e}`}function z(){return`48px`}function B(e,{height:t=`48px`,...n}){let r={...n,height:t};function i(){h({iframe:e,amount:r.amount})}function a(){g({iframe:e,merchantName:r.merchantName})}function o(){m({iframe:e,height:r.height??`48px`,props:r.buttonProps??{}})}function s(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:d(e),f({iframe:e,appearance:{}}),i(),a(),o();break;case`UPDATE_HEIGHT`:r.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:f({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:r.onAppearanceReady?.();break;case`CREATE_PAYMENT_INTENT`:r.onInitiatePaymentIntentRequest({paymentIntentCreateAttributes:t.data.paymentIntentCreateAttributes,customerCreateAttributes:t.data.customerCreateAttributes}).then(t=>{S({iframe:e,token:t})}).catch(e=>{r.onResult({status:`failed`,errorMessage:e instanceof Error?e.message:`Unknown error`})});break;case`CONFIRMATION_RESULT`:r.onResult(t.data.result)}}return window.addEventListener(`message`,s),{update(e){let t=`amount`in e,n=`merchantName`in e,s=`height`in e||`buttonProps`in e;r={...r,...e},t&&i(),n&&a(),s&&o()},destroy(){window.removeEventListener(`message`,s)}}}function oe({paymentData:e}){return{paymentMethod:{type:`googlepay`,billing_address_attributes:{name:e.shippingAddress?.name,address_line1:e.shippingAddress?.address1,address_line2:e.shippingAddress?.address2,city:e.shippingAddress?.locality,state:e.shippingAddress?.administrativeArea,postal_code:e.shippingAddress?.postalCode,country:e.shippingAddress?.countryCode,email:e.email,phone:e.shippingAddress?.phoneNumber},card_profile_attributes:{wallet_payload:e.paymentMethodData.tokenizationData.token}}}}var V={country:212,full:452},se=80,H={country:400,full:640};function U(e,t={cardholderName:!1},n=`country`){let r=Object.entries(t).filter(([,e])=>e).map(([e])=>e).join(`,`),a=new URLSearchParams({token:e,additionalFields:r,billingAddressRequirement:n});return`${i(e)}/iframe/card?${a}`}function W(e,t=`country`){let n=new URLSearchParams({token:e,billingAddressRequirement:t});return`${i(e)}/iframe/bank?${n}`}function G(e={cardholderName:!1},t=`country`){return`${(V[t]??V.country)+(e.cardholderName?se:0)}px`}function K(e=`country`){return`${H[e]??H.country}px`}function q(e,t){let n={...t};function r(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:d(e),f({iframe:e,appearance:n.appearance});break;case`UPDATE_HEIGHT`:n.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:f({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:n.onAppearanceReady?.();break;case`FORM_VALIDITY_CHANGE`:if(s(e)?.requiresVerification)break;n.onValidityChange?.({isValid:t.data.isValid});break;case`CONFIRMATION_RESULT`:n.onResult(t.data.result)}}return window.addEventListener(`message`,r),{update(t){let r=`appearance`in t;n={...n,...t},r&&f({iframe:e,appearance:n.appearance})},destroy(){window.removeEventListener(`message`,r)}}}var J=`https://cdn.plaid.com/link/v2/stable/link-initialize.js`;function Y({amount:e,achThreshold:t}){return t==null?!1:e==null||e>=t}function ce(e){if(e==null)return;let t=e.trim();if(t===``)return;let n=Number(t.replace(/[^\d.]/g,``));if(Number.isFinite(n))return Math.round(n*100)}function le(e){return e.account_id??e.account?.id??e.accounts?.[0]?.id}function ue(e){let t=e.account??e.accounts?.[0];return{bankName:e.institution?.name??`Bank account`,last4:t?.mask??``}}var X;function de(){for(let e of document.querySelectorAll(`script[src="${J}"]`))e.remove()}function fe(){return typeof window>`u`?Promise.reject(Error(`Plaid Link requires a browser`)):window.Plaid?Promise.resolve():X||(de(),X=new Promise((e,t)=>{let n=document.createElement(`script`);n.src=J,n.async=!0;let r=e=>{n.remove(),X=void 0,t(Error(e))};n.addEventListener(`load`,()=>{if(window.Plaid){e();return}r(`Plaid Link failed to initialize`)},{once:!0}),n.addEventListener(`error`,()=>r(`Failed to load Plaid Link`),{once:!0}),document.head.append(n)}),X)}async function pe({token:e,onSuccess:t,onExit:n,signal:r}){if(await fe(),r?.aborted)return()=>{};if(!window.Plaid)throw Error(`Plaid Link failed to initialize`);let i=window.Plaid.create({token:e,onSuccess:t,onExit:e=>{n?.(e)}});return r?.aborted?(i.destroy(),()=>{}):(i.open(),()=>{i.destroy()})}var me=`amos-js-plaid-bank-ui-styles`,he=`
|
|
68
|
+
`;function A(){if(document.getElementById(k))return;let e=document.createElement(`style`);e.id=k,e.textContent=ne,document.head.appendChild(e)}function j(e,t){for(let[t,n]of Object.entries(te))e.style.setProperty(t,n);let n=t?.themeVariables;if(n)for(let[t,r]of Object.entries(n))typeof r==`string`&&r.trim()!==``&&e.style.setProperty(t,r.trim())}function M(e,t){let n=document.createElement(`div`);if(n.className=e,t)for(let e of t)n.appendChild(e);return n}function N(e,t){let n=M(`amos-js-form-skeleton-field`);t!==void 0&&(n.style.flexGrow=String(t)),e===`above`&&n.appendChild(M(`amos-js-form-skeleton-label`));let r=M(`amos-js-form-skeleton-input`);return e===`floating`&&r.classList.add(`amos-js-form-skeleton-input-floating`),n.appendChild(r),n}function P(e,t){return M(t?`amos-js-form-skeleton-row-stack`:`amos-js-form-skeleton-row`,e)}function re({labels:e,requirement:t,wrapCountryZip:n}){return t===`full`?[N(e),N(e),P([N(e,1.4),N(e,.7),N(e,.8)],!1),N(e)]:[P([N(e),N(e)],n)]}function ie(e){let t=e.appearance?.labels??`above`,n=e.billingAddressRequirement??`country`;if(e.kind===`card`){let r=[N(t),P([N(t),N(t)],!1)];return e.additionalFields?.cardholderName&&r.push(N(t)),r.push(...re({labels:t,requirement:n,wrapCountryZip:!1})),r}return[N(t),P([N(t),N(t)],!0),N(t),P([N(`above`),N(`above`)],!0),...re({labels:t,requirement:n,wrapCountryZip:!0})]}function ae(e){A();let t=M(`amos-js-form-skeleton`);t.setAttribute(`aria-hidden`,`true`);function n(e){j(t,e.appearance),t.replaceChildren(...ie(e))}return n(e),{element:t,update:n}}function F(e){A();let t=M(`amos-js-form-skeleton-input amos-js-wallet-skeleton`);t.setAttribute(`aria-hidden`,`true`);function n(e){j(t,void 0),t.style.height=e.height,t.style.borderRadius=e.borderRadius??`4px`}return n(e),{element:t,update:n}}function I(e){if(typeof e==`number`&&Number.isFinite(e))return`${e}px`;if(typeof e==`string`&&e.trim()!==``)return e.trim()}function L({iframeStyle:e,buttonProps:t}){return I(e?.borderRadius)??I(t?.buttonRadius)??I(t?.style?.borderRadius)??I(t?.style?.[`--apple-pay-button-border-radius`])??`4px`}function R(e){return`${i(e)}/iframe/google-pay?token=${e}`}function z(){return`48px`}function B(e,{height:t=`48px`,...n}){let r={...n,height:t};function i(){h({iframe:e,amount:r.amount})}function a(){g({iframe:e,merchantName:r.merchantName})}function o(){m({iframe:e,height:r.height??`48px`,props:r.buttonProps??{}})}function s(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:d(e),f({iframe:e,appearance:{}}),i(),a(),o();break;case`UPDATE_HEIGHT`:r.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:f({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:r.onAppearanceReady?.();break;case`CREATE_PAYMENT_INTENT`:r.onInitiatePaymentIntentRequest({paymentIntentCreateAttributes:t.data.paymentIntentCreateAttributes,customerCreateAttributes:t.data.customerCreateAttributes}).then(t=>{S({iframe:e,token:t})}).catch(e=>{r.onResult({status:`failed`,errorMessage:e instanceof Error?e.message:`Unknown error`})});break;case`CONFIRMATION_RESULT`:r.onResult(t.data.result)}}return window.addEventListener(`message`,s),{update(e){let t=`amount`in e,n=`merchantName`in e,s=`height`in e||`buttonProps`in e;r={...r,...e},t&&i(),n&&a(),s&&o()},destroy(){window.removeEventListener(`message`,s)}}}function oe({paymentData:e}){return{paymentMethod:{type:`googlepay`,billing_address_attributes:{name:e.shippingAddress?.name,address_line1:e.shippingAddress?.address1,address_line2:e.shippingAddress?.address2,city:e.shippingAddress?.locality,state:e.shippingAddress?.administrativeArea,postal_code:e.shippingAddress?.postalCode,country:e.shippingAddress?.countryCode,email:e.email,phone:e.shippingAddress?.phoneNumber},card_profile_attributes:{wallet_payload:e.paymentMethodData.tokenizationData.token}}}}var V={country:212,full:452},se=80,H={country:400,full:640};function U(e,t={cardholderName:!1},n=`country`){let r=Object.entries(t).filter(([,e])=>e).map(([e])=>e).join(`,`),a=new URLSearchParams({token:e,additionalFields:r,billingAddressRequirement:n});return`${i(e)}/iframe/card?${a}`}function W(e,t=`country`){let n=new URLSearchParams({token:e,billingAddressRequirement:t});return`${i(e)}/iframe/bank?${n}`}function G(e={cardholderName:!1},t=`country`){return`${(V[t]??V.country)+(e.cardholderName?se:0)}px`}function K(e=`country`){return`${H[e]??H.country}px`}function q(e,t){let n={...t};function r(t){if(t.source===e.contentWindow)switch(t.data.type){case`IFRAME_READY`:d(e),f({iframe:e,appearance:n.appearance});break;case`UPDATE_HEIGHT`:n.onHeightChange?.(t.data.height);break;case`UPDATE_APPEARANCE`:f({iframe:e,appearance:t.data.appearance});break;case`UPDATED_APPEARANCE`:n.onAppearanceReady?.();break;case`FORM_VALIDITY_CHANGE`:if(s(e)?.requiresVerification)break;n.onValidityChange?.({isValid:t.data.isValid});break;case`CARD_BRAND_CHANGE`:n.onCardBrandChanged?.({brand:t.data.brand});break;case`CONFIRMATION_RESULT`:n.onResult(t.data.result)}}return window.addEventListener(`message`,r),{update(t){let r=`appearance`in t;n={...n,...t},r&&f({iframe:e,appearance:n.appearance})},destroy(){window.removeEventListener(`message`,r)}}}var J=`https://cdn.plaid.com/link/v2/stable/link-initialize.js`;function Y({amount:e,achThreshold:t}){return t==null?!1:e==null||e>=t}function ce(e){if(e==null)return;let t=e.trim();if(t===``)return;let n=Number(t.replace(/[^\d.]/g,``));if(Number.isFinite(n))return Math.round(n*100)}function le(e){return e.account_id??e.account?.id??e.accounts?.[0]?.id}function ue(e){let t=e.account??e.accounts?.[0];return{bankName:e.institution?.name??`Bank account`,last4:t?.mask??``}}var X;function de(){for(let e of document.querySelectorAll(`script[src="${J}"]`))e.remove()}function fe(){return typeof window>`u`?Promise.reject(Error(`Plaid Link requires a browser`)):window.Plaid?Promise.resolve():X||(de(),X=new Promise((e,t)=>{let n=document.createElement(`script`);n.src=J,n.async=!0;let r=e=>{n.remove(),X=void 0,t(Error(e))};n.addEventListener(`load`,()=>{if(window.Plaid){e();return}r(`Plaid Link failed to initialize`)},{once:!0}),n.addEventListener(`error`,()=>r(`Failed to load Plaid Link`),{once:!0}),document.head.append(n)}),X)}async function pe({token:e,onSuccess:t,onExit:n,signal:r}){if(await fe(),r?.aborted)return()=>{};if(!window.Plaid)throw Error(`Plaid Link failed to initialize`);let i=window.Plaid.create({token:e,onSuccess:t,onExit:e=>{n?.(e)}});return r?.aborted?(i.destroy(),()=>{}):(i.open(),()=>{i.destroy()})}var me=`amos-js-plaid-bank-ui-styles`,he=`
|
|
69
69
|
.amos-js-plaid-panel {
|
|
70
70
|
box-sizing: border-box;
|
|
71
71
|
color: var(--foreground, oklch(0.145 0 0));
|
package/dist/index.mjs
CHANGED
|
@@ -578,6 +578,9 @@ function q(e, t) {
|
|
|
578
578
|
if (s(e)?.requiresVerification) break;
|
|
579
579
|
n.onValidityChange?.({ isValid: t.data.isValid });
|
|
580
580
|
break;
|
|
581
|
+
case "CARD_BRAND_CHANGE":
|
|
582
|
+
n.onCardBrandChanged?.({ brand: t.data.brand });
|
|
583
|
+
break;
|
|
581
584
|
case "CONFIRMATION_RESULT": n.onResult(t.data.result);
|
|
582
585
|
}
|
|
583
586
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Appearance, ConfirmationResult, PaymentMethodFormValidityChangeEvent } from './types';
|
|
1
|
+
import { Appearance, ConfirmationResult, PaymentMethodFormCardBrandChangeEvent, PaymentMethodFormValidityChangeEvent } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* The additional fields beyond the standard card number, expiration
|
|
4
4
|
* date, CVV, and billing address fields that are required to be filled
|
|
@@ -65,6 +65,13 @@ export type PaymentMethodFormListenerOptions = {
|
|
|
65
65
|
* PCI data. Use this to enable or disable a host checkout button.
|
|
66
66
|
*/
|
|
67
67
|
onValidityChange?: (event: PaymentMethodFormValidityChangeEvent) => void;
|
|
68
|
+
/**
|
|
69
|
+
* Called when the detected card brand changes. `brand` is the matched
|
|
70
|
+
* network, or `null` when the field is empty or the digits do not
|
|
71
|
+
* match a known brand. Does not include PCI data. Credit-card form
|
|
72
|
+
* only — never fired for bank account.
|
|
73
|
+
*/
|
|
74
|
+
onCardBrandChanged?: (event: PaymentMethodFormCardBrandChangeEvent) => void;
|
|
68
75
|
/**
|
|
69
76
|
* Called when the interactive confirmation flow finishes (success or
|
|
70
77
|
* terminal failure). Not settlement proof — verify via webhooks.
|
package/dist/types.d.ts
CHANGED
|
@@ -7,6 +7,18 @@ import { components } from '@amos.com/node';
|
|
|
7
7
|
export type PaymentMethodFormValidityChangeEvent = {
|
|
8
8
|
isValid: boolean;
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Detected card network from the PAN prefix inside the iframe.
|
|
12
|
+
* `null` when the field is empty or the digits do not match a known brand.
|
|
13
|
+
*/
|
|
14
|
+
export type CardBrand = "visa" | "mastercard" | "amex" | "discover" | "diners" | "jcb";
|
|
15
|
+
/**
|
|
16
|
+
* PCI-safe card brand update from the credit-card iframe. Does not
|
|
17
|
+
* include the PAN, last4, or BIN.
|
|
18
|
+
*/
|
|
19
|
+
export type PaymentMethodFormCardBrandChangeEvent = {
|
|
20
|
+
brand: CardBrand | null;
|
|
21
|
+
};
|
|
10
22
|
/**
|
|
11
23
|
* Why an interactive confirmation attempt ended with `status: "incomplete"`.
|
|
12
24
|
*
|
|
@@ -226,6 +238,14 @@ export type Message = {
|
|
|
226
238
|
*/
|
|
227
239
|
type: "FORM_VALIDITY_CHANGE";
|
|
228
240
|
isValid: boolean;
|
|
241
|
+
} | {
|
|
242
|
+
/**
|
|
243
|
+
* Embed → parent: detected card brand changed. `brand` is the
|
|
244
|
+
* matched network, or `null` when the field is empty or the
|
|
245
|
+
* digits do not match a known brand. Does not include PCI data.
|
|
246
|
+
*/
|
|
247
|
+
type: "CARD_BRAND_CHANGE";
|
|
248
|
+
brand: CardBrand | null;
|
|
229
249
|
} | {
|
|
230
250
|
/**
|
|
231
251
|
* Embed → parent: merchant ACH verification threshold for this
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -94,10 +94,12 @@ export type {
|
|
|
94
94
|
Appearance,
|
|
95
95
|
AppearanceLabels,
|
|
96
96
|
ApplePayButtonElementProps,
|
|
97
|
+
CardBrand,
|
|
97
98
|
ConfirmationIncompleteReason,
|
|
98
99
|
ConfirmationResult,
|
|
99
100
|
GooglePayButtonElementProps,
|
|
100
101
|
Message,
|
|
102
|
+
PaymentMethodFormCardBrandChangeEvent,
|
|
101
103
|
PaymentMethodFormValidityChangeEvent,
|
|
102
104
|
ThemeVariable,
|
|
103
105
|
} from "./types";
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
Appearance,
|
|
9
9
|
ConfirmationResult,
|
|
10
10
|
Message,
|
|
11
|
+
PaymentMethodFormCardBrandChangeEvent,
|
|
11
12
|
PaymentMethodFormValidityChangeEvent,
|
|
12
13
|
} from "./types";
|
|
13
14
|
|
|
@@ -138,6 +139,13 @@ export type PaymentMethodFormListenerOptions = {
|
|
|
138
139
|
* PCI data. Use this to enable or disable a host checkout button.
|
|
139
140
|
*/
|
|
140
141
|
onValidityChange?: (event: PaymentMethodFormValidityChangeEvent) => void;
|
|
142
|
+
/**
|
|
143
|
+
* Called when the detected card brand changes. `brand` is the matched
|
|
144
|
+
* network, or `null` when the field is empty or the digits do not
|
|
145
|
+
* match a known brand. Does not include PCI data. Credit-card form
|
|
146
|
+
* only — never fired for bank account.
|
|
147
|
+
*/
|
|
148
|
+
onCardBrandChanged?: (event: PaymentMethodFormCardBrandChangeEvent) => void;
|
|
141
149
|
/**
|
|
142
150
|
* Called when the interactive confirmation flow finishes (success or
|
|
143
151
|
* terminal failure). Not settlement proof — verify via webhooks.
|
|
@@ -210,6 +218,10 @@ export function attachPaymentMethodFormListeners(
|
|
|
210
218
|
current.onValidityChange?.({ isValid: event.data.isValid });
|
|
211
219
|
break;
|
|
212
220
|
|
|
221
|
+
case "CARD_BRAND_CHANGE":
|
|
222
|
+
current.onCardBrandChanged?.({ brand: event.data.brand });
|
|
223
|
+
break;
|
|
224
|
+
|
|
213
225
|
case "CONFIRMATION_RESULT":
|
|
214
226
|
current.onResult(event.data.result);
|
|
215
227
|
break;
|
package/src/types.ts
CHANGED
|
@@ -11,6 +11,26 @@ export type PaymentMethodFormValidityChangeEvent = {
|
|
|
11
11
|
isValid: boolean;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Detected card network from the PAN prefix inside the iframe.
|
|
16
|
+
* `null` when the field is empty or the digits do not match a known brand.
|
|
17
|
+
*/
|
|
18
|
+
export type CardBrand =
|
|
19
|
+
| "visa"
|
|
20
|
+
| "mastercard"
|
|
21
|
+
| "amex"
|
|
22
|
+
| "discover"
|
|
23
|
+
| "diners"
|
|
24
|
+
| "jcb";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* PCI-safe card brand update from the credit-card iframe. Does not
|
|
28
|
+
* include the PAN, last4, or BIN.
|
|
29
|
+
*/
|
|
30
|
+
export type PaymentMethodFormCardBrandChangeEvent = {
|
|
31
|
+
brand: CardBrand | null;
|
|
32
|
+
};
|
|
33
|
+
|
|
14
34
|
/**
|
|
15
35
|
* Why an interactive confirmation attempt ended with `status: "incomplete"`.
|
|
16
36
|
*
|
|
@@ -505,6 +525,15 @@ export type Message =
|
|
|
505
525
|
type: "FORM_VALIDITY_CHANGE";
|
|
506
526
|
isValid: boolean;
|
|
507
527
|
}
|
|
528
|
+
| {
|
|
529
|
+
/**
|
|
530
|
+
* Embed → parent: detected card brand changed. `brand` is the
|
|
531
|
+
* matched network, or `null` when the field is empty or the
|
|
532
|
+
* digits do not match a known brand. Does not include PCI data.
|
|
533
|
+
*/
|
|
534
|
+
type: "CARD_BRAND_CHANGE";
|
|
535
|
+
brand: CardBrand | null;
|
|
536
|
+
}
|
|
508
537
|
| {
|
|
509
538
|
/**
|
|
510
539
|
* Embed → parent: merchant ACH verification threshold for this
|