@payment-kit-js/vanilla 0.5.9 → 0.5.10

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 (35) hide show
  1. package/dist/{airwallex-apple-pay-adapter-I_pnNYdy.d.mts → airwallex-apple-pay-adapter-BCYt7Jzc.d.mts} +2 -1
  2. package/dist/airwallex-apple-pay-adapter-BCYt7Jzc.d.mts.map +1 -0
  3. package/dist/{airwallex-apple-pay-adapter-BE15xREr.mjs → airwallex-apple-pay-adapter-BFsoDoSf.mjs} +6 -2
  4. package/dist/airwallex-apple-pay-adapter-BFsoDoSf.mjs.map +1 -0
  5. package/dist/cdn/paymentkit.js +1156 -60
  6. package/dist/cdn/paymentkit.js.map +4 -4
  7. package/dist/cdn/paymentkit.min.js +10 -10
  8. package/dist/cdn/paymentkit.min.js.map +4 -4
  9. package/dist/index.d.mts.map +1 -1
  10. package/dist/index.mjs +7 -1
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/payment-methods/airwallex-apple-pay-adapter.d.mts +1 -1
  13. package/dist/payment-methods/airwallex-apple-pay-adapter.mjs +1 -1
  14. package/dist/payment-methods/apple-pay.d.mts +15 -1
  15. package/dist/payment-methods/apple-pay.d.mts.map +1 -1
  16. package/dist/payment-methods/apple-pay.mjs +45 -13
  17. package/dist/payment-methods/apple-pay.mjs.map +1 -1
  18. package/dist/payment-methods/card.d.mts.map +1 -1
  19. package/dist/payment-methods/card.mjs +115 -20
  20. package/dist/payment-methods/card.mjs.map +1 -1
  21. package/dist/payment-methods/google-pay.d.mts +18 -1
  22. package/dist/payment-methods/google-pay.d.mts.map +1 -1
  23. package/dist/payment-methods/google-pay.mjs +28 -9
  24. package/dist/payment-methods/google-pay.mjs.map +1 -1
  25. package/dist/payment-methods/stripe-google-pay-adapter.d.mts +1 -1
  26. package/dist/payment-methods/stripe-google-pay-adapter.mjs +1 -1
  27. package/dist/{stripe-google-pay-adapter-CqcUEoM3.mjs → stripe-google-pay-adapter-3cx0KNjK.mjs} +7 -2
  28. package/dist/stripe-google-pay-adapter-3cx0KNjK.mjs.map +1 -0
  29. package/dist/{stripe-google-pay-adapter-C3NCBSO3.d.mts → stripe-google-pay-adapter-Bdox4xBq.d.mts} +2 -1
  30. package/dist/stripe-google-pay-adapter-Bdox4xBq.d.mts.map +1 -0
  31. package/package.json +4 -7
  32. package/dist/airwallex-apple-pay-adapter-BE15xREr.mjs.map +0 -1
  33. package/dist/airwallex-apple-pay-adapter-I_pnNYdy.d.mts.map +0 -1
  34. package/dist/stripe-google-pay-adapter-C3NCBSO3.d.mts.map +0 -1
  35. package/dist/stripe-google-pay-adapter-CqcUEoM3.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;cA2BM,YAAY"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;cA6BM,YAAY"}
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { o as getOrCreateCheckoutRequestId, r as createCheckoutIFrame } from "./
4
4
  import posthog from "posthog-js";
5
5
 
6
6
  //#region package.json
7
- var version = "0.5.9";
7
+ var version = "0.5.10";
8
8
 
9
9
  //#endregion
10
10
  //#region src/analytics/mock-adapter.ts
@@ -383,6 +383,12 @@ const createTunnelXConnection = (baseUrl, apiBaseUrl, token) => {
383
383
  checkout_token: token,
384
384
  api_base_url: apiBaseUrl
385
385
  });
386
+ Object.assign(iframe.style, {
387
+ width: "0",
388
+ height: "0",
389
+ position: "absolute",
390
+ visibility: "hidden"
391
+ });
386
392
  document.body.appendChild(iframe);
387
393
  const connection = connectToTunnelXIframe(iframe, {});
388
394
  const unmount = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["STATIC_ENVIRONMENT_URLS: Record<Exclude<PaymentKitEnvironment, \"tunnel\">, EnvironmentUrls>","PaymentKit: PaymentKitType","PACKAGE_VERSION","externalFuncsMapByPm: ExternalFuncsMapByPm<PaymentMethods>","submit: PaymentKitReturnType[\"submit\"]"],"sources":["../package.json","../src/analytics/mock-adapter.ts","../src/analytics/posthog-adapter.ts","../src/analytics/service.ts","../src/analytics/checkout-timing.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@payment-kit-js/vanilla\",\n \"version\": \"0.5.9\",\n \"main\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.mts\",\n \"module\": \"./dist/index.mjs\",\n \"exports\": {\n \".\": \"./dist/index.mjs\",\n \"./payment-methods/airwallex-apple-pay-adapter\": \"./dist/payment-methods/airwallex-apple-pay-adapter.mjs\",\n \"./payment-methods/airwallex-google-pay-adapter\": \"./dist/payment-methods/airwallex-google-pay-adapter.mjs\",\n \"./payment-methods/apple-pay\": \"./dist/payment-methods/apple-pay.mjs\",\n \"./payment-methods/card\": \"./dist/payment-methods/card.mjs\",\n \"./payment-methods/google-pay\": \"./dist/payment-methods/google-pay.mjs\",\n \"./payment-methods/next-action-handlers\": \"./dist/payment-methods/next-action-handlers.mjs\",\n \"./payment-methods/paypal\": \"./dist/payment-methods/paypal.mjs\",\n \"./payment-methods/stripe-apple-pay-adapter\": \"./dist/payment-methods/stripe-apple-pay-adapter.mjs\",\n \"./payment-methods/stripe-google-pay-adapter\": \"./dist/payment-methods/stripe-google-pay-adapter.mjs\",\n \"./payment-methods/vgs-collect-loader\": \"./dist/payment-methods/vgs-collect-loader.mjs\",\n \"./penpal/connect-card\": \"./dist/penpal/connect-card.mjs\",\n \"./penpal/connect-tunnel-x\": \"./dist/penpal/connect-tunnel-x.mjs\",\n \"./package.json\": \"./package.json\"\n },\n \"license\": \"MIT\",\n \"description\": \"Vanilla package for PaymentKit\",\n \"files\": [\n \"dist\",\n \"dist/cdn\"\n ],\n \"scripts\": {\n \"dev\": \"yarn tsdown --watch ./src\",\n \"build:npm\": \"yarn tsdown\",\n \"build:cdn\": \"node build-cdn.mjs\",\n \"build\": \"yarn build:npm && yarn build:cdn\",\n \"test\": \"vitest run\"\n },\n \"packageManager\": \"yarn@4.10.3\",\n \"dependencies\": {\n \"nanoid\": \"^5.0.7\",\n \"penpal\": \"^7.0.4\",\n \"posthog-js\": \"^1.196.0\",\n \"valibot\": \"^1.1.0\"\n },\n \"devDependencies\": {\n \"@pkg/sdk\": \"workspace:*\",\n \"@pkg/tsconfig\": \"workspace:*\",\n \"@stripe/stripe-js\": \"^8.6.1\",\n \"@types/applepayjs\": \"^14.0.9\",\n \"esbuild\": \"^0.24.2\",\n \"jsdom\": \"^26.1.0\",\n \"tsdown\": \"^0.15.10\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^3.1.4\"\n },\n \"stableVersion\": \"0.5.9\"\n}\n","import type { AnalyticsAdapter, CapturedEvent } from \"./types\";\n\n/**\n * Mock analytics adapter for testing.\n *\n * Records all captured events for assertion in tests.\n */\nexport class MockAnalyticsAdapter implements AnalyticsAdapter {\n private events: CapturedEvent[] = [];\n private distinctId: string | null = null;\n\n identify(distinctId: string): void {\n this.distinctId = distinctId;\n }\n\n capture(event: string, properties?: Record<string, unknown>): void {\n this.events.push({\n event,\n distinct_id: this.distinctId,\n properties,\n timestamp: Date.now(),\n });\n }\n\n isInitialized(): boolean {\n return true;\n }\n\n // Test helper methods\n\n /**\n * Get all captured events.\n */\n getEvents(): CapturedEvent[] {\n return [...this.events];\n }\n\n /**\n * Get events by name.\n */\n getEventsByName(eventName: string): CapturedEvent[] {\n return this.events.filter((e) => e.event === eventName);\n }\n\n /**\n * Clear all captured events.\n */\n clear(): void {\n this.events = [];\n }\n}\n","import posthog from \"posthog-js\";\nimport type { AnalyticsAdapter } from \"./types\";\n\n// PostHog API key (PaymentKit internal)\nconst POSTHOG_API_KEY = \"phc_u9YDYUeUxo3CYn16XGrrwpVb8ycXgcjz5DarvIKRAAG\";\n\n/**\n * PostHog implementation of the analytics adapter.\n *\n * Singleton stored in window to ensure only one instance exists across\n * all script loads. Configures PostHog to use the reverse proxy at\n * /ingest to avoid ad blockers.\n */\nexport class PostHogAdapter implements AnalyticsAdapter {\n private initialized = false;\n\n /**\n * Get or create the PostHog adapter singleton (stored in window).\n *\n * @param apiBaseUrl - The API base URL for the reverse proxy\n * @throws Error if called with a different apiBaseUrl than the first call\n */\n static getInstance(apiBaseUrl: string): PostHogAdapter {\n if (typeof window === \"undefined\") {\n throw new Error(\"[PaymentKit Analytics] PostHog requires a browser environment\");\n }\n\n const existing = window.__paymentKitPostHog__;\n if (existing) {\n if (existing.apiBaseUrl !== apiBaseUrl) {\n throw new Error(\n `[PaymentKit Analytics] PostHog already initialized with apiBaseUrl \"${existing.apiBaseUrl}\", ` +\n `cannot re-initialize with different apiBaseUrl \"${apiBaseUrl}\"`,\n );\n }\n return existing.instance;\n }\n\n const instance = new PostHogAdapter(apiBaseUrl);\n window.__paymentKitPostHog__ = { instance, apiBaseUrl };\n return instance;\n }\n\n private constructor(apiBaseUrl: string) {\n this.initPostHog(apiBaseUrl);\n }\n\n private initPostHog(apiBaseUrl: string): void {\n try {\n posthog.init(POSTHOG_API_KEY, {\n // Use reverse proxy to avoid ad blockers\n api_host: `${apiBaseUrl}/ingest`,\n // PostHog UI host (for toolbar, if ever needed)\n ui_host: \"https://us.posthog.com\",\n // Memory persistence - no cookies in embedded checkout iframe\n persistence: \"memory\",\n // Disable session recording - not needed for metrics\n disable_session_recording: true,\n // Manual events only - no autocapture\n autocapture: false,\n // Manual pageview control\n capture_pageview: false,\n // Disable batching - send events immediately to avoid data loss on page close\n request_batching: false,\n // Disable bot detection - allows events from automated tests and debugging environments\n // PostHog detects Playwright/headless browsers as bots by default\n opt_out_useragent_filter: true,\n // Callback when PostHog is ready\n loaded: () => {\n this.initialized = true;\n },\n });\n } catch (e) {\n console.warn(\"[PaymentKit Analytics] Failed to initialize PostHog:\", e);\n }\n }\n\n identify(distinctId: string): void {\n try {\n posthog.identify(distinctId);\n } catch (e) {\n // Silent fail - never break checkout\n console.warn(\"[PaymentKit Analytics] Failed to identify:\", e);\n }\n }\n\n capture(event: string, properties?: Record<string, unknown>): void {\n try {\n posthog.capture(event, properties);\n } catch (e) {\n // Silent fail - never break checkout\n console.warn(\"[PaymentKit Analytics] Failed to capture event:\", e);\n }\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n}\n","import { MockAnalyticsAdapter } from \"./mock-adapter\";\nimport { PostHogAdapter } from \"./posthog-adapter\";\nimport type { AnalyticsAdapter } from \"./types\";\n\n/**\n * Analytics service singleton.\n *\n * Provides a global interface for capturing analytics events.\n * Supports multiple adapters that receive all events (composite pattern).\n *\n * Usage:\n * // Initialize (typically done once at SDK init)\n * AnalyticsService.init(\"http://localhost:9000\");\n *\n * // Capture events - broadcasts to all registered adapters\n * AnalyticsService.capture(\"checkout_page_ready\", { session_id: \"...\" });\n *\n * // For testing - add a mock adapter\n * import { MockAnalyticsAdapter } from \"./mock-adapter\";\n * const mock = new MockAnalyticsAdapter();\n * AnalyticsService.addAdapter(mock);\n *\n * // Or use the built-in test mock (exposed globally as window.__paymentKitAnalytics__)\n * AnalyticsService.enableTestMode();\n * // Events can be read via window.__paymentKitAnalytics__.getEvents()\n */\nclass AnalyticsServiceClass {\n private adapters: AnalyticsAdapter[] = [];\n private testMock: MockAnalyticsAdapter | null = null;\n\n /**\n * Initialize the analytics service with PostHog.\n *\n * @param apiBaseUrl - The API base URL for the reverse proxy\n * @param enableTestMode - Enable test mode for capturing events in tests\n */\n init(apiBaseUrl: string, enableTestMode?: boolean): void {\n try {\n // Add PostHog adapter (singleton - safe to call multiple times with same URL)\n this.addAdapter(PostHogAdapter.getInstance(apiBaseUrl));\n\n // Enable test mode if explicitly requested\n if (enableTestMode) {\n this.enableTestMode();\n }\n } catch (e) {\n // Silent fail - analytics should never break checkout\n console.warn(\"[PaymentKit Analytics] Init failed:\", e);\n }\n }\n\n /**\n * Enable test mode by adding a mock adapter and exposing it globally.\n * The mock adapter is accessible via window.__paymentKitAnalytics__\n */\n enableTestMode(): void {\n if (this.testMock) return; // Already enabled\n\n this.testMock = new MockAnalyticsAdapter();\n this.addAdapter(this.testMock);\n\n // Expose globally for Playwright/test access\n if (typeof window !== \"undefined\") {\n window.__paymentKitAnalytics__ = this.testMock;\n }\n }\n\n /**\n * Get the test mock adapter (if test mode is enabled).\n */\n getTestMock(): MockAnalyticsAdapter | null {\n return this.testMock;\n }\n\n /**\n * Add an analytics adapter.\n * Events will be broadcast to all registered adapters.\n * Duplicate adapters (same instance) are ignored.\n *\n * @param adapter - The adapter to add\n */\n addAdapter(adapter: AnalyticsAdapter): void {\n if (!this.adapters.includes(adapter)) {\n this.adapters.push(adapter);\n }\n }\n\n /**\n * Clear all adapters.\n */\n clearAdapters(): void {\n this.adapters = [];\n this.testMock = null;\n if (typeof window !== \"undefined\") {\n delete window.__paymentKitAnalytics__;\n }\n }\n\n /**\n * Set the distinct_id for all adapters.\n * This is used to correlate frontend events with backend events.\n * Should be called with the checkout session secure token.\n */\n identify(distinctId: string): void {\n for (const adapter of this.adapters) {\n try {\n adapter.identify(distinctId);\n } catch {\n // Silent fail - never break checkout\n }\n }\n }\n\n /**\n * Capture an analytics event.\n * Broadcasts to all registered adapters. Silently fails on errors.\n */\n capture(event: string, properties?: Record<string, unknown>): void {\n for (const adapter of this.adapters) {\n try {\n adapter.capture(event, properties);\n } catch {\n // Silent fail - never break checkout\n }\n }\n }\n\n /**\n * Check if any adapter is initialized.\n */\n isInitialized(): boolean {\n return this.adapters.some((adapter) => adapter.isInitialized());\n }\n}\n\n/**\n * Global analytics service instance.\n */\nexport const AnalyticsService = new AnalyticsServiceClass();\n","import { AnalyticsService } from \"./service\";\n\n/**\n * Tracks timing metrics throughout the checkout flow.\n *\n * Create one instance per checkout session and call the track methods\n * at appropriate points in the checkout flow.\n *\n * Usage:\n * const requestId = getOrCreateCheckoutRequestId(environment);\n * const tracker = new CheckoutTimingTracker(secureToken, requestId);\n * tracker.trackPageReady();\n * // ... iframe loads ...\n * tracker.trackInputReady();\n * // ... user submits ...\n * tracker.trackSubmit();\n * // ... API response ...\n * tracker.trackSuccess(attemptId);\n */\nexport class CheckoutTimingTracker {\n // Class-level guard to prevent duplicate page_ready events across PaymentKit instances\n private static pageReadyTracked = false;\n\n private startTime: number;\n private checkoutSessionId: string;\n private requestId: string;\n private inputReadyTracked = false;\n\n constructor(checkoutSessionId: string, requestId: string) {\n this.startTime = performance.now();\n this.checkoutSessionId = checkoutSessionId;\n this.requestId = requestId;\n }\n\n /**\n * Track when SDK is initialized and ready.\n * Call immediately after PaymentKit() initialization.\n * Only tracks once per page load (subsequent calls are no-ops).\n */\n trackPageReady(): void {\n if (CheckoutTimingTracker.pageReadyTracked) return;\n CheckoutTimingTracker.pageReadyTracked = true;\n\n AnalyticsService.capture(\"checkout_page_ready\", {\n checkout_session_id: this.checkoutSessionId,\n request_id: this.requestId,\n elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track when card input iframe is loaded and ready for input.\n * Should only be called once (for first iframe, typically card_pan).\n * Subsequent calls are no-ops.\n */\n trackInputReady(): void {\n if (this.inputReadyTracked) return;\n this.inputReadyTracked = true;\n\n AnalyticsService.capture(\"checkout_input_ready\", {\n checkout_session_id: this.checkoutSessionId,\n request_id: this.requestId,\n elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track when user clicks submit button.\n */\n trackSubmit(): void {\n AnalyticsService.capture(\"checkout_submit\", {\n checkout_session_id: this.checkoutSessionId,\n request_id: this.requestId,\n elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track successful checkout.\n *\n * @param checkoutAttemptId - The checkout attempt ID\n */\n trackSuccess(checkoutAttemptId: string): void {\n AnalyticsService.capture(\"checkout_success\", {\n checkout_session_id: this.checkoutSessionId,\n checkout_attempt_id: checkoutAttemptId,\n request_id: this.requestId,\n total_elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track failed checkout.\n *\n * @param checkoutAttemptId - The checkout attempt ID (may be null if failed early)\n * @param errorCode - The error code from the checkout response\n * @param errorMessage - The customer-facing error message\n */\n trackFail(checkoutAttemptId: string | null, errorCode: string | null, errorMessage: string | null): void {\n AnalyticsService.capture(\"checkout_fail\", {\n checkout_session_id: this.checkoutSessionId,\n checkout_attempt_id: checkoutAttemptId,\n request_id: this.requestId,\n error_code: errorCode,\n error_message: errorMessage,\n total_elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Get elapsed time in milliseconds since tracker creation.\n */\n private getElapsedMs(): number {\n return Math.round(performance.now() - this.startTime);\n }\n}\n","import type { CheckoutTimingTracker } from \"./analytics\";\nimport type { CardErrorCode } from \"./penpal/connect-card\";\nimport type { TunnelXIFrameConnection } from \"./penpal/connect-tunnel-x\";\n\nexport type PaymentKitEnvironment = \"local\" | \"tunnel\" | \"sandbox\" | \"production\";\n\ntype EnvironmentUrls = {\n baseUrl: string;\n apiBaseUrl: string;\n};\n\n// TODO: Cleanup this after launch to only use SDK instead of plain fetch.\nconst STATIC_ENVIRONMENT_URLS: Record<Exclude<PaymentKitEnvironment, \"tunnel\">, EnvironmentUrls> = {\n local: {\n baseUrl: \"http://localhost:9101\",\n apiBaseUrl: \"http://localhost:9000\",\n },\n sandbox: {\n baseUrl: \"https://staging.paymentkit.com/customer\",\n apiBaseUrl: \"https://staging.paymentkit.com\",\n },\n production: {\n baseUrl: \"https://app.paymentkit.com/customer\",\n apiBaseUrl: \"https://app.paymentkit.com\",\n },\n};\n\nfunction getTunnelUrls(): EnvironmentUrls {\n if (typeof window !== \"undefined\") {\n const params = new URLSearchParams(window.location.search);\n const apiBaseUrl = params.get(\"api_base_url\");\n if (apiBaseUrl) {\n return {\n baseUrl: window.location.origin,\n apiBaseUrl,\n };\n }\n // For loclx-style tunnels where API hostname is derived from the current hostname\n const hostname = window.location.hostname;\n if (hostname.includes(\"loclx.io\")) {\n const apiHostname = hostname.replace(/cportal|playground/, \"api\");\n return {\n baseUrl: `https://${hostname}`,\n apiBaseUrl: `https://${apiHostname}`,\n };\n }\n }\n // Fallback\n return STATIC_ENVIRONMENT_URLS.local;\n}\n\nexport function getUrlsForEnvironment(environment: string): EnvironmentUrls {\n if (environment === \"tunnel\") {\n return getTunnelUrls();\n }\n const env = environment as Exclude<PaymentKitEnvironment, \"tunnel\">;\n const urls = STATIC_ENVIRONMENT_URLS[env];\n if (!urls) {\n throw new Error(`Invalid environment: ${environment}. Must be one of: local, tunnel, sandbox, production`);\n }\n return urls;\n}\n\ntype FormFieldNames =\n | \"customer_name\"\n | \"customer_email\"\n | \"customer_country\"\n | \"customer_zip_code\"\n | \"customer_business_name\"\n | \"customer_address_line1\"\n | \"customer_address_line2\"\n | \"customer_city\"\n | \"customer_state\"\n | \"customer_tax_ids\"\n | \"shipping_address_line1\"\n | \"shipping_address_line2\"\n | \"shipping_city\"\n | \"shipping_state\"\n | \"shipping_zip_code\"\n | \"shipping_country\";\n\nexport type FormErrorCodes = \"required\" | \"invalid\";\n\nexport type CardSubmitOptions = {\n skipCustomerValidation?: boolean;\n};\n\nexport type TInternalFuncs = {\n submitPayment: (\n fields: PaymentKitFields,\n options?: CardSubmitOptions,\n ) => Promise<{ data: { [key: string]: unknown }; errors?: never } | { data?: never; errors: PaymentKitErrors }>;\n cleanup?: () => void;\n};\n\nexport type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {\n environment: string;\n secureToken: string;\n paymentMethods: T;\n /** Card tokenization mode from checkout session */\n cardTokenizationMode?: \"direct\" | \"vgs\";\n /** VGS vault ID from checkout session */\n vgsVaultId?: string;\n /** VGS environment from checkout session */\n vgsEnvironment?: string;\n /** @internal Enable analytics test mode for e2e testing */\n __enableAnalyticsTestMode?: boolean;\n}) => ExternalFuncsMapByPm<T> & {\n submit: PaymentKitSubmitHandler<T>;\n cleanup: () => void;\n};\n\ntype PaymentKitSubmitHandler<T extends readonly PaymentMethod<unknown>[]> = <\n N extends keyof ExternalFuncsMapByPm<T>,\n>(options: {\n fields: Partial<PaymentKitFields>;\n paymentMethod: N;\n options?: unknown;\n onError: (error: PaymentKitErrors) => void;\n onSuccess: (data: { [key: string]: unknown }) => void;\n}) => void;\n\nexport type PaymentKitStates = {\n baseUrl: string;\n apiBaseUrl: string;\n secureToken: string;\n environment: string;\n tunnelXConnection: TunnelXIFrameConnection;\n timingTracker: CheckoutTimingTracker;\n /** Checkout request ID for correlating all API calls and analytics events */\n checkoutRequestId: string;\n /** Card tokenization mode: 'direct' (KMS) or 'vgs' (VGS Collect + proxy) */\n cardTokenizationMode?: \"direct\" | \"vgs\";\n /** VGS vault ID (only when cardTokenizationMode is 'vgs') */\n vgsVaultId?: string;\n /** VGS environment: 'sandbox' or 'live' (only when cardTokenizationMode is 'vgs') */\n vgsEnvironment?: string;\n /** @internal Promise that resolves when session config (incl. VGS mode) is auto-detected */\n _sessionConfigReady?: Promise<void>;\n};\n\nexport type PaymentKitErrors = {\n root?: string;\n card_pan?: CardErrorCode;\n card_exp?: CardErrorCode;\n card_cvc?: CardErrorCode;\n paypal?: string;\n google_pay?: string;\n apple_pay?: string;\n processor_id?: string;\n amount?: string;\n currency?: string;\n country?: string;\n} & { [key in FormFieldNames]?: FormErrorCodes | string };\n\nexport type PaymentKitFields = { [key in FormFieldNames]: string };\n\nexport type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates: PaymentKitStates) => {\n name: TName;\n externalFuncs: TExternalFuncs;\n internalFuncs: TInternalFuncs;\n};\n\nexport type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = {\n [K in T[number] as ReturnType<K>[\"name\"]]: ReturnType<K>[\"externalFuncs\"];\n};\n","import { version as PACKAGE_VERSION } from \"../package.json\";\nimport { AnalyticsService, CheckoutTimingTracker } from \"./analytics\";\nimport { connectToTunnelXIframe } from \"./penpal/connect-tunnel-x\";\nimport type { ExternalFuncsMapByPm, PaymentKitFields, PaymentKit as PaymentKitType } from \"./types\";\nimport { getUrlsForEnvironment } from \"./types\";\nimport { createCheckoutIFrame } from \"./utils\";\nimport { getOrCreateCheckoutRequestId } from \"./utils/checkout-request-id\";\n\ntype PaymentKitReturnType = ReturnType<PaymentKitType>;\n\nconst createTunnelXConnection = (baseUrl: string, apiBaseUrl: string, token: string) => {\n const iframe = createCheckoutIFrame(\"tunnel-x\", baseUrl, {\n checkout_token: token,\n api_base_url: apiBaseUrl,\n });\n document.body.appendChild(iframe);\n\n const connection = connectToTunnelXIframe(iframe, {});\n\n const unmount = () => {\n connection.destroy();\n document.body.removeChild(iframe);\n };\n\n return { unmount, connection };\n};\n\nconst PaymentKit: PaymentKitType = ({\n environment,\n secureToken,\n paymentMethods,\n cardTokenizationMode,\n vgsVaultId,\n vgsEnvironment,\n __enableAnalyticsTestMode,\n}) => {\n type PaymentMethods = typeof paymentMethods;\n\n // Resolve URLs from environment\n const { baseUrl, apiBaseUrl } = getUrlsForEnvironment(environment);\n\n // Log version for debugging\n console.log(`[PaymentKit] v${PACKAGE_VERSION} initialized (env: ${environment})`);\n\n // Generate checkout request ID for correlating all API calls and analytics events\n // This is idempotent - same ID is reused across multiple PaymentKit instantiations\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[PaymentKit] checkout_request_id: ${checkoutRequestId}`);\n\n // Initialize analytics and identify with secure token for correlation\n AnalyticsService.init(apiBaseUrl, __enableAnalyticsTestMode);\n AnalyticsService.identify(secureToken);\n\n // Create timing tracker for this checkout session\n const timingTracker = new CheckoutTimingTracker(secureToken, checkoutRequestId);\n\n // Track page ready immediately\n timingTracker.trackPageReady();\n\n const { connection: tunnelXConnection, unmount: unmountTunnelX } = createTunnelXConnection(\n baseUrl,\n apiBaseUrl,\n secureToken,\n );\n\n const paymentKitStates = {\n baseUrl,\n apiBaseUrl,\n secureToken,\n environment,\n tunnelXConnection,\n timingTracker,\n checkoutRequestId,\n cardTokenizationMode,\n vgsVaultId,\n vgsEnvironment,\n _sessionConfigReady: undefined as Promise<void> | undefined,\n };\n\n // Auto-detect VGS mode from session API if not explicitly provided.\n // The promise resolves before any card mount or submit needs the mode.\n if (cardTokenizationMode === undefined) {\n const sessionConfigUrl = `${apiBaseUrl}/api/checkout-sessions/token/${secureToken}`;\n console.log(\n `[PaymentKit] cardTokenizationMode not provided — auto-detecting from session API: ${sessionConfigUrl}`,\n );\n paymentKitStates._sessionConfigReady = fetch(sessionConfigUrl)\n .then((resp) => {\n if (!resp.ok) {\n console.warn(`[PaymentKit] Session config fetch failed with status ${resp.status}`);\n return null;\n }\n return resp.json();\n })\n .then((session) => {\n if (session && typeof session === \"object\" && typeof session.card_tokenization_mode === \"string\") {\n paymentKitStates.cardTokenizationMode = session.card_tokenization_mode || \"direct\";\n console.log(\n `[PaymentKit] Session config detected — cardTokenizationMode: ${paymentKitStates.cardTokenizationMode}`,\n );\n\n // Validate VGS config from API before trusting it\n const vaultId = session.vgs_vault_id;\n const vgsEnv = session.vgs_environment;\n if (vaultId && /^tnt[a-z0-9]+$/.test(vaultId) && (vgsEnv === \"sandbox\" || vgsEnv === \"live\")) {\n paymentKitStates.vgsVaultId = vaultId;\n paymentKitStates.vgsEnvironment = vgsEnv;\n console.log(`[PaymentKit] VGS config valid — vaultId: ${vaultId}, environment: ${vgsEnv}`);\n } else if (paymentKitStates.cardTokenizationMode === \"vgs\") {\n console.warn(\n `[PaymentKit] Invalid VGS config from session API (vaultId: ${vaultId}, env: ${vgsEnv}), falling back to direct mode`,\n );\n paymentKitStates.cardTokenizationMode = \"direct\";\n }\n } else {\n console.log(\"[PaymentKit] Session response missing card_tokenization_mode — defaulting to direct mode\");\n paymentKitStates.cardTokenizationMode = \"direct\";\n }\n })\n .catch((err) => {\n console.error(\"[PaymentKit] Session config fetch error — falling back to direct mode:\", err);\n paymentKitStates.cardTokenizationMode = \"direct\";\n });\n } else {\n console.log(`[PaymentKit] cardTokenizationMode explicitly set: ${cardTokenizationMode}`);\n }\n\n const pmInstances = paymentMethods.map((paymentMethod) => paymentMethod(paymentKitStates));\n\n const externalFuncsMapByPm: ExternalFuncsMapByPm<PaymentMethods> = pmInstances.reduce(\n (acc, { name, externalFuncs }) => {\n // @ts-expect-error - typecase this better in future\n acc[name] = externalFuncs;\n return acc;\n },\n {} as ExternalFuncsMapByPm<PaymentMethods>,\n );\n\n const submit: PaymentKitReturnType[\"submit\"] = ({\n paymentMethod: paymentMethodName,\n fields,\n options,\n onSuccess,\n onError,\n }) => {\n const paymentMethod = pmInstances.find(({ name }) => name === paymentMethodName);\n if (!paymentMethod) {\n onError({ root: \"payment_method_not_found\" });\n return;\n }\n paymentMethod.internalFuncs\n .submitPayment(fields, options)\n .then(({ data, errors }) => {\n errors ? onError(errors) : onSuccess(data);\n })\n .catch((e) => {\n console.error(\"PaymentKit:submit:catch\", e);\n\n // Try to extract error message from response\n if (e?.response?.data) {\n onError(e.response.data);\n } else if (e?.message) {\n onError({ root: e.message });\n } else {\n onError({ root: \"unknown_error\" });\n }\n });\n };\n\n const cleanup = () => {\n // Clean up all payment method instances\n for (const pm of pmInstances) {\n if (pm.internalFuncs.cleanup) {\n pm.internalFuncs.cleanup();\n }\n }\n unmountTunnelX();\n };\n\n return {\n submit,\n cleanup,\n ...externalFuncsMapByPm,\n };\n};\n\nexport type { PaymentKitFields };\n\nexport default PaymentKit;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["STATIC_ENVIRONMENT_URLS: Record<Exclude<PaymentKitEnvironment, \"tunnel\">, EnvironmentUrls>","PaymentKit: PaymentKitType","PACKAGE_VERSION","externalFuncsMapByPm: ExternalFuncsMapByPm<PaymentMethods>","submit: PaymentKitReturnType[\"submit\"]"],"sources":["../package.json","../src/analytics/mock-adapter.ts","../src/analytics/posthog-adapter.ts","../src/analytics/service.ts","../src/analytics/checkout-timing.ts","../src/types.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@payment-kit-js/vanilla\",\n \"version\": \"0.5.10\",\n \"main\": \"./dist/index.mjs\",\n \"types\": \"./dist/index.d.mts\",\n \"module\": \"./dist/index.mjs\",\n \"exports\": {\n \".\": \"./dist/index.mjs\",\n \"./payment-methods/airwallex-apple-pay-adapter\": \"./dist/payment-methods/airwallex-apple-pay-adapter.mjs\",\n \"./payment-methods/airwallex-google-pay-adapter\": \"./dist/payment-methods/airwallex-google-pay-adapter.mjs\",\n \"./payment-methods/apple-pay\": \"./dist/payment-methods/apple-pay.mjs\",\n \"./payment-methods/card\": \"./dist/payment-methods/card.mjs\",\n \"./payment-methods/google-pay\": \"./dist/payment-methods/google-pay.mjs\",\n \"./payment-methods/next-action-handlers\": \"./dist/payment-methods/next-action-handlers.mjs\",\n \"./payment-methods/paypal\": \"./dist/payment-methods/paypal.mjs\",\n \"./payment-methods/stripe-apple-pay-adapter\": \"./dist/payment-methods/stripe-apple-pay-adapter.mjs\",\n \"./payment-methods/stripe-google-pay-adapter\": \"./dist/payment-methods/stripe-google-pay-adapter.mjs\",\n \"./payment-methods/vgs-collect-loader\": \"./dist/payment-methods/vgs-collect-loader.mjs\",\n \"./penpal/connect-card\": \"./dist/penpal/connect-card.mjs\",\n \"./penpal/connect-tunnel-x\": \"./dist/penpal/connect-tunnel-x.mjs\",\n \"./package.json\": \"./package.json\"\n },\n \"license\": \"MIT\",\n \"description\": \"Vanilla package for PaymentKit\",\n \"files\": [\n \"dist\",\n \"dist/cdn\"\n ],\n \"scripts\": {\n \"dev\": \"yarn tsdown --watch ./src\",\n \"build:npm\": \"yarn tsdown\",\n \"build:cdn\": \"node build-cdn.mjs\",\n \"build\": \"yarn build:npm && yarn build:cdn\"\n },\n \"packageManager\": \"yarn@4.10.3\",\n \"dependencies\": {\n \"nanoid\": \"^5.0.7\",\n \"penpal\": \"^7.0.4\",\n \"posthog-js\": \"^1.196.0\",\n \"valibot\": \"^1.1.0\"\n },\n \"devDependencies\": {\n \"@pkg/sdk\": \"workspace:*\",\n \"@pkg/tsconfig\": \"workspace:*\",\n \"@stripe/stripe-js\": \"^8.6.1\",\n \"@types/applepayjs\": \"^14.0.9\",\n \"esbuild\": \"^0.24.2\",\n \"tsdown\": \"^0.15.10\",\n \"typescript\": \"^5.9.3\"\n },\n \"stableVersion\": \"0.5.10\"\n}\n","import type { AnalyticsAdapter, CapturedEvent } from \"./types\";\n\n/**\n * Mock analytics adapter for testing.\n *\n * Records all captured events for assertion in tests.\n */\nexport class MockAnalyticsAdapter implements AnalyticsAdapter {\n private events: CapturedEvent[] = [];\n private distinctId: string | null = null;\n\n identify(distinctId: string): void {\n this.distinctId = distinctId;\n }\n\n capture(event: string, properties?: Record<string, unknown>): void {\n this.events.push({\n event,\n distinct_id: this.distinctId,\n properties,\n timestamp: Date.now(),\n });\n }\n\n isInitialized(): boolean {\n return true;\n }\n\n // Test helper methods\n\n /**\n * Get all captured events.\n */\n getEvents(): CapturedEvent[] {\n return [...this.events];\n }\n\n /**\n * Get events by name.\n */\n getEventsByName(eventName: string): CapturedEvent[] {\n return this.events.filter((e) => e.event === eventName);\n }\n\n /**\n * Clear all captured events.\n */\n clear(): void {\n this.events = [];\n }\n}\n","import posthog from \"posthog-js\";\nimport type { AnalyticsAdapter } from \"./types\";\n\n// PostHog API key (PaymentKit internal)\nconst POSTHOG_API_KEY = \"phc_u9YDYUeUxo3CYn16XGrrwpVb8ycXgcjz5DarvIKRAAG\";\n\n/**\n * PostHog implementation of the analytics adapter.\n *\n * Singleton stored in window to ensure only one instance exists across\n * all script loads. Configures PostHog to use the reverse proxy at\n * /ingest to avoid ad blockers.\n */\nexport class PostHogAdapter implements AnalyticsAdapter {\n private initialized = false;\n\n /**\n * Get or create the PostHog adapter singleton (stored in window).\n *\n * @param apiBaseUrl - The API base URL for the reverse proxy\n * @throws Error if called with a different apiBaseUrl than the first call\n */\n static getInstance(apiBaseUrl: string): PostHogAdapter {\n if (typeof window === \"undefined\") {\n throw new Error(\"[PaymentKit Analytics] PostHog requires a browser environment\");\n }\n\n const existing = window.__paymentKitPostHog__;\n if (existing) {\n if (existing.apiBaseUrl !== apiBaseUrl) {\n throw new Error(\n `[PaymentKit Analytics] PostHog already initialized with apiBaseUrl \"${existing.apiBaseUrl}\", ` +\n `cannot re-initialize with different apiBaseUrl \"${apiBaseUrl}\"`,\n );\n }\n return existing.instance;\n }\n\n const instance = new PostHogAdapter(apiBaseUrl);\n window.__paymentKitPostHog__ = { instance, apiBaseUrl };\n return instance;\n }\n\n private constructor(apiBaseUrl: string) {\n this.initPostHog(apiBaseUrl);\n }\n\n private initPostHog(apiBaseUrl: string): void {\n try {\n posthog.init(POSTHOG_API_KEY, {\n // Use reverse proxy to avoid ad blockers\n api_host: `${apiBaseUrl}/ingest`,\n // PostHog UI host (for toolbar, if ever needed)\n ui_host: \"https://us.posthog.com\",\n // Memory persistence - no cookies in embedded checkout iframe\n persistence: \"memory\",\n // Disable session recording - not needed for metrics\n disable_session_recording: true,\n // Manual events only - no autocapture\n autocapture: false,\n // Manual pageview control\n capture_pageview: false,\n // Disable batching - send events immediately to avoid data loss on page close\n request_batching: false,\n // Disable bot detection - allows events from automated tests and debugging environments\n // PostHog detects Playwright/headless browsers as bots by default\n opt_out_useragent_filter: true,\n // Callback when PostHog is ready\n loaded: () => {\n this.initialized = true;\n },\n });\n } catch (e) {\n console.warn(\"[PaymentKit Analytics] Failed to initialize PostHog:\", e);\n }\n }\n\n identify(distinctId: string): void {\n try {\n posthog.identify(distinctId);\n } catch (e) {\n // Silent fail - never break checkout\n console.warn(\"[PaymentKit Analytics] Failed to identify:\", e);\n }\n }\n\n capture(event: string, properties?: Record<string, unknown>): void {\n try {\n posthog.capture(event, properties);\n } catch (e) {\n // Silent fail - never break checkout\n console.warn(\"[PaymentKit Analytics] Failed to capture event:\", e);\n }\n }\n\n isInitialized(): boolean {\n return this.initialized;\n }\n}\n","import { MockAnalyticsAdapter } from \"./mock-adapter\";\nimport { PostHogAdapter } from \"./posthog-adapter\";\nimport type { AnalyticsAdapter } from \"./types\";\n\n/**\n * Analytics service singleton.\n *\n * Provides a global interface for capturing analytics events.\n * Supports multiple adapters that receive all events (composite pattern).\n *\n * Usage:\n * // Initialize (typically done once at SDK init)\n * AnalyticsService.init(\"http://localhost:9000\");\n *\n * // Capture events - broadcasts to all registered adapters\n * AnalyticsService.capture(\"checkout_page_ready\", { session_id: \"...\" });\n *\n * // For testing - add a mock adapter\n * import { MockAnalyticsAdapter } from \"./mock-adapter\";\n * const mock = new MockAnalyticsAdapter();\n * AnalyticsService.addAdapter(mock);\n *\n * // Or use the built-in test mock (exposed globally as window.__paymentKitAnalytics__)\n * AnalyticsService.enableTestMode();\n * // Events can be read via window.__paymentKitAnalytics__.getEvents()\n */\nclass AnalyticsServiceClass {\n private adapters: AnalyticsAdapter[] = [];\n private testMock: MockAnalyticsAdapter | null = null;\n\n /**\n * Initialize the analytics service with PostHog.\n *\n * @param apiBaseUrl - The API base URL for the reverse proxy\n * @param enableTestMode - Enable test mode for capturing events in tests\n */\n init(apiBaseUrl: string, enableTestMode?: boolean): void {\n try {\n // Add PostHog adapter (singleton - safe to call multiple times with same URL)\n this.addAdapter(PostHogAdapter.getInstance(apiBaseUrl));\n\n // Enable test mode if explicitly requested\n if (enableTestMode) {\n this.enableTestMode();\n }\n } catch (e) {\n // Silent fail - analytics should never break checkout\n console.warn(\"[PaymentKit Analytics] Init failed:\", e);\n }\n }\n\n /**\n * Enable test mode by adding a mock adapter and exposing it globally.\n * The mock adapter is accessible via window.__paymentKitAnalytics__\n */\n enableTestMode(): void {\n if (this.testMock) return; // Already enabled\n\n this.testMock = new MockAnalyticsAdapter();\n this.addAdapter(this.testMock);\n\n // Expose globally for Playwright/test access\n if (typeof window !== \"undefined\") {\n window.__paymentKitAnalytics__ = this.testMock;\n }\n }\n\n /**\n * Get the test mock adapter (if test mode is enabled).\n */\n getTestMock(): MockAnalyticsAdapter | null {\n return this.testMock;\n }\n\n /**\n * Add an analytics adapter.\n * Events will be broadcast to all registered adapters.\n * Duplicate adapters (same instance) are ignored.\n *\n * @param adapter - The adapter to add\n */\n addAdapter(adapter: AnalyticsAdapter): void {\n if (!this.adapters.includes(adapter)) {\n this.adapters.push(adapter);\n }\n }\n\n /**\n * Clear all adapters.\n */\n clearAdapters(): void {\n this.adapters = [];\n this.testMock = null;\n if (typeof window !== \"undefined\") {\n delete window.__paymentKitAnalytics__;\n }\n }\n\n /**\n * Set the distinct_id for all adapters.\n * This is used to correlate frontend events with backend events.\n * Should be called with the checkout session secure token.\n */\n identify(distinctId: string): void {\n for (const adapter of this.adapters) {\n try {\n adapter.identify(distinctId);\n } catch {\n // Silent fail - never break checkout\n }\n }\n }\n\n /**\n * Capture an analytics event.\n * Broadcasts to all registered adapters. Silently fails on errors.\n */\n capture(event: string, properties?: Record<string, unknown>): void {\n for (const adapter of this.adapters) {\n try {\n adapter.capture(event, properties);\n } catch {\n // Silent fail - never break checkout\n }\n }\n }\n\n /**\n * Check if any adapter is initialized.\n */\n isInitialized(): boolean {\n return this.adapters.some((adapter) => adapter.isInitialized());\n }\n}\n\n/**\n * Global analytics service instance.\n */\nexport const AnalyticsService = new AnalyticsServiceClass();\n","import { AnalyticsService } from \"./service\";\n\n/**\n * Tracks timing metrics throughout the checkout flow.\n *\n * Create one instance per checkout session and call the track methods\n * at appropriate points in the checkout flow.\n *\n * Usage:\n * const requestId = getOrCreateCheckoutRequestId(environment);\n * const tracker = new CheckoutTimingTracker(secureToken, requestId);\n * tracker.trackPageReady();\n * // ... iframe loads ...\n * tracker.trackInputReady();\n * // ... user submits ...\n * tracker.trackSubmit();\n * // ... API response ...\n * tracker.trackSuccess(attemptId);\n */\nexport class CheckoutTimingTracker {\n // Class-level guard to prevent duplicate page_ready events across PaymentKit instances\n private static pageReadyTracked = false;\n\n private startTime: number;\n private checkoutSessionId: string;\n private requestId: string;\n private inputReadyTracked = false;\n\n constructor(checkoutSessionId: string, requestId: string) {\n this.startTime = performance.now();\n this.checkoutSessionId = checkoutSessionId;\n this.requestId = requestId;\n }\n\n /**\n * Track when SDK is initialized and ready.\n * Call immediately after PaymentKit() initialization.\n * Only tracks once per page load (subsequent calls are no-ops).\n */\n trackPageReady(): void {\n if (CheckoutTimingTracker.pageReadyTracked) return;\n CheckoutTimingTracker.pageReadyTracked = true;\n\n AnalyticsService.capture(\"checkout_page_ready\", {\n checkout_session_id: this.checkoutSessionId,\n request_id: this.requestId,\n elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track when card input iframe is loaded and ready for input.\n * Should only be called once (for first iframe, typically card_pan).\n * Subsequent calls are no-ops.\n */\n trackInputReady(): void {\n if (this.inputReadyTracked) return;\n this.inputReadyTracked = true;\n\n AnalyticsService.capture(\"checkout_input_ready\", {\n checkout_session_id: this.checkoutSessionId,\n request_id: this.requestId,\n elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track when user clicks submit button.\n */\n trackSubmit(): void {\n AnalyticsService.capture(\"checkout_submit\", {\n checkout_session_id: this.checkoutSessionId,\n request_id: this.requestId,\n elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track successful checkout.\n *\n * @param checkoutAttemptId - The checkout attempt ID\n */\n trackSuccess(checkoutAttemptId: string): void {\n AnalyticsService.capture(\"checkout_success\", {\n checkout_session_id: this.checkoutSessionId,\n checkout_attempt_id: checkoutAttemptId,\n request_id: this.requestId,\n total_elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Track failed checkout.\n *\n * @param checkoutAttemptId - The checkout attempt ID (may be null if failed early)\n * @param errorCode - The error code from the checkout response\n * @param errorMessage - The customer-facing error message\n */\n trackFail(checkoutAttemptId: string | null, errorCode: string | null, errorMessage: string | null): void {\n AnalyticsService.capture(\"checkout_fail\", {\n checkout_session_id: this.checkoutSessionId,\n checkout_attempt_id: checkoutAttemptId,\n request_id: this.requestId,\n error_code: errorCode,\n error_message: errorMessage,\n total_elapsed_ms: this.getElapsedMs(),\n });\n }\n\n /**\n * Get elapsed time in milliseconds since tracker creation.\n */\n private getElapsedMs(): number {\n return Math.round(performance.now() - this.startTime);\n }\n}\n","import type { CheckoutTimingTracker } from \"./analytics\";\nimport type { CardErrorCode } from \"./penpal/connect-card\";\nimport type { TunnelXIFrameConnection } from \"./penpal/connect-tunnel-x\";\n\nexport type PaymentKitEnvironment = \"local\" | \"tunnel\" | \"sandbox\" | \"production\";\n\ntype EnvironmentUrls = {\n baseUrl: string;\n apiBaseUrl: string;\n};\n\n// TODO: Cleanup this after launch to only use SDK instead of plain fetch.\nconst STATIC_ENVIRONMENT_URLS: Record<Exclude<PaymentKitEnvironment, \"tunnel\">, EnvironmentUrls> = {\n local: {\n baseUrl: \"http://localhost:9101\",\n apiBaseUrl: \"http://localhost:9000\",\n },\n sandbox: {\n baseUrl: \"https://staging.paymentkit.com/customer\",\n apiBaseUrl: \"https://staging.paymentkit.com\",\n },\n production: {\n baseUrl: \"https://app.paymentkit.com/customer\",\n apiBaseUrl: \"https://app.paymentkit.com\",\n },\n};\n\nfunction getTunnelUrls(): EnvironmentUrls {\n if (typeof window !== \"undefined\") {\n const params = new URLSearchParams(window.location.search);\n const apiBaseUrl = params.get(\"api_base_url\");\n if (apiBaseUrl) {\n return {\n baseUrl: window.location.origin,\n apiBaseUrl,\n };\n }\n // For loclx-style tunnels where API hostname is derived from the current hostname\n const hostname = window.location.hostname;\n if (hostname.includes(\"loclx.io\")) {\n const apiHostname = hostname.replace(/cportal|playground/, \"api\");\n return {\n baseUrl: `https://${hostname}`,\n apiBaseUrl: `https://${apiHostname}`,\n };\n }\n }\n // Fallback\n return STATIC_ENVIRONMENT_URLS.local;\n}\n\nexport function getUrlsForEnvironment(environment: string): EnvironmentUrls {\n if (environment === \"tunnel\") {\n return getTunnelUrls();\n }\n const env = environment as Exclude<PaymentKitEnvironment, \"tunnel\">;\n const urls = STATIC_ENVIRONMENT_URLS[env];\n if (!urls) {\n throw new Error(`Invalid environment: ${environment}. Must be one of: local, tunnel, sandbox, production`);\n }\n return urls;\n}\n\ntype FormFieldNames =\n | \"customer_name\"\n | \"customer_email\"\n | \"customer_country\"\n | \"customer_zip_code\"\n | \"customer_business_name\"\n | \"customer_address_line1\"\n | \"customer_address_line2\"\n | \"customer_city\"\n | \"customer_state\"\n | \"customer_tax_ids\"\n | \"shipping_address_line1\"\n | \"shipping_address_line2\"\n | \"shipping_city\"\n | \"shipping_state\"\n | \"shipping_zip_code\"\n | \"shipping_country\";\n\nexport type FormErrorCodes = \"required\" | \"invalid\";\n\nexport type CardSubmitOptions = {\n skipCustomerValidation?: boolean;\n};\n\nexport type TInternalFuncs = {\n submitPayment: (\n fields: PaymentKitFields,\n options?: CardSubmitOptions,\n ) => Promise<{ data: { [key: string]: unknown }; errors?: never } | { data?: never; errors: PaymentKitErrors }>;\n cleanup?: () => void;\n};\n\nexport type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {\n environment: string;\n secureToken: string;\n paymentMethods: T;\n /** Card tokenization mode from checkout session */\n cardTokenizationMode?: \"direct\" | \"vgs\";\n /** VGS vault ID from checkout session */\n vgsVaultId?: string;\n /** VGS environment from checkout session */\n vgsEnvironment?: string;\n /** @internal Enable analytics test mode for e2e testing */\n __enableAnalyticsTestMode?: boolean;\n}) => ExternalFuncsMapByPm<T> & {\n submit: PaymentKitSubmitHandler<T>;\n cleanup: () => void;\n};\n\ntype PaymentKitSubmitHandler<T extends readonly PaymentMethod<unknown>[]> = <\n N extends keyof ExternalFuncsMapByPm<T>,\n>(options: {\n fields: Partial<PaymentKitFields>;\n paymentMethod: N;\n options?: unknown;\n onError: (error: PaymentKitErrors) => void;\n onSuccess: (data: { [key: string]: unknown }) => void;\n}) => void;\n\nexport type PaymentKitStates = {\n baseUrl: string;\n apiBaseUrl: string;\n secureToken: string;\n environment: string;\n tunnelXConnection: TunnelXIFrameConnection;\n timingTracker: CheckoutTimingTracker;\n /** Checkout request ID for correlating all API calls and analytics events */\n checkoutRequestId: string;\n /** Card tokenization mode: 'direct' (KMS) or 'vgs' (VGS Collect + proxy) */\n cardTokenizationMode?: \"direct\" | \"vgs\";\n /** VGS vault ID (only when cardTokenizationMode is 'vgs') */\n vgsVaultId?: string;\n /** VGS environment: 'sandbox' or 'live' (only when cardTokenizationMode is 'vgs') */\n vgsEnvironment?: string;\n /** @internal Promise that resolves when session config (incl. VGS mode) is auto-detected */\n _sessionConfigReady?: Promise<void>;\n};\n\nexport type PaymentKitErrors = {\n root?: string;\n card_pan?: CardErrorCode;\n card_exp?: CardErrorCode;\n card_cvc?: CardErrorCode;\n paypal?: string;\n google_pay?: string;\n apple_pay?: string;\n processor_id?: string;\n amount?: string;\n currency?: string;\n country?: string;\n} & { [key in FormFieldNames]?: FormErrorCodes | string };\n\nexport type PaymentKitFields = { [key in FormFieldNames]: string };\n\nexport type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates: PaymentKitStates) => {\n name: TName;\n externalFuncs: TExternalFuncs;\n internalFuncs: TInternalFuncs;\n};\n\nexport type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = {\n [K in T[number] as ReturnType<K>[\"name\"]]: ReturnType<K>[\"externalFuncs\"];\n};\n","import { version as PACKAGE_VERSION } from \"../package.json\";\nimport { AnalyticsService, CheckoutTimingTracker } from \"./analytics\";\nimport { connectToTunnelXIframe } from \"./penpal/connect-tunnel-x\";\nimport type { ExternalFuncsMapByPm, PaymentKitFields, PaymentKit as PaymentKitType } from \"./types\";\nimport { getUrlsForEnvironment } from \"./types\";\nimport { createCheckoutIFrame } from \"./utils\";\nimport { getOrCreateCheckoutRequestId } from \"./utils/checkout-request-id\";\n\ntype PaymentKitReturnType = ReturnType<PaymentKitType>;\n\nconst createTunnelXConnection = (baseUrl: string, apiBaseUrl: string, token: string) => {\n const iframe = createCheckoutIFrame(\"tunnel-x\", baseUrl, {\n checkout_token: token,\n api_base_url: apiBaseUrl,\n });\n // Tunnel-X is a hidden communication iframe, not a visible UI element\n Object.assign(iframe.style, { width: \"0\", height: \"0\", position: \"absolute\", visibility: \"hidden\" });\n document.body.appendChild(iframe);\n\n const connection = connectToTunnelXIframe(iframe, {});\n\n const unmount = () => {\n connection.destroy();\n document.body.removeChild(iframe);\n };\n\n return { unmount, connection };\n};\n\nconst PaymentKit: PaymentKitType = ({\n environment,\n secureToken,\n paymentMethods,\n cardTokenizationMode,\n vgsVaultId,\n vgsEnvironment,\n __enableAnalyticsTestMode,\n}) => {\n type PaymentMethods = typeof paymentMethods;\n\n // Resolve URLs from environment\n const { baseUrl, apiBaseUrl } = getUrlsForEnvironment(environment);\n\n // Log version for debugging\n console.log(`[PaymentKit] v${PACKAGE_VERSION} initialized (env: ${environment})`);\n\n // Generate checkout request ID for correlating all API calls and analytics events\n // This is idempotent - same ID is reused across multiple PaymentKit instantiations\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[PaymentKit] checkout_request_id: ${checkoutRequestId}`);\n\n // Initialize analytics and identify with secure token for correlation\n AnalyticsService.init(apiBaseUrl, __enableAnalyticsTestMode);\n AnalyticsService.identify(secureToken);\n\n // Create timing tracker for this checkout session\n const timingTracker = new CheckoutTimingTracker(secureToken, checkoutRequestId);\n\n // Track page ready immediately\n timingTracker.trackPageReady();\n\n const { connection: tunnelXConnection, unmount: unmountTunnelX } = createTunnelXConnection(\n baseUrl,\n apiBaseUrl,\n secureToken,\n );\n\n const paymentKitStates = {\n baseUrl,\n apiBaseUrl,\n secureToken,\n environment,\n tunnelXConnection,\n timingTracker,\n checkoutRequestId,\n cardTokenizationMode,\n vgsVaultId,\n vgsEnvironment,\n _sessionConfigReady: undefined as Promise<void> | undefined,\n };\n\n // Auto-detect VGS mode from session API if not explicitly provided.\n // The promise resolves before any card mount or submit needs the mode.\n if (cardTokenizationMode === undefined) {\n const sessionConfigUrl = `${apiBaseUrl}/api/checkout-sessions/token/${secureToken}`;\n console.log(\n `[PaymentKit] cardTokenizationMode not provided — auto-detecting from session API: ${sessionConfigUrl}`,\n );\n paymentKitStates._sessionConfigReady = fetch(sessionConfigUrl)\n .then((resp) => {\n if (!resp.ok) {\n console.warn(`[PaymentKit] Session config fetch failed with status ${resp.status}`);\n return null;\n }\n return resp.json();\n })\n .then((session) => {\n if (session && typeof session === \"object\" && typeof session.card_tokenization_mode === \"string\") {\n paymentKitStates.cardTokenizationMode = session.card_tokenization_mode || \"direct\";\n console.log(\n `[PaymentKit] Session config detected — cardTokenizationMode: ${paymentKitStates.cardTokenizationMode}`,\n );\n\n // Validate VGS config from API before trusting it\n const vaultId = session.vgs_vault_id;\n const vgsEnv = session.vgs_environment;\n if (vaultId && /^tnt[a-z0-9]+$/.test(vaultId) && (vgsEnv === \"sandbox\" || vgsEnv === \"live\")) {\n paymentKitStates.vgsVaultId = vaultId;\n paymentKitStates.vgsEnvironment = vgsEnv;\n console.log(`[PaymentKit] VGS config valid — vaultId: ${vaultId}, environment: ${vgsEnv}`);\n } else if (paymentKitStates.cardTokenizationMode === \"vgs\") {\n console.warn(\n `[PaymentKit] Invalid VGS config from session API (vaultId: ${vaultId}, env: ${vgsEnv}), falling back to direct mode`,\n );\n paymentKitStates.cardTokenizationMode = \"direct\";\n }\n } else {\n console.log(\"[PaymentKit] Session response missing card_tokenization_mode — defaulting to direct mode\");\n paymentKitStates.cardTokenizationMode = \"direct\";\n }\n })\n .catch((err) => {\n console.error(\"[PaymentKit] Session config fetch error — falling back to direct mode:\", err);\n paymentKitStates.cardTokenizationMode = \"direct\";\n });\n } else {\n console.log(`[PaymentKit] cardTokenizationMode explicitly set: ${cardTokenizationMode}`);\n }\n\n const pmInstances = paymentMethods.map((paymentMethod) => paymentMethod(paymentKitStates));\n\n const externalFuncsMapByPm: ExternalFuncsMapByPm<PaymentMethods> = pmInstances.reduce(\n (acc, { name, externalFuncs }) => {\n // @ts-expect-error - typecase this better in future\n acc[name] = externalFuncs;\n return acc;\n },\n {} as ExternalFuncsMapByPm<PaymentMethods>,\n );\n\n const submit: PaymentKitReturnType[\"submit\"] = ({\n paymentMethod: paymentMethodName,\n fields,\n options,\n onSuccess,\n onError,\n }) => {\n const paymentMethod = pmInstances.find(({ name }) => name === paymentMethodName);\n if (!paymentMethod) {\n onError({ root: \"payment_method_not_found\" });\n return;\n }\n paymentMethod.internalFuncs\n .submitPayment(fields, options)\n .then(({ data, errors }) => {\n errors ? onError(errors) : onSuccess(data);\n })\n .catch((e) => {\n console.error(\"PaymentKit:submit:catch\", e);\n\n // Try to extract error message from response\n if (e?.response?.data) {\n onError(e.response.data);\n } else if (e?.message) {\n onError({ root: e.message });\n } else {\n onError({ root: \"unknown_error\" });\n }\n });\n };\n\n const cleanup = () => {\n // Clean up all payment method instances\n for (const pm of pmInstances) {\n if (pm.internalFuncs.cleanup) {\n pm.internalFuncs.cleanup();\n }\n }\n unmountTunnelX();\n };\n\n return {\n submit,\n cleanup,\n ...externalFuncsMapByPm,\n };\n};\n\nexport type { PaymentKitFields };\n\nexport default PaymentKit;\n"],"mappings":";;;;;;cAEa;;;;;;;;;ACKb,IAAa,uBAAb,MAA8D;CAC5D,AAAQ,SAA0B,EAAE;CACpC,AAAQ,aAA4B;CAEpC,SAAS,YAA0B;AACjC,OAAK,aAAa;;CAGpB,QAAQ,OAAe,YAA4C;AACjE,OAAK,OAAO,KAAK;GACf;GACA,aAAa,KAAK;GAClB;GACA,WAAW,KAAK,KAAK;GACtB,CAAC;;CAGJ,gBAAyB;AACvB,SAAO;;;;;CAQT,YAA6B;AAC3B,SAAO,CAAC,GAAG,KAAK,OAAO;;;;;CAMzB,gBAAgB,WAAoC;AAClD,SAAO,KAAK,OAAO,QAAQ,MAAM,EAAE,UAAU,UAAU;;;;;CAMzD,QAAc;AACZ,OAAK,SAAS,EAAE;;;;;;AC5CpB,MAAM,kBAAkB;;;;;;;;AASxB,IAAa,iBAAb,MAAa,eAA2C;CACtD,AAAQ,cAAc;;;;;;;CAQtB,OAAO,YAAY,YAAoC;AACrD,MAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MAAM,gEAAgE;EAGlF,MAAM,WAAW,OAAO;AACxB,MAAI,UAAU;AACZ,OAAI,SAAS,eAAe,WAC1B,OAAM,IAAI,MACR,uEAAuE,SAAS,WAAW,qDACtC,WAAW,GACjE;AAEH,UAAO,SAAS;;EAGlB,MAAM,WAAW,IAAI,eAAe,WAAW;AAC/C,SAAO,wBAAwB;GAAE;GAAU;GAAY;AACvD,SAAO;;CAGT,AAAQ,YAAY,YAAoB;AACtC,OAAK,YAAY,WAAW;;CAG9B,AAAQ,YAAY,YAA0B;AAC5C,MAAI;AACF,WAAQ,KAAK,iBAAiB;IAE5B,UAAU,GAAG,WAAW;IAExB,SAAS;IAET,aAAa;IAEb,2BAA2B;IAE3B,aAAa;IAEb,kBAAkB;IAElB,kBAAkB;IAGlB,0BAA0B;IAE1B,cAAc;AACZ,UAAK,cAAc;;IAEtB,CAAC;WACK,GAAG;AACV,WAAQ,KAAK,wDAAwD,EAAE;;;CAI3E,SAAS,YAA0B;AACjC,MAAI;AACF,WAAQ,SAAS,WAAW;WACrB,GAAG;AAEV,WAAQ,KAAK,8CAA8C,EAAE;;;CAIjE,QAAQ,OAAe,YAA4C;AACjE,MAAI;AACF,WAAQ,QAAQ,OAAO,WAAW;WAC3B,GAAG;AAEV,WAAQ,KAAK,mDAAmD,EAAE;;;CAItE,gBAAyB;AACvB,SAAO,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtEhB,IAAM,wBAAN,MAA4B;CAC1B,AAAQ,WAA+B,EAAE;CACzC,AAAQ,WAAwC;;;;;;;CAQhD,KAAK,YAAoB,gBAAgC;AACvD,MAAI;AAEF,QAAK,WAAW,eAAe,YAAY,WAAW,CAAC;AAGvD,OAAI,eACF,MAAK,gBAAgB;WAEhB,GAAG;AAEV,WAAQ,KAAK,uCAAuC,EAAE;;;;;;;CAQ1D,iBAAuB;AACrB,MAAI,KAAK,SAAU;AAEnB,OAAK,WAAW,IAAI,sBAAsB;AAC1C,OAAK,WAAW,KAAK,SAAS;AAG9B,MAAI,OAAO,WAAW,YACpB,QAAO,0BAA0B,KAAK;;;;;CAO1C,cAA2C;AACzC,SAAO,KAAK;;;;;;;;;CAUd,WAAW,SAAiC;AAC1C,MAAI,CAAC,KAAK,SAAS,SAAS,QAAQ,CAClC,MAAK,SAAS,KAAK,QAAQ;;;;;CAO/B,gBAAsB;AACpB,OAAK,WAAW,EAAE;AAClB,OAAK,WAAW;AAChB,MAAI,OAAO,WAAW,YACpB,QAAO,OAAO;;;;;;;CASlB,SAAS,YAA0B;AACjC,OAAK,MAAM,WAAW,KAAK,SACzB,KAAI;AACF,WAAQ,SAAS,WAAW;UACtB;;;;;;CAUZ,QAAQ,OAAe,YAA4C;AACjE,OAAK,MAAM,WAAW,KAAK,SACzB,KAAI;AACF,WAAQ,QAAQ,OAAO,WAAW;UAC5B;;;;;CASZ,gBAAyB;AACvB,SAAO,KAAK,SAAS,MAAM,YAAY,QAAQ,eAAe,CAAC;;;;;;AAOnE,MAAa,mBAAmB,IAAI,uBAAuB;;;;;;;;;;;;;;;;;;;;;ACvH3D,IAAa,wBAAb,MAAa,sBAAsB;CAEjC,OAAe,mBAAmB;CAElC,AAAQ;CACR,AAAQ;CACR,AAAQ;CACR,AAAQ,oBAAoB;CAE5B,YAAY,mBAA2B,WAAmB;AACxD,OAAK,YAAY,YAAY,KAAK;AAClC,OAAK,oBAAoB;AACzB,OAAK,YAAY;;;;;;;CAQnB,iBAAuB;AACrB,MAAI,sBAAsB,iBAAkB;AAC5C,wBAAsB,mBAAmB;AAEzC,mBAAiB,QAAQ,uBAAuB;GAC9C,qBAAqB,KAAK;GAC1B,YAAY,KAAK;GACjB,YAAY,KAAK,cAAc;GAChC,CAAC;;;;;;;CAQJ,kBAAwB;AACtB,MAAI,KAAK,kBAAmB;AAC5B,OAAK,oBAAoB;AAEzB,mBAAiB,QAAQ,wBAAwB;GAC/C,qBAAqB,KAAK;GAC1B,YAAY,KAAK;GACjB,YAAY,KAAK,cAAc;GAChC,CAAC;;;;;CAMJ,cAAoB;AAClB,mBAAiB,QAAQ,mBAAmB;GAC1C,qBAAqB,KAAK;GAC1B,YAAY,KAAK;GACjB,YAAY,KAAK,cAAc;GAChC,CAAC;;;;;;;CAQJ,aAAa,mBAAiC;AAC5C,mBAAiB,QAAQ,oBAAoB;GAC3C,qBAAqB,KAAK;GAC1B,qBAAqB;GACrB,YAAY,KAAK;GACjB,kBAAkB,KAAK,cAAc;GACtC,CAAC;;;;;;;;;CAUJ,UAAU,mBAAkC,WAA0B,cAAmC;AACvG,mBAAiB,QAAQ,iBAAiB;GACxC,qBAAqB,KAAK;GAC1B,qBAAqB;GACrB,YAAY,KAAK;GACjB,YAAY;GACZ,eAAe;GACf,kBAAkB,KAAK,cAAc;GACtC,CAAC;;;;;CAMJ,AAAQ,eAAuB;AAC7B,SAAO,KAAK,MAAM,YAAY,KAAK,GAAG,KAAK,UAAU;;;;;;ACrGzD,MAAMA,0BAA6F;CACjG,OAAO;EACL,SAAS;EACT,YAAY;EACb;CACD,SAAS;EACP,SAAS;EACT,YAAY;EACb;CACD,YAAY;EACV,SAAS;EACT,YAAY;EACb;CACF;AAED,SAAS,gBAAiC;AACxC,KAAI,OAAO,WAAW,aAAa;EAEjC,MAAM,aADS,IAAI,gBAAgB,OAAO,SAAS,OAAO,CAChC,IAAI,eAAe;AAC7C,MAAI,WACF,QAAO;GACL,SAAS,OAAO,SAAS;GACzB;GACD;EAGH,MAAM,WAAW,OAAO,SAAS;AACjC,MAAI,SAAS,SAAS,WAAW,EAAE;GACjC,MAAM,cAAc,SAAS,QAAQ,sBAAsB,MAAM;AACjE,UAAO;IACL,SAAS,WAAW;IACpB,YAAY,WAAW;IACxB;;;AAIL,QAAO,wBAAwB;;AAGjC,SAAgB,sBAAsB,aAAsC;AAC1E,KAAI,gBAAgB,SAClB,QAAO,eAAe;CAGxB,MAAM,OAAO,wBADD;AAEZ,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,wBAAwB,YAAY,sDAAsD;AAE5G,QAAO;;;;;AClDT,MAAM,2BAA2B,SAAiB,YAAoB,UAAkB;CACtF,MAAM,SAAS,qBAAqB,YAAY,SAAS;EACvD,gBAAgB;EAChB,cAAc;EACf,CAAC;AAEF,QAAO,OAAO,OAAO,OAAO;EAAE,OAAO;EAAK,QAAQ;EAAK,UAAU;EAAY,YAAY;EAAU,CAAC;AACpG,UAAS,KAAK,YAAY,OAAO;CAEjC,MAAM,aAAa,uBAAuB,QAAQ,EAAE,CAAC;CAErD,MAAM,gBAAgB;AACpB,aAAW,SAAS;AACpB,WAAS,KAAK,YAAY,OAAO;;AAGnC,QAAO;EAAE;EAAS;EAAY;;AAGhC,MAAMC,cAA8B,EAClC,aACA,aACA,gBACA,sBACA,YACA,gBACA,gCACI;CAIJ,MAAM,EAAE,SAAS,eAAe,sBAAsB,YAAY;AAGlE,SAAQ,IAAI,iBAAiBC,QAAgB,qBAAqB,YAAY,GAAG;CAIjF,MAAM,oBAAoB,6BAA6B,YAAY;AACnE,SAAQ,IAAI,qCAAqC,oBAAoB;AAGrE,kBAAiB,KAAK,YAAY,0BAA0B;AAC5D,kBAAiB,SAAS,YAAY;CAGtC,MAAM,gBAAgB,IAAI,sBAAsB,aAAa,kBAAkB;AAG/E,eAAc,gBAAgB;CAE9B,MAAM,EAAE,YAAY,mBAAmB,SAAS,mBAAmB,wBACjE,SACA,YACA,YACD;CAED,MAAM,mBAAmB;EACvB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,qBAAqB;EACtB;AAID,KAAI,yBAAyB,QAAW;EACtC,MAAM,mBAAmB,GAAG,WAAW,+BAA+B;AACtE,UAAQ,IACN,qFAAqF,mBACtF;AACD,mBAAiB,sBAAsB,MAAM,iBAAiB,CAC3D,MAAM,SAAS;AACd,OAAI,CAAC,KAAK,IAAI;AACZ,YAAQ,KAAK,wDAAwD,KAAK,SAAS;AACnF,WAAO;;AAET,UAAO,KAAK,MAAM;IAClB,CACD,MAAM,YAAY;AACjB,OAAI,WAAW,OAAO,YAAY,YAAY,OAAO,QAAQ,2BAA2B,UAAU;AAChG,qBAAiB,uBAAuB,QAAQ,0BAA0B;AAC1E,YAAQ,IACN,gEAAgE,iBAAiB,uBAClF;IAGD,MAAM,UAAU,QAAQ;IACxB,MAAM,SAAS,QAAQ;AACvB,QAAI,WAAW,iBAAiB,KAAK,QAAQ,KAAK,WAAW,aAAa,WAAW,SAAS;AAC5F,sBAAiB,aAAa;AAC9B,sBAAiB,iBAAiB;AAClC,aAAQ,IAAI,4CAA4C,QAAQ,iBAAiB,SAAS;eACjF,iBAAiB,yBAAyB,OAAO;AAC1D,aAAQ,KACN,8DAA8D,QAAQ,SAAS,OAAO,gCACvF;AACD,sBAAiB,uBAAuB;;UAErC;AACL,YAAQ,IAAI,2FAA2F;AACvG,qBAAiB,uBAAuB;;IAE1C,CACD,OAAO,QAAQ;AACd,WAAQ,MAAM,0EAA0E,IAAI;AAC5F,oBAAiB,uBAAuB;IACxC;OAEJ,SAAQ,IAAI,qDAAqD,uBAAuB;CAG1F,MAAM,cAAc,eAAe,KAAK,kBAAkB,cAAc,iBAAiB,CAAC;CAE1F,MAAMC,uBAA6D,YAAY,QAC5E,KAAK,EAAE,MAAM,oBAAoB;AAEhC,MAAI,QAAQ;AACZ,SAAO;IAET,EAAE,CACH;CAED,MAAMC,UAA0C,EAC9C,eAAe,mBACf,QACA,SACA,WACA,cACI;EACJ,MAAM,gBAAgB,YAAY,MAAM,EAAE,WAAW,SAAS,kBAAkB;AAChF,MAAI,CAAC,eAAe;AAClB,WAAQ,EAAE,MAAM,4BAA4B,CAAC;AAC7C;;AAEF,gBAAc,cACX,cAAc,QAAQ,QAAQ,CAC9B,MAAM,EAAE,MAAM,aAAa;AAC1B,YAAS,QAAQ,OAAO,GAAG,UAAU,KAAK;IAC1C,CACD,OAAO,MAAM;AACZ,WAAQ,MAAM,2BAA2B,EAAE;AAG3C,OAAI,GAAG,UAAU,KACf,SAAQ,EAAE,SAAS,KAAK;YACf,GAAG,QACZ,SAAQ,EAAE,MAAM,EAAE,SAAS,CAAC;OAE5B,SAAQ,EAAE,MAAM,iBAAiB,CAAC;IAEpC;;CAGN,MAAM,gBAAgB;AAEpB,OAAK,MAAM,MAAM,YACf,KAAI,GAAG,cAAc,QACnB,IAAG,cAAc,SAAS;AAG9B,kBAAgB;;AAGlB,QAAO;EACL;EACA;EACA,GAAG;EACJ;;AAKH,kBAAe"}
@@ -1,2 +1,2 @@
1
- import { a as ApplePayEncryptedToken, i as AirwallexApplePayShowResult, n as AirwallexApplePayConfig, o as MerchantValidationCallback, r as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-I_pnNYdy.mjs";
1
+ import { a as ApplePayEncryptedToken, i as AirwallexApplePayShowResult, n as AirwallexApplePayConfig, o as MerchantValidationCallback, r as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-BCYt7Jzc.mjs";
2
2
  export { AirwallexApplePayAdapter, AirwallexApplePayConfig, AirwallexApplePayMockScenario, AirwallexApplePayShowResult, ApplePayEncryptedToken, MerchantValidationCallback };
@@ -1,3 +1,3 @@
1
- import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-BE15xREr.mjs";
1
+ import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-BFsoDoSf.mjs";
2
2
 
3
3
  export { AirwallexApplePayAdapter, AirwallexApplePayMockScenario };
@@ -1,7 +1,7 @@
1
1
  import { r as PaymentMethod } from "../types-D88-nhWu.mjs";
2
2
  import "../connect-card-Cxy51W6t.mjs";
3
3
  import "../connect-tunnel-x-lv6Wtdme.mjs";
4
- import { a as ApplePayEncryptedToken } from "../airwallex-apple-pay-adapter-I_pnNYdy.mjs";
4
+ import { a as ApplePayEncryptedToken } from "../airwallex-apple-pay-adapter-BCYt7Jzc.mjs";
5
5
  import { t as ApplePayMockScenario } from "../stripe-apple-pay-adapter-DhpGclW9.mjs";
6
6
 
7
7
  //#region src/payment-methods/apple-pay.d.ts
@@ -46,15 +46,29 @@ type ApplePayConfirmRequest = {
46
46
  apple_pay_token?: ApplePayEncryptedToken | {
47
47
  [key: string]: unknown;
48
48
  };
49
+ payer_email?: string;
49
50
  mock_scenario?: string;
50
51
  };
51
52
  type ApplePayConfirmResponse = {
52
53
  charge_status: "success" | "fail" | "pending";
53
54
  transaction_id?: string;
55
+ error_code?: string;
54
56
  error_message_for_customer?: string;
55
57
  error_message_for_debug?: string;
56
58
  checkout_attempt_id: string;
59
+ checkout_session_id?: string;
57
60
  next_action?: Airwallex3dsNextAction;
61
+ payment_intent_id?: string;
62
+ customer_id?: string;
63
+ payment_method_id?: string;
64
+ processor_used?: string;
65
+ subscription_id?: string;
66
+ invoice_id?: string;
67
+ invoice_number?: number;
68
+ card_brand?: string;
69
+ card_last4?: string;
70
+ card_exp_month?: number;
71
+ card_exp_year?: number;
58
72
  };
59
73
  type ApplePaySubmitOptions = {
60
74
  processorId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"apple-pay.d.mts","names":[],"sources":["../../src/payment-methods/apple-pay.ts"],"sourcesContent":[],"mappings":";;;;;;;KAYY,oBAAA;;;;KAKA,oBAAA;EALA,YAAA,EAAA,MAAA;EAKA,aAAA,EAEK,oBAAA;EAYL,cAAA,EAAA;IAkBA,SAAA,CAAA,EAAA,MAAA;IAKA,WAAA,CAAA,EAAA;MAQA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAuB;IASvB,CAAA;IAoKU,kBAAe,CAAA,EAAA;MAwFrB,CAAA,GAAA,EAAA,MAAA,CAAkB,EAAA,OAAA;IAOlB,CAAA;EA2ZV,CAAA;EAI2B,aAAA,CAAA,EAAA,MAAA;EAAqB,cAAA,CAAA,EAAA,MAAA;EAAA,kBAAA,CAAA,EAAA,MAAA;CAJ3B;KAtsBf,qBAAA;;;;;;;;;;;;KAkBA,sBAAA;;;;KAKA,sBAAA;;oBAIQ;;;;;KAIR,uBAAA;;;;;;gBAMI;;KAGJ,qBAAA;;;gBAGI;iBACC;;;;;;;;;;;;;iBAgKK,eAAA,mDAGX,6CAER;;;;;;;;iBAmFa,kBAAA,CAAA;;;;iBAOA,qBAAA,CAAA;cA2ZV,uBAIgD;6BAArB,0BAAqB"}
1
+ {"version":3,"file":"apple-pay.d.mts","names":[],"sources":["../../src/payment-methods/apple-pay.ts"],"sourcesContent":[],"mappings":";;;;;;;KAYY,oBAAA;;;;KAKA,oBAAA;EALA,YAAA,EAAA,MAAA;EAKA,aAAA,EAEK,oBAAA;EAYL,cAAA,EAAA;IAkBA,SAAA,CAAA,EAAA,MAAA;IAKA,WAAA,CAAA,EAAA;MAUA,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAuB;IAsBvB,CAAA;IAqLU,kBAAe,CAAA,EAAA;MAwFrB,CAAA,GAAA,EAAA,MAAA,CAAkB,EAAA,OAAA;IAOlB,CAAA;EAqbV,CAAA;EAI2B,aAAA,CAAA,EAAA,MAAA;EAAqB,cAAA,CAAA,EAAA,MAAA;EAAA,kBAAA,CAAA,EAAA,MAAA;CAJ3B;KAhwBf,qBAAA;;;;;;;;;;;;KAkBA,sBAAA;;;;KAKA,sBAAA;;oBAIQ;;;;;;KAMR,uBAAA;;;;;;;;gBAQI;;;;;;;;;;;;;KAcJ,qBAAA;;;gBAGI;iBACC;;;;;;;;;;;;;iBAiLK,eAAA,mDAGX,6CAER;;;;;;;;iBAmFa,kBAAA,CAAA;;;;iBAOA,qBAAA,CAAA;cAqbV,uBAIgD;6BAArB,0BAAqB"}
@@ -1,5 +1,5 @@
1
1
  import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-B70Y8YcZ.mjs";
2
- import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-BE15xREr.mjs";
2
+ import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-BFsoDoSf.mjs";
3
3
  import { t as handleNextAction } from "../next-action-handlers-CTx8tRt0.mjs";
4
4
  import { n as StripeApplePayAdapter, t as ApplePayMockScenario } from "../stripe-apple-pay-adapter-Cd9LVNnp.mjs";
5
5
 
@@ -47,12 +47,13 @@ function initializeStripeAdapter(stripePk, mockScenario) {
47
47
  if (!adapter.initialize(stripePk)) return { error: "Stripe.js not loaded. Add <script src=\"https://js.stripe.com/v3/\"><\/script> to your page." };
48
48
  return { adapter };
49
49
  }
50
- async function callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId, mockScenarioStr, checkoutRequestId) {
50
+ async function callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId, mockScenarioStr, checkoutRequestId, payerEmail) {
51
51
  const result = await apiCall(`${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/confirm`, {
52
52
  method: "POST",
53
53
  headers: { "Content-Type": "application/json" },
54
54
  body: JSON.stringify({
55
55
  payment_method_id: paymentMethodId,
56
+ payer_email: payerEmail,
56
57
  mock_scenario: mockScenarioStr
57
58
  })
58
59
  }, checkoutRequestId);
@@ -61,8 +62,23 @@ async function callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodI
61
62
  if (confirmData.charge_status === "success") return { data: {
62
63
  id: confirmData.transaction_id,
63
64
  checkoutAttemptId: confirmData.checkout_attempt_id,
64
- checkoutSessionId: secureToken,
65
- state: "checkout_succeeded"
65
+ checkoutSessionId: confirmData.checkout_session_id ?? secureToken,
66
+ state: "checkout_succeeded",
67
+ paymentIntentId: confirmData.payment_intent_id,
68
+ customerId: confirmData.customer_id,
69
+ paymentMethodId: confirmData.payment_method_id,
70
+ processorUsed: confirmData.processor_used,
71
+ subscriptionId: confirmData.subscription_id,
72
+ invoiceId: confirmData.invoice_id,
73
+ invoiceNumber: confirmData.invoice_number,
74
+ cardBrand: confirmData.card_brand,
75
+ cardLast4: confirmData.card_last4,
76
+ cardExpMonth: confirmData.card_exp_month,
77
+ cardExpYear: confirmData.card_exp_year,
78
+ errorCode: confirmData.error_code,
79
+ errorMessageForCustomer: confirmData.error_message_for_customer,
80
+ errorMessageForDebug: confirmData.error_message_for_debug,
81
+ nextAction: confirmData.next_action
66
82
  } };
67
83
  return { errors: { apple_pay: confirmData.error_message_for_customer || confirmData.error_message_for_debug || "Payment failed" } };
68
84
  }
@@ -159,12 +175,13 @@ async function callAirwallexStartEndpoint(apiBaseUrl, secureToken, options, vali
159
175
  })
160
176
  }, checkoutRequestId);
161
177
  }
162
- async function callAirwallexConfirmEndpoint(apiBaseUrl, secureToken, applePayToken, mockScenarioStr, checkoutRequestId) {
178
+ async function callAirwallexConfirmEndpoint(apiBaseUrl, secureToken, applePayToken, mockScenarioStr, checkoutRequestId, payerEmail) {
163
179
  const result = await apiCall(`${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/confirm`, {
164
180
  method: "POST",
165
181
  headers: { "Content-Type": "application/json" },
166
182
  body: JSON.stringify({
167
183
  apple_pay_token: applePayToken,
184
+ payer_email: payerEmail,
168
185
  mock_scenario: mockScenarioStr
169
186
  })
170
187
  }, checkoutRequestId);
@@ -191,8 +208,23 @@ function toApplePayResult(response, secureToken) {
191
208
  if (response.charge_status === "success") return { data: {
192
209
  id: response.transaction_id,
193
210
  checkoutAttemptId: response.checkout_attempt_id,
194
- checkoutSessionId: secureToken,
195
- state: "checkout_succeeded"
211
+ checkoutSessionId: response.checkout_session_id ?? secureToken,
212
+ state: "checkout_succeeded",
213
+ paymentIntentId: response.payment_intent_id,
214
+ customerId: response.customer_id,
215
+ paymentMethodId: response.payment_method_id,
216
+ processorUsed: response.processor_used,
217
+ subscriptionId: response.subscription_id,
218
+ invoiceId: response.invoice_id,
219
+ invoiceNumber: response.invoice_number,
220
+ cardBrand: response.card_brand,
221
+ cardLast4: response.card_last4,
222
+ cardExpMonth: response.card_exp_month,
223
+ cardExpYear: response.card_exp_year,
224
+ errorCode: response.error_code,
225
+ errorMessageForCustomer: response.error_message_for_customer,
226
+ errorMessageForDebug: response.error_message_for_debug,
227
+ nextAction: response.next_action
196
228
  } };
197
229
  return { errors: { apple_pay: response.error_message_for_customer || response.error_message_for_debug || "Payment failed" } };
198
230
  }
@@ -234,8 +266,8 @@ async function runAirwallexFlow(apiBaseUrl, secureToken, options, mockScenarioSt
234
266
  if ("cancelled" in paymentResult && paymentResult.cancelled) return { errors: { apple_pay: "Apple Pay cancelled by user" } };
235
267
  return { errors: { apple_pay: paymentResult.error || "Apple Pay failed" } };
236
268
  }
237
- const { token, complete } = paymentResult;
238
- let response = await callAirwallexConfirmEndpoint(apiBaseUrl, secureToken, token, mockScenarioStr, checkoutRequestId);
269
+ const { token, complete, payerEmail } = paymentResult;
270
+ let response = await callAirwallexConfirmEndpoint(apiBaseUrl, secureToken, token, mockScenarioStr, checkoutRequestId, payerEmail);
239
271
  let userActionCount = 0;
240
272
  while (response.charge_status === "pending" && response.next_action && userActionCount < MAX_USER_ACTIONS) {
241
273
  userActionCount++;
@@ -282,8 +314,8 @@ const defSubmitPayment = (states) => {
282
314
  if ("cancelled" in paymentResult$1 && paymentResult$1.cancelled) return { errors: { apple_pay: "Apple Pay cancelled by user" } };
283
315
  return { errors: { apple_pay: "error" in paymentResult$1 ? paymentResult$1.error : "Unknown error" } };
284
316
  }
285
- const { paymentMethodId: paymentMethodId$1, paymentMethodEvent: paymentMethodEvent$1 } = paymentResult$1;
286
- const confirmResult$1 = await callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId$1, mockScenarioStr, preparedStripeState.checkoutRequestId);
317
+ const { paymentMethodId: paymentMethodId$1, paymentMethodEvent: paymentMethodEvent$1, billingDetails: billingDetails$1 } = paymentResult$1;
318
+ const confirmResult$1 = await callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId$1, mockScenarioStr, preparedStripeState.checkoutRequestId, billingDetails$1?.email);
287
319
  if (confirmResult$1.data) {
288
320
  paymentMethodEvent$1.complete("success");
289
321
  clearPreparedApplePay();
@@ -319,8 +351,8 @@ const defSubmitPayment = (states) => {
319
351
  if ("cancelled" in paymentResult && paymentResult.cancelled) return { errors: { apple_pay: "Apple Pay cancelled by user" } };
320
352
  return { errors: { apple_pay: "error" in paymentResult ? paymentResult.error : "Unknown error" } };
321
353
  }
322
- const { paymentMethodId, paymentMethodEvent } = paymentResult;
323
- const confirmResult = await callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId, mockScenarioStr, checkoutRequestId);
354
+ const { paymentMethodId, paymentMethodEvent, billingDetails } = paymentResult;
355
+ const confirmResult = await callStripeConfirmEndpoint(apiBaseUrl, secureToken, paymentMethodId, mockScenarioStr, checkoutRequestId, billingDetails?.email);
324
356
  if (confirmResult.data) {
325
357
  paymentMethodEvent.complete("success");
326
358
  return confirmResult;
@@ -1 +1 @@
1
- {"version":3,"file":"apple-pay.mjs","names":["preparedStripeState: PreparedStripeApplePayState | null","airwallexMockScenario: AirwallexApplePayMockScenario","config: AirwallexApplePayConfig","submitPayment: TInternalFuncs[\"submitPayment\"]","paymentResult","confirmResult","paymentMethodId"],"sources":["../../src/payment-methods/apple-pay.ts"],"sourcesContent":["import type { PaymentKitErrors, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport { collectFraudMetadata, definePaymentMethod, getOrCreateCheckoutRequestId } from \"../utils\";\nimport {\n AirwallexApplePayAdapter,\n type AirwallexApplePayConfig,\n AirwallexApplePayMockScenario,\n type ApplePayEncryptedToken,\n} from \"./airwallex-apple-pay-adapter\";\nimport { handleNextAction } from \"./next-action-handlers\";\nimport { ApplePayMockScenario, StripeApplePayAdapter } from \"./stripe-apple-pay-adapter\";\n\n// Apple Pay-specific types\nexport type ApplePayCustomerInfo = {\n first_name: string;\n last_name: string;\n};\n\nexport type ApplePayStartRequest = {\n processor_id: string;\n customer_info: ApplePayCustomerInfo;\n fraud_metadata: {\n ipAddress?: string;\n browserInfo?: { [key: string]: unknown };\n processorFraudInfo?: { [key: string]: unknown };\n };\n mock_scenario?: string;\n // Airwallex-specific fields (sent on /start for merchant validation)\n validation_url?: string;\n initiative_context?: string;\n};\n\nexport type ApplePayStartResponse = {\n checkout_attempt_id: string;\n amount: number;\n currency: string;\n country: string;\n\n // Processor discriminator\n processor: \"stripe\" | \"airwallex\";\n\n // Stripe-specific fields (when processor=\"stripe\")\n client_secret?: string;\n stripe_pk?: string;\n\n // Airwallex-specific fields (when processor=\"airwallex\")\n merchant_session?: { [key: string]: unknown }; // Apple merchant session for completeMerchantValidation()\n};\n\n// Airwallex 3DS next action type (matches backend snake_case response)\nexport type Airwallex3dsNextAction = {\n type: \"airwallex_3ds\";\n url: string;\n};\n\nexport type ApplePayConfirmRequest = {\n // Stripe: Send PaymentMethod ID\n payment_method_id?: string;\n // Airwallex: Send encrypted Apple Pay token\n apple_pay_token?: ApplePayEncryptedToken | { [key: string]: unknown };\n mock_scenario?: string;\n};\n\nexport type ApplePayConfirmResponse = {\n charge_status: \"success\" | \"fail\" | \"pending\";\n transaction_id?: string;\n error_message_for_customer?: string;\n error_message_for_debug?: string;\n checkout_attempt_id: string;\n next_action?: Airwallex3dsNextAction; // Present when charge_status=\"pending\" for 3DS\n};\n\nexport type ApplePaySubmitOptions = {\n processorId: string;\n processorType?: \"stripe\" | \"airwallex\";\n customerInfo: ApplePayCustomerInfo;\n mockScenario?: ApplePayMockScenario;\n amount?: number; // Amount in atomic units (cents) for Apple Pay sheet display\n currency?: string; // Currency code (e.g., \"usd\")\n country: string; // Country code (e.g., \"US\") for Apple Pay sheet — required\n merchantName?: string; // Merchant display name on Apple Pay sheet\n};\n\ntype ApplePayResult =\n | { data: { [key: string]: unknown }; errors?: undefined }\n | { data?: undefined; errors: PaymentKitErrors };\n\n// =============================================================================\n// Prepared Payment State (for Stripe pre-fetching before click)\n// =============================================================================\n\ntype PreparedStripeApplePayState = {\n processor: \"stripe\";\n adapter: StripeApplePayAdapter;\n startData: ApplePayStartResponse;\n mockScenarioStr?: string;\n checkoutRequestId: string;\n};\n\n// Global state to store prepared Apple Pay data (Stripe only - Airwallex uses native session)\nlet preparedStripeState: PreparedStripeApplePayState | null = null;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\nasync function apiCall<T>(\n url: string,\n options: RequestInit,\n checkoutRequestId?: string,\n): Promise<{ data?: T; error?: string }> {\n const headers = new Headers(options.headers);\n if (checkoutRequestId) {\n headers.set(\"x-request-id\", checkoutRequestId);\n }\n\n const response = await fetch(url, { ...options, headers });\n if (!response.ok) {\n let errorMessage = `Request failed (${response.status})`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.detail || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n return { error: errorMessage };\n }\n return { data: await response.json() };\n}\n\nfunction validateOptions(options: ApplePaySubmitOptions): PaymentKitErrors | null {\n if (!options?.processorId) {\n return { processor_id: \"Processor ID is required\" };\n }\n return null;\n}\n\nfunction getMockScenarioStr(mockScenario?: ApplePayMockScenario): string | undefined {\n return mockScenario && mockScenario !== ApplePayMockScenario.None ? mockScenario : undefined;\n}\n\n// =============================================================================\n// Stripe Apple Pay Flow\n// =============================================================================\n\nasync function callStripeStartEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<{ data?: ApplePayStartResponse; error?: string }> {\n return apiCall<ApplePayStartResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/start`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n processor_id: options.processorId,\n customer_info: options.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n mock_scenario: mockScenarioStr,\n } as ApplePayStartRequest),\n },\n checkoutRequestId,\n );\n}\n\nfunction initializeStripeAdapter(\n stripePk: string,\n mockScenario?: ApplePayMockScenario,\n): { adapter?: StripeApplePayAdapter; error?: string } {\n const adapter = new StripeApplePayAdapter(mockScenario);\n\n if (!adapter.initialize(stripePk)) {\n return { error: 'Stripe.js not loaded. Add <script src=\"https://js.stripe.com/v3/\"></script> to your page.' };\n }\n\n return { adapter };\n}\n\nasync function callStripeConfirmEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n paymentMethodId: string,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<ApplePayResult> {\n const result = await apiCall<ApplePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/confirm`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n payment_method_id: paymentMethodId,\n mock_scenario: mockScenarioStr,\n } as ApplePayConfirmRequest),\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return { errors: { apple_pay: result.error || \"Failed to confirm payment\" } };\n }\n\n const confirmData = result.data;\n\n if (confirmData.charge_status === \"success\") {\n return {\n data: {\n id: confirmData.transaction_id,\n checkoutAttemptId: confirmData.checkout_attempt_id,\n checkoutSessionId: secureToken,\n state: \"checkout_succeeded\",\n },\n };\n }\n\n return {\n errors: {\n apple_pay: confirmData.error_message_for_customer || confirmData.error_message_for_debug || \"Payment failed\",\n },\n };\n}\n\n// =============================================================================\n// Prepare Function (call BEFORE the click handler)\n// =============================================================================\n\n/**\n * Pre-fetch Apple Pay data and prepare the PaymentRequest.\n * Call this when the checkout page loads, NOT in the click handler.\n *\n * For Stripe: pre-fetches data and prepares PaymentRequest for immediate show.\n * For Airwallex: returns success with processor=\"airwallex\" so submit uses native ApplePaySession.\n */\nexport async function prepareApplePay(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n environment: string,\n): Promise<{ success: boolean; error?: string; applePay?: boolean }> {\n console.log(\"[ApplePay] prepareApplePay called\");\n\n // Clear any previous state\n preparedStripeState = null;\n\n const mockScenarioStr = getMockScenarioStr(options.mockScenario);\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[ApplePay] Using checkout_request_id: ${checkoutRequestId}`);\n\n // Airwallex doesn't use the prepare pattern - it uses native ApplePaySession\n // Skip the Stripe /start call entirely for Airwallex processors\n if (options.processorType === \"airwallex\") {\n console.log(\"[ApplePay] Airwallex processor - will use native ApplePaySession on submit\");\n return { success: true, applePay: true };\n }\n\n // Call Stripe start endpoint to get PaymentIntent details\n const startResult = await callStripeStartEndpoint(\n apiBaseUrl,\n secureToken,\n options,\n mockScenarioStr,\n checkoutRequestId,\n );\n if (startResult.error || !startResult.data) {\n return { success: false, error: startResult.error || \"Failed to start Apple Pay\" };\n }\n\n const startData = startResult.data;\n\n // Initialize Stripe adapter\n if (!startData.stripe_pk) {\n return { success: false, error: \"Stripe publishable key not provided\" };\n }\n\n const { adapter, error: adapterError } = initializeStripeAdapter(startData.stripe_pk, options.mockScenario);\n if (!adapter) {\n return { success: false, error: adapterError };\n }\n\n // Create PaymentRequest and call canMakePayment() (required before show())\n const prepareResult = await adapter.preparePaymentRequest({\n country: startData.country,\n currency: startData.currency.toLowerCase(),\n total: {\n label: \"Total\",\n amount: startData.amount,\n },\n });\n\n if (!prepareResult.success) {\n return {\n success: false,\n error: prepareResult.error || \"Failed to prepare payment request\",\n applePay: prepareResult.applePay,\n };\n }\n\n if (!prepareResult.applePay) {\n return {\n success: false,\n error: \"Apple Pay is not available on this device or Stripe account\",\n applePay: false,\n };\n }\n\n // Store the prepared state\n preparedStripeState = {\n processor: \"stripe\",\n adapter,\n startData,\n mockScenarioStr,\n checkoutRequestId,\n };\n\n console.log(\"[ApplePay] prepareApplePay success (Stripe), ready for click\");\n return { success: true, applePay: true };\n}\n\n/**\n * Check if Apple Pay has been prepared and is ready.\n */\nexport function isApplePayPrepared(): boolean {\n return preparedStripeState?.adapter.isPrepared() ?? false;\n}\n\n/**\n * Clear prepared state (call on unmount or when checkout changes).\n */\nexport function clearPreparedApplePay(): void {\n if (preparedStripeState) {\n preparedStripeState.adapter.clearPrepared();\n }\n preparedStripeState = null;\n}\n\n// =============================================================================\n// Airwallex Apple Pay Flow\n// =============================================================================\n\nasync function callAirwallexStartEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n validationUrl: string,\n initiativeContext: string,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<{ data?: ApplePayStartResponse; error?: string }> {\n return apiCall<ApplePayStartResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/start`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n processor_id: options.processorId,\n customer_info: options.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n validation_url: validationUrl,\n initiative_context: initiativeContext,\n mock_scenario: mockScenarioStr,\n } as ApplePayStartRequest),\n },\n checkoutRequestId,\n );\n}\n\nasync function callAirwallexConfirmEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n applePayToken: ApplePayEncryptedToken,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<ApplePayConfirmResponse> {\n const result = await apiCall<ApplePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/confirm`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n apple_pay_token: applePayToken,\n mock_scenario: mockScenarioStr,\n } as ApplePayConfirmRequest),\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message_for_debug: result.error || \"Failed to confirm payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\nasync function callAirwallexVerifyEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n checkoutRequestId?: string,\n): Promise<ApplePayConfirmResponse> {\n const result = await apiCall<ApplePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/verify`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message_for_debug: result.error || \"Failed to verify payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\nfunction toApplePayResult(response: ApplePayConfirmResponse, secureToken: string): ApplePayResult {\n if (response.charge_status === \"success\") {\n return {\n data: {\n id: response.transaction_id,\n checkoutAttemptId: response.checkout_attempt_id,\n checkoutSessionId: secureToken,\n state: \"checkout_succeeded\",\n },\n };\n }\n return {\n errors: {\n apple_pay: response.error_message_for_customer || response.error_message_for_debug || \"Payment failed\",\n },\n };\n}\n\nconst MAX_USER_ACTIONS = 5;\n\n/**\n * Run the Airwallex Apple Pay flow with 3DS loop support.\n *\n * Flow:\n * 1. Show native ApplePaySession, call /start for merchant validation\n * 2. On payment authorized, call /confirm with token\n * 3. If 3DS required, handle it and call /verify\n * 4. Loop if more 3DS needed\n */\nasync function runAirwallexFlow(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<ApplePayResult> {\n // Convert mock scenario\n let airwallexMockScenario: AirwallexApplePayMockScenario = AirwallexApplePayMockScenario.None;\n if (options.mockScenario === ApplePayMockScenario.Success) {\n airwallexMockScenario = AirwallexApplePayMockScenario.Success;\n } else if (options.mockScenario === ApplePayMockScenario.Cancelled) {\n airwallexMockScenario = AirwallexApplePayMockScenario.Cancelled;\n }\n\n // Initialize adapter\n const adapter = new AirwallexApplePayAdapter(airwallexMockScenario);\n\n const config: AirwallexApplePayConfig = {\n amount: options.amount || 0,\n currency: (options.currency || \"USD\").toUpperCase(),\n country: options.country.toUpperCase(),\n merchantName: options.merchantName || \"Total\",\n };\n\n if (!adapter.initialize(config)) {\n return { errors: { apple_pay: \"Apple Pay not available on this device (requires Safari)\" } };\n }\n\n const canPay = await adapter.canMakePayment();\n if (!canPay) {\n return { errors: { apple_pay: \"Apple Pay not available on this device\" } };\n }\n\n // Get current domain for initiative_context\n const initiativeContext = typeof window !== \"undefined\" ? window.location.hostname : \"\";\n\n // In mock mode, call /start first to create checkout attempt (mock adapter skips merchant validation)\n if (airwallexMockScenario !== AirwallexApplePayMockScenario.None) {\n const startResult = await callAirwallexStartEndpoint(\n apiBaseUrl,\n secureToken,\n options,\n \"https://mock-apple-pay-gateway.example.com/paymentservices/startSession\",\n initiativeContext,\n mockScenarioStr,\n checkoutRequestId,\n );\n if (startResult.error || !startResult.data) {\n return { errors: { apple_pay: startResult.error || \"Failed to start mock checkout\" } };\n }\n }\n\n // Show Apple Pay sheet with merchant validation callback\n const paymentResult = await adapter.showPaymentSheet(async (validationUrl: string) => {\n // Call /start endpoint for merchant validation\n const startResult = await callAirwallexStartEndpoint(\n apiBaseUrl,\n secureToken,\n options,\n validationUrl,\n initiativeContext,\n mockScenarioStr,\n checkoutRequestId,\n );\n\n if (startResult.error || !startResult.data) {\n return { error: startResult.error || \"Merchant validation failed\" };\n }\n\n if (!startResult.data.merchant_session) {\n return { error: \"No merchant session returned from server\" };\n }\n\n return { merchantSession: startResult.data.merchant_session };\n });\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { errors: { apple_pay: \"Apple Pay cancelled by user\" } };\n }\n return { errors: { apple_pay: paymentResult.error || \"Apple Pay failed\" } };\n }\n\n const { token, complete } = paymentResult;\n\n // Call /confirm with the token\n let response = await callAirwallexConfirmEndpoint(apiBaseUrl, secureToken, token, mockScenarioStr, checkoutRequestId);\n\n // Handle 3DS loop\n let userActionCount = 0;\n while (response.charge_status === \"pending\" && response.next_action && userActionCount < MAX_USER_ACTIONS) {\n userActionCount++;\n\n // Handle 3DS challenge — Airwallex3dsNextAction is structurally identical to SDK's Airwallex3dsAction\n const nextAction = response.next_action as Airwallex3dsNextAction;\n const actionResult = await handleNextAction({ type: nextAction.type, url: nextAction.url });\n\n // Call verify endpoint\n const verifyResponse = await callAirwallexVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId);\n\n // Check if another 3DS action is required\n if (verifyResponse.charge_status === \"pending\" && verifyResponse.next_action) {\n if (!actionResult.success) {\n console.log(\"[ApplePay:Airwallex] 3DS failed but retry available, continuing loop...\");\n }\n response = verifyResponse;\n continue;\n }\n\n // No more actions - check final result\n if (!actionResult.success) {\n complete(\"fail\");\n return {\n errors: {\n apple_pay:\n verifyResponse.error_message_for_customer ||\n verifyResponse.error_message_for_debug ||\n actionResult.error ||\n \"3DS authentication failed\",\n },\n };\n }\n\n // 3DS succeeded\n complete(verifyResponse.charge_status === \"success\" ? \"success\" : \"fail\");\n return toApplePayResult(verifyResponse, secureToken);\n }\n\n // Check for max attempts exceeded\n if (userActionCount >= MAX_USER_ACTIONS) {\n complete(\"fail\");\n return { errors: { apple_pay: \"Too many authentication attempts. Please try again.\" } };\n }\n\n // No 3DS required - complete with result\n complete(response.charge_status === \"success\" ? \"success\" : \"fail\");\n return toApplePayResult(response, secureToken);\n}\n\n// =============================================================================\n// Main Submit Function\n// =============================================================================\n\nconst defSubmitPayment = (states: PaymentKitStates) => {\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n const { apiBaseUrl, secureToken, environment } = states;\n const applePayOptions = options as ApplePaySubmitOptions;\n\n // Validate options\n const validationError = validateOptions(applePayOptions);\n if (validationError) {\n return { errors: validationError };\n }\n\n try {\n const mockScenarioStr = getMockScenarioStr(applePayOptions.mockScenario);\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[ApplePay] Using checkout_request_id: ${checkoutRequestId}`);\n\n // Check if we have prepared Stripe state\n if (preparedStripeState?.adapter.isPrepared()) {\n console.log(\"[ApplePay] Using prepared Stripe state for immediate sheet display\");\n\n // Show Apple Pay sheet IMMEDIATELY using the prepared PaymentRequest\n const paymentResultPromise = preparedStripeState.adapter.showPreparedPaymentSheet();\n const paymentResult = await paymentResultPromise;\n\n if (!paymentResult.success) {\n clearPreparedApplePay();\n\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { errors: { apple_pay: \"Apple Pay cancelled by user\" } };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { errors: { apple_pay: errorMessage } };\n }\n\n const { paymentMethodId, paymentMethodEvent } = paymentResult;\n\n // Confirm with backend using the PaymentMethod ID\n const confirmResult = await callStripeConfirmEndpoint(\n apiBaseUrl,\n secureToken,\n paymentMethodId,\n mockScenarioStr,\n preparedStripeState.checkoutRequestId,\n );\n\n // Complete Apple Pay UI based on result\n if (confirmResult.data) {\n paymentMethodEvent.complete(\"success\");\n clearPreparedApplePay();\n return confirmResult;\n } else {\n paymentMethodEvent.complete(\"fail\");\n clearPreparedApplePay();\n return confirmResult;\n }\n }\n\n // Check if this is an Airwallex processor - route directly to Airwallex flow\n if (applePayOptions.processorType === \"airwallex\") {\n console.log(\"[ApplePay] Running Airwallex flow (processorType=airwallex)\");\n return await runAirwallexFlow(apiBaseUrl, secureToken, applePayOptions, mockScenarioStr, checkoutRequestId);\n }\n\n // No prepared state for Stripe - call start endpoint\n const startResult = await callStripeStartEndpoint(\n apiBaseUrl,\n secureToken,\n applePayOptions,\n mockScenarioStr,\n checkoutRequestId,\n );\n\n if (startResult.error || !startResult.data) {\n return { errors: { apple_pay: startResult.error || \"Failed to start Apple Pay\" } };\n }\n\n const startData = startResult.data;\n\n // Stripe flow without prepared state - this may fail due to user gesture requirements\n console.warn(\"[ApplePay] Stripe flow without prepared state - may fail due to user gesture requirements\");\n\n if (!startData.stripe_pk) {\n return { errors: { apple_pay: \"Stripe publishable key not provided\" } };\n }\n\n const { adapter, error: adapterError } = initializeStripeAdapter(\n startData.stripe_pk,\n applePayOptions.mockScenario,\n );\n if (!adapter) {\n return { errors: { apple_pay: adapterError || \"Failed to initialize Stripe adapter\" } };\n }\n\n // This will likely fail due to user gesture requirements\n const prepareResult = await adapter.preparePaymentRequest({\n country: startData.country,\n currency: startData.currency.toLowerCase(),\n total: { label: \"Total\", amount: startData.amount },\n });\n\n if (!prepareResult.success || !prepareResult.applePay) {\n return { errors: { apple_pay: prepareResult.error || \"Apple Pay not available\" } };\n }\n\n const paymentResult = await adapter.showPreparedPaymentSheet();\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { errors: { apple_pay: \"Apple Pay cancelled by user\" } };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { errors: { apple_pay: errorMessage } };\n }\n\n const { paymentMethodId, paymentMethodEvent } = paymentResult;\n\n const confirmResult = await callStripeConfirmEndpoint(\n apiBaseUrl,\n secureToken,\n paymentMethodId,\n mockScenarioStr,\n checkoutRequestId,\n );\n\n if (confirmResult.data) {\n paymentMethodEvent.complete(\"success\");\n return confirmResult;\n } else {\n paymentMethodEvent.complete(\"fail\");\n return confirmResult;\n }\n } catch (error) {\n clearPreparedApplePay();\n return { errors: { apple_pay: `Apple Pay error: ${error}` } };\n }\n };\n\n return submitPayment;\n};\n\n// =============================================================================\n// Payment Method Definition\n// =============================================================================\n\nconst ApplePayPaymentMethod = definePaymentMethod((paymentKitStates) => {\n return {\n name: \"apple_pay\",\n externalFuncs: {\n prepareApplePay: (options: ApplePaySubmitOptions) =>\n prepareApplePay(\n paymentKitStates.apiBaseUrl,\n paymentKitStates.secureToken,\n options,\n paymentKitStates.environment,\n ),\n },\n internalFuncs: {\n submitPayment: defSubmitPayment(paymentKitStates),\n cleanup: () => {\n clearPreparedApplePay();\n },\n },\n };\n});\n\nexport { ApplePayMockScenario };\n\nexport default ApplePayPaymentMethod;\n"],"mappings":"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"}
1
+ {"version":3,"file":"apple-pay.mjs","names":["preparedStripeState: PreparedStripeApplePayState | null","airwallexMockScenario: AirwallexApplePayMockScenario","config: AirwallexApplePayConfig","submitPayment: TInternalFuncs[\"submitPayment\"]","paymentResult","confirmResult","paymentMethodId","billingDetails"],"sources":["../../src/payment-methods/apple-pay.ts"],"sourcesContent":["import type { PaymentKitErrors, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport { collectFraudMetadata, definePaymentMethod, getOrCreateCheckoutRequestId } from \"../utils\";\nimport {\n AirwallexApplePayAdapter,\n type AirwallexApplePayConfig,\n AirwallexApplePayMockScenario,\n type ApplePayEncryptedToken,\n} from \"./airwallex-apple-pay-adapter\";\nimport { handleNextAction } from \"./next-action-handlers\";\nimport { ApplePayMockScenario, StripeApplePayAdapter } from \"./stripe-apple-pay-adapter\";\n\n// Apple Pay-specific types\nexport type ApplePayCustomerInfo = {\n first_name: string;\n last_name: string;\n};\n\nexport type ApplePayStartRequest = {\n processor_id: string;\n customer_info: ApplePayCustomerInfo;\n fraud_metadata: {\n ipAddress?: string;\n browserInfo?: { [key: string]: unknown };\n processorFraudInfo?: { [key: string]: unknown };\n };\n mock_scenario?: string;\n // Airwallex-specific fields (sent on /start for merchant validation)\n validation_url?: string;\n initiative_context?: string;\n};\n\nexport type ApplePayStartResponse = {\n checkout_attempt_id: string;\n amount: number;\n currency: string;\n country: string;\n\n // Processor discriminator\n processor: \"stripe\" | \"airwallex\";\n\n // Stripe-specific fields (when processor=\"stripe\")\n client_secret?: string;\n stripe_pk?: string;\n\n // Airwallex-specific fields (when processor=\"airwallex\")\n merchant_session?: { [key: string]: unknown }; // Apple merchant session for completeMerchantValidation()\n};\n\n// Airwallex 3DS next action type (matches backend snake_case response)\nexport type Airwallex3dsNextAction = {\n type: \"airwallex_3ds\";\n url: string;\n};\n\nexport type ApplePayConfirmRequest = {\n // Stripe: Send PaymentMethod ID\n payment_method_id?: string;\n // Airwallex: Send encrypted Apple Pay token\n apple_pay_token?: ApplePayEncryptedToken | { [key: string]: unknown };\n // Email from payment sheet (Stripe Apple Pay) — used to fill missing customer email\n payer_email?: string;\n mock_scenario?: string;\n};\n\nexport type ApplePayConfirmResponse = {\n charge_status: \"success\" | \"fail\" | \"pending\";\n transaction_id?: string;\n error_code?: string;\n error_message_for_customer?: string;\n error_message_for_debug?: string;\n checkout_attempt_id: string;\n checkout_session_id?: string;\n next_action?: Airwallex3dsNextAction; // Present when charge_status=\"pending\" for 3DS\n payment_intent_id?: string;\n customer_id?: string;\n payment_method_id?: string;\n processor_used?: string;\n subscription_id?: string;\n invoice_id?: string;\n invoice_number?: number;\n card_brand?: string;\n card_last4?: string;\n card_exp_month?: number;\n card_exp_year?: number;\n};\n\nexport type ApplePaySubmitOptions = {\n processorId: string;\n processorType?: \"stripe\" | \"airwallex\";\n customerInfo: ApplePayCustomerInfo;\n mockScenario?: ApplePayMockScenario;\n amount?: number; // Amount in atomic units (cents) for Apple Pay sheet display\n currency?: string; // Currency code (e.g., \"usd\")\n country: string; // Country code (e.g., \"US\") for Apple Pay sheet — required\n merchantName?: string; // Merchant display name on Apple Pay sheet\n};\n\ntype ApplePayResult =\n | { data: { [key: string]: unknown }; errors?: undefined }\n | { data?: undefined; errors: PaymentKitErrors };\n\n// =============================================================================\n// Prepared Payment State (for Stripe pre-fetching before click)\n// =============================================================================\n\ntype PreparedStripeApplePayState = {\n processor: \"stripe\";\n adapter: StripeApplePayAdapter;\n startData: ApplePayStartResponse;\n mockScenarioStr?: string;\n checkoutRequestId: string;\n};\n\n// Global state to store prepared Apple Pay data (Stripe only - Airwallex uses native session)\nlet preparedStripeState: PreparedStripeApplePayState | null = null;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\nasync function apiCall<T>(\n url: string,\n options: RequestInit,\n checkoutRequestId?: string,\n): Promise<{ data?: T; error?: string }> {\n const headers = new Headers(options.headers);\n if (checkoutRequestId) {\n headers.set(\"x-request-id\", checkoutRequestId);\n }\n\n const response = await fetch(url, { ...options, headers });\n if (!response.ok) {\n let errorMessage = `Request failed (${response.status})`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.detail || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n return { error: errorMessage };\n }\n return { data: await response.json() };\n}\n\nfunction validateOptions(options: ApplePaySubmitOptions): PaymentKitErrors | null {\n if (!options?.processorId) {\n return { processor_id: \"Processor ID is required\" };\n }\n return null;\n}\n\nfunction getMockScenarioStr(mockScenario?: ApplePayMockScenario): string | undefined {\n return mockScenario && mockScenario !== ApplePayMockScenario.None ? mockScenario : undefined;\n}\n\n// =============================================================================\n// Stripe Apple Pay Flow\n// =============================================================================\n\nasync function callStripeStartEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<{ data?: ApplePayStartResponse; error?: string }> {\n return apiCall<ApplePayStartResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/start`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n processor_id: options.processorId,\n customer_info: options.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n mock_scenario: mockScenarioStr,\n } as ApplePayStartRequest),\n },\n checkoutRequestId,\n );\n}\n\nfunction initializeStripeAdapter(\n stripePk: string,\n mockScenario?: ApplePayMockScenario,\n): { adapter?: StripeApplePayAdapter; error?: string } {\n const adapter = new StripeApplePayAdapter(mockScenario);\n\n if (!adapter.initialize(stripePk)) {\n return { error: 'Stripe.js not loaded. Add <script src=\"https://js.stripe.com/v3/\"></script> to your page.' };\n }\n\n return { adapter };\n}\n\nasync function callStripeConfirmEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n paymentMethodId: string,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n payerEmail?: string,\n): Promise<ApplePayResult> {\n const result = await apiCall<ApplePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/apple-pay/confirm`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n payment_method_id: paymentMethodId,\n payer_email: payerEmail,\n mock_scenario: mockScenarioStr,\n } as ApplePayConfirmRequest),\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return { errors: { apple_pay: result.error || \"Failed to confirm payment\" } };\n }\n\n const confirmData = result.data;\n\n if (confirmData.charge_status === \"success\") {\n return {\n data: {\n id: confirmData.transaction_id,\n checkoutAttemptId: confirmData.checkout_attempt_id,\n checkoutSessionId: confirmData.checkout_session_id ?? secureToken,\n state: \"checkout_succeeded\",\n paymentIntentId: confirmData.payment_intent_id,\n customerId: confirmData.customer_id,\n paymentMethodId: confirmData.payment_method_id,\n processorUsed: confirmData.processor_used,\n subscriptionId: confirmData.subscription_id,\n invoiceId: confirmData.invoice_id,\n invoiceNumber: confirmData.invoice_number,\n cardBrand: confirmData.card_brand,\n cardLast4: confirmData.card_last4,\n cardExpMonth: confirmData.card_exp_month,\n cardExpYear: confirmData.card_exp_year,\n errorCode: confirmData.error_code,\n errorMessageForCustomer: confirmData.error_message_for_customer,\n errorMessageForDebug: confirmData.error_message_for_debug,\n nextAction: confirmData.next_action,\n },\n };\n }\n\n return {\n errors: {\n apple_pay: confirmData.error_message_for_customer || confirmData.error_message_for_debug || \"Payment failed\",\n },\n };\n}\n\n// =============================================================================\n// Prepare Function (call BEFORE the click handler)\n// =============================================================================\n\n/**\n * Pre-fetch Apple Pay data and prepare the PaymentRequest.\n * Call this when the checkout page loads, NOT in the click handler.\n *\n * For Stripe: pre-fetches data and prepares PaymentRequest for immediate show.\n * For Airwallex: returns success with processor=\"airwallex\" so submit uses native ApplePaySession.\n */\nexport async function prepareApplePay(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n environment: string,\n): Promise<{ success: boolean; error?: string; applePay?: boolean }> {\n console.log(\"[ApplePay] prepareApplePay called\");\n\n // Clear any previous state\n preparedStripeState = null;\n\n const mockScenarioStr = getMockScenarioStr(options.mockScenario);\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[ApplePay] Using checkout_request_id: ${checkoutRequestId}`);\n\n // Airwallex doesn't use the prepare pattern - it uses native ApplePaySession\n // Skip the Stripe /start call entirely for Airwallex processors\n if (options.processorType === \"airwallex\") {\n console.log(\"[ApplePay] Airwallex processor - will use native ApplePaySession on submit\");\n return { success: true, applePay: true };\n }\n\n // Call Stripe start endpoint to get PaymentIntent details\n const startResult = await callStripeStartEndpoint(\n apiBaseUrl,\n secureToken,\n options,\n mockScenarioStr,\n checkoutRequestId,\n );\n if (startResult.error || !startResult.data) {\n return { success: false, error: startResult.error || \"Failed to start Apple Pay\" };\n }\n\n const startData = startResult.data;\n\n // Initialize Stripe adapter\n if (!startData.stripe_pk) {\n return { success: false, error: \"Stripe publishable key not provided\" };\n }\n\n const { adapter, error: adapterError } = initializeStripeAdapter(startData.stripe_pk, options.mockScenario);\n if (!adapter) {\n return { success: false, error: adapterError };\n }\n\n // Create PaymentRequest and call canMakePayment() (required before show())\n const prepareResult = await adapter.preparePaymentRequest({\n country: startData.country,\n currency: startData.currency.toLowerCase(),\n total: {\n label: \"Total\",\n amount: startData.amount,\n },\n });\n\n if (!prepareResult.success) {\n return {\n success: false,\n error: prepareResult.error || \"Failed to prepare payment request\",\n applePay: prepareResult.applePay,\n };\n }\n\n if (!prepareResult.applePay) {\n return {\n success: false,\n error: \"Apple Pay is not available on this device or Stripe account\",\n applePay: false,\n };\n }\n\n // Store the prepared state\n preparedStripeState = {\n processor: \"stripe\",\n adapter,\n startData,\n mockScenarioStr,\n checkoutRequestId,\n };\n\n console.log(\"[ApplePay] prepareApplePay success (Stripe), ready for click\");\n return { success: true, applePay: true };\n}\n\n/**\n * Check if Apple Pay has been prepared and is ready.\n */\nexport function isApplePayPrepared(): boolean {\n return preparedStripeState?.adapter.isPrepared() ?? false;\n}\n\n/**\n * Clear prepared state (call on unmount or when checkout changes).\n */\nexport function clearPreparedApplePay(): void {\n if (preparedStripeState) {\n preparedStripeState.adapter.clearPrepared();\n }\n preparedStripeState = null;\n}\n\n// =============================================================================\n// Airwallex Apple Pay Flow\n// =============================================================================\n\nasync function callAirwallexStartEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n validationUrl: string,\n initiativeContext: string,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<{ data?: ApplePayStartResponse; error?: string }> {\n return apiCall<ApplePayStartResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/start`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n processor_id: options.processorId,\n customer_info: options.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n validation_url: validationUrl,\n initiative_context: initiativeContext,\n mock_scenario: mockScenarioStr,\n } as ApplePayStartRequest),\n },\n checkoutRequestId,\n );\n}\n\nasync function callAirwallexConfirmEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n applePayToken: ApplePayEncryptedToken,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n payerEmail?: string,\n): Promise<ApplePayConfirmResponse> {\n const result = await apiCall<ApplePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/confirm`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n apple_pay_token: applePayToken,\n payer_email: payerEmail,\n mock_scenario: mockScenarioStr,\n } as ApplePayConfirmRequest),\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message_for_debug: result.error || \"Failed to confirm payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\nasync function callAirwallexVerifyEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n checkoutRequestId?: string,\n): Promise<ApplePayConfirmResponse> {\n const result = await apiCall<ApplePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/airwallex/apple-pay/verify`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message_for_debug: result.error || \"Failed to verify payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\nfunction toApplePayResult(response: ApplePayConfirmResponse, secureToken: string): ApplePayResult {\n if (response.charge_status === \"success\") {\n return {\n data: {\n id: response.transaction_id,\n checkoutAttemptId: response.checkout_attempt_id,\n checkoutSessionId: response.checkout_session_id ?? secureToken,\n state: \"checkout_succeeded\",\n paymentIntentId: response.payment_intent_id,\n customerId: response.customer_id,\n paymentMethodId: response.payment_method_id,\n processorUsed: response.processor_used,\n subscriptionId: response.subscription_id,\n invoiceId: response.invoice_id,\n invoiceNumber: response.invoice_number,\n cardBrand: response.card_brand,\n cardLast4: response.card_last4,\n cardExpMonth: response.card_exp_month,\n cardExpYear: response.card_exp_year,\n errorCode: response.error_code,\n errorMessageForCustomer: response.error_message_for_customer,\n errorMessageForDebug: response.error_message_for_debug,\n nextAction: response.next_action,\n },\n };\n }\n return {\n errors: {\n apple_pay: response.error_message_for_customer || response.error_message_for_debug || \"Payment failed\",\n },\n };\n}\n\nconst MAX_USER_ACTIONS = 5;\n\n/**\n * Run the Airwallex Apple Pay flow with 3DS loop support.\n *\n * Flow:\n * 1. Show native ApplePaySession, call /start for merchant validation\n * 2. On payment authorized, call /confirm with token\n * 3. If 3DS required, handle it and call /verify\n * 4. Loop if more 3DS needed\n */\nasync function runAirwallexFlow(\n apiBaseUrl: string,\n secureToken: string,\n options: ApplePaySubmitOptions,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<ApplePayResult> {\n // Convert mock scenario\n let airwallexMockScenario: AirwallexApplePayMockScenario = AirwallexApplePayMockScenario.None;\n if (options.mockScenario === ApplePayMockScenario.Success) {\n airwallexMockScenario = AirwallexApplePayMockScenario.Success;\n } else if (options.mockScenario === ApplePayMockScenario.Cancelled) {\n airwallexMockScenario = AirwallexApplePayMockScenario.Cancelled;\n }\n\n // Initialize adapter\n const adapter = new AirwallexApplePayAdapter(airwallexMockScenario);\n\n const config: AirwallexApplePayConfig = {\n amount: options.amount || 0,\n currency: (options.currency || \"USD\").toUpperCase(),\n country: options.country.toUpperCase(),\n merchantName: options.merchantName || \"Total\",\n };\n\n if (!adapter.initialize(config)) {\n return { errors: { apple_pay: \"Apple Pay not available on this device (requires Safari)\" } };\n }\n\n const canPay = await adapter.canMakePayment();\n if (!canPay) {\n return { errors: { apple_pay: \"Apple Pay not available on this device\" } };\n }\n\n // Get current domain for initiative_context\n const initiativeContext = typeof window !== \"undefined\" ? window.location.hostname : \"\";\n\n // In mock mode, call /start first to create checkout attempt (mock adapter skips merchant validation)\n if (airwallexMockScenario !== AirwallexApplePayMockScenario.None) {\n const startResult = await callAirwallexStartEndpoint(\n apiBaseUrl,\n secureToken,\n options,\n \"https://mock-apple-pay-gateway.example.com/paymentservices/startSession\",\n initiativeContext,\n mockScenarioStr,\n checkoutRequestId,\n );\n if (startResult.error || !startResult.data) {\n return { errors: { apple_pay: startResult.error || \"Failed to start mock checkout\" } };\n }\n }\n\n // Show Apple Pay sheet with merchant validation callback\n const paymentResult = await adapter.showPaymentSheet(async (validationUrl: string) => {\n // Call /start endpoint for merchant validation\n const startResult = await callAirwallexStartEndpoint(\n apiBaseUrl,\n secureToken,\n options,\n validationUrl,\n initiativeContext,\n mockScenarioStr,\n checkoutRequestId,\n );\n\n if (startResult.error || !startResult.data) {\n return { error: startResult.error || \"Merchant validation failed\" };\n }\n\n if (!startResult.data.merchant_session) {\n return { error: \"No merchant session returned from server\" };\n }\n\n return { merchantSession: startResult.data.merchant_session };\n });\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { errors: { apple_pay: \"Apple Pay cancelled by user\" } };\n }\n return { errors: { apple_pay: paymentResult.error || \"Apple Pay failed\" } };\n }\n\n const { token, complete, payerEmail } = paymentResult;\n\n // Call /confirm with the token\n let response = await callAirwallexConfirmEndpoint(\n apiBaseUrl,\n secureToken,\n token,\n mockScenarioStr,\n checkoutRequestId,\n payerEmail,\n );\n\n // Handle 3DS loop\n let userActionCount = 0;\n while (response.charge_status === \"pending\" && response.next_action && userActionCount < MAX_USER_ACTIONS) {\n userActionCount++;\n\n // Handle 3DS challenge — Airwallex3dsNextAction is structurally identical to SDK's Airwallex3dsAction\n const nextAction = response.next_action as Airwallex3dsNextAction;\n const actionResult = await handleNextAction({ type: nextAction.type, url: nextAction.url });\n\n // Call verify endpoint\n const verifyResponse = await callAirwallexVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId);\n\n // Check if another 3DS action is required\n if (verifyResponse.charge_status === \"pending\" && verifyResponse.next_action) {\n if (!actionResult.success) {\n console.log(\"[ApplePay:Airwallex] 3DS failed but retry available, continuing loop...\");\n }\n response = verifyResponse;\n continue;\n }\n\n // No more actions - check final result\n if (!actionResult.success) {\n complete(\"fail\");\n return {\n errors: {\n apple_pay:\n verifyResponse.error_message_for_customer ||\n verifyResponse.error_message_for_debug ||\n actionResult.error ||\n \"3DS authentication failed\",\n },\n };\n }\n\n // 3DS succeeded\n complete(verifyResponse.charge_status === \"success\" ? \"success\" : \"fail\");\n return toApplePayResult(verifyResponse, secureToken);\n }\n\n // Check for max attempts exceeded\n if (userActionCount >= MAX_USER_ACTIONS) {\n complete(\"fail\");\n return { errors: { apple_pay: \"Too many authentication attempts. Please try again.\" } };\n }\n\n // No 3DS required - complete with result\n complete(response.charge_status === \"success\" ? \"success\" : \"fail\");\n return toApplePayResult(response, secureToken);\n}\n\n// =============================================================================\n// Main Submit Function\n// =============================================================================\n\nconst defSubmitPayment = (states: PaymentKitStates) => {\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n const { apiBaseUrl, secureToken, environment } = states;\n const applePayOptions = options as ApplePaySubmitOptions;\n\n // Validate options\n const validationError = validateOptions(applePayOptions);\n if (validationError) {\n return { errors: validationError };\n }\n\n try {\n const mockScenarioStr = getMockScenarioStr(applePayOptions.mockScenario);\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[ApplePay] Using checkout_request_id: ${checkoutRequestId}`);\n\n // Check if we have prepared Stripe state\n if (preparedStripeState?.adapter.isPrepared()) {\n console.log(\"[ApplePay] Using prepared Stripe state for immediate sheet display\");\n\n // Show Apple Pay sheet IMMEDIATELY using the prepared PaymentRequest\n const paymentResultPromise = preparedStripeState.adapter.showPreparedPaymentSheet();\n const paymentResult = await paymentResultPromise;\n\n if (!paymentResult.success) {\n clearPreparedApplePay();\n\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { errors: { apple_pay: \"Apple Pay cancelled by user\" } };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { errors: { apple_pay: errorMessage } };\n }\n\n const { paymentMethodId, paymentMethodEvent, billingDetails } = paymentResult;\n\n // Confirm with backend using the PaymentMethod ID\n const confirmResult = await callStripeConfirmEndpoint(\n apiBaseUrl,\n secureToken,\n paymentMethodId,\n mockScenarioStr,\n preparedStripeState.checkoutRequestId,\n billingDetails?.email,\n );\n\n // Complete Apple Pay UI based on result\n if (confirmResult.data) {\n paymentMethodEvent.complete(\"success\");\n clearPreparedApplePay();\n return confirmResult;\n } else {\n paymentMethodEvent.complete(\"fail\");\n clearPreparedApplePay();\n return confirmResult;\n }\n }\n\n // Check if this is an Airwallex processor - route directly to Airwallex flow\n if (applePayOptions.processorType === \"airwallex\") {\n console.log(\"[ApplePay] Running Airwallex flow (processorType=airwallex)\");\n return await runAirwallexFlow(apiBaseUrl, secureToken, applePayOptions, mockScenarioStr, checkoutRequestId);\n }\n\n // No prepared state for Stripe - call start endpoint\n const startResult = await callStripeStartEndpoint(\n apiBaseUrl,\n secureToken,\n applePayOptions,\n mockScenarioStr,\n checkoutRequestId,\n );\n\n if (startResult.error || !startResult.data) {\n return { errors: { apple_pay: startResult.error || \"Failed to start Apple Pay\" } };\n }\n\n const startData = startResult.data;\n\n // Stripe flow without prepared state - this may fail due to user gesture requirements\n console.warn(\"[ApplePay] Stripe flow without prepared state - may fail due to user gesture requirements\");\n\n if (!startData.stripe_pk) {\n return { errors: { apple_pay: \"Stripe publishable key not provided\" } };\n }\n\n const { adapter, error: adapterError } = initializeStripeAdapter(\n startData.stripe_pk,\n applePayOptions.mockScenario,\n );\n if (!adapter) {\n return { errors: { apple_pay: adapterError || \"Failed to initialize Stripe adapter\" } };\n }\n\n // This will likely fail due to user gesture requirements\n const prepareResult = await adapter.preparePaymentRequest({\n country: startData.country,\n currency: startData.currency.toLowerCase(),\n total: { label: \"Total\", amount: startData.amount },\n });\n\n if (!prepareResult.success || !prepareResult.applePay) {\n return { errors: { apple_pay: prepareResult.error || \"Apple Pay not available\" } };\n }\n\n const paymentResult = await adapter.showPreparedPaymentSheet();\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { errors: { apple_pay: \"Apple Pay cancelled by user\" } };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { errors: { apple_pay: errorMessage } };\n }\n\n const { paymentMethodId, paymentMethodEvent, billingDetails } = paymentResult;\n\n const confirmResult = await callStripeConfirmEndpoint(\n apiBaseUrl,\n secureToken,\n paymentMethodId,\n mockScenarioStr,\n checkoutRequestId,\n billingDetails?.email,\n );\n\n if (confirmResult.data) {\n paymentMethodEvent.complete(\"success\");\n return confirmResult;\n } else {\n paymentMethodEvent.complete(\"fail\");\n return confirmResult;\n }\n } catch (error) {\n clearPreparedApplePay();\n return { errors: { apple_pay: `Apple Pay error: ${error}` } };\n }\n };\n\n return submitPayment;\n};\n\n// =============================================================================\n// Payment Method Definition\n// =============================================================================\n\nconst ApplePayPaymentMethod = definePaymentMethod((paymentKitStates) => {\n return {\n name: \"apple_pay\",\n externalFuncs: {\n prepareApplePay: (options: ApplePaySubmitOptions) =>\n prepareApplePay(\n paymentKitStates.apiBaseUrl,\n paymentKitStates.secureToken,\n options,\n paymentKitStates.environment,\n ),\n },\n internalFuncs: {\n submitPayment: defSubmitPayment(paymentKitStates),\n cleanup: () => {\n clearPreparedApplePay();\n },\n },\n };\n});\n\nexport { ApplePayMockScenario };\n\nexport default ApplePayPaymentMethod;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"card.d.mts","names":[],"sources":["../../src/payment-methods/card.ts"],"sourcesContent":[],"mappings":";;;;;KAQY,aAAA,GAAgB;KAChB,gBAAA,GAAmB;KAqG1B,oBAAA,GAAuB,QAAQ,kBAAkB;UAC5C;EAvGE,WAAA,CAAA,EAAA,MAAa;AACzB,CAAA;AAAsD,cA4oBhD,iBAviBmB,EAQyC,aARzC,CAAA;EAA6B,aAAA,EAAA,CAAA,IAAA,EAQtC,eARsC,EAAA,OAAA,EAQR,oBARQ,EAAA,GAAA;IAAlB,KAAA,EAAA,CAAA,cAAA,EAAA,MAAA,EAAA,GAAA;MAAR,OAAA,EAAA,GAAA,GAAA,IAAA;IAClB,CAAA;EAAM,CAAA;AAAA,CAAA,EAAA,MAsiBV,CAAA"}
1
+ {"version":3,"file":"card.d.mts","names":[],"sources":["../../src/payment-methods/card.ts"],"sourcesContent":[],"mappings":";;;;;KAQY,aAAA,GAAgB;KAChB,gBAAA,GAAmB;KAqG1B,oBAAA,GAAuB,QAAQ,kBAAkB;UAC5C;EAvGE,WAAA,CAAA,EAAA,MAAa;AACzB,CAAA;AAAsD,cA6vBhD,iBAxpBmB,EAQyC,aARzC,CAAA;EAA6B,aAAA,EAAA,CAAA,IAAA,EAQtC,eARsC,EAAA,OAAA,EAQR,oBARQ,EAAA,GAAA;IAAlB,KAAA,EAAA,CAAA,cAAA,EAAA,MAAA,EAAA,GAAA;MAAR,OAAA,EAAA,GAAA,GAAA,IAAA;IAClB,CAAA;EAAM,CAAA;AAAA,CAAA,EAAA,MAupBV,CAAA"}