@payment-kit-js/vanilla 0.5.17 → 0.5.19
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 +14 -0
- package/dist/{bnpl-shared-DGs1YzS9.mjs → bnpl-shared-CL900HFN.mjs} +2 -2
- package/dist/{bnpl-shared-DGs1YzS9.mjs.map → bnpl-shared-CL900HFN.mjs.map} +1 -1
- package/dist/{bnpl-shared-BQwCBD45.d.mts → bnpl-shared-D-Kd58Qz.d.mts} +2 -2
- package/dist/{bnpl-shared-BQwCBD45.d.mts.map → bnpl-shared-D-Kd58Qz.d.mts.map} +1 -1
- package/dist/cdn/paymentkit.js +263 -61
- package/dist/cdn/paymentkit.js.map +3 -3
- package/dist/cdn/paymentkit.min.js +24 -24
- package/dist/cdn/paymentkit.min.js.map +3 -3
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +75 -6
- package/dist/index.mjs.map +1 -1
- package/dist/{next-action-handlers-CLOt1wzO.mjs → next-action-handlers-DzhzSvEB.mjs} +19 -19
- package/dist/next-action-handlers-DzhzSvEB.mjs.map +1 -0
- package/dist/payment-methods/affirm.d.mts +2 -2
- package/dist/payment-methods/affirm.mjs +2 -2
- package/dist/payment-methods/afterpay.d.mts +2 -2
- package/dist/payment-methods/afterpay.mjs +2 -2
- package/dist/payment-methods/apple-pay.d.mts +2 -2
- package/dist/payment-methods/apple-pay.d.mts.map +1 -1
- package/dist/payment-methods/apple-pay.mjs +2 -2
- package/dist/payment-methods/apple-pay.mjs.map +1 -1
- package/dist/payment-methods/bnpl-shared.d.mts +2 -2
- package/dist/payment-methods/bnpl-shared.mjs +2 -2
- package/dist/payment-methods/card.d.mts +1 -1
- package/dist/payment-methods/card.d.mts.map +1 -1
- package/dist/payment-methods/card.mjs +14 -8
- package/dist/payment-methods/card.mjs.map +1 -1
- package/dist/payment-methods/google-pay.d.mts +25 -3
- package/dist/payment-methods/google-pay.d.mts.map +1 -1
- package/dist/payment-methods/google-pay.mjs +131 -10
- package/dist/payment-methods/google-pay.mjs.map +1 -1
- package/dist/payment-methods/klarna.d.mts +2 -2
- package/dist/payment-methods/klarna.mjs +2 -2
- package/dist/payment-methods/next-action-handlers.mjs +1 -1
- package/dist/payment-methods/paypal.d.mts +1 -1
- package/dist/payment-methods/paypal.mjs +1 -1
- package/dist/{types-B3mjYfOm.d.mts → types-Cjcc3xak.d.mts} +6 -9
- package/dist/types-Cjcc3xak.d.mts.map +1 -0
- package/dist/{utils-Dc6zwOe1.mjs → utils-DIqrx4XF.mjs} +10 -7
- package/dist/utils-DIqrx4XF.mjs.map +1 -0
- package/package.json +2 -2
- package/dist/next-action-handlers-CLOt1wzO.mjs.map +0 -1
- package/dist/types-B3mjYfOm.d.mts.map +0 -1
- package/dist/utils-Dc6zwOe1.mjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as PaymentMethod } from "../types-Cjcc3xak.mjs";
|
|
2
2
|
import "../connect-card-CZhzK_Tp.mjs";
|
|
3
3
|
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
|
-
import { n as BnplCustomerInfo, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-
|
|
4
|
+
import { n as BnplCustomerInfo, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-D-Kd58Qz.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/payment-methods/klarna.d.ts
|
|
7
7
|
type KlarnaCustomerInfo = BnplCustomerInfo;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../utils-
|
|
2
|
-
import { t as createBnplPaymentMethod } from "../bnpl-shared-
|
|
1
|
+
import "../utils-DIqrx4XF.mjs";
|
|
2
|
+
import { t as createBnplPaymentMethod } from "../bnpl-shared-CL900HFN.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/payment-methods/klarna.ts
|
|
5
5
|
const KlarnaPaymentMethod = createBnplPaymentMethod({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-
|
|
1
|
+
import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-DIqrx4XF.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/payment-methods/paypal.ts
|
|
4
4
|
const defSubmitPayment = (states) => {
|
|
@@ -64,14 +64,11 @@ declare class CheckoutTimingTracker {
|
|
|
64
64
|
}
|
|
65
65
|
//#endregion
|
|
66
66
|
//#region src/types.d.ts
|
|
67
|
-
|
|
67
|
+
type PaymentKitEnvironment = "local" | "tunnel" | "sandbox" | "staging" | "production";
|
|
68
68
|
type FormFieldNames = "customer_name" | "customer_email" | "customer_country" | "customer_zip_code" | "customer_business_name" | "customer_address_line1" | "customer_address_line2" | "customer_city" | "customer_state" | "customer_tax_ids" | "shipping_address_line1" | "shipping_address_line2" | "shipping_city" | "shipping_state" | "shipping_zip_code" | "shipping_country";
|
|
69
69
|
type FormErrorCodes = "required" | "invalid";
|
|
70
|
-
type CardSubmitOptions = {
|
|
71
|
-
skipCustomerValidation?: boolean;
|
|
72
|
-
};
|
|
73
70
|
type TInternalFuncs = {
|
|
74
|
-
submitPayment: (fields: PaymentKitFields
|
|
71
|
+
submitPayment: (fields: Partial<PaymentKitFields>, options?: unknown) => Promise<{
|
|
75
72
|
data: {
|
|
76
73
|
[key: string]: unknown;
|
|
77
74
|
};
|
|
@@ -83,7 +80,7 @@ type TInternalFuncs = {
|
|
|
83
80
|
cleanup?: () => void;
|
|
84
81
|
};
|
|
85
82
|
type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {
|
|
86
|
-
environment
|
|
83
|
+
environment?: PaymentKitEnvironment;
|
|
87
84
|
secureToken: string;
|
|
88
85
|
paymentMethods: T;
|
|
89
86
|
/** Card tokenization mode from checkout session */
|
|
@@ -111,7 +108,7 @@ type PaymentKitStates = {
|
|
|
111
108
|
baseUrl: string;
|
|
112
109
|
apiBaseUrl: string;
|
|
113
110
|
secureToken: string;
|
|
114
|
-
environment:
|
|
111
|
+
environment: PaymentKitEnvironment;
|
|
115
112
|
tunnelXConnection: TunnelXIFrameConnection;
|
|
116
113
|
timingTracker: CheckoutTimingTracker;
|
|
117
114
|
/** Checkout request ID for correlating all API calls and analytics events */
|
|
@@ -146,5 +143,5 @@ type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates
|
|
|
146
143
|
};
|
|
147
144
|
type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = { [K in T[number] as ReturnType<K>["name"]]: ReturnType<K>["externalFuncs"] };
|
|
148
145
|
//#endregion
|
|
149
|
-
export {
|
|
150
|
-
//# sourceMappingURL=types-
|
|
146
|
+
export { PaymentMethod as i, PaymentKitEnvironment as n, PaymentKitFields as r, PaymentKit as t };
|
|
147
|
+
//# sourceMappingURL=types-Cjcc3xak.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-Cjcc3xak.d.mts","names":[],"sources":["../src/analytics/checkout-timing.ts","../src/types.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -9,10 +9,10 @@ import * as v from "valibot";
|
|
|
9
9
|
const ENV_TO_SLUG = {
|
|
10
10
|
local: "dev",
|
|
11
11
|
tunnel: "dev",
|
|
12
|
-
sandbox: "
|
|
12
|
+
sandbox: "prod",
|
|
13
|
+
staging: "stg",
|
|
13
14
|
production: "prod"
|
|
14
15
|
};
|
|
15
|
-
const WINDOW_KEY = "__paymentKitRequestId__";
|
|
16
16
|
/**
|
|
17
17
|
* Generates a checkout request ID for correlating all API calls within a checkout session.
|
|
18
18
|
*
|
|
@@ -24,7 +24,7 @@ const WINDOW_KEY = "__paymentKitRequestId__";
|
|
|
24
24
|
* Example: pk_stg_a1b2c3d4e5f6
|
|
25
25
|
*/
|
|
26
26
|
function generateCheckoutRequestId(environment) {
|
|
27
|
-
return `pk_${ENV_TO_SLUG[environment]
|
|
27
|
+
return `pk_${ENV_TO_SLUG[environment] ?? "dev"}_${nanoid(12)}`;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* Gets or creates a checkout request ID, storing it in window for idempotency.
|
|
@@ -36,9 +36,9 @@ function generateCheckoutRequestId(environment) {
|
|
|
36
36
|
* The ID is generated once on first call and reused thereafter.
|
|
37
37
|
*/
|
|
38
38
|
function getOrCreateCheckoutRequestId(environment) {
|
|
39
|
-
if (typeof window !== "undefined" && window
|
|
39
|
+
if (typeof window !== "undefined" && window.__paymentKitRequestId__) return window.__paymentKitRequestId__;
|
|
40
40
|
const requestId = generateCheckoutRequestId(environment);
|
|
41
|
-
if (typeof window !== "undefined") window
|
|
41
|
+
if (typeof window !== "undefined") window.__paymentKitRequestId__ = requestId;
|
|
42
42
|
return requestId;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
@@ -66,7 +66,10 @@ const validateFormFields = async (fields, options = {}) => {
|
|
|
66
66
|
return errors;
|
|
67
67
|
}, {})
|
|
68
68
|
};
|
|
69
|
-
return {
|
|
69
|
+
return {
|
|
70
|
+
isSuccess: true,
|
|
71
|
+
errors: {}
|
|
72
|
+
};
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
//#endregion
|
|
@@ -108,4 +111,4 @@ function collectFraudMetadata() {
|
|
|
108
111
|
|
|
109
112
|
//#endregion
|
|
110
113
|
export { validateFormFields as a, definePaymentMethod as i, collectFraudMetadata as n, getOrCreateCheckoutRequestId as o, createCheckoutIFrame as r, withRequestId as s, $ as t };
|
|
111
|
-
//# sourceMappingURL=utils-
|
|
114
|
+
//# sourceMappingURL=utils-DIqrx4XF.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-DIqrx4XF.mjs","names":["ENV_TO_SLUG: Record<PaymentKitEnvironment, string>"],"sources":["../src/utils/checkout-request-id.ts","../src/utils/validate-form-fields.ts","../src/utils/index.ts"],"sourcesContent":["import { nanoid } from \"nanoid\";\nimport type { PaymentKitEnvironment } from \"../types\";\n\ndeclare global {\n interface Window {\n __paymentKitRequestId__?: string;\n }\n}\n\n/**\n * Maps PaymentKit environment to request ID env slug.\n * This must match the backend's env slug format.\n */\nconst ENV_TO_SLUG: Record<PaymentKitEnvironment, string> = {\n local: \"dev\",\n tunnel: \"dev\",\n sandbox: \"prod\",\n staging: \"stg\",\n production: \"prod\",\n};\n\n/**\n * Generates a checkout request ID for correlating all API calls within a checkout session.\n *\n * Format: pk_{env}_{nanoid(12)}\n * - pk = PaymentKit.js (client-generated)\n * - env = dev, stg, or prod\n * - nanoid(12) = 12 character random string\n *\n * Example: pk_stg_a1b2c3d4e5f6\n */\nexport function generateCheckoutRequestId(environment: PaymentKitEnvironment): string {\n const envSlug = ENV_TO_SLUG[environment] ?? \"dev\";\n const randomPart = nanoid(12);\n return `pk_${envSlug}_${randomPart}`;\n}\n\n/**\n * Gets or creates a checkout request ID, storing it in window for idempotency.\n *\n * This ensures the same request ID is used across:\n * - Multiple PaymentKit instantiations on the same page\n * - All analytics events and API calls within a checkout session\n *\n * The ID is generated once on first call and reused thereafter.\n */\nexport function getOrCreateCheckoutRequestId(environment: PaymentKitEnvironment): string {\n if (typeof window !== \"undefined\" && window.__paymentKitRequestId__) {\n return window.__paymentKitRequestId__;\n }\n\n const requestId = generateCheckoutRequestId(environment);\n\n if (typeof window !== \"undefined\") {\n window.__paymentKitRequestId__ = requestId;\n }\n\n return requestId;\n}\n\n/**\n * Creates RequestOptions with the x-request-id header set.\n */\nexport function withRequestId(checkoutRequestId: string) {\n return {\n headers: {\n \"x-request-id\": checkoutRequestId,\n },\n };\n}\n","import * as v from \"valibot\";\nimport type { FormErrorCodes, PaymentKitErrors, PaymentKitFields } from \"../types\";\n\ntype Options = {\n optionalZipCode?: boolean;\n};\n\nexport const validateFormFields = async (fields: PaymentKitFields, options: Options = {}) => {\n const schema = v.object({\n customer_name: v.pipe(\n v.string(\"required\"),\n v.nonEmpty(\"required\"),\n v.minLength(4, \"invalid\"),\n v.maxLength(40, \"invalid\"),\n ),\n customer_email: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\"), v.email(\"invalid\")),\n customer_country: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n customer_zip_code: options.optionalZipCode\n ? v.pipe(v.string(\"required\"))\n : v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n });\n\n const result = v.safeParse(schema, fields);\n\n if (result.issues) {\n const errors = result.issues.reduce((errors, issue) => {\n const field = v.getDotPath(issue) as keyof PaymentKitErrors;\n\n errors[field] = issue.kind === \"schema\" ? \"required\" : (issue.message as FormErrorCodes);\n return errors;\n }, {} as PaymentKitErrors);\n return { isSuccess: false, errors };\n }\n\n return { isSuccess: true, errors: {} as PaymentKitErrors };\n};\n","import type { PaymentMethod } from \"../types\";\n\nexport { generateCheckoutRequestId, getOrCreateCheckoutRequestId, withRequestId } from \"./checkout-request-id\";\nexport { validateFormFields } from \"./validate-form-fields\";\n\nexport const $ = (selector: string) => {\n const ele = document.querySelector(selector);\n if (!ele) {\n throw new Error(`Cannot find element with selector: ${selector}`);\n }\n return ele;\n};\n\nexport const definePaymentMethod = <TExternalFuncs, TName extends string>(\n paymentMethod: PaymentMethod<TExternalFuncs, TName>,\n) => paymentMethod;\n\nexport const createCheckoutIFrame = (type: string, baseUrl: string, params?: Record<string, string>) => {\n const iframe = document.createElement(\"iframe\");\n\n const searchParams = new URLSearchParams(params);\n const searchParamsStr = searchParams.toString();\n\n iframe.src = `${baseUrl}/embeds/v1/${type}${searchParamsStr ? `?${searchParamsStr}` : \"\"}`;\n\n Object.assign(iframe.style, { width: \"100%\", height: \"100%\", border: \"none\" });\n\n return iframe;\n};\n\n/**\n * Collects browser and client information for fraud detection.\n */\nexport function collectFraudMetadata() {\n return {\n ipAddress: undefined, // IP address should be collected server-side\n browserInfo: {\n userAgent: navigator.userAgent,\n language: navigator.language,\n screenHeight: window.screen.height,\n screenWidth: window.screen.width,\n colorDepth: window.screen.colorDepth,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n },\n processorFraudInfo: undefined,\n };\n}\n\ntype AddressInput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zip_code?: string;\n country?: string;\n};\n\ntype AddressOutput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zipCode?: string;\n country?: string;\n};\n\n/**\n * Maps address fields from snake_case to camelCase format.\n */\nexport function mapAddress(address?: AddressInput): AddressOutput | undefined {\n if (!address) return undefined;\n\n return {\n line1: address.line1,\n line2: address.line2,\n city: address.city,\n state: address.state,\n zipCode: address.zip_code,\n country: address.country,\n };\n}\n"],"mappings":";;;;;;;;AAaA,MAAMA,cAAqD;CACzD,OAAO;CACP,QAAQ;CACR,SAAS;CACT,SAAS;CACT,YAAY;CACb;;;;;;;;;;;AAYD,SAAgB,0BAA0B,aAA4C;AAGpF,QAAO,MAFS,YAAY,gBAAgB,MAEvB,GADF,OAAO,GAAG;;;;;;;;;;;AAa/B,SAAgB,6BAA6B,aAA4C;AACvF,KAAI,OAAO,WAAW,eAAe,OAAO,wBAC1C,QAAO,OAAO;CAGhB,MAAM,YAAY,0BAA0B,YAAY;AAExD,KAAI,OAAO,WAAW,YACpB,QAAO,0BAA0B;AAGnC,QAAO;;;;;AAMT,SAAgB,cAAc,mBAA2B;AACvD,QAAO,EACL,SAAS,EACP,gBAAgB,mBACjB,EACF;;;;;AC7DH,MAAa,qBAAqB,OAAO,QAA0B,UAAmB,EAAE,KAAK;CAC3F,MAAM,SAAS,EAAE,OAAO;EACtB,eAAe,EAAE,KACf,EAAE,OAAO,WAAW,EACpB,EAAE,SAAS,WAAW,EACtB,EAAE,UAAU,GAAG,UAAU,EACzB,EAAE,UAAU,IAAI,UAAU,CAC3B;EACD,gBAAgB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,UAAU,CAAC;EACxF,kBAAkB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACtE,mBAAmB,QAAQ,kBACvB,EAAE,KAAK,EAAE,OAAO,WAAW,CAAC,GAC5B,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACzD,CAAC;CAEF,MAAM,SAAS,EAAE,UAAU,QAAQ,OAAO;AAE1C,KAAI,OAAO,OAOT,QAAO;EAAE,WAAW;EAAO,QANZ,OAAO,OAAO,QAAQ,QAAQ,UAAU;GACrD,MAAM,QAAQ,EAAE,WAAW,MAAM;AAEjC,UAAO,SAAS,MAAM,SAAS,WAAW,aAAc,MAAM;AAC9D,UAAO;KACN,EAAE,CAAqB;EACS;AAGrC,QAAO;EAAE,WAAW;EAAM,QAAQ,EAAE;EAAsB;;;;;AC7B5D,MAAa,KAAK,aAAqB;CACrC,MAAM,MAAM,SAAS,cAAc,SAAS;AAC5C,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,sCAAsC,WAAW;AAEnE,QAAO;;AAGT,MAAa,uBACX,kBACG;AAEL,MAAa,wBAAwB,MAAc,SAAiB,WAAoC;CACtG,MAAM,SAAS,SAAS,cAAc,SAAS;CAG/C,MAAM,kBADe,IAAI,gBAAgB,OAAO,CACX,UAAU;AAE/C,QAAO,MAAM,GAAG,QAAQ,aAAa,OAAO,kBAAkB,IAAI,oBAAoB;AAEtF,QAAO,OAAO,OAAO,OAAO;EAAE,OAAO;EAAQ,QAAQ;EAAQ,QAAQ;EAAQ,CAAC;AAE9E,QAAO;;;;;AAMT,SAAgB,uBAAuB;AACrC,QAAO;EACL,WAAW;EACX,aAAa;GACX,WAAW,UAAU;GACrB,UAAU,UAAU;GACpB,cAAc,OAAO,OAAO;GAC5B,aAAa,OAAO,OAAO;GAC3B,YAAY,OAAO,OAAO;GAC1B,UAAU,KAAK,gBAAgB,CAAC,iBAAiB,CAAC;GACnD;EACD,oBAAoB;EACrB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payment-kit-js/vanilla",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.19",
|
|
4
4
|
"main": "./dist/index.mjs",
|
|
5
5
|
"types": "./dist/index.d.mts",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"tsdown": "^0.15.10",
|
|
53
53
|
"typescript": "^5.9.3"
|
|
54
54
|
},
|
|
55
|
-
"stableVersion": "0.5.
|
|
55
|
+
"stableVersion": "0.5.19"
|
|
56
56
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"next-action-handlers-CLOt1wzO.mjs","names":[],"sources":["../src/utils/3ds-iframe-modal.ts","../src/payment-methods/next-action-handlers.ts"],"sourcesContent":["/**\n * 3DS iframe modal for displaying authentication pages.\n *\n * This module provides an iframe modal used by payment processors\n * that need to display a 3DS authentication page.\n */\n\ntype IframeModalResult = { success: true; data: Record<string, unknown> } | { success: false; error: string };\n\ntype ThreeDSCompleteMessage = {\n type: \"3ds_complete\";\n processor: string | null;\n isSuccess: boolean;\n error?: string;\n};\n\ntype IframeModalMessageHandler = (\n event: MessageEvent<ThreeDSCompleteMessage>,\n) => { handled: true; result: IframeModalResult } | { handled: false };\n\ninterface IframeModalOptions {\n /** URL to load in the iframe */\n url: string;\n /** Size of the iframe in pixels */\n size: { width: number; height: number };\n /** Border radius for the iframe in pixels (default: 16) */\n radius?: number;\n /** Handler to process postMessage events from the iframe */\n onMessage: IframeModalMessageHandler;\n}\n\n/**\n * Shows an iframe modal and waits for a result via postMessage.\n *\n * Features:\n * - Close/cancel button positioned outside the iframe\n * - Responsive design (works on mobile)\n * - Keyboard accessibility (Escape to close, focus trap)\n * - Fade-in/fade-out animations\n * - Iframe load error handling\n *\n * @param options - Modal configuration options\n * @returns Promise that resolves with success/failure result\n *\n * @example\n * ```ts\n * const result = await show3DSIframeModal({\n * url: \"https://bank.com/3ds-auth\",\n * size: { width: 605, height: 500 },\n * radius: 6,\n * onMessage: (event) => {\n * if (event.data?.type === \"auth_complete\") {\n * return {\n * handled: true,\n * result: event.data.succeeded\n * ? { success: true, data: { id: event.data.id } }\n * : { success: false, error: event.data.error }\n * };\n * }\n * return { handled: false };\n * },\n * });\n * ```\n */\n\nexport default function show3DSIframeModal(options: IframeModalOptions): Promise<IframeModalResult> {\n const { url, size, radius = 6, onMessage } = options;\n\n return new Promise((resolve) => {\n let resolved = false;\n\n // Create modal overlay with fade-in animation\n const overlay = document.createElement(\"div\");\n overlay.id = \"pk-iframe-modal-overlay\";\n overlay.setAttribute(\"role\", \"dialog\");\n overlay.setAttribute(\"aria-modal\", \"true\");\n overlay.setAttribute(\"aria-label\", \"3D Secure Verification\");\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n transition: background 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n `;\n\n // Create container for iframe and close button\n const container = document.createElement(\"div\");\n container.style.cssText = `\n position: relative;\n width: ${size.width}px;\n height: ${size.height}px;\n max-width: calc(100vw - 32px);\n max-height: calc(100vh - 64px);\n overflow: visible;\n opacity: 0;\n transform: scale(0.95) translateY(10px);\n transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n `;\n\n // Create close button (positioned outside top-right of iframe)\n const closeButton = document.createElement(\"button\");\n closeButton.id = \"pk-iframe-modal-close\";\n closeButton.setAttribute(\"aria-label\", \"Cancel verification\");\n closeButton.setAttribute(\"type\", \"button\");\n closeButton.style.cssText = `\n position: absolute;\n top: -40px;\n right: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: white;\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: background 0.15s ease;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n `;\n closeButton.innerHTML = `\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 1L13 13M1 13L13 1\" stroke=\"#666\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n `;\n closeButton.onmouseenter = (): void => {\n closeButton.style.background = \"#f5f5f5\";\n };\n closeButton.onmouseleave = (): void => {\n closeButton.style.background = \"white\";\n };\n\n // Create iframe (hidden initially until loaded)\n const iframe = document.createElement(\"iframe\");\n iframe.src = url;\n iframe.setAttribute(\"title\", \"3D Secure Verification\");\n iframe.style.cssText = `\n width: 100%;\n height: 100%;\n border: none;\n opacity: 0;\n border-radius: ${radius}px;\n background: white;\n transition: opacity 0.2s ease;\n position: relative;\n z-index: 1;\n `;\n\n // Handle iframe load success\n iframe.onload = (): void => {\n iframe.style.opacity = \"1\";\n };\n\n // Handle iframe load error\n iframe.onerror = (): void => {\n if (!resolved) {\n console.error(\"[IframeModal] Failed to load iframe\");\n cleanupWithAnimation();\n resolve({ success: false, error: \"Failed to load verification page. Please try again.\" });\n }\n };\n\n container.appendChild(closeButton);\n container.appendChild(iframe);\n overlay.appendChild(container);\n document.body.appendChild(overlay);\n\n // Trigger fade-in animation\n requestAnimationFrame(() => {\n overlay.style.background = \"rgba(0, 0, 0, 0.5)\";\n container.style.opacity = \"1\";\n container.style.transform = \"scale(1) translateY(0)\";\n });\n\n // Cleanup with fade-out animation\n const cleanupWithAnimation = (): void => {\n if (resolved) return;\n resolved = true;\n\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"keydown\", handleKeydown);\n\n // Use requestAnimationFrame to ensure transition is applied\n requestAnimationFrame(() => {\n overlay.style.background = \"rgba(0, 0, 0, 0)\";\n container.style.opacity = \"0\";\n container.style.transform = \"scale(0.95) translateY(10px)\";\n\n setTimeout(() => {\n if (overlay.parentNode) {\n overlay.parentNode.removeChild(overlay);\n }\n }, 250);\n });\n };\n\n // Handle close button click\n const handleCancel = (): void => {\n if (!resolved) {\n console.log(\"[IframeModal] User cancelled\");\n cleanupWithAnimation();\n resolve({ success: false, error: \"Verification cancelled\" });\n }\n };\n\n closeButton.onclick = handleCancel;\n\n // Handle Escape key\n const handleKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n handleCancel();\n }\n // Trap focus within modal (Tab key cycles through close button and iframe)\n if (event.key === \"Tab\") {\n event.preventDefault();\n if (document.activeElement === closeButton) {\n iframe.focus();\n } else {\n closeButton.focus();\n }\n }\n };\n\n window.addEventListener(\"keydown\", handleKeydown);\n\n // Set initial focus to close button for accessibility\n closeButton.focus();\n\n const handleMessage = (event: MessageEvent): void => {\n const messageResult = onMessage(event);\n if (messageResult.handled) {\n cleanupWithAnimation();\n resolve(messageResult.result);\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n });\n}\n","/**\n * Next action handlers for processor-specific user actions (e.g., 3DS authentication).\n *\n * This module abstracts processor-specific logic away from the generic card payment flow.\n * Each handler implements the logic needed for a specific next action type.\n */\n\nimport type { PublicCardCheckoutResponse } from \"@pkg/sdk/models\";\nimport type { Stripe } from \"@stripe/stripe-js\";\nimport show3DSIframeModal from \"../utils/3ds-iframe-modal\";\n\n// Helper to wait for a condition\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n// Check if Stripe.js is loaded via script tag\nconst isStripeJsPresent = (): boolean => \"Stripe\" in window;\n\n/**\n * Get the Stripe instance from the global window object.\n * Expects Stripe.js to be loaded via HTML script tag.\n * Polls for up to 5 seconds waiting for Stripe to be available.\n */\nconst getLoadedStripe = async (publishableKey: string): Promise<Stripe> => {\n // Poll for Stripe.js to be loaded (up to 5 seconds)\n for (let i = 0; i < 10; i++) {\n if (isStripeJsPresent()) {\n break;\n }\n await sleep(500);\n }\n\n if (!isStripeJsPresent()) {\n throw new Error(\n \"Stripe.js not loaded. Add this script tag to your HTML <head>:\\n\" +\n '<script src=\"https://js.stripe.com/v3/\"></script>',\n );\n }\n\n // @ts-expect-error Stripe is loaded globally via script tag\n const stripe: Stripe = new window.Stripe(publishableKey);\n return stripe;\n};\n\n/**\n * Result of handling a next action.\n */\nexport type NextActionResult = { success: true } | { success: false; error: string };\n\n/**\n * Handle Stripe 3DS authentication.\n */\nconst handleStripe3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"stripe_3ds\" }>,\n): Promise<NextActionResult> => {\n const { clientSecret, stripePk } = nextAction;\n\n const stripe = await getLoadedStripe(stripePk);\n\n // Show 3DS modal\n const { error: stripeError } = await stripe.confirmCardPayment(clientSecret);\n\n if (stripeError) {\n console.error(\"[3DS:Stripe] Authentication failed:\", stripeError.message);\n return { success: false, error: stripeError.message || \"3DS authentication failed\" };\n }\n\n return { success: true };\n};\n\n/**\n * Handle Airwallex 3DS authentication via iframe.\n *\n * Renders an iframe with the 3DS authentication URL. The iframe will redirect\n * to the 3DS callback page which sends a postMessage back to complete the flow.\n */\nconst handleAirwallex3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"airwallex_3ds\" }>,\n): Promise<NextActionResult> => {\n return show3DSIframeModal({\n url: nextAction.url,\n size: { width: 605, height: 550 },\n onMessage: (event) => {\n if (event.data.type !== \"3ds_complete\") {\n return { handled: false };\n }\n\n const { isSuccess, error } = event.data;\n\n if (isSuccess) {\n return { handled: true, result: { success: true, data: {} } };\n } else {\n console.error(\"[3DS:Airwallex] Authentication failed:\", error);\n return {\n handled: true,\n result: { success: false, error: error || \"3DS authentication failed\" },\n };\n }\n },\n });\n};\n\n/**\n * Handle a next action based on its type.\n * Routes to the appropriate processor-specific handler.\n *\n * @param nextAction - The next action from the checkout response\n * @returns Result indicating success or failure with error message\n */\nexport const handleNextAction = async (\n nextAction: NonNullable<PublicCardCheckoutResponse[\"nextAction\"]>,\n): Promise<NextActionResult> => {\n switch (nextAction.type) {\n case \"stripe_3ds\":\n return handleStripe3ds(nextAction);\n case \"airwallex_3ds\":\n return handleAirwallex3ds(nextAction);\n default:\n // TypeScript will catch if we miss a case when new action types are added\n return { success: false, error: `Unknown next action type: ${(nextAction as { type: string }).type}` };\n }\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-B3mjYfOm.d.mts","names":[],"sources":["../src/analytics/checkout-timing.ts","../src/types.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-Dc6zwOe1.mjs","names":["ENV_TO_SLUG: Record<string, string>"],"sources":["../src/utils/checkout-request-id.ts","../src/utils/validate-form-fields.ts","../src/utils/index.ts"],"sourcesContent":["import { nanoid } from \"nanoid\";\n\n/**\n * Maps PaymentKit environment to request ID env slug.\n * This must match the backend's env slug format.\n */\nconst ENV_TO_SLUG: Record<string, string> = {\n local: \"dev\",\n tunnel: \"dev\",\n sandbox: \"stg\",\n production: \"prod\",\n};\n\n// Window key for storing the request ID across PaymentKit instantiations\nconst WINDOW_KEY = \"__paymentKitRequestId__\";\n\n/**\n * Generates a checkout request ID for correlating all API calls within a checkout session.\n *\n * Format: pk_{env}_{nanoid(12)}\n * - pk = PaymentKit.js (client-generated)\n * - env = dev, stg, or prod\n * - nanoid(12) = 12 character random string\n *\n * Example: pk_stg_a1b2c3d4e5f6\n */\nexport function generateCheckoutRequestId(environment: string): string {\n const envSlug = ENV_TO_SLUG[environment] || \"dev\";\n const randomPart = nanoid(12);\n return `pk_${envSlug}_${randomPart}`;\n}\n\n/**\n * Gets or creates a checkout request ID, storing it in window for idempotency.\n *\n * This ensures the same request ID is used across:\n * - Multiple PaymentKit instantiations on the same page\n * - All analytics events and API calls within a checkout session\n *\n * The ID is generated once on first call and reused thereafter.\n */\nexport function getOrCreateCheckoutRequestId(environment: string): string {\n if (typeof window !== \"undefined\" && window[WINDOW_KEY]) {\n return window[WINDOW_KEY] as string;\n }\n\n const requestId = generateCheckoutRequestId(environment);\n\n if (typeof window !== \"undefined\") {\n (window as Record<string, unknown>)[WINDOW_KEY] = requestId;\n }\n\n return requestId;\n}\n\n/**\n * Creates RequestOptions with the x-request-id header set.\n */\nexport function withRequestId(checkoutRequestId: string) {\n return {\n headers: {\n \"x-request-id\": checkoutRequestId,\n },\n };\n}\n","import * as v from \"valibot\";\nimport type { FormErrorCodes, PaymentKitErrors, PaymentKitFields } from \"../types\";\n\ntype Options = {\n optionalZipCode?: boolean;\n};\n\nexport const validateFormFields = async (fields: PaymentKitFields, options: Options = {}) => {\n const schema = v.object({\n customer_name: v.pipe(\n v.string(\"required\"),\n v.nonEmpty(\"required\"),\n v.minLength(4, \"invalid\"),\n v.maxLength(40, \"invalid\"),\n ),\n customer_email: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\"), v.email(\"invalid\")),\n customer_country: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n customer_zip_code: options.optionalZipCode\n ? v.pipe(v.string(\"required\"))\n : v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n });\n\n const result = v.safeParse(schema, fields);\n\n if (result.issues) {\n const errors = result.issues.reduce((errors, issue) => {\n const field = v.getDotPath(issue) as keyof PaymentKitErrors;\n\n errors[field] = issue.kind === \"schema\" ? \"required\" : (issue.message as FormErrorCodes);\n return errors;\n }, {} as PaymentKitErrors);\n return { isSuccess: false, errors };\n }\n\n return { isSuccess: true };\n};\n","import type { PaymentMethod } from \"../types\";\n\nexport { generateCheckoutRequestId, getOrCreateCheckoutRequestId, withRequestId } from \"./checkout-request-id\";\nexport { validateFormFields } from \"./validate-form-fields\";\n\nexport const $ = (selector: string) => {\n const ele = document.querySelector(selector);\n if (!ele) {\n throw new Error(`Cannot find element with selector: ${selector}`);\n }\n return ele;\n};\n\nexport const definePaymentMethod = <TExternalFuncs, TName extends string>(\n paymentMethod: PaymentMethod<TExternalFuncs, TName>,\n) => paymentMethod;\n\nexport const createCheckoutIFrame = (type: string, baseUrl: string, params?: Record<string, string>) => {\n const iframe = document.createElement(\"iframe\");\n\n const searchParams = new URLSearchParams(params);\n const searchParamsStr = searchParams.toString();\n\n iframe.src = `${baseUrl}/embeds/v1/${type}${searchParamsStr ? `?${searchParamsStr}` : \"\"}`;\n\n Object.assign(iframe.style, { width: \"100%\", height: \"100%\", border: \"none\" });\n\n return iframe;\n};\n\n/**\n * Collects browser and client information for fraud detection.\n */\nexport function collectFraudMetadata() {\n return {\n ipAddress: undefined, // IP address should be collected server-side\n browserInfo: {\n userAgent: navigator.userAgent,\n language: navigator.language,\n screenHeight: window.screen.height,\n screenWidth: window.screen.width,\n colorDepth: window.screen.colorDepth,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n },\n processorFraudInfo: undefined,\n };\n}\n\ntype AddressInput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zip_code?: string;\n country?: string;\n};\n\ntype AddressOutput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zipCode?: string;\n country?: string;\n};\n\n/**\n * Maps address fields from snake_case to camelCase format.\n */\nexport function mapAddress(address?: AddressInput): AddressOutput | undefined {\n if (!address) return undefined;\n\n return {\n line1: address.line1,\n line2: address.line2,\n city: address.city,\n state: address.state,\n zipCode: address.zip_code,\n country: address.country,\n };\n}\n"],"mappings":";;;;;;;;AAMA,MAAMA,cAAsC;CAC1C,OAAO;CACP,QAAQ;CACR,SAAS;CACT,YAAY;CACb;AAGD,MAAM,aAAa;;;;;;;;;;;AAYnB,SAAgB,0BAA0B,aAA6B;AAGrE,QAAO,MAFS,YAAY,gBAAgB,MAEvB,GADF,OAAO,GAAG;;;;;;;;;;;AAa/B,SAAgB,6BAA6B,aAA6B;AACxE,KAAI,OAAO,WAAW,eAAe,OAAO,YAC1C,QAAO,OAAO;CAGhB,MAAM,YAAY,0BAA0B,YAAY;AAExD,KAAI,OAAO,WAAW,YACpB,CAAC,OAAmC,cAAc;AAGpD,QAAO;;;;;AAMT,SAAgB,cAAc,mBAA2B;AACvD,QAAO,EACL,SAAS,EACP,gBAAgB,mBACjB,EACF;;;;;ACxDH,MAAa,qBAAqB,OAAO,QAA0B,UAAmB,EAAE,KAAK;CAC3F,MAAM,SAAS,EAAE,OAAO;EACtB,eAAe,EAAE,KACf,EAAE,OAAO,WAAW,EACpB,EAAE,SAAS,WAAW,EACtB,EAAE,UAAU,GAAG,UAAU,EACzB,EAAE,UAAU,IAAI,UAAU,CAC3B;EACD,gBAAgB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,UAAU,CAAC;EACxF,kBAAkB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACtE,mBAAmB,QAAQ,kBACvB,EAAE,KAAK,EAAE,OAAO,WAAW,CAAC,GAC5B,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACzD,CAAC;CAEF,MAAM,SAAS,EAAE,UAAU,QAAQ,OAAO;AAE1C,KAAI,OAAO,OAOT,QAAO;EAAE,WAAW;EAAO,QANZ,OAAO,OAAO,QAAQ,QAAQ,UAAU;GACrD,MAAM,QAAQ,EAAE,WAAW,MAAM;AAEjC,UAAO,SAAS,MAAM,SAAS,WAAW,aAAc,MAAM;AAC9D,UAAO;KACN,EAAE,CAAqB;EACS;AAGrC,QAAO,EAAE,WAAW,MAAM;;;;;AC7B5B,MAAa,KAAK,aAAqB;CACrC,MAAM,MAAM,SAAS,cAAc,SAAS;AAC5C,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,sCAAsC,WAAW;AAEnE,QAAO;;AAGT,MAAa,uBACX,kBACG;AAEL,MAAa,wBAAwB,MAAc,SAAiB,WAAoC;CACtG,MAAM,SAAS,SAAS,cAAc,SAAS;CAG/C,MAAM,kBADe,IAAI,gBAAgB,OAAO,CACX,UAAU;AAE/C,QAAO,MAAM,GAAG,QAAQ,aAAa,OAAO,kBAAkB,IAAI,oBAAoB;AAEtF,QAAO,OAAO,OAAO,OAAO;EAAE,OAAO;EAAQ,QAAQ;EAAQ,QAAQ;EAAQ,CAAC;AAE9E,QAAO;;;;;AAMT,SAAgB,uBAAuB;AACrC,QAAO;EACL,WAAW;EACX,aAAa;GACX,WAAW,UAAU;GACrB,UAAU,UAAU;GACpB,cAAc,OAAO,OAAO;GAC5B,aAAa,OAAO,OAAO;GAC3B,YAAY,OAAO,OAAO;GAC1B,UAAU,KAAK,gBAAgB,CAAC,iBAAiB,CAAC;GACnD;EACD,oBAAoB;EACrB"}
|