@payment-kit-js/vanilla 0.4.0-alpha.0 → 0.5.1

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 (79) hide show
  1. package/README.md +1 -61
  2. package/dist/airwallex-apple-pay-adapter-BE15xREr.mjs +237 -0
  3. package/dist/airwallex-apple-pay-adapter-BE15xREr.mjs.map +1 -0
  4. package/dist/airwallex-apple-pay-adapter-I_pnNYdy.d.mts +98 -0
  5. package/dist/airwallex-apple-pay-adapter-I_pnNYdy.d.mts.map +1 -0
  6. package/dist/airwallex-google-pay-adapter-CHol_8f2.mjs +167 -0
  7. package/dist/airwallex-google-pay-adapter-CHol_8f2.mjs.map +1 -0
  8. package/dist/airwallex-google-pay-adapter-CY379Rre.d.mts +140 -0
  9. package/dist/airwallex-google-pay-adapter-CY379Rre.d.mts.map +1 -0
  10. package/dist/cdn/paymentkit.js +7989 -0
  11. package/dist/cdn/paymentkit.js.map +7 -0
  12. package/dist/cdn/paymentkit.min.js +65 -0
  13. package/dist/cdn/paymentkit.min.js.map +7 -0
  14. package/dist/{connect-card-DO2EJxu6.mjs → connect-card-CMZkeppE.mjs} +1 -1
  15. package/dist/{connect-card-DO2EJxu6.mjs.map → connect-card-CMZkeppE.mjs.map} +1 -1
  16. package/dist/{connect-card-C582hcWw.d.mts → connect-card-Cxy51W6t.d.mts} +1 -1
  17. package/dist/{connect-card-C582hcWw.d.mts.map → connect-card-Cxy51W6t.d.mts.map} +1 -1
  18. package/dist/connect-tunnel-x-BhVAej5Q.mjs.map +1 -1
  19. package/dist/{connect-tunnel-x-rLA6I_EO.d.mts → connect-tunnel-x-lv6Wtdme.d.mts} +23 -3
  20. package/dist/connect-tunnel-x-lv6Wtdme.d.mts.map +1 -0
  21. package/dist/index.d.mts +3 -3
  22. package/dist/index.d.mts.map +1 -1
  23. package/dist/index.mjs +385 -7
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/next-action-handlers-CTx8tRt0.mjs +271 -0
  26. package/dist/next-action-handlers-CTx8tRt0.mjs.map +1 -0
  27. package/dist/payment-methods/airwallex-apple-pay-adapter.d.mts +2 -0
  28. package/dist/payment-methods/airwallex-apple-pay-adapter.mjs +3 -0
  29. package/dist/payment-methods/airwallex-google-pay-adapter.d.mts +2 -0
  30. package/dist/payment-methods/airwallex-google-pay-adapter.mjs +3 -0
  31. package/dist/payment-methods/apple-pay.d.mts +98 -0
  32. package/dist/payment-methods/apple-pay.d.mts.map +1 -0
  33. package/dist/payment-methods/apple-pay.mjs +354 -0
  34. package/dist/payment-methods/apple-pay.mjs.map +1 -0
  35. package/dist/payment-methods/card.d.mts +3 -3
  36. package/dist/payment-methods/card.d.mts.map +1 -1
  37. package/dist/payment-methods/card.mjs +222 -38
  38. package/dist/payment-methods/card.mjs.map +1 -1
  39. package/dist/payment-methods/google-pay.d.mts +25 -7
  40. package/dist/payment-methods/google-pay.d.mts.map +1 -1
  41. package/dist/payment-methods/google-pay.mjs +165 -31
  42. package/dist/payment-methods/google-pay.mjs.map +1 -1
  43. package/dist/payment-methods/next-action-handlers.d.mts.map +1 -1
  44. package/dist/payment-methods/next-action-handlers.mjs +1 -1
  45. package/dist/payment-methods/paypal.d.mts +3 -3
  46. package/dist/payment-methods/paypal.d.mts.map +1 -1
  47. package/dist/payment-methods/paypal.mjs +8 -3
  48. package/dist/payment-methods/paypal.mjs.map +1 -1
  49. package/dist/payment-methods/stripe-apple-pay-adapter.d.mts +2 -0
  50. package/dist/payment-methods/stripe-apple-pay-adapter.mjs +3 -0
  51. package/dist/payment-methods/stripe-google-pay-adapter.d.mts +1 -1
  52. package/dist/payment-methods/stripe-google-pay-adapter.mjs +1 -1
  53. package/dist/payment-methods/vgs-collect-loader.d.mts +28 -0
  54. package/dist/payment-methods/vgs-collect-loader.d.mts.map +1 -0
  55. package/dist/payment-methods/vgs-collect-loader.mjs +3 -0
  56. package/dist/penpal/connect-card.d.mts +1 -1
  57. package/dist/penpal/connect-card.mjs +1 -1
  58. package/dist/penpal/connect-tunnel-x.d.mts +1 -1
  59. package/dist/stripe-apple-pay-adapter-Cd9LVNnp.mjs +313 -0
  60. package/dist/stripe-apple-pay-adapter-Cd9LVNnp.mjs.map +1 -0
  61. package/dist/stripe-apple-pay-adapter-DhpGclW9.d.mts +141 -0
  62. package/dist/stripe-apple-pay-adapter-DhpGclW9.d.mts.map +1 -0
  63. package/dist/{stripe-google-pay-adapter-DUUB46SG.d.mts → stripe-google-pay-adapter-C3NCBSO3.d.mts} +1 -1
  64. package/dist/{stripe-google-pay-adapter-DUUB46SG.d.mts.map → stripe-google-pay-adapter-C3NCBSO3.d.mts.map} +1 -1
  65. package/dist/{stripe-google-pay-adapter-DMDArVp2.mjs → stripe-google-pay-adapter-CqcUEoM3.mjs} +1 -1
  66. package/dist/{stripe-google-pay-adapter-DMDArVp2.mjs.map → stripe-google-pay-adapter-CqcUEoM3.mjs.map} +1 -1
  67. package/dist/types-CZk3V0Qt.d.mts +147 -0
  68. package/dist/types-CZk3V0Qt.d.mts.map +1 -0
  69. package/dist/{utils-h0dxplHy.mjs → utils-B70Y8YcZ.mjs} +51 -2
  70. package/dist/utils-B70Y8YcZ.mjs.map +1 -0
  71. package/dist/vgs-collect-loader-DVYzFDwC.mjs +84 -0
  72. package/dist/vgs-collect-loader-DVYzFDwC.mjs.map +1 -0
  73. package/package.json +17 -5
  74. package/dist/connect-tunnel-x-rLA6I_EO.d.mts.map +0 -1
  75. package/dist/next-action-handlers-DTsWjUIA.mjs +0 -53
  76. package/dist/next-action-handlers-DTsWjUIA.mjs.map +0 -1
  77. package/dist/types-WgbMhIYb.d.mts +0 -64
  78. package/dist/types-WgbMhIYb.d.mts.map +0 -1
  79. package/dist/utils-h0dxplHy.mjs.map +0 -1
@@ -0,0 +1,147 @@
1
+ import { t as CardErrorCode } from "./connect-card-Cxy51W6t.mjs";
2
+ import { t as TunnelXIFrameConnection } from "./connect-tunnel-x-lv6Wtdme.mjs";
3
+
4
+ //#region src/analytics/checkout-timing.d.ts
5
+
6
+ /**
7
+ * Tracks timing metrics throughout the checkout flow.
8
+ *
9
+ * Create one instance per checkout session and call the track methods
10
+ * at appropriate points in the checkout flow.
11
+ *
12
+ * Usage:
13
+ * const requestId = getOrCreateCheckoutRequestId(environment);
14
+ * const tracker = new CheckoutTimingTracker(secureToken, requestId);
15
+ * tracker.trackPageReady();
16
+ * // ... iframe loads ...
17
+ * tracker.trackInputReady();
18
+ * // ... user submits ...
19
+ * tracker.trackSubmit();
20
+ * // ... API response ...
21
+ * tracker.trackSuccess(attemptId);
22
+ */
23
+ declare class CheckoutTimingTracker {
24
+ private static pageReadyTracked;
25
+ private startTime;
26
+ private checkoutSessionId;
27
+ private requestId;
28
+ private inputReadyTracked;
29
+ constructor(checkoutSessionId: string, requestId: string);
30
+ /**
31
+ * Track when SDK is initialized and ready.
32
+ * Call immediately after PaymentKit() initialization.
33
+ * Only tracks once per page load (subsequent calls are no-ops).
34
+ */
35
+ trackPageReady(): void;
36
+ /**
37
+ * Track when card input iframe is loaded and ready for input.
38
+ * Should only be called once (for first iframe, typically card_pan).
39
+ * Subsequent calls are no-ops.
40
+ */
41
+ trackInputReady(): void;
42
+ /**
43
+ * Track when user clicks submit button.
44
+ */
45
+ trackSubmit(): void;
46
+ /**
47
+ * Track successful checkout.
48
+ *
49
+ * @param checkoutAttemptId - The checkout attempt ID
50
+ */
51
+ trackSuccess(checkoutAttemptId: string): void;
52
+ /**
53
+ * Track failed checkout.
54
+ *
55
+ * @param checkoutAttemptId - The checkout attempt ID (may be null if failed early)
56
+ * @param errorCode - The error code from the checkout response
57
+ * @param errorMessage - The customer-facing error message
58
+ */
59
+ trackFail(checkoutAttemptId: string | null, errorCode: string | null, errorMessage: string | null): void;
60
+ /**
61
+ * Get elapsed time in milliseconds since tracker creation.
62
+ */
63
+ private getElapsedMs;
64
+ }
65
+ //#endregion
66
+ //#region src/types.d.ts
67
+
68
+ type FormFieldNames = "customer_name" | "customer_email" | "customer_country" | "customer_zip_code";
69
+ type FormErrorCodes = "required" | "invalid";
70
+ type TInternalFuncs = {
71
+ submitPayment: (fields: PaymentKitFields, options?: unknown) => Promise<{
72
+ data: {
73
+ [key: string]: unknown;
74
+ };
75
+ errors?: never;
76
+ } | {
77
+ data?: never;
78
+ errors: PaymentKitErrors;
79
+ }>;
80
+ cleanup?: () => void;
81
+ };
82
+ type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {
83
+ environment: string;
84
+ secureToken: string;
85
+ paymentMethods: T;
86
+ /** Card tokenization mode from checkout session */
87
+ cardTokenizationMode?: "direct" | "vgs";
88
+ /** VGS vault ID from checkout session */
89
+ vgsVaultId?: string;
90
+ /** VGS environment from checkout session */
91
+ vgsEnvironment?: string;
92
+ /** @internal Enable analytics test mode for e2e testing */
93
+ __enableAnalyticsTestMode?: boolean;
94
+ }) => ExternalFuncsMapByPm<T> & {
95
+ submit: PaymentKitSubmitHandler<T>;
96
+ cleanup: () => void;
97
+ };
98
+ type PaymentKitSubmitHandler<T extends readonly PaymentMethod<unknown>[]> = <N extends keyof ExternalFuncsMapByPm<T>>(options: {
99
+ fields: Partial<PaymentKitFields>;
100
+ paymentMethod: N;
101
+ options?: unknown;
102
+ onError: (error: PaymentKitErrors) => void;
103
+ onSuccess: (data: {
104
+ [key: string]: unknown;
105
+ }) => void;
106
+ }) => void;
107
+ type PaymentKitStates = {
108
+ baseUrl: string;
109
+ apiBaseUrl: string;
110
+ secureToken: string;
111
+ environment: string;
112
+ tunnelXConnection: TunnelXIFrameConnection;
113
+ timingTracker: CheckoutTimingTracker;
114
+ /** Checkout request ID for correlating all API calls and analytics events */
115
+ checkoutRequestId: string;
116
+ /** Card tokenization mode: 'direct' (KMS) or 'vgs' (VGS Collect + proxy) */
117
+ cardTokenizationMode?: "direct" | "vgs";
118
+ /** VGS vault ID (only when cardTokenizationMode is 'vgs') */
119
+ vgsVaultId?: string;
120
+ /** VGS environment: 'sandbox' or 'live' (only when cardTokenizationMode is 'vgs') */
121
+ vgsEnvironment?: string;
122
+ /** @internal Promise that resolves when session config (incl. VGS mode) is auto-detected */
123
+ _sessionConfigReady?: Promise<void>;
124
+ };
125
+ type PaymentKitErrors = {
126
+ root?: string;
127
+ card_pan?: CardErrorCode;
128
+ card_exp?: CardErrorCode;
129
+ card_cvc?: CardErrorCode;
130
+ paypal?: string;
131
+ google_pay?: string;
132
+ apple_pay?: string;
133
+ processor_id?: string;
134
+ amount?: string;
135
+ currency?: string;
136
+ country?: string;
137
+ } & { [key in FormFieldNames]?: FormErrorCodes | string };
138
+ type PaymentKitFields = { [key in FormFieldNames]: string };
139
+ type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates: PaymentKitStates) => {
140
+ name: TName;
141
+ externalFuncs: TExternalFuncs;
142
+ internalFuncs: TInternalFuncs;
143
+ };
144
+ type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = { [K in T[number] as ReturnType<K>["name"]]: ReturnType<K>["externalFuncs"] };
145
+ //#endregion
146
+ export { PaymentKitFields as n, PaymentMethod as r, PaymentKit as t };
147
+ //# sourceMappingURL=types-CZk3V0Qt.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-CZk3V0Qt.d.mts","names":[],"sources":["../src/analytics/checkout-timing.ts","../src/types.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,5 +1,54 @@
1
+ import { nanoid } from "nanoid";
1
2
  import * as v from "valibot";
2
3
 
4
+ //#region src/utils/checkout-request-id.ts
5
+ /**
6
+ * Maps PaymentKit environment to request ID env slug.
7
+ * This must match the backend's env slug format.
8
+ */
9
+ const ENV_TO_SLUG = {
10
+ local: "dev",
11
+ tunnel: "dev",
12
+ sandbox: "stg",
13
+ production: "prod"
14
+ };
15
+ const WINDOW_KEY = "__paymentKitRequestId__";
16
+ /**
17
+ * Generates a checkout request ID for correlating all API calls within a checkout session.
18
+ *
19
+ * Format: pk_{env}_{nanoid(12)}
20
+ * - pk = PaymentKit.js (client-generated)
21
+ * - env = dev, stg, or prod
22
+ * - nanoid(12) = 12 character random string
23
+ *
24
+ * Example: pk_stg_a1b2c3d4e5f6
25
+ */
26
+ function generateCheckoutRequestId(environment) {
27
+ return `pk_${ENV_TO_SLUG[environment] || "dev"}_${nanoid(12)}`;
28
+ }
29
+ /**
30
+ * Gets or creates a checkout request ID, storing it in window for idempotency.
31
+ *
32
+ * This ensures the same request ID is used across:
33
+ * - Multiple PaymentKit instantiations on the same page
34
+ * - All analytics events and API calls within a checkout session
35
+ *
36
+ * The ID is generated once on first call and reused thereafter.
37
+ */
38
+ function getOrCreateCheckoutRequestId(environment) {
39
+ if (typeof window !== "undefined" && window[WINDOW_KEY]) return window[WINDOW_KEY];
40
+ const requestId = generateCheckoutRequestId(environment);
41
+ if (typeof window !== "undefined") window[WINDOW_KEY] = requestId;
42
+ return requestId;
43
+ }
44
+ /**
45
+ * Creates RequestOptions with the x-request-id header set.
46
+ */
47
+ function withRequestId(checkoutRequestId) {
48
+ return { headers: { "x-request-id": checkoutRequestId } };
49
+ }
50
+
51
+ //#endregion
3
52
  //#region src/utils/validate-form-fields.ts
4
53
  const validateFormFields = async (fields, options = {}) => {
5
54
  const schema = v.object({
@@ -58,5 +107,5 @@ function collectFraudMetadata() {
58
107
  }
59
108
 
60
109
  //#endregion
61
- export { validateFormFields as a, definePaymentMethod as i, collectFraudMetadata as n, createCheckoutIFrame as r, $ as t };
62
- //# sourceMappingURL=utils-h0dxplHy.mjs.map
110
+ export { validateFormFields as a, definePaymentMethod as i, collectFraudMetadata as n, getOrCreateCheckoutRequestId as o, createCheckoutIFrame as r, withRequestId as s, $ as t };
111
+ //# sourceMappingURL=utils-B70Y8YcZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-B70Y8YcZ.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"}
@@ -0,0 +1,84 @@
1
+ //#region src/payment-methods/vgs-collect-loader.ts
2
+ const VGS_COLLECT_CDN = "https://js.verygoodvault.com/vgs-collect/3.2.1/vgs-collect.js";
3
+ let loadPromise = null;
4
+ /**
5
+ * Loads VGS Collect JS from CDN. Idempotent — subsequent calls return the same promise.
6
+ */
7
+ function loadVgsCollectScript() {
8
+ if (loadPromise) return loadPromise;
9
+ loadPromise = new Promise((resolve, reject) => {
10
+ if (typeof window !== "undefined" && window.VGSCollect) {
11
+ resolve();
12
+ return;
13
+ }
14
+ const script = document.createElement("script");
15
+ script.src = VGS_COLLECT_CDN;
16
+ script.async = true;
17
+ script.onload = () => resolve();
18
+ script.onerror = () => {
19
+ loadPromise = null;
20
+ reject(/* @__PURE__ */ new Error("Failed to load VGS Collect JS"));
21
+ };
22
+ document.head.appendChild(script);
23
+ });
24
+ return loadPromise;
25
+ }
26
+ /**
27
+ * Initializes a VGS Collect form instance.
28
+ */
29
+ function initVgsCollect(vaultId, environment) {
30
+ if (!window.VGSCollect) throw new Error("VGS Collect JS not loaded. Call loadVgsCollectScript() first.");
31
+ return window.VGSCollect.create(vaultId, environment, () => {});
32
+ }
33
+ /**
34
+ * Creates and mounts VGS Collect card fields using CMP-specific field methods.
35
+ *
36
+ * Uses cardNumberField(), cardExpirationDateField(), cardCVCField() which are
37
+ * required for the CMP createCard() flow. After mounting, call form.createCard()
38
+ * to create a card in the VGS vault, which returns aliases for PAN and CVC.
39
+ *
40
+ * @param form - VGS Collect form instance
41
+ * @param mountPoints - CSS selectors for PAN, expiry, and CVC containers
42
+ * @param css - Optional CSS to apply to VGS Collect iframe fields
43
+ */
44
+ function createVgsCardFields(form, mountPoints, css, onFocusChangeCallbacks) {
45
+ const fieldCss = css ?? {
46
+ height: "46px",
47
+ "font-size": "1rem",
48
+ color: "#18181b",
49
+ "font-family": "ui-sans-serif, system-ui, sans-serif"
50
+ };
51
+ const panField = form.cardNumberField(mountPoints.pan, {
52
+ placeholder: "Card number",
53
+ validations: ["required", "validCardNumber"],
54
+ css: fieldCss
55
+ });
56
+ const expField = form.cardExpirationDateField(mountPoints.exp, {
57
+ placeholder: "MM / YY",
58
+ validations: ["required", "validCardExpirationDate"],
59
+ css: fieldCss
60
+ });
61
+ const cvcField = form.cardCVCField(mountPoints.cvc, {
62
+ placeholder: "123",
63
+ validations: ["required", "validCardSecurityCode"],
64
+ css: fieldCss
65
+ });
66
+ if (onFocusChangeCallbacks) {
67
+ const fieldMap = [
68
+ [panField, "card_pan"],
69
+ [expField, "card_exp"],
70
+ [cvcField, "card_cvc"]
71
+ ];
72
+ for (const [field, key] of fieldMap) {
73
+ const cb = onFocusChangeCallbacks[key];
74
+ if (cb) {
75
+ field.on("focus", () => cb(true));
76
+ field.on("blur", () => cb(false));
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ //#endregion
83
+ export { initVgsCollect as n, loadVgsCollectScript as r, createVgsCardFields as t };
84
+ //# sourceMappingURL=vgs-collect-loader-DVYzFDwC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vgs-collect-loader-DVYzFDwC.mjs","names":["loadPromise: Promise<void> | null","fieldMap: [VGSCollectField, string][]"],"sources":["../src/payment-methods/vgs-collect-loader.ts"],"sourcesContent":["const VGS_COLLECT_CDN = \"https://js.verygoodvault.com/vgs-collect/3.2.1/vgs-collect.js\";\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads VGS Collect JS from CDN. Idempotent — subsequent calls return the same promise.\n */\nexport function loadVgsCollectScript(): Promise<void> {\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise<void>((resolve, reject) => {\n if (typeof window !== \"undefined\" && window.VGSCollect) {\n resolve();\n return;\n }\n\n const script = document.createElement(\"script\");\n script.src = VGS_COLLECT_CDN;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => {\n loadPromise = null;\n reject(new Error(\"Failed to load VGS Collect JS\"));\n };\n document.head.appendChild(script);\n });\n\n return loadPromise;\n}\n\n/**\n * Initializes a VGS Collect form instance.\n */\nexport function initVgsCollect(vaultId: string, environment: string): VGSCollectForm {\n if (!window.VGSCollect) {\n throw new Error(\"VGS Collect JS not loaded. Call loadVgsCollectScript() first.\");\n }\n return window.VGSCollect.create(vaultId, environment, () => {});\n}\n\n/**\n * Creates and mounts VGS Collect card fields using CMP-specific field methods.\n *\n * Uses cardNumberField(), cardExpirationDateField(), cardCVCField() which are\n * required for the CMP createCard() flow. After mounting, call form.createCard()\n * to create a card in the VGS vault, which returns aliases for PAN and CVC.\n *\n * @param form - VGS Collect form instance\n * @param mountPoints - CSS selectors for PAN, expiry, and CVC containers\n * @param css - Optional CSS to apply to VGS Collect iframe fields\n */\nexport function createVgsCardFields(\n form: VGSCollectForm,\n mountPoints: { pan: string; exp: string; cvc: string },\n css?: Record<string, string>,\n onFocusChangeCallbacks?: Partial<Record<string, (isFocused: boolean) => void>>,\n) {\n const fieldCss = css ?? {\n height: \"46px\",\n \"font-size\": \"1rem\",\n color: \"#18181b\",\n \"font-family\": \"ui-sans-serif, system-ui, sans-serif\",\n };\n\n const panField = form.cardNumberField(mountPoints.pan, {\n placeholder: \"Card number\",\n validations: [\"required\", \"validCardNumber\"],\n css: fieldCss,\n });\n\n const expField = form.cardExpirationDateField(mountPoints.exp, {\n placeholder: \"MM / YY\",\n validations: [\"required\", \"validCardExpirationDate\"],\n css: fieldCss,\n });\n\n const cvcField = form.cardCVCField(mountPoints.cvc, {\n placeholder: \"123\",\n validations: [\"required\", \"validCardSecurityCode\"],\n css: fieldCss,\n });\n\n if (onFocusChangeCallbacks) {\n const fieldMap: [VGSCollectField, string][] = [\n [panField, \"card_pan\"],\n [expField, \"card_exp\"],\n [cvcField, \"card_cvc\"],\n ];\n for (const [field, key] of fieldMap) {\n const cb = onFocusChangeCallbacks[key];\n if (cb) {\n field.on(\"focus\", () => cb(true));\n field.on(\"blur\", () => cb(false));\n }\n }\n }\n}\n"],"mappings":";AAAA,MAAM,kBAAkB;AAExB,IAAIA,cAAoC;;;;AAKxC,SAAgB,uBAAsC;AACpD,KAAI,YAAa,QAAO;AAExB,eAAc,IAAI,SAAe,SAAS,WAAW;AACnD,MAAI,OAAO,WAAW,eAAe,OAAO,YAAY;AACtD,YAAS;AACT;;EAGF,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,SAAO,MAAM;AACb,SAAO,QAAQ;AACf,SAAO,eAAe,SAAS;AAC/B,SAAO,gBAAgB;AACrB,iBAAc;AACd,0BAAO,IAAI,MAAM,gCAAgC,CAAC;;AAEpD,WAAS,KAAK,YAAY,OAAO;GACjC;AAEF,QAAO;;;;;AAMT,SAAgB,eAAe,SAAiB,aAAqC;AACnF,KAAI,CAAC,OAAO,WACV,OAAM,IAAI,MAAM,gEAAgE;AAElF,QAAO,OAAO,WAAW,OAAO,SAAS,mBAAmB,GAAG;;;;;;;;;;;;;AAcjE,SAAgB,oBACd,MACA,aACA,KACA,wBACA;CACA,MAAM,WAAW,OAAO;EACtB,QAAQ;EACR,aAAa;EACb,OAAO;EACP,eAAe;EAChB;CAED,MAAM,WAAW,KAAK,gBAAgB,YAAY,KAAK;EACrD,aAAa;EACb,aAAa,CAAC,YAAY,kBAAkB;EAC5C,KAAK;EACN,CAAC;CAEF,MAAM,WAAW,KAAK,wBAAwB,YAAY,KAAK;EAC7D,aAAa;EACb,aAAa,CAAC,YAAY,0BAA0B;EACpD,KAAK;EACN,CAAC;CAEF,MAAM,WAAW,KAAK,aAAa,YAAY,KAAK;EAClD,aAAa;EACb,aAAa,CAAC,YAAY,wBAAwB;EAClD,KAAK;EACN,CAAC;AAEF,KAAI,wBAAwB;EAC1B,MAAMC,WAAwC;GAC5C,CAAC,UAAU,WAAW;GACtB,CAAC,UAAU,WAAW;GACtB,CAAC,UAAU,WAAW;GACvB;AACD,OAAK,MAAM,CAAC,OAAO,QAAQ,UAAU;GACnC,MAAM,KAAK,uBAAuB;AAClC,OAAI,IAAI;AACN,UAAM,GAAG,eAAe,GAAG,KAAK,CAAC;AACjC,UAAM,GAAG,cAAc,GAAG,MAAM,CAAC"}
package/package.json CHANGED
@@ -1,16 +1,21 @@
1
1
  {
2
2
  "name": "@payment-kit-js/vanilla",
3
- "version": "0.4.0-alpha.0",
3
+ "version": "0.5.1",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "module": "./dist/index.mjs",
7
7
  "exports": {
8
8
  ".": "./dist/index.mjs",
9
+ "./payment-methods/airwallex-apple-pay-adapter": "./dist/payment-methods/airwallex-apple-pay-adapter.mjs",
10
+ "./payment-methods/airwallex-google-pay-adapter": "./dist/payment-methods/airwallex-google-pay-adapter.mjs",
11
+ "./payment-methods/apple-pay": "./dist/payment-methods/apple-pay.mjs",
9
12
  "./payment-methods/card": "./dist/payment-methods/card.mjs",
10
13
  "./payment-methods/google-pay": "./dist/payment-methods/google-pay.mjs",
11
14
  "./payment-methods/next-action-handlers": "./dist/payment-methods/next-action-handlers.mjs",
12
15
  "./payment-methods/paypal": "./dist/payment-methods/paypal.mjs",
16
+ "./payment-methods/stripe-apple-pay-adapter": "./dist/payment-methods/stripe-apple-pay-adapter.mjs",
13
17
  "./payment-methods/stripe-google-pay-adapter": "./dist/payment-methods/stripe-google-pay-adapter.mjs",
18
+ "./payment-methods/vgs-collect-loader": "./dist/payment-methods/vgs-collect-loader.mjs",
14
19
  "./penpal/connect-card": "./dist/penpal/connect-card.mjs",
15
20
  "./penpal/connect-tunnel-x": "./dist/penpal/connect-tunnel-x.mjs",
16
21
  "./package.json": "./package.json"
@@ -18,23 +23,30 @@
18
23
  "license": "MIT",
19
24
  "description": "Vanilla package for PaymentKit",
20
25
  "files": [
21
- "dist"
26
+ "dist",
27
+ "dist/cdn"
22
28
  ],
23
29
  "scripts": {
24
30
  "dev": "yarn tsdown --watch ./src",
25
- "build": "yarn tsdown"
31
+ "build:npm": "yarn tsdown",
32
+ "build:cdn": "node build-cdn.mjs",
33
+ "build": "yarn build:npm && yarn build:cdn"
26
34
  },
27
35
  "packageManager": "yarn@4.10.3",
28
36
  "dependencies": {
37
+ "nanoid": "^5.0.7",
29
38
  "penpal": "^7.0.4",
39
+ "posthog-js": "^1.196.0",
30
40
  "valibot": "^1.1.0"
31
41
  },
32
42
  "devDependencies": {
33
43
  "@pkg/sdk": "0.10.21",
34
44
  "@pkg/tsconfig": "0.0.0",
35
- "@stripe/stripe-js": "^5.5.0",
45
+ "@stripe/stripe-js": "^8.6.1",
46
+ "@types/applepayjs": "^14.0.9",
47
+ "esbuild": "^0.24.2",
36
48
  "tsdown": "^0.15.10",
37
49
  "typescript": "^5.9.3"
38
50
  },
39
- "stableVersion": "0.1.0-alpha.6"
51
+ "stableVersion": "0.5.1"
40
52
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"connect-tunnel-x-rLA6I_EO.d.mts","names":[],"sources":["../src/penpal/connect-tunnel-x.ts"],"sourcesContent":[],"mappings":";;;AAEyC,KAMpC,oBAAA,GAAoB;EAGE,YAAA,EAAA,GAAA,GAAA,IAAA;EAA2B,cAAA,EAAA,GAAA,GAAA,IAAA;EAEO,cAAA,EAAA,CAAA,MAAA,EAFlC,MAEkC,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,GAFP,OAEO,CAAA,OAAA,CAAA;EAAR,kBAAA,EAAA,GAAA,GAAA,IAAA;EACK,kBAAA,EAAA,CAAA,iBAAA,EAAA,MAAA,EAAA,GADL,OACK,CADG,eACH,CAAA;EAAR,qBAAA,EAAA,CAAA,WAAA,EAAA,MAAA,EAAA,GAAA,OAAA,CAAQ,wBAAR,CAAA;EACqB,mBAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAA,cAAA,EAAA,GAAmB,OAAnB,CAAA,OAAA,CAAA;CAAmB;KAGrF,oBAAA,GAAuB,MAHqE,CAAA,MAAA,EAAA,KAAA,CAAA;AAG5F,KAEO,uBAAA,GAA0B,UAFJ,CAEe,oBAFf,CAAA;AAEtB,KAEA,uBAAA,GAA0B,UAFW,CAEA,oBAFX,CAAA;AAE1B,cAEC,sBAFoC,EAAA,CAAA,MAAA,EAEF,iBAFT,EAAA,OAAU,EAE2B,oBAF3B,EAAA,GAE+C,UAF/C,CAE+C,oBAF/C,CAAA;AAEnC,cAIA,sBAFZ,EAAA,CAAA,OAAA,EAE+C,oBAF/C,EAAA,GAEmE,UAFnE,CAEmE,oBAFnE,CAAA;;;;;KAUI,oBAAA,GAZ0F;EAIlF,CAAA,UAAA,EAAA,MAAA,CAAA,EAAA,CAAA,MAEZ,EAAA,OAAA,EAAA,OAAA,CAAA,EAOmD,cAPnD,EAAA,GAOsE,OAPtE,CAAA,OAAA,CAAA;CAF+C;AAAoB,cAYvD,cAAA,CAZuD;EAAA,QAAA,UAAA;EAAA,QAAA,EAcjD,oBAdiD;EAQ/D,OAAA,0BAAoB,EAC2B,CAAA,UAAA,EAOK,uBAPqB,EAAA,GAOE,OAPF,CAOE,cAPF,CAAA;EAGjE,QAAA,WAAc,CAAA;EAER;;;;EAiBM,IAAA,eAAA,CAAA,CAAA,EAAA,oBAAA;EAAoB,OAAA,CAAA,CAAA,EAAA,IAAA"}
@@ -1,53 +0,0 @@
1
- //#region src/payment-methods/next-action-handlers.ts
2
- const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3
- const isStripeJsPresent = () => "Stripe" in window;
4
- /**
5
- * Get the Stripe instance from the global window object.
6
- * Expects Stripe.js to be loaded via HTML script tag.
7
- * Polls for up to 5 seconds waiting for Stripe to be available.
8
- */
9
- const getLoadedStripe = async (publishableKey) => {
10
- for (let i = 0; i < 10; i++) {
11
- if (isStripeJsPresent()) break;
12
- await sleep(500);
13
- }
14
- if (!isStripeJsPresent()) throw new Error("Stripe.js not loaded. Add this script tag to your HTML <head>:\n<script src=\"https://js.stripe.com/v3/\"><\/script>");
15
- return new window.Stripe(publishableKey);
16
- };
17
- /**
18
- * Handle Stripe 3DS authentication.
19
- */
20
- const handleStripe3ds = async (nextAction) => {
21
- console.log("3DS authentication required, loading Stripe...");
22
- const { clientSecret, stripePk } = nextAction;
23
- const { error: stripeError } = await (await getLoadedStripe(stripePk)).confirmCardPayment(clientSecret);
24
- if (stripeError) {
25
- console.error("3DS authentication failed:", stripeError);
26
- return {
27
- success: false,
28
- error: stripeError.message || "3DS authentication failed"
29
- };
30
- }
31
- console.log("3DS authentication completed");
32
- return { success: true };
33
- };
34
- /**
35
- * Handle a next action based on its type.
36
- * Routes to the appropriate processor-specific handler.
37
- *
38
- * @param nextAction - The next action from the checkout response
39
- * @returns Result indicating success or failure with error message
40
- */
41
- const handleNextAction = async (nextAction) => {
42
- switch (nextAction.type) {
43
- case "stripe_3ds": return handleStripe3ds(nextAction);
44
- default: return {
45
- success: false,
46
- error: `Unknown next action type: ${nextAction.type}`
47
- };
48
- }
49
- };
50
-
51
- //#endregion
52
- export { handleNextAction as t };
53
- //# sourceMappingURL=next-action-handlers-DTsWjUIA.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"next-action-handlers-DTsWjUIA.mjs","names":[],"sources":["../src/payment-methods/next-action-handlers.ts"],"sourcesContent":["/**\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\";\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 console.log(\"3DS authentication required, loading Stripe...\");\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 authentication failed:\", stripeError);\n return { success: false, error: stripeError.message || \"3DS authentication failed\" };\n }\n\n console.log(\"3DS authentication completed\");\n return { success: true };\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 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":";AAWA,MAAM,SAAS,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;AAG9F,MAAM,0BAAmC,YAAY;;;;;;AAOrD,MAAM,kBAAkB,OAAO,mBAA4C;AAEzE,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,MAAI,mBAAmB,CACrB;AAEF,QAAM,MAAM,IAAI;;AAGlB,KAAI,CAAC,mBAAmB,CACtB,OAAM,IAAI,MACR,uHAED;AAKH,QADuB,IAAI,OAAO,OAAO,eAAe;;;;;AAY1D,MAAM,kBAAkB,OACtB,eAC8B;AAC9B,SAAQ,IAAI,iDAAiD;CAC7D,MAAM,EAAE,cAAc,aAAa;CAKnC,MAAM,EAAE,OAAO,gBAAgB,OAHhB,MAAM,gBAAgB,SAAS,EAGF,mBAAmB,aAAa;AAE5E,KAAI,aAAa;AACf,UAAQ,MAAM,8BAA8B,YAAY;AACxD,SAAO;GAAE,SAAS;GAAO,OAAO,YAAY,WAAW;GAA6B;;AAGtF,SAAQ,IAAI,+BAA+B;AAC3C,QAAO,EAAE,SAAS,MAAM;;;;;;;;;AAU1B,MAAa,mBAAmB,OAC9B,eAC8B;AAC9B,SAAQ,WAAW,MAAnB;EACE,KAAK,aACH,QAAO,gBAAgB,WAAW;EACpC,QAEE,QAAO;GAAE,SAAS;GAAO,OAAO,6BAA8B,WAAgC;GAAQ"}
@@ -1,64 +0,0 @@
1
- import { t as CardErrorCode } from "./connect-card-C582hcWw.mjs";
2
- import { t as TunnelXIFrameConnection } from "./connect-tunnel-x-rLA6I_EO.mjs";
3
-
4
- //#region src/types.d.ts
5
-
6
- type FormFieldNames = "customer_name" | "customer_email" | "customer_country" | "customer_zip_code";
7
- type FormErrorCodes = "required" | "invalid";
8
- type TInternalFuncs = {
9
- submitPayment: (fields: PaymentKitFields, options?: unknown) => Promise<{
10
- data: {
11
- [key: string]: unknown;
12
- };
13
- errors?: never;
14
- } | {
15
- data?: never;
16
- errors: PaymentKitErrors;
17
- }>;
18
- cleanup?: () => void;
19
- };
20
- type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {
21
- environment: string;
22
- secureToken: string;
23
- paymentMethods: T;
24
- }) => ExternalFuncsMapByPm<T> & {
25
- submit: PaymentKitSubmitHandler<T>;
26
- cleanup: () => void;
27
- };
28
- type PaymentKitSubmitHandler<T extends readonly PaymentMethod<unknown>[]> = <N extends keyof ExternalFuncsMapByPm<T>>(options: {
29
- fields: PaymentKitFields;
30
- paymentMethod: N;
31
- options?: unknown;
32
- onError: (error: PaymentKitErrors) => void;
33
- onSuccess: (data: {
34
- [key: string]: unknown;
35
- }) => void;
36
- }) => void;
37
- type PaymentKitStates = {
38
- baseUrl: string;
39
- apiBaseUrl: string;
40
- secureToken: string;
41
- tunnelXConnection: TunnelXIFrameConnection;
42
- };
43
- type PaymentKitErrors = {
44
- root?: string;
45
- card_pan?: CardErrorCode;
46
- card_exp?: CardErrorCode;
47
- card_cvc?: CardErrorCode;
48
- paypal?: string;
49
- google_pay?: string;
50
- processor_id?: string;
51
- amount?: string;
52
- currency?: string;
53
- country?: string;
54
- } & { [key in FormFieldNames]?: FormErrorCodes | string };
55
- type PaymentKitFields = { [key in FormFieldNames]: string };
56
- type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates: PaymentKitStates) => {
57
- name: TName;
58
- externalFuncs: TExternalFuncs;
59
- internalFuncs: TInternalFuncs;
60
- };
61
- type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = { [K in T[number] as ReturnType<K>["name"]]: ReturnType<K>["externalFuncs"] };
62
- //#endregion
63
- export { PaymentKitFields as n, PaymentMethod as r, PaymentKit as t };
64
- //# sourceMappingURL=types-WgbMhIYb.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-WgbMhIYb.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;KAmCK,cAAA,GAQyF,eAAA,GAAA,gBAAA,GAAA,kBAAA,GAAA,mBAAA;AAAvF,KANK,cAAA,GAML,UAAA,GAAA,SAAA;AAAO,KAJF,cAAA,GAIE;EAIF,aAAU,EAAA,CAAA,MAAA,EANV,gBAMU,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,GAJf,OAIe,CAAA;IAAuB,IAAA,EAAA;MAG3B,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IACS,CAAA;IAArB,MAAA,CAAA,EAAA,KAAA;EAC4B,CAAA,GAAA;IAAxB,IAAA,CAAA,EAAA,KAAA;IAAuB,MAAA,EAT6D,gBAS7D;EAI5B,CAAA,CAAA;EAA2C,OAAA,CAAA,EAAA,GAAA,GAAA,IAAA;CACT;AAArB,KAVN,UAAA,GAUM,CAAA,UAAA,SAV2B,aAU3B,CAAA,OAAA,CAAA,EAAA,CAAA,CAAA,OAAA,EAAA;EAER,WAAA,EAAA,MAAA;EACO,WAAA,EAAA,MAAA;EAEE,cAAA,EAZD,CAYC;CAAgB,EAAA,GAX7B,oBAW6B,CAXR,CAWQ,CAAA,GAAA;EAIvB,MAAA,EAdF,uBAkBW,CAlBa,CAkBb,CAAA;EAGT,OAAA,EAAA,GAAA,GAAA,IAAgB;CAEf;KAnBR,uBAoBQ,CAAA,UAAA,SApBmC,aAoBnC,CAAA,OAAA,CAAA,EAAA,CAAA,GAAA,CAAA,UAAA,MAnBK,oBAmBL,CAnB0B,CAmB1B,CAAA,CAAA,CAAA,OAAA,EAAA;EACA,MAAA,EAlBH,gBAkBG;EAOC,aAAA,EAxBG,CAwBH;EAAkB,OAAA,CAAA,EAAA,OAAA;EAAc,OAAA,EAAA,CAAA,KAAA,EAtB3B,gBAsB2B,EAAA,GAAA,IAAA;EAElC,SAAA,EAAA,CAAA,IAAA,EAAA;IAEA,CAAA,GAAA,EAAA,MAAa,CAAA,EAAA,OAAA;EAAgE,CAAA,EAAA,GAAA,IAAA;CACjF,EAAA,GAAA,IAAA;AACS,KAxBL,gBAAA,GAwBK;EACA,OAAA,EAAA,MAAA;EAAc,UAAA,EAAA,MAAA;EAGnB,WAAA,EAAA,MAAA;EAAwC,iBAAA,EAxB/B,uBAwB+B;CAC5C;AAAwB,KAtBpB,gBAAA,GAsBoB;EAAX,IAAA,CAAA,EAAA,MAAA;EAAmC,QAAA,CAAA,EApB3C,aAoB2C;EAAX,QAAA,CAAA,EAnBhC,aAmBgC;EAAU,QAAA,CAAA,EAlB1C,aAkB0C;;;;;;;cAXzC,kBAAkB;KAEpB,gBAAA,aAA6B;KAE7B,6EAA6E;QACjF;iBACS;iBACA;;KAGL,wCAAwC,oCAC5C,aAAa,WAAW,aAAa,WAAW"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils-h0dxplHy.mjs","names":[],"sources":["../src/utils/validate-form-fields.ts","../src/utils/index.ts"],"sourcesContent":["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 { 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":";;;AAOA,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;;;;;AC9B5B,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"}