@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.
Files changed (46) hide show
  1. package/README.md +14 -0
  2. package/dist/{bnpl-shared-DGs1YzS9.mjs → bnpl-shared-CL900HFN.mjs} +2 -2
  3. package/dist/{bnpl-shared-DGs1YzS9.mjs.map → bnpl-shared-CL900HFN.mjs.map} +1 -1
  4. package/dist/{bnpl-shared-BQwCBD45.d.mts → bnpl-shared-D-Kd58Qz.d.mts} +2 -2
  5. package/dist/{bnpl-shared-BQwCBD45.d.mts.map → bnpl-shared-D-Kd58Qz.d.mts.map} +1 -1
  6. package/dist/cdn/paymentkit.js +263 -61
  7. package/dist/cdn/paymentkit.js.map +3 -3
  8. package/dist/cdn/paymentkit.min.js +24 -24
  9. package/dist/cdn/paymentkit.min.js.map +3 -3
  10. package/dist/index.d.mts +2 -2
  11. package/dist/index.d.mts.map +1 -1
  12. package/dist/index.mjs +75 -6
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/{next-action-handlers-CLOt1wzO.mjs → next-action-handlers-DzhzSvEB.mjs} +19 -19
  15. package/dist/next-action-handlers-DzhzSvEB.mjs.map +1 -0
  16. package/dist/payment-methods/affirm.d.mts +2 -2
  17. package/dist/payment-methods/affirm.mjs +2 -2
  18. package/dist/payment-methods/afterpay.d.mts +2 -2
  19. package/dist/payment-methods/afterpay.mjs +2 -2
  20. package/dist/payment-methods/apple-pay.d.mts +2 -2
  21. package/dist/payment-methods/apple-pay.d.mts.map +1 -1
  22. package/dist/payment-methods/apple-pay.mjs +2 -2
  23. package/dist/payment-methods/apple-pay.mjs.map +1 -1
  24. package/dist/payment-methods/bnpl-shared.d.mts +2 -2
  25. package/dist/payment-methods/bnpl-shared.mjs +2 -2
  26. package/dist/payment-methods/card.d.mts +1 -1
  27. package/dist/payment-methods/card.d.mts.map +1 -1
  28. package/dist/payment-methods/card.mjs +14 -8
  29. package/dist/payment-methods/card.mjs.map +1 -1
  30. package/dist/payment-methods/google-pay.d.mts +25 -3
  31. package/dist/payment-methods/google-pay.d.mts.map +1 -1
  32. package/dist/payment-methods/google-pay.mjs +131 -10
  33. package/dist/payment-methods/google-pay.mjs.map +1 -1
  34. package/dist/payment-methods/klarna.d.mts +2 -2
  35. package/dist/payment-methods/klarna.mjs +2 -2
  36. package/dist/payment-methods/next-action-handlers.mjs +1 -1
  37. package/dist/payment-methods/paypal.d.mts +1 -1
  38. package/dist/payment-methods/paypal.mjs +1 -1
  39. package/dist/{types-B3mjYfOm.d.mts → types-Cjcc3xak.d.mts} +6 -9
  40. package/dist/types-Cjcc3xak.d.mts.map +1 -0
  41. package/dist/{utils-Dc6zwOe1.mjs → utils-DIqrx4XF.mjs} +10 -7
  42. package/dist/utils-DIqrx4XF.mjs.map +1 -0
  43. package/package.json +2 -2
  44. package/dist/next-action-handlers-CLOt1wzO.mjs.map +0 -1
  45. package/dist/types-B3mjYfOm.d.mts.map +0 -1
  46. package/dist/utils-Dc6zwOe1.mjs.map +0 -1
package/README.md CHANGED
@@ -7,3 +7,17 @@ Vanilla JavaScript SDK for PaymentKit. A type-safe, framework-agnostic payment p
7
7
  For complete documentation, guides, and examples, visit:
8
8
 
9
9
  **[PaymentKit.js Documentation](https://docs.paymentkit.com/guides/integration/sdk-reference/payment-kit-js/getting-started)**
10
+
11
+ ## Content-Security-Policy Requirements
12
+
13
+ If your site uses a Content-Security-Policy header, you must add the following domains to your `script-src` directive to allow fraud prevention scripts:
14
+
15
+ - **Production:** `https://static.airwallex.com`
16
+ - **Sandbox:** `https://static-demo.airwallex.com`
17
+
18
+ Example:
19
+ ```
20
+ Content-Security-Policy: script-src 'self' https://static.airwallex.com;
21
+ ```
22
+
23
+ If these domains are blocked, PaymentKit.js will log an error to the console with the required domain.
@@ -1,4 +1,4 @@
1
- import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "./utils-Dc6zwOe1.mjs";
1
+ import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "./utils-DIqrx4XF.mjs";
2
2
 
3
3
  //#region src/payment-methods/bnpl-shared.ts
4
4
  const createSubmitPayment = (states, config) => {
@@ -104,4 +104,4 @@ function createBnplPaymentMethod(config) {
104
104
 
105
105
  //#endregion
106
106
  export { createBnplPaymentMethod as t };
107
- //# sourceMappingURL=bnpl-shared-DGs1YzS9.mjs.map
107
+ //# sourceMappingURL=bnpl-shared-CL900HFN.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"bnpl-shared-DGs1YzS9.mjs","names":["submitPayment: TInternalFuncs[\"submitPayment\"]","requestBody: BnplStartRequest","localStates: BnplStates"],"sources":["../src/payment-methods/bnpl-shared.ts"],"sourcesContent":["/**\n * Shared BNPL (Buy Now Pay Later) payment method factory.\n * Used by Klarna, Afterpay, and Affirm payment methods.\n */\n\nimport type { PaymentKitErrors, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport { collectFraudMetadata, definePaymentMethod, getOrCreateCheckoutRequestId } from \"../utils\";\n\nexport type BnplCustomerInfo = {\n first_name: string;\n last_name: string;\n email?: string;\n};\n\nexport type BnplStartRequest = {\n processor_id: string;\n customer_info: BnplCustomerInfo;\n fraud_metadata: {\n ipAddress?: string;\n browserInfo?: { [key: string]: unknown };\n processorFraudInfo?: { [key: string]: unknown };\n };\n setup_future_usage?: boolean;\n};\n\nexport type BnplStartResponse = {\n approval_url: string;\n popup_token: string;\n checkout_attempt_id: string;\n};\n\nexport type BnplStatusResponse = {\n completed: boolean;\n status: \"success\" | \"failed\" | \"cancelled\";\n result?: unknown;\n error?: string;\n};\n\nexport type BnplCheckoutResponse = {\n id: string;\n checkoutAttemptId: string;\n checkoutSessionId: string;\n state: string;\n customerId?: string;\n paymentMethodId?: string;\n processorUsed?: string;\n subscriptionId?: string;\n invoiceId?: string;\n invoiceNumber?: number;\n};\n\nexport type BnplSubmitOptions = {\n processorId: string;\n customerInfo: BnplCustomerInfo;\n setupFutureUsage?: boolean;\n};\n\ntype BnplStates = PaymentKitStates & {\n popup?: Window | null;\n pollInterval?: ReturnType<typeof setInterval>;\n};\n\nexport type BnplProviderConfig = {\n name: string;\n endpointPath: string;\n supportsSetupFutureUsage?: boolean;\n};\n\nconst createSubmitPayment = (states: BnplStates, config: BnplProviderConfig) => {\n const { name, endpointPath, supportsSetupFutureUsage } = config;\n const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);\n\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n const { apiBaseUrl, secureToken, environment } = states;\n const bnplOptions = options as BnplSubmitOptions;\n\n if (!bnplOptions?.processorId) {\n return { errors: { processor_id: \"Processor ID is required\" } as PaymentKitErrors };\n }\n\n if (!bnplOptions?.customerInfo?.first_name || !bnplOptions?.customerInfo?.last_name) {\n return {\n errors: {\n customer_name: \"Customer first and last name are required\",\n } as PaymentKitErrors,\n };\n }\n\n try {\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n\n const requestBody: BnplStartRequest = {\n processor_id: bnplOptions.processorId,\n customer_info: bnplOptions.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n };\n\n if (supportsSetupFutureUsage && bnplOptions.setupFutureUsage !== undefined) {\n requestBody.setup_future_usage = bnplOptions.setupFutureUsage;\n }\n\n const startResponse = await fetch(`${apiBaseUrl}/api/checkout/${secureToken}/stripe/${endpointPath}/start`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-request-id\": checkoutRequestId,\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!startResponse.ok) {\n let errorMessage = `Failed to start ${capitalizedName} checkout (${startResponse.status})`;\n try {\n const errorData = await startResponse.json();\n errorMessage = errorData.detail || errorMessage;\n } catch {\n errorMessage = startResponse.statusText || errorMessage;\n }\n return {\n errors: {\n [name]: errorMessage,\n } as PaymentKitErrors,\n };\n }\n\n const { approval_url, popup_token, checkout_attempt_id } = (await startResponse.json()) as BnplStartResponse;\n\n const popup = window.open(approval_url, capitalizedName, \"width=600,height=700\");\n\n if (!popup) {\n return {\n errors: {\n [name]: `Failed to open ${capitalizedName} popup. Please allow popups for this site.`,\n } as PaymentKitErrors,\n };\n }\n\n states.popup = popup;\n\n return new Promise((resolve) => {\n let popupClosedGracePolls = 0;\n const MAX_GRACE_POLLS = 5;\n\n const pollInterval = setInterval(async () => {\n try {\n const statusResponse = await fetch(\n `${apiBaseUrl}/api/checkout/${secureToken}/popup/status?popup_token=${popup_token}`,\n );\n\n if (!statusResponse.ok) {\n clearInterval(pollInterval);\n popup.close();\n resolve({\n errors: {\n [name]: `Failed to check ${capitalizedName} status`,\n } as PaymentKitErrors,\n });\n return;\n }\n\n const statusResult = (await statusResponse.json()) as BnplStatusResponse;\n\n if (statusResult.completed) {\n clearInterval(pollInterval);\n popup.close();\n\n if (statusResult.status === \"success\") {\n // Result is returned directly from popup status endpoint\n const result = statusResult.result || {\n id: checkout_attempt_id,\n checkoutAttemptId: checkout_attempt_id,\n checkoutSessionId: secureToken,\n state: \"checkout_succeeded\",\n };\n\n resolve({ data: result });\n } else {\n resolve({\n errors: {\n [name]: statusResult.error || `${capitalizedName} checkout ${statusResult.status}`,\n } as PaymentKitErrors,\n });\n }\n return;\n }\n\n if (popup.closed) {\n popupClosedGracePolls++;\n if (popupClosedGracePolls >= MAX_GRACE_POLLS) {\n clearInterval(pollInterval);\n resolve({\n errors: {\n [name]: `${capitalizedName} popup closed by user`,\n } as PaymentKitErrors,\n });\n }\n return;\n }\n } catch (error) {\n clearInterval(pollInterval);\n popup.close();\n resolve({\n errors: {\n [name]: `Polling error: ${error}`,\n } as PaymentKitErrors,\n });\n }\n }, 2000);\n\n states.pollInterval = pollInterval;\n });\n } catch (error) {\n return {\n errors: {\n [name]: `${capitalizedName} checkout error: ${error}`,\n } as PaymentKitErrors,\n };\n }\n };\n\n return submitPayment;\n};\n\nexport function createBnplPaymentMethod(config: BnplProviderConfig) {\n return definePaymentMethod((paymentKitStates) => {\n const localStates: BnplStates = { ...paymentKitStates };\n\n return {\n name: config.name,\n externalFuncs: {},\n internalFuncs: {\n submitPayment: createSubmitPayment(localStates, config),\n cleanup: () => {\n if (localStates.pollInterval) {\n clearInterval(localStates.pollInterval);\n }\n if (localStates.popup && !localStates.popup.closed) {\n localStates.popup.close();\n }\n },\n },\n };\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bnpl-shared-CL900HFN.mjs","names":["submitPayment: TInternalFuncs[\"submitPayment\"]","requestBody: BnplStartRequest","localStates: BnplStates"],"sources":["../src/payment-methods/bnpl-shared.ts"],"sourcesContent":["/**\n * Shared BNPL (Buy Now Pay Later) payment method factory.\n * Used by Klarna, Afterpay, and Affirm payment methods.\n */\n\nimport type { PaymentKitErrors, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport { collectFraudMetadata, definePaymentMethod, getOrCreateCheckoutRequestId } from \"../utils\";\n\nexport type BnplCustomerInfo = {\n first_name: string;\n last_name: string;\n email?: string;\n};\n\nexport type BnplStartRequest = {\n processor_id: string;\n customer_info: BnplCustomerInfo;\n fraud_metadata: {\n ipAddress?: string;\n browserInfo?: { [key: string]: unknown };\n processorFraudInfo?: { [key: string]: unknown };\n };\n setup_future_usage?: boolean;\n};\n\nexport type BnplStartResponse = {\n approval_url: string;\n popup_token: string;\n checkout_attempt_id: string;\n};\n\nexport type BnplStatusResponse = {\n completed: boolean;\n status: \"success\" | \"failed\" | \"cancelled\";\n result?: unknown;\n error?: string;\n};\n\nexport type BnplCheckoutResponse = {\n id: string;\n checkoutAttemptId: string;\n checkoutSessionId: string;\n state: string;\n customerId?: string;\n paymentMethodId?: string;\n processorUsed?: string;\n subscriptionId?: string;\n invoiceId?: string;\n invoiceNumber?: number;\n};\n\nexport type BnplSubmitOptions = {\n processorId: string;\n customerInfo: BnplCustomerInfo;\n setupFutureUsage?: boolean;\n};\n\ntype BnplStates = PaymentKitStates & {\n popup?: Window | null;\n pollInterval?: ReturnType<typeof setInterval>;\n};\n\nexport type BnplProviderConfig = {\n name: string;\n endpointPath: string;\n supportsSetupFutureUsage?: boolean;\n};\n\nconst createSubmitPayment = (states: BnplStates, config: BnplProviderConfig) => {\n const { name, endpointPath, supportsSetupFutureUsage } = config;\n const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);\n\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n const { apiBaseUrl, secureToken, environment } = states;\n const bnplOptions = options as BnplSubmitOptions;\n\n if (!bnplOptions?.processorId) {\n return { errors: { processor_id: \"Processor ID is required\" } as PaymentKitErrors };\n }\n\n if (!bnplOptions?.customerInfo?.first_name || !bnplOptions?.customerInfo?.last_name) {\n return {\n errors: {\n customer_name: \"Customer first and last name are required\",\n } as PaymentKitErrors,\n };\n }\n\n try {\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n\n const requestBody: BnplStartRequest = {\n processor_id: bnplOptions.processorId,\n customer_info: bnplOptions.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n };\n\n if (supportsSetupFutureUsage && bnplOptions.setupFutureUsage !== undefined) {\n requestBody.setup_future_usage = bnplOptions.setupFutureUsage;\n }\n\n const startResponse = await fetch(`${apiBaseUrl}/api/checkout/${secureToken}/stripe/${endpointPath}/start`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-request-id\": checkoutRequestId,\n },\n body: JSON.stringify(requestBody),\n });\n\n if (!startResponse.ok) {\n let errorMessage = `Failed to start ${capitalizedName} checkout (${startResponse.status})`;\n try {\n const errorData = await startResponse.json();\n errorMessage = errorData.detail || errorMessage;\n } catch {\n errorMessage = startResponse.statusText || errorMessage;\n }\n return {\n errors: {\n [name]: errorMessage,\n } as PaymentKitErrors,\n };\n }\n\n const { approval_url, popup_token, checkout_attempt_id } = (await startResponse.json()) as BnplStartResponse;\n\n const popup = window.open(approval_url, capitalizedName, \"width=600,height=700\");\n\n if (!popup) {\n return {\n errors: {\n [name]: `Failed to open ${capitalizedName} popup. Please allow popups for this site.`,\n } as PaymentKitErrors,\n };\n }\n\n states.popup = popup;\n\n return new Promise((resolve) => {\n let popupClosedGracePolls = 0;\n const MAX_GRACE_POLLS = 5;\n\n const pollInterval = setInterval(async () => {\n try {\n const statusResponse = await fetch(\n `${apiBaseUrl}/api/checkout/${secureToken}/popup/status?popup_token=${popup_token}`,\n );\n\n if (!statusResponse.ok) {\n clearInterval(pollInterval);\n popup.close();\n resolve({\n errors: {\n [name]: `Failed to check ${capitalizedName} status`,\n } as PaymentKitErrors,\n });\n return;\n }\n\n const statusResult = (await statusResponse.json()) as BnplStatusResponse;\n\n if (statusResult.completed) {\n clearInterval(pollInterval);\n popup.close();\n\n if (statusResult.status === \"success\") {\n // Result is returned directly from popup status endpoint\n const result = statusResult.result || {\n id: checkout_attempt_id,\n checkoutAttemptId: checkout_attempt_id,\n checkoutSessionId: secureToken,\n state: \"checkout_succeeded\",\n };\n\n resolve({ data: result });\n } else {\n resolve({\n errors: {\n [name]: statusResult.error || `${capitalizedName} checkout ${statusResult.status}`,\n } as PaymentKitErrors,\n });\n }\n return;\n }\n\n if (popup.closed) {\n popupClosedGracePolls++;\n if (popupClosedGracePolls >= MAX_GRACE_POLLS) {\n clearInterval(pollInterval);\n resolve({\n errors: {\n [name]: `${capitalizedName} popup closed by user`,\n } as PaymentKitErrors,\n });\n }\n return;\n }\n } catch (error) {\n clearInterval(pollInterval);\n popup.close();\n resolve({\n errors: {\n [name]: `Polling error: ${error}`,\n } as PaymentKitErrors,\n });\n }\n }, 2000);\n\n states.pollInterval = pollInterval;\n });\n } catch (error) {\n return {\n errors: {\n [name]: `${capitalizedName} checkout error: ${error}`,\n } as PaymentKitErrors,\n };\n }\n };\n\n return submitPayment;\n};\n\nexport function createBnplPaymentMethod(config: BnplProviderConfig) {\n return definePaymentMethod((paymentKitStates) => {\n const localStates: BnplStates = { ...paymentKitStates };\n\n return {\n name: config.name,\n externalFuncs: {},\n internalFuncs: {\n submitPayment: createSubmitPayment(localStates, config),\n cleanup: () => {\n if (localStates.pollInterval) {\n clearInterval(localStates.pollInterval);\n }\n if (localStates.popup && !localStates.popup.closed) {\n localStates.popup.close();\n }\n },\n },\n };\n });\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { r as PaymentMethod } from "./types-B3mjYfOm.mjs";
1
+ import { i as PaymentMethod } from "./types-Cjcc3xak.mjs";
2
2
 
3
3
  //#region src/payment-methods/bnpl-shared.d.ts
4
4
 
@@ -61,4 +61,4 @@ type BnplProviderConfig = {
61
61
  declare function createBnplPaymentMethod(config: BnplProviderConfig): PaymentMethod<{}, string>;
62
62
  //#endregion
63
63
  export { BnplStartResponse as a, createBnplPaymentMethod as c, BnplStartRequest as i, BnplCustomerInfo as n, BnplStatusResponse as o, BnplProviderConfig as r, BnplSubmitOptions as s, BnplCheckoutResponse as t };
64
- //# sourceMappingURL=bnpl-shared-BQwCBD45.d.mts.map
64
+ //# sourceMappingURL=bnpl-shared-D-Kd58Qz.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bnpl-shared-BQwCBD45.d.mts","names":[],"sources":["../src/payment-methods/bnpl-shared.ts"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAMY,KANA,gBAAA,GAMgB;EAWhB,UAAA,EAAA,MAAA;EAMA,SAAA,EAAA,MAAA;EAOA,KAAA,CAAA,EAAA,MAAA;AAaZ,CAAA;AAWY,KAhDA,gBAAA,GAgDkB;EAiKd,YAAA,EAAA,MAAA;iBA/MC;;;;;;;;;;;;KASL,iBAAA;;;;;KAMA,kBAAA;;;;;;KAOA,oBAAA;;;;;;;;;;;;KAaA,iBAAA;;gBAEI;;;KASJ,kBAAA;;;;;iBAiKI,uBAAA,SAAgC,qBAAkB"}
1
+ {"version":3,"file":"bnpl-shared-D-Kd58Qz.d.mts","names":[],"sources":["../src/payment-methods/bnpl-shared.ts"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAMY,KANA,gBAAA,GAMgB;EAWhB,UAAA,EAAA,MAAA;EAMA,SAAA,EAAA,MAAA;EAOA,KAAA,CAAA,EAAA,MAAA;AAaZ,CAAA;AAWY,KAhDA,gBAAA,GAgDkB;EAiKd,YAAA,EAAA,MAAA;iBA/MC;;;;;;;;;;;;KASL,iBAAA;;;;;KAMA,kBAAA;;;;;;KAOA,oBAAA;;;;;;;;;;;;KAaA,iBAAA;;gBAEI;;;KASJ,kBAAA;;;;;iBAiKI,uBAAA,SAAgC,qBAAkB"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PaymentKit.js v0.5.17
2
+ * PaymentKit.js v0.5.19
3
3
  * https://paymentkit.com
4
4
  *
5
5
  * @license MIT
@@ -42,7 +42,7 @@ var PaymentKit = (() => {
42
42
  });
43
43
 
44
44
  // package.json
45
- var version = "0.5.17";
45
+ var version = "0.5.19";
46
46
 
47
47
  // src/analytics/mock-adapter.ts
48
48
  var MockAnalyticsAdapter = class {
@@ -6049,6 +6049,10 @@ var PaymentKit = (() => {
6049
6049
  apiBaseUrl: "http://localhost:9000"
6050
6050
  },
6051
6051
  sandbox: {
6052
+ baseUrl: "https://app.paymentkit.com/customer",
6053
+ apiBaseUrl: "https://app.paymentkit.com"
6054
+ },
6055
+ staging: {
6052
6056
  baseUrl: "https://staging.paymentkit.com/customer",
6053
6057
  apiBaseUrl: "https://staging.paymentkit.com"
6054
6058
  },
@@ -6082,10 +6086,10 @@ var PaymentKit = (() => {
6082
6086
  if (environment === "tunnel") {
6083
6087
  return getTunnelUrls();
6084
6088
  }
6085
- const env = environment;
6086
- const urls = STATIC_ENVIRONMENT_URLS[env];
6089
+ const urls = STATIC_ENVIRONMENT_URLS[environment];
6087
6090
  if (!urls) {
6088
- throw new Error(`Invalid environment: ${environment}. Must be one of: local, tunnel, sandbox, production`);
6091
+ console.warn(`[PaymentKit] Invalid environment "${environment}", falling back to local`);
6092
+ return STATIC_ENVIRONMENT_URLS.local;
6089
6093
  }
6090
6094
  return urls;
6091
6095
  }
@@ -6107,22 +6111,22 @@ var PaymentKit = (() => {
6107
6111
  var ENV_TO_SLUG = {
6108
6112
  local: "dev",
6109
6113
  tunnel: "dev",
6110
- sandbox: "stg",
6114
+ sandbox: "prod",
6115
+ staging: "stg",
6111
6116
  production: "prod"
6112
6117
  };
6113
- var WINDOW_KEY = "__paymentKitRequestId__";
6114
6118
  function generateCheckoutRequestId(environment) {
6115
- const envSlug = ENV_TO_SLUG[environment] || "dev";
6119
+ const envSlug = ENV_TO_SLUG[environment] ?? "dev";
6116
6120
  const randomPart = nanoid(12);
6117
6121
  return `pk_${envSlug}_${randomPart}`;
6118
6122
  }
6119
6123
  function getOrCreateCheckoutRequestId(environment) {
6120
- if (typeof window !== "undefined" && window[WINDOW_KEY]) {
6121
- return window[WINDOW_KEY];
6124
+ if (typeof window !== "undefined" && window.__paymentKitRequestId__) {
6125
+ return window.__paymentKitRequestId__;
6122
6126
  }
6123
6127
  const requestId = generateCheckoutRequestId(environment);
6124
6128
  if (typeof window !== "undefined") {
6125
- window[WINDOW_KEY] = requestId;
6129
+ window.__paymentKitRequestId__ = requestId;
6126
6130
  }
6127
6131
  return requestId;
6128
6132
  }
@@ -6423,7 +6427,7 @@ var PaymentKit = (() => {
6423
6427
  }, {});
6424
6428
  return { isSuccess: false, errors };
6425
6429
  }
6426
- return { isSuccess: true };
6430
+ return { isSuccess: true, errors: {} };
6427
6431
  };
6428
6432
 
6429
6433
  // src/utils/index.ts
@@ -6460,6 +6464,18 @@ var PaymentKit = (() => {
6460
6464
  }
6461
6465
 
6462
6466
  // src/index.ts
6467
+ function appendScriptToDOM(script) {
6468
+ const target = document.body ?? document.head;
6469
+ target.appendChild(script);
6470
+ }
6471
+ function getFraudScriptId(url) {
6472
+ if (url.includes("airwallex.com")) {
6473
+ return "airwallex-fraud-api";
6474
+ }
6475
+ const urlObj = new URL(url);
6476
+ const hash = btoa(urlObj.origin + urlObj.pathname).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12);
6477
+ return `pk-fraud-script-${hash}`;
6478
+ }
6463
6479
  var createTunnelXConnection = (baseUrl, apiBaseUrl, token) => {
6464
6480
  const iframe = createCheckoutIFrame("tunnel-x", baseUrl, {
6465
6481
  checkout_token: token,
@@ -6468,14 +6484,17 @@ var PaymentKit = (() => {
6468
6484
  Object.assign(iframe.style, { width: "0", height: "0", position: "absolute", visibility: "hidden" });
6469
6485
  document.body.appendChild(iframe);
6470
6486
  const connection = connectToTunnelXIframe(iframe, {});
6487
+ let destroyed = false;
6471
6488
  const unmount = () => {
6489
+ if (destroyed) return;
6490
+ destroyed = true;
6472
6491
  connection.destroy();
6473
- document.body.removeChild(iframe);
6492
+ iframe.remove();
6474
6493
  };
6475
6494
  return { unmount, connection };
6476
6495
  };
6477
6496
  var PaymentKit = ({
6478
- environment,
6497
+ environment = "production",
6479
6498
  secureToken,
6480
6499
  paymentMethods,
6481
6500
  cardTokenizationMode,
@@ -6507,7 +6526,9 @@ var PaymentKit = (() => {
6507
6526
  cardTokenizationMode,
6508
6527
  vgsVaultId,
6509
6528
  vgsEnvironment,
6510
- _sessionConfigReady: void 0
6529
+ _sessionConfigReady: void 0,
6530
+ _fraudScriptIds: [],
6531
+ _fraudScriptsReady: void 0
6511
6532
  };
6512
6533
  if (cardTokenizationMode === void 0) {
6513
6534
  const sessionConfigUrl = `${apiBaseUrl}/api/checkout-sessions/token/${secureToken}`;
@@ -6538,6 +6559,48 @@ var PaymentKit = (() => {
6538
6559
  );
6539
6560
  paymentKitStates.cardTokenizationMode = "direct";
6540
6561
  }
6562
+ if (session?.fraud_script_urls?.length) {
6563
+ const loadPromises = [];
6564
+ session.fraud_script_urls.forEach((url) => {
6565
+ const scriptId = getFraudScriptId(url);
6566
+ if (document.getElementById(scriptId)) {
6567
+ console.log(`[PaymentKit] Fraud script already present: ${scriptId}`);
6568
+ loadPromises.push(Promise.resolve());
6569
+ return;
6570
+ }
6571
+ const script = document.createElement("script");
6572
+ script.type = "text/javascript";
6573
+ script.async = true;
6574
+ script.id = scriptId;
6575
+ script.src = url;
6576
+ script.dataset.orderSessionId = checkoutRequestId;
6577
+ const loadPromise2 = new Promise((resolve) => {
6578
+ script.onload = () => {
6579
+ console.log(`[PaymentKit] Fraud script loaded: ${scriptId}`);
6580
+ resolve();
6581
+ };
6582
+ script.onerror = () => {
6583
+ console.error(
6584
+ `[PaymentKit] Failed to load fraud prevention script. If using Content-Security-Policy, add to script-src: ${new URL(url).origin}`
6585
+ );
6586
+ resolve();
6587
+ };
6588
+ });
6589
+ loadPromises.push(loadPromise2);
6590
+ paymentKitStates._fraudScriptIds.push(scriptId);
6591
+ appendScriptToDOM(script);
6592
+ });
6593
+ paymentKitStates._fraudScriptsReady = Promise.all(loadPromises).then(() => {
6594
+ console.log(`[PaymentKit] All ${loadPromises.length} fraud fingerprinting script(s) ready`);
6595
+ });
6596
+ session.fraud_script_urls.forEach((url) => {
6597
+ const scriptId = getFraudScriptId(url);
6598
+ console.log(
6599
+ `[PaymentKit] Fraud script injected: id=${scriptId}, data-order-session-id=${checkoutRequestId}, src=${url}`
6600
+ );
6601
+ });
6602
+ console.log(`[PaymentKit] Injected ${session.fraud_script_urls.length} fraud fingerprinting script(s)`);
6603
+ }
6541
6604
  } else {
6542
6605
  console.log("[PaymentKit] Session response missing card_tokenization_mode \u2014 defaulting to direct mode");
6543
6606
  paymentKitStates.cardTokenizationMode = "direct";
@@ -6583,6 +6646,13 @@ var PaymentKit = (() => {
6583
6646
  });
6584
6647
  };
6585
6648
  const cleanup = () => {
6649
+ for (const scriptId of paymentKitStates._fraudScriptIds) {
6650
+ const script = document.getElementById(scriptId);
6651
+ if (script) {
6652
+ script.remove();
6653
+ }
6654
+ }
6655
+ paymentKitStates._fraudScriptIds = [];
6586
6656
  for (const pm of pmInstances) {
6587
6657
  if (pm.internalFuncs.cleanup) {
6588
6658
  pm.internalFuncs.cleanup();
@@ -7023,21 +7093,21 @@ var PaymentKit = (() => {
7023
7093
  closeButton.setAttribute("aria-label", "Cancel verification");
7024
7094
  closeButton.setAttribute("type", "button");
7025
7095
  closeButton.style.cssText = `
7026
- position: absolute;
7027
- top: -40px;
7028
- right: 0;
7029
- width: 32px;
7030
- height: 32px;
7031
- border: none;
7032
- background: white;
7033
- border-radius: 8px;
7034
- cursor: pointer;
7035
- display: flex;
7036
- align-items: center;
7037
- justify-content: center;
7038
- z-index: 10;
7039
- transition: background 0.15s ease;
7040
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
7096
+ position: absolute !important;
7097
+ top: 8px !important;
7098
+ right: 8px !important;
7099
+ width: 32px !important;
7100
+ height: 32px !important;
7101
+ border: none !important;
7102
+ background: white !important;
7103
+ border-radius: 8px !important;
7104
+ cursor: pointer !important;
7105
+ display: flex !important;
7106
+ align-items: center !important;
7107
+ justify-content: center !important;
7108
+ z-index: 10 !important;
7109
+ transition: background 0.15s ease !important;
7110
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15) !important;
7041
7111
  `;
7042
7112
  closeButton.innerHTML = `
7043
7113
  <svg width="12" height="12" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -7045,10 +7115,10 @@ var PaymentKit = (() => {
7045
7115
  </svg>
7046
7116
  `;
7047
7117
  closeButton.onmouseenter = () => {
7048
- closeButton.style.background = "#f5f5f5";
7118
+ closeButton.style.setProperty("background", "#f5f5f5", "important");
7049
7119
  };
7050
7120
  closeButton.onmouseleave = () => {
7051
- closeButton.style.background = "white";
7121
+ closeButton.style.setProperty("background", "white", "important");
7052
7122
  };
7053
7123
  const iframe = document.createElement("iframe");
7054
7124
  iframe.src = url;
@@ -7093,9 +7163,7 @@ var PaymentKit = (() => {
7093
7163
  container.style.opacity = "0";
7094
7164
  container.style.transform = "scale(0.95) translateY(10px)";
7095
7165
  setTimeout(() => {
7096
- if (overlay.parentNode) {
7097
- overlay.parentNode.removeChild(overlay);
7098
- }
7166
+ overlay.remove();
7099
7167
  }, 250);
7100
7168
  });
7101
7169
  };
@@ -7643,12 +7711,7 @@ var PaymentKit = (() => {
7643
7711
  console.log("[ApplePay] Airwallex prepared state:", preparedAirwallexState);
7644
7712
  return { success: true, applePay: true };
7645
7713
  }
7646
- const startResult = await callStripeStartEndpoint(
7647
- apiBaseUrl,
7648
- secureToken,
7649
- options,
7650
- checkoutRequestId
7651
- );
7714
+ const startResult = await callStripeStartEndpoint(apiBaseUrl, secureToken, options, checkoutRequestId);
7652
7715
  if (startResult.error || !startResult.data) {
7653
7716
  return { success: false, error: startResult.error || "Failed to start Apple Pay" };
7654
7717
  }
@@ -7981,12 +8044,7 @@ var PaymentKit = (() => {
7981
8044
  preparedAirwallexState = null;
7982
8045
  }
7983
8046
  }
7984
- const startResult = await callStripeStartEndpoint(
7985
- apiBaseUrl,
7986
- secureToken,
7987
- applePayOptions,
7988
- checkoutRequestId
7989
- );
8047
+ const startResult = await callStripeStartEndpoint(apiBaseUrl, secureToken, applePayOptions, checkoutRequestId);
7990
8048
  if (startResult.error || !startResult.data) {
7991
8049
  return { errors: { apple_pay: startResult.error || "Failed to start Apple Pay" } };
7992
8050
  }
@@ -8485,10 +8543,7 @@ var PaymentKit = (() => {
8485
8543
  cleanupDirect = () => {
8486
8544
  const connection = cardInputConnections[type];
8487
8545
  connection?.destroy();
8488
- try {
8489
- parent.removeChild(iframe);
8490
- } catch {
8491
- }
8546
+ iframe.remove();
8492
8547
  states.cardInputConnections[type] = void 0;
8493
8548
  };
8494
8549
  parent.appendChild(iframe);
@@ -8530,7 +8585,7 @@ var PaymentKit = (() => {
8530
8585
  const requestOptions = withRequestId(checkoutRequestId);
8531
8586
  const tunnelX = await TunnelXManager.createFromPenpalConnection(states.tunnelXConnection);
8532
8587
  const skipCustomerValidation = options?.skipCustomerValidation === true;
8533
- const validateFormResult = skipCustomerValidation ? { isSuccess: true } : await validateFormFields(fields);
8588
+ const validateFormResult = skipCustomerValidation ? { isSuccess: true, errors: {} } : await validateFormFields(fields);
8534
8589
  if (!isVgsMode) {
8535
8590
  const validateCardResult = await validateCardFields(states);
8536
8591
  if (!(validateCardResult.isSuccess && validateFormResult.isSuccess)) {
@@ -8576,13 +8631,19 @@ var PaymentKit = (() => {
8576
8631
  }
8577
8632
  console.log("Card setup intent is set \u2705", cardSetupIntent);
8578
8633
  console.log("Fields", fields);
8634
+ const fraudMetadata = {
8635
+ ...collectFraudMetadata(),
8636
+ processorFraudInfo: {
8637
+ airwallexDeviceId: states.checkoutRequestId
8638
+ }
8639
+ };
8579
8640
  let currentResult = await tunnelX.publicEndpoints.cardCheckout(
8580
8641
  {
8581
8642
  checkoutToken: states.secureToken,
8582
8643
  publicCardCheckoutRequest: {
8583
8644
  cardSetupIntentId: states.cardSetupIntentId,
8584
8645
  customerInfo: mapFieldsToCustomerInfo(fields),
8585
- fraudMetadata: collectFraudMetadata()
8646
+ fraudMetadata
8586
8647
  }
8587
8648
  },
8588
8649
  requestOptions
@@ -8805,6 +8866,12 @@ var PaymentKit = (() => {
8805
8866
  return { errors, isSuccess: false };
8806
8867
  }
8807
8868
  const { pan_alias, cvc_alias, exp_month, exp_year } = cardResult.data.attributes;
8869
+ if (!cvc_alias) {
8870
+ console.warn(
8871
+ `${logPrefix} VGS createCard response missing cvc_alias (303 dedup):`,
8872
+ JSON.stringify(cardResult.data.attributes)
8873
+ );
8874
+ }
8808
8875
  const fullYear = exp_year < 100 ? 2e3 + exp_year : exp_year;
8809
8876
  const formattedExp = `${String(exp_month).padStart(2, "0")}/${fullYear}`;
8810
8877
  const cmpCardId = cardResult.data.id;
@@ -8815,7 +8882,7 @@ var PaymentKit = (() => {
8815
8882
  updateCardSetupIntentReq: {
8816
8883
  cardPan: pan_alias,
8817
8884
  cardExp: formattedExp,
8818
- cardCvc: cvc_alias,
8885
+ ...cvc_alias ? { cardCvc: cvc_alias } : {},
8819
8886
  cmpCardId,
8820
8887
  fraudMetadata: collectFraudMetadata()
8821
8888
  }
@@ -9217,12 +9284,41 @@ var PaymentKit = (() => {
9217
9284
  }
9218
9285
  return { data: await response.json() };
9219
9286
  }
9220
- function validateOptions2(options) {
9221
- if (!options?.processorId) {
9287
+ function validateOptions2(options, autoPrepareConfig) {
9288
+ if (!options?.processorId && !autoPrepareConfig?.processorId) {
9222
9289
  return { processor_id: "Processor ID is required" };
9223
9290
  }
9224
9291
  return null;
9225
9292
  }
9293
+ async function checkGooglePayAvailability() {
9294
+ if (!window.google?.payments?.api?.PaymentsClient) {
9295
+ console.log("[GooglePay] Google Pay API not loaded");
9296
+ return false;
9297
+ }
9298
+ try {
9299
+ const client = new window.google.payments.api.PaymentsClient({
9300
+ environment: "TEST"
9301
+ });
9302
+ const request = {
9303
+ apiVersion: 2,
9304
+ apiVersionMinor: 0,
9305
+ allowedPaymentMethods: [
9306
+ {
9307
+ type: "CARD",
9308
+ parameters: {
9309
+ allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
9310
+ allowedCardNetworks: ["VISA", "MASTERCARD", "AMEX", "DISCOVER", "JCB"]
9311
+ }
9312
+ }
9313
+ ]
9314
+ };
9315
+ const response = await client.isReadyToPay(request);
9316
+ return response.result;
9317
+ } catch (error) {
9318
+ console.error("[GooglePay] availability check error:", error);
9319
+ return false;
9320
+ }
9321
+ }
9226
9322
  function getMockScenarioStr2(mockScenario) {
9227
9323
  return mockScenario && mockScenario !== "none" /* None */ ? mockScenario : void 0;
9228
9324
  }
@@ -9456,14 +9552,19 @@ var PaymentKit = (() => {
9456
9552
  }
9457
9553
  return toGooglePayResult(response, secureToken);
9458
9554
  }
9459
- var defSubmitPayment3 = (states) => {
9555
+ var defSubmitPayment3 = (states, getAutoPrepareConfig) => {
9460
9556
  const submitPayment = async (_fields, options) => {
9461
9557
  const { apiBaseUrl, secureToken, environment } = states;
9462
9558
  const gpayOptions = options;
9463
- const validationError = validateOptions2(gpayOptions);
9559
+ const autoPrepareConfig = getAutoPrepareConfig();
9560
+ const validationError = validateOptions2(gpayOptions, autoPrepareConfig);
9464
9561
  if (validationError) {
9465
9562
  return { errors: validationError };
9466
9563
  }
9564
+ const effectiveOptions = {
9565
+ ...gpayOptions,
9566
+ processorId: gpayOptions.processorId || autoPrepareConfig?.processorId || ""
9567
+ };
9467
9568
  try {
9468
9569
  const mockScenarioStr = getMockScenarioStr2(gpayOptions.mockScenario);
9469
9570
  const checkoutRequestId = getOrCreateCheckoutRequestId(environment);
@@ -9471,7 +9572,7 @@ var PaymentKit = (() => {
9471
9572
  const startResult = await callStartEndpoint(
9472
9573
  apiBaseUrl,
9473
9574
  secureToken,
9474
- gpayOptions,
9575
+ effectiveOptions,
9475
9576
  mockScenarioStr,
9476
9577
  checkoutRequestId
9477
9578
  );
@@ -9517,12 +9618,113 @@ var PaymentKit = (() => {
9517
9618
  return submitPayment;
9518
9619
  };
9519
9620
  var GooglePayPaymentMethod = definePaymentMethod((paymentKitStates) => {
9621
+ const { apiBaseUrl, secureToken, environment } = paymentKitStates;
9622
+ let autoPrepareConfig = null;
9623
+ let onGooglePayReadyCallbacks = [];
9624
+ let isGooglePayReadyState = false;
9625
+ let autoPrepareInProgress = false;
9626
+ let cleanupGeneration = 0;
9627
+ let pendingAutoPrepareArgs = null;
9628
+ let pendingPrepareResolvers = [];
9629
+ function instanceSetGooglePayReady(ready) {
9630
+ isGooglePayReadyState = ready;
9631
+ for (const cb of onGooglePayReadyCallbacks) cb(ready);
9632
+ }
9633
+ function instanceClearPreparedGooglePay() {
9634
+ instanceSetGooglePayReady(false);
9635
+ }
9636
+ async function instanceAutoPrepare(apBase, sToken, env) {
9637
+ if (autoPrepareInProgress) {
9638
+ pendingAutoPrepareArgs = { apiBaseUrl: apBase, secureToken: sToken, environment: env };
9639
+ return new Promise((resolve) => pendingPrepareResolvers.push(resolve));
9640
+ }
9641
+ autoPrepareInProgress = true;
9642
+ const capturedGeneration = cleanupGeneration;
9643
+ instanceSetGooglePayReady(false);
9644
+ try {
9645
+ const result = await apiCall2(`${apBase}/api/checkout-sessions/token/${sToken}`, {
9646
+ method: "GET"
9647
+ });
9648
+ if (cleanupGeneration !== capturedGeneration) return;
9649
+ if (result.error || !result.data) {
9650
+ console.warn("[GooglePay] Auto-prepare: failed to fetch session config:", result.error);
9651
+ return;
9652
+ }
9653
+ const processorId = result.data.express_checkout_processor_id;
9654
+ if (!processorId) {
9655
+ console.log("[GooglePay] Auto-prepare: no express checkout processor configured");
9656
+ return;
9657
+ }
9658
+ const processorTypeRaw = result.data.express_checkout_processor_type;
9659
+ const processorType = processorTypeRaw === "airwallex" || processorTypeRaw === "stripe" ? processorTypeRaw : void 0;
9660
+ autoPrepareConfig = { processorId, processorType };
9661
+ const isAvailable = await checkGooglePayAvailability();
9662
+ if (cleanupGeneration !== capturedGeneration) return;
9663
+ instanceSetGooglePayReady(isAvailable);
9664
+ } catch (err) {
9665
+ if (cleanupGeneration === capturedGeneration) {
9666
+ console.error("[GooglePay] Auto-prepare failed:", err);
9667
+ }
9668
+ } finally {
9669
+ autoPrepareInProgress = false;
9670
+ const stale = cleanupGeneration !== capturedGeneration;
9671
+ const pending = pendingAutoPrepareArgs;
9672
+ const resolvers = pendingPrepareResolvers.splice(0);
9673
+ if (!stale && pending) {
9674
+ pendingAutoPrepareArgs = null;
9675
+ instanceAutoPrepare(pending.apiBaseUrl, pending.secureToken, pending.environment).then(() => {
9676
+ for (const r2 of resolvers) r2();
9677
+ });
9678
+ } else {
9679
+ pendingAutoPrepareArgs = null;
9680
+ for (const r2 of resolvers) r2();
9681
+ }
9682
+ }
9683
+ }
9684
+ instanceAutoPrepare(apiBaseUrl, secureToken, environment).catch(
9685
+ (err) => console.error("[GooglePay] Unhandled init error:", err)
9686
+ );
9520
9687
  return {
9521
9688
  name: "google_pay",
9522
- externalFuncs: {},
9689
+ externalFuncs: {
9690
+ /**
9691
+ * Register a callback to be notified when Google Pay becomes ready (or stops being ready).
9692
+ * Fires immediately with the current state, then on every state change.
9693
+ * Multiple registrations are all notified — none are silently overwritten.
9694
+ *
9695
+ * @example
9696
+ * paymentKit.google_pay.onGooglePayReady((isReady) => {
9697
+ * googlePayButton.disabled = !isReady;
9698
+ * });
9699
+ */
9700
+ onGooglePayReady: (callback) => {
9701
+ onGooglePayReadyCallbacks.push(callback);
9702
+ callback(isGooglePayReadyState);
9703
+ },
9704
+ /**
9705
+ * Notify the SDK that the payment amount has changed (e.g. coupon applied).
9706
+ * The SDK will disable Google Pay, re-prepare with the new amount, then re-enable.
9707
+ * The returned promise resolves when re-prepare is fully complete.
9708
+ *
9709
+ * @example
9710
+ * await paymentKit.google_pay.notifyAmountChanged();
9711
+ */
9712
+ notifyAmountChanged: () => {
9713
+ instanceClearPreparedGooglePay();
9714
+ autoPrepareConfig = null;
9715
+ return instanceAutoPrepare(apiBaseUrl, secureToken, environment);
9716
+ }
9717
+ },
9523
9718
  internalFuncs: {
9524
- submitPayment: defSubmitPayment3(paymentKitStates),
9719
+ submitPayment: defSubmitPayment3(paymentKitStates, () => autoPrepareConfig),
9525
9720
  cleanup: () => {
9721
+ cleanupGeneration++;
9722
+ onGooglePayReadyCallbacks = [];
9723
+ isGooglePayReadyState = false;
9724
+ autoPrepareConfig = null;
9725
+ pendingAutoPrepareArgs = null;
9726
+ pendingPrepareResolvers = [];
9727
+ autoPrepareInProgress = false;
9526
9728
  }
9527
9729
  }
9528
9730
  };