@payment-kit-js/vanilla 0.5.15 → 0.5.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{airwallex-apple-pay-adapter-Bs8AdQKY.mjs → airwallex-apple-pay-adapter-CPz54c9e.mjs} +1 -1
- package/dist/{airwallex-apple-pay-adapter-Bs8AdQKY.mjs.map → airwallex-apple-pay-adapter-CPz54c9e.mjs.map} +1 -1
- package/dist/{airwallex-apple-pay-adapter-D8enI9Vq.d.mts → airwallex-apple-pay-adapter-CnnZ7VL6.d.mts} +1 -1
- package/dist/{airwallex-apple-pay-adapter-D8enI9Vq.d.mts.map → airwallex-apple-pay-adapter-CnnZ7VL6.d.mts.map} +1 -1
- package/dist/{airwallex-google-pay-adapter-C8JTp01q.mjs → airwallex-google-pay-adapter-BvlROwj_.mjs} +1 -1
- package/dist/{airwallex-google-pay-adapter-C8JTp01q.mjs.map → airwallex-google-pay-adapter-BvlROwj_.mjs.map} +1 -1
- package/dist/{airwallex-google-pay-adapter-adaDktQM.d.mts → airwallex-google-pay-adapter-D-AxVLLq.d.mts} +1 -1
- package/dist/{airwallex-google-pay-adapter-adaDktQM.d.mts.map → airwallex-google-pay-adapter-D-AxVLLq.d.mts.map} +1 -1
- package/dist/analytics-Blvs2DW7.mjs +333 -0
- package/dist/analytics-Blvs2DW7.mjs.map +1 -0
- package/dist/{bnpl-shared-B-en2sPr.d.mts → bnpl-shared-BQwCBD45.d.mts} +2 -2
- package/dist/{bnpl-shared-B-en2sPr.d.mts.map → bnpl-shared-BQwCBD45.d.mts.map} +1 -1
- package/dist/{bnpl-shared-CEAXTL3Q.mjs → bnpl-shared-DGs1YzS9.mjs} +2 -2
- package/dist/{bnpl-shared-CEAXTL3Q.mjs.map → bnpl-shared-DGs1YzS9.mjs.map} +1 -1
- package/dist/cdn/paymentkit.js +67 -12
- package/dist/cdn/paymentkit.js.map +2 -2
- package/dist/cdn/paymentkit.min.js +5 -5
- package/dist/cdn/paymentkit.min.js.map +3 -3
- package/dist/{connect-card-Cra_F1cC.d.mts → connect-card-CZhzK_Tp.d.mts} +1 -1
- package/dist/{connect-card-Cra_F1cC.d.mts.map → connect-card-CZhzK_Tp.d.mts.map} +1 -1
- package/dist/{connect-card-D3Je4V7p.mjs → connect-card-kXLdSNTL.mjs} +2 -2
- package/dist/{connect-card-D3Je4V7p.mjs.map → connect-card-kXLdSNTL.mjs.map} +1 -1
- package/dist/{connect-tunnel-x-BhVAej5Q.mjs → connect-tunnel-x-5XOct5Tm.mjs} +2 -2
- package/dist/{connect-tunnel-x-BhVAej5Q.mjs.map → connect-tunnel-x-5XOct5Tm.mjs.map} +1 -1
- package/dist/{connect-tunnel-x-Wh-JG1O5.d.mts → connect-tunnel-x-BKtMfoGh.d.mts} +1 -1
- package/dist/{connect-tunnel-x-Wh-JG1O5.d.mts.map → connect-tunnel-x-BKtMfoGh.d.mts.map} +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +5 -334
- package/dist/index.mjs.map +1 -1
- package/dist/{next-action-handlers-BZs04hYb.mjs → next-action-handlers-CLOt1wzO.mjs} +1 -1
- package/dist/{next-action-handlers-BZs04hYb.mjs.map → next-action-handlers-CLOt1wzO.mjs.map} +1 -1
- package/dist/payment-methods/affirm.d.mts +4 -4
- package/dist/payment-methods/affirm.mjs +2 -2
- package/dist/payment-methods/afterpay.d.mts +4 -4
- package/dist/payment-methods/afterpay.mjs +2 -2
- package/dist/payment-methods/airwallex-apple-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/airwallex-apple-pay-adapter.mjs +1 -1
- package/dist/payment-methods/airwallex-google-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/airwallex-google-pay-adapter.mjs +1 -1
- package/dist/payment-methods/apple-pay.d.mts +5 -5
- package/dist/payment-methods/apple-pay.mjs +4 -4
- package/dist/payment-methods/bnpl-shared.d.mts +4 -4
- package/dist/payment-methods/bnpl-shared.mjs +2 -2
- package/dist/payment-methods/card.d.mts +3 -3
- package/dist/payment-methods/card.d.mts.map +1 -1
- package/dist/payment-methods/card.mjs +77 -18
- package/dist/payment-methods/card.mjs.map +1 -1
- package/dist/payment-methods/google-pay.d.mts +5 -5
- package/dist/payment-methods/google-pay.mjs +4 -4
- package/dist/payment-methods/klarna.d.mts +4 -4
- package/dist/payment-methods/klarna.mjs +2 -2
- package/dist/payment-methods/next-action-handlers.mjs +1 -1
- package/dist/payment-methods/paypal.d.mts +3 -3
- package/dist/payment-methods/paypal.mjs +1 -1
- package/dist/payment-methods/stripe-apple-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/stripe-apple-pay-adapter.mjs +1 -1
- package/dist/payment-methods/stripe-google-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/stripe-google-pay-adapter.mjs +1 -1
- package/dist/payment-methods/vgs-collect-loader.mjs +1 -1
- package/dist/penpal/connect-card.d.mts +1 -1
- package/dist/penpal/connect-card.mjs +2 -2
- package/dist/penpal/connect-tunnel-x.d.mts +1 -1
- package/dist/penpal/connect-tunnel-x.mjs +2 -2
- package/dist/{penpal-BFKeZTVz.mjs → penpal-CBrj43M5.mjs} +1 -1
- package/dist/{penpal-BFKeZTVz.mjs.map → penpal-CBrj43M5.mjs.map} +1 -1
- package/dist/{stripe-apple-pay-adapter-BLRjqgDf.mjs → stripe-apple-pay-adapter-7rF6xRIG.mjs} +1 -1
- package/dist/{stripe-apple-pay-adapter-BLRjqgDf.mjs.map → stripe-apple-pay-adapter-7rF6xRIG.mjs.map} +1 -1
- package/dist/{stripe-apple-pay-adapter-DcuGlQqQ.d.mts → stripe-apple-pay-adapter-D2OJRlAl.d.mts} +1 -1
- package/dist/{stripe-apple-pay-adapter-DcuGlQqQ.d.mts.map → stripe-apple-pay-adapter-D2OJRlAl.d.mts.map} +1 -1
- package/dist/{stripe-google-pay-adapter-BlQ2jVpE.d.mts → stripe-google-pay-adapter-B330fRiH.d.mts} +1 -1
- package/dist/{stripe-google-pay-adapter-BlQ2jVpE.d.mts.map → stripe-google-pay-adapter-B330fRiH.d.mts.map} +1 -1
- package/dist/{stripe-google-pay-adapter-CIkgjhw8.mjs → stripe-google-pay-adapter-B346KXt4.mjs} +1 -1
- package/dist/{stripe-google-pay-adapter-CIkgjhw8.mjs.map → stripe-google-pay-adapter-B346KXt4.mjs.map} +1 -1
- package/dist/{types-CQ8xbgoh.d.mts → types-B3mjYfOm.d.mts} +3 -3
- package/dist/{types-CQ8xbgoh.d.mts.map → types-B3mjYfOm.d.mts.map} +1 -1
- package/dist/{utils-B70Y8YcZ.mjs → utils-Dc6zwOe1.mjs} +1 -1
- package/dist/{utils-B70Y8YcZ.mjs.map → utils-Dc6zwOe1.mjs.map} +1 -1
- package/dist/{vgs-collect-loader-l5_Pnmhz.mjs → vgs-collect-loader-CTLSv4qv.mjs} +1 -1
- package/dist/{vgs-collect-loader-l5_Pnmhz.mjs.map → vgs-collect-loader-CTLSv4qv.mjs.map} +1 -1
- package/package.json +2 -2
package/dist/{next-action-handlers-BZs04hYb.mjs.map → next-action-handlers-CLOt1wzO.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-action-handlers-BZs04hYb.mjs","names":[],"sources":["../src/utils/3ds-iframe-modal.ts","../src/payment-methods/next-action-handlers.ts"],"sourcesContent":["/**\n * 3DS iframe modal for displaying authentication pages.\n *\n * This module provides an iframe modal used by payment processors\n * that need to display a 3DS authentication page.\n */\n\ntype IframeModalResult = { success: true; data: Record<string, unknown> } | { success: false; error: string };\n\ntype ThreeDSCompleteMessage = {\n type: \"3ds_complete\";\n processor: string | null;\n isSuccess: boolean;\n error?: string;\n};\n\ntype IframeModalMessageHandler = (\n event: MessageEvent<ThreeDSCompleteMessage>,\n) => { handled: true; result: IframeModalResult } | { handled: false };\n\ninterface IframeModalOptions {\n /** URL to load in the iframe */\n url: string;\n /** Size of the iframe in pixels */\n size: { width: number; height: number };\n /** Border radius for the iframe in pixels (default: 16) */\n radius?: number;\n /** Handler to process postMessage events from the iframe */\n onMessage: IframeModalMessageHandler;\n}\n\n/**\n * Shows an iframe modal and waits for a result via postMessage.\n *\n * Features:\n * - Close/cancel button positioned outside the iframe\n * - Responsive design (works on mobile)\n * - Keyboard accessibility (Escape to close, focus trap)\n * - Fade-in/fade-out animations\n * - Iframe load error handling\n *\n * @param options - Modal configuration options\n * @returns Promise that resolves with success/failure result\n *\n * @example\n * ```ts\n * const result = await show3DSIframeModal({\n * url: \"https://bank.com/3ds-auth\",\n * size: { width: 605, height: 500 },\n * radius: 6,\n * onMessage: (event) => {\n * if (event.data?.type === \"auth_complete\") {\n * return {\n * handled: true,\n * result: event.data.succeeded\n * ? { success: true, data: { id: event.data.id } }\n * : { success: false, error: event.data.error }\n * };\n * }\n * return { handled: false };\n * },\n * });\n * ```\n */\n\nexport default function show3DSIframeModal(options: IframeModalOptions): Promise<IframeModalResult> {\n const { url, size, radius = 6, onMessage } = options;\n\n return new Promise((resolve) => {\n let resolved = false;\n\n // Create modal overlay with fade-in animation\n const overlay = document.createElement(\"div\");\n overlay.id = \"pk-iframe-modal-overlay\";\n overlay.setAttribute(\"role\", \"dialog\");\n overlay.setAttribute(\"aria-modal\", \"true\");\n overlay.setAttribute(\"aria-label\", \"3D Secure Verification\");\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n transition: background 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n `;\n\n // Create container for iframe and close button\n const container = document.createElement(\"div\");\n container.style.cssText = `\n position: relative;\n width: ${size.width}px;\n height: ${size.height}px;\n max-width: calc(100vw - 32px);\n max-height: calc(100vh - 64px);\n overflow: visible;\n opacity: 0;\n transform: scale(0.95) translateY(10px);\n transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n `;\n\n // Create close button (positioned outside top-right of iframe)\n const closeButton = document.createElement(\"button\");\n closeButton.id = \"pk-iframe-modal-close\";\n closeButton.setAttribute(\"aria-label\", \"Cancel verification\");\n closeButton.setAttribute(\"type\", \"button\");\n closeButton.style.cssText = `\n position: absolute;\n top: -40px;\n right: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: white;\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: background 0.15s ease;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n `;\n closeButton.innerHTML = `\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 1L13 13M1 13L13 1\" stroke=\"#666\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n `;\n closeButton.onmouseenter = (): void => {\n closeButton.style.background = \"#f5f5f5\";\n };\n closeButton.onmouseleave = (): void => {\n closeButton.style.background = \"white\";\n };\n\n // Create iframe (hidden initially until loaded)\n const iframe = document.createElement(\"iframe\");\n iframe.src = url;\n iframe.setAttribute(\"title\", \"3D Secure Verification\");\n iframe.style.cssText = `\n width: 100%;\n height: 100%;\n border: none;\n opacity: 0;\n border-radius: ${radius}px;\n background: white;\n transition: opacity 0.2s ease;\n position: relative;\n z-index: 1;\n `;\n\n // Handle iframe load success\n iframe.onload = (): void => {\n iframe.style.opacity = \"1\";\n };\n\n // Handle iframe load error\n iframe.onerror = (): void => {\n if (!resolved) {\n console.error(\"[IframeModal] Failed to load iframe\");\n cleanupWithAnimation();\n resolve({ success: false, error: \"Failed to load verification page. Please try again.\" });\n }\n };\n\n container.appendChild(closeButton);\n container.appendChild(iframe);\n overlay.appendChild(container);\n document.body.appendChild(overlay);\n\n // Trigger fade-in animation\n requestAnimationFrame(() => {\n overlay.style.background = \"rgba(0, 0, 0, 0.5)\";\n container.style.opacity = \"1\";\n container.style.transform = \"scale(1) translateY(0)\";\n });\n\n // Cleanup with fade-out animation\n const cleanupWithAnimation = (): void => {\n if (resolved) return;\n resolved = true;\n\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"keydown\", handleKeydown);\n\n // Use requestAnimationFrame to ensure transition is applied\n requestAnimationFrame(() => {\n overlay.style.background = \"rgba(0, 0, 0, 0)\";\n container.style.opacity = \"0\";\n container.style.transform = \"scale(0.95) translateY(10px)\";\n\n setTimeout(() => {\n if (overlay.parentNode) {\n overlay.parentNode.removeChild(overlay);\n }\n }, 250);\n });\n };\n\n // Handle close button click\n const handleCancel = (): void => {\n if (!resolved) {\n console.log(\"[IframeModal] User cancelled\");\n cleanupWithAnimation();\n resolve({ success: false, error: \"Verification cancelled\" });\n }\n };\n\n closeButton.onclick = handleCancel;\n\n // Handle Escape key\n const handleKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n handleCancel();\n }\n // Trap focus within modal (Tab key cycles through close button and iframe)\n if (event.key === \"Tab\") {\n event.preventDefault();\n if (document.activeElement === closeButton) {\n iframe.focus();\n } else {\n closeButton.focus();\n }\n }\n };\n\n window.addEventListener(\"keydown\", handleKeydown);\n\n // Set initial focus to close button for accessibility\n closeButton.focus();\n\n const handleMessage = (event: MessageEvent): void => {\n const messageResult = onMessage(event);\n if (messageResult.handled) {\n cleanupWithAnimation();\n resolve(messageResult.result);\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n });\n}\n","/**\n * Next action handlers for processor-specific user actions (e.g., 3DS authentication).\n *\n * This module abstracts processor-specific logic away from the generic card payment flow.\n * Each handler implements the logic needed for a specific next action type.\n */\n\nimport type { PublicCardCheckoutResponse } from \"@pkg/sdk/models\";\nimport type { Stripe } from \"@stripe/stripe-js\";\nimport show3DSIframeModal from \"../utils/3ds-iframe-modal\";\n\n// Helper to wait for a condition\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n// Check if Stripe.js is loaded via script tag\nconst isStripeJsPresent = (): boolean => \"Stripe\" in window;\n\n/**\n * Get the Stripe instance from the global window object.\n * Expects Stripe.js to be loaded via HTML script tag.\n * Polls for up to 5 seconds waiting for Stripe to be available.\n */\nconst getLoadedStripe = async (publishableKey: string): Promise<Stripe> => {\n // Poll for Stripe.js to be loaded (up to 5 seconds)\n for (let i = 0; i < 10; i++) {\n if (isStripeJsPresent()) {\n break;\n }\n await sleep(500);\n }\n\n if (!isStripeJsPresent()) {\n throw new Error(\n \"Stripe.js not loaded. Add this script tag to your HTML <head>:\\n\" +\n '<script src=\"https://js.stripe.com/v3/\"></script>',\n );\n }\n\n // @ts-expect-error Stripe is loaded globally via script tag\n const stripe: Stripe = new window.Stripe(publishableKey);\n return stripe;\n};\n\n/**\n * Result of handling a next action.\n */\nexport type NextActionResult = { success: true } | { success: false; error: string };\n\n/**\n * Handle Stripe 3DS authentication.\n */\nconst handleStripe3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"stripe_3ds\" }>,\n): Promise<NextActionResult> => {\n const { clientSecret, stripePk } = nextAction;\n\n const stripe = await getLoadedStripe(stripePk);\n\n // Show 3DS modal\n const { error: stripeError } = await stripe.confirmCardPayment(clientSecret);\n\n if (stripeError) {\n console.error(\"[3DS:Stripe] Authentication failed:\", stripeError.message);\n return { success: false, error: stripeError.message || \"3DS authentication failed\" };\n }\n\n return { success: true };\n};\n\n/**\n * Handle Airwallex 3DS authentication via iframe.\n *\n * Renders an iframe with the 3DS authentication URL. The iframe will redirect\n * to the 3DS callback page which sends a postMessage back to complete the flow.\n */\nconst handleAirwallex3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"airwallex_3ds\" }>,\n): Promise<NextActionResult> => {\n return show3DSIframeModal({\n url: nextAction.url,\n size: { width: 605, height: 550 },\n onMessage: (event) => {\n if (event.data.type !== \"3ds_complete\") {\n return { handled: false };\n }\n\n const { isSuccess, error } = event.data;\n\n if (isSuccess) {\n return { handled: true, result: { success: true, data: {} } };\n } else {\n console.error(\"[3DS:Airwallex] Authentication failed:\", error);\n return {\n handled: true,\n result: { success: false, error: error || \"3DS authentication failed\" },\n };\n }\n },\n });\n};\n\n/**\n * Handle a next action based on its type.\n * Routes to the appropriate processor-specific handler.\n *\n * @param nextAction - The next action from the checkout response\n * @returns Result indicating success or failure with error message\n */\nexport const handleNextAction = async (\n nextAction: NonNullable<PublicCardCheckoutResponse[\"nextAction\"]>,\n): Promise<NextActionResult> => {\n switch (nextAction.type) {\n case \"stripe_3ds\":\n return handleStripe3ds(nextAction);\n case \"airwallex_3ds\":\n return handleAirwallex3ds(nextAction);\n default:\n // TypeScript will catch if we miss a case when new action types are added\n return { success: false, error: `Unknown next action type: ${(nextAction as { type: string }).type}` };\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"next-action-handlers-CLOt1wzO.mjs","names":[],"sources":["../src/utils/3ds-iframe-modal.ts","../src/payment-methods/next-action-handlers.ts"],"sourcesContent":["/**\n * 3DS iframe modal for displaying authentication pages.\n *\n * This module provides an iframe modal used by payment processors\n * that need to display a 3DS authentication page.\n */\n\ntype IframeModalResult = { success: true; data: Record<string, unknown> } | { success: false; error: string };\n\ntype ThreeDSCompleteMessage = {\n type: \"3ds_complete\";\n processor: string | null;\n isSuccess: boolean;\n error?: string;\n};\n\ntype IframeModalMessageHandler = (\n event: MessageEvent<ThreeDSCompleteMessage>,\n) => { handled: true; result: IframeModalResult } | { handled: false };\n\ninterface IframeModalOptions {\n /** URL to load in the iframe */\n url: string;\n /** Size of the iframe in pixels */\n size: { width: number; height: number };\n /** Border radius for the iframe in pixels (default: 16) */\n radius?: number;\n /** Handler to process postMessage events from the iframe */\n onMessage: IframeModalMessageHandler;\n}\n\n/**\n * Shows an iframe modal and waits for a result via postMessage.\n *\n * Features:\n * - Close/cancel button positioned outside the iframe\n * - Responsive design (works on mobile)\n * - Keyboard accessibility (Escape to close, focus trap)\n * - Fade-in/fade-out animations\n * - Iframe load error handling\n *\n * @param options - Modal configuration options\n * @returns Promise that resolves with success/failure result\n *\n * @example\n * ```ts\n * const result = await show3DSIframeModal({\n * url: \"https://bank.com/3ds-auth\",\n * size: { width: 605, height: 500 },\n * radius: 6,\n * onMessage: (event) => {\n * if (event.data?.type === \"auth_complete\") {\n * return {\n * handled: true,\n * result: event.data.succeeded\n * ? { success: true, data: { id: event.data.id } }\n * : { success: false, error: event.data.error }\n * };\n * }\n * return { handled: false };\n * },\n * });\n * ```\n */\n\nexport default function show3DSIframeModal(options: IframeModalOptions): Promise<IframeModalResult> {\n const { url, size, radius = 6, onMessage } = options;\n\n return new Promise((resolve) => {\n let resolved = false;\n\n // Create modal overlay with fade-in animation\n const overlay = document.createElement(\"div\");\n overlay.id = \"pk-iframe-modal-overlay\";\n overlay.setAttribute(\"role\", \"dialog\");\n overlay.setAttribute(\"aria-modal\", \"true\");\n overlay.setAttribute(\"aria-label\", \"3D Secure Verification\");\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10000;\n transition: background 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n `;\n\n // Create container for iframe and close button\n const container = document.createElement(\"div\");\n container.style.cssText = `\n position: relative;\n width: ${size.width}px;\n height: ${size.height}px;\n max-width: calc(100vw - 32px);\n max-height: calc(100vh - 64px);\n overflow: visible;\n opacity: 0;\n transform: scale(0.95) translateY(10px);\n transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1), transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n `;\n\n // Create close button (positioned outside top-right of iframe)\n const closeButton = document.createElement(\"button\");\n closeButton.id = \"pk-iframe-modal-close\";\n closeButton.setAttribute(\"aria-label\", \"Cancel verification\");\n closeButton.setAttribute(\"type\", \"button\");\n closeButton.style.cssText = `\n position: absolute;\n top: -40px;\n right: 0;\n width: 32px;\n height: 32px;\n border: none;\n background: white;\n border-radius: 8px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n transition: background 0.15s ease;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n `;\n closeButton.innerHTML = `\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1 1L13 13M1 13L13 1\" stroke=\"#666\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n `;\n closeButton.onmouseenter = (): void => {\n closeButton.style.background = \"#f5f5f5\";\n };\n closeButton.onmouseleave = (): void => {\n closeButton.style.background = \"white\";\n };\n\n // Create iframe (hidden initially until loaded)\n const iframe = document.createElement(\"iframe\");\n iframe.src = url;\n iframe.setAttribute(\"title\", \"3D Secure Verification\");\n iframe.style.cssText = `\n width: 100%;\n height: 100%;\n border: none;\n opacity: 0;\n border-radius: ${radius}px;\n background: white;\n transition: opacity 0.2s ease;\n position: relative;\n z-index: 1;\n `;\n\n // Handle iframe load success\n iframe.onload = (): void => {\n iframe.style.opacity = \"1\";\n };\n\n // Handle iframe load error\n iframe.onerror = (): void => {\n if (!resolved) {\n console.error(\"[IframeModal] Failed to load iframe\");\n cleanupWithAnimation();\n resolve({ success: false, error: \"Failed to load verification page. Please try again.\" });\n }\n };\n\n container.appendChild(closeButton);\n container.appendChild(iframe);\n overlay.appendChild(container);\n document.body.appendChild(overlay);\n\n // Trigger fade-in animation\n requestAnimationFrame(() => {\n overlay.style.background = \"rgba(0, 0, 0, 0.5)\";\n container.style.opacity = \"1\";\n container.style.transform = \"scale(1) translateY(0)\";\n });\n\n // Cleanup with fade-out animation\n const cleanupWithAnimation = (): void => {\n if (resolved) return;\n resolved = true;\n\n window.removeEventListener(\"message\", handleMessage);\n window.removeEventListener(\"keydown\", handleKeydown);\n\n // Use requestAnimationFrame to ensure transition is applied\n requestAnimationFrame(() => {\n overlay.style.background = \"rgba(0, 0, 0, 0)\";\n container.style.opacity = \"0\";\n container.style.transform = \"scale(0.95) translateY(10px)\";\n\n setTimeout(() => {\n if (overlay.parentNode) {\n overlay.parentNode.removeChild(overlay);\n }\n }, 250);\n });\n };\n\n // Handle close button click\n const handleCancel = (): void => {\n if (!resolved) {\n console.log(\"[IframeModal] User cancelled\");\n cleanupWithAnimation();\n resolve({ success: false, error: \"Verification cancelled\" });\n }\n };\n\n closeButton.onclick = handleCancel;\n\n // Handle Escape key\n const handleKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Escape\") {\n handleCancel();\n }\n // Trap focus within modal (Tab key cycles through close button and iframe)\n if (event.key === \"Tab\") {\n event.preventDefault();\n if (document.activeElement === closeButton) {\n iframe.focus();\n } else {\n closeButton.focus();\n }\n }\n };\n\n window.addEventListener(\"keydown\", handleKeydown);\n\n // Set initial focus to close button for accessibility\n closeButton.focus();\n\n const handleMessage = (event: MessageEvent): void => {\n const messageResult = onMessage(event);\n if (messageResult.handled) {\n cleanupWithAnimation();\n resolve(messageResult.result);\n }\n };\n\n window.addEventListener(\"message\", handleMessage);\n });\n}\n","/**\n * Next action handlers for processor-specific user actions (e.g., 3DS authentication).\n *\n * This module abstracts processor-specific logic away from the generic card payment flow.\n * Each handler implements the logic needed for a specific next action type.\n */\n\nimport type { PublicCardCheckoutResponse } from \"@pkg/sdk/models\";\nimport type { Stripe } from \"@stripe/stripe-js\";\nimport show3DSIframeModal from \"../utils/3ds-iframe-modal\";\n\n// Helper to wait for a condition\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n// Check if Stripe.js is loaded via script tag\nconst isStripeJsPresent = (): boolean => \"Stripe\" in window;\n\n/**\n * Get the Stripe instance from the global window object.\n * Expects Stripe.js to be loaded via HTML script tag.\n * Polls for up to 5 seconds waiting for Stripe to be available.\n */\nconst getLoadedStripe = async (publishableKey: string): Promise<Stripe> => {\n // Poll for Stripe.js to be loaded (up to 5 seconds)\n for (let i = 0; i < 10; i++) {\n if (isStripeJsPresent()) {\n break;\n }\n await sleep(500);\n }\n\n if (!isStripeJsPresent()) {\n throw new Error(\n \"Stripe.js not loaded. Add this script tag to your HTML <head>:\\n\" +\n '<script src=\"https://js.stripe.com/v3/\"></script>',\n );\n }\n\n // @ts-expect-error Stripe is loaded globally via script tag\n const stripe: Stripe = new window.Stripe(publishableKey);\n return stripe;\n};\n\n/**\n * Result of handling a next action.\n */\nexport type NextActionResult = { success: true } | { success: false; error: string };\n\n/**\n * Handle Stripe 3DS authentication.\n */\nconst handleStripe3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"stripe_3ds\" }>,\n): Promise<NextActionResult> => {\n const { clientSecret, stripePk } = nextAction;\n\n const stripe = await getLoadedStripe(stripePk);\n\n // Show 3DS modal\n const { error: stripeError } = await stripe.confirmCardPayment(clientSecret);\n\n if (stripeError) {\n console.error(\"[3DS:Stripe] Authentication failed:\", stripeError.message);\n return { success: false, error: stripeError.message || \"3DS authentication failed\" };\n }\n\n return { success: true };\n};\n\n/**\n * Handle Airwallex 3DS authentication via iframe.\n *\n * Renders an iframe with the 3DS authentication URL. The iframe will redirect\n * to the 3DS callback page which sends a postMessage back to complete the flow.\n */\nconst handleAirwallex3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"airwallex_3ds\" }>,\n): Promise<NextActionResult> => {\n return show3DSIframeModal({\n url: nextAction.url,\n size: { width: 605, height: 550 },\n onMessage: (event) => {\n if (event.data.type !== \"3ds_complete\") {\n return { handled: false };\n }\n\n const { isSuccess, error } = event.data;\n\n if (isSuccess) {\n return { handled: true, result: { success: true, data: {} } };\n } else {\n console.error(\"[3DS:Airwallex] Authentication failed:\", error);\n return {\n handled: true,\n result: { success: false, error: error || \"3DS authentication failed\" },\n };\n }\n },\n });\n};\n\n/**\n * Handle a next action based on its type.\n * Routes to the appropriate processor-specific handler.\n *\n * @param nextAction - The next action from the checkout response\n * @returns Result indicating success or failure with error message\n */\nexport const handleNextAction = async (\n nextAction: NonNullable<PublicCardCheckoutResponse[\"nextAction\"]>,\n): Promise<NextActionResult> => {\n switch (nextAction.type) {\n case \"stripe_3ds\":\n return handleStripe3ds(nextAction);\n case \"airwallex_3ds\":\n return handleAirwallex3ds(nextAction);\n default:\n // TypeScript will catch if we miss a case when new action types are added\n return { success: false, error: `Unknown next action type: ${(nextAction as { type: string }).type}` };\n }\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as PaymentMethod } from "../types-
|
|
2
|
-
import "../connect-card-
|
|
3
|
-
import "../connect-tunnel-x-
|
|
4
|
-
import { n as BnplCustomerInfo, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-
|
|
1
|
+
import { r as PaymentMethod } from "../types-B3mjYfOm.mjs";
|
|
2
|
+
import "../connect-card-CZhzK_Tp.mjs";
|
|
3
|
+
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
|
+
import { n as BnplCustomerInfo, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-BQwCBD45.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/payment-methods/affirm.d.ts
|
|
7
7
|
type AffirmCustomerInfo = BnplCustomerInfo;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../utils-
|
|
2
|
-
import { t as createBnplPaymentMethod } from "../bnpl-shared-
|
|
1
|
+
import "../utils-Dc6zwOe1.mjs";
|
|
2
|
+
import { t as createBnplPaymentMethod } from "../bnpl-shared-DGs1YzS9.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/payment-methods/affirm.ts
|
|
5
5
|
const AffirmPaymentMethod = createBnplPaymentMethod({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { r as PaymentMethod } from "../types-
|
|
2
|
-
import "../connect-card-
|
|
3
|
-
import "../connect-tunnel-x-
|
|
4
|
-
import { n as BnplCustomerInfo, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-
|
|
1
|
+
import { r as PaymentMethod } from "../types-B3mjYfOm.mjs";
|
|
2
|
+
import "../connect-card-CZhzK_Tp.mjs";
|
|
3
|
+
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
|
+
import { n as BnplCustomerInfo, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-BQwCBD45.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/payment-methods/afterpay.d.ts
|
|
7
7
|
type AfterpayCustomerInfo = BnplCustomerInfo;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../utils-
|
|
2
|
-
import { t as createBnplPaymentMethod } from "../bnpl-shared-
|
|
1
|
+
import "../utils-Dc6zwOe1.mjs";
|
|
2
|
+
import { t as createBnplPaymentMethod } from "../bnpl-shared-DGs1YzS9.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/payment-methods/afterpay.ts
|
|
5
5
|
const AfterpayPaymentMethod = createBnplPaymentMethod({
|
|
@@ -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-
|
|
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-CnnZ7VL6.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-
|
|
1
|
+
import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-CPz54c9e.mjs";
|
|
2
2
|
|
|
3
3
|
export { AirwallexApplePayAdapter, AirwallexApplePayMockScenario };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as GooglePayEncryptedToken, i as AirwallexShowPaymentResult, n as AirwallexGooglePayConfig, r as AirwallexGooglePayMockScenario, t as AirwallexGooglePayAdapter } from "../airwallex-google-pay-adapter-
|
|
1
|
+
import { a as GooglePayEncryptedToken, i as AirwallexShowPaymentResult, n as AirwallexGooglePayConfig, r as AirwallexGooglePayMockScenario, t as AirwallexGooglePayAdapter } from "../airwallex-google-pay-adapter-D-AxVLLq.mjs";
|
|
2
2
|
export { AirwallexGooglePayAdapter, AirwallexGooglePayConfig, AirwallexGooglePayMockScenario, AirwallexShowPaymentResult, GooglePayEncryptedToken };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as AirwallexGooglePayMockScenario, t as AirwallexGooglePayAdapter } from "../airwallex-google-pay-adapter-
|
|
1
|
+
import { n as AirwallexGooglePayMockScenario, t as AirwallexGooglePayAdapter } from "../airwallex-google-pay-adapter-BvlROwj_.mjs";
|
|
2
2
|
|
|
3
3
|
export { AirwallexGooglePayAdapter, AirwallexGooglePayMockScenario };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { r as PaymentMethod } from "../types-
|
|
2
|
-
import "../connect-card-
|
|
3
|
-
import "../connect-tunnel-x-
|
|
4
|
-
import { a as ApplePayEncryptedToken } from "../airwallex-apple-pay-adapter-
|
|
5
|
-
import { t as ApplePayMockScenario } from "../stripe-apple-pay-adapter-
|
|
1
|
+
import { r as PaymentMethod } from "../types-B3mjYfOm.mjs";
|
|
2
|
+
import "../connect-card-CZhzK_Tp.mjs";
|
|
3
|
+
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
|
+
import { a as ApplePayEncryptedToken } from "../airwallex-apple-pay-adapter-CnnZ7VL6.mjs";
|
|
5
|
+
import { t as ApplePayMockScenario } from "../stripe-apple-pay-adapter-D2OJRlAl.mjs";
|
|
6
6
|
|
|
7
7
|
//#region src/payment-methods/apple-pay.d.ts
|
|
8
8
|
type ApplePayCustomerInfo = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-
|
|
2
|
-
import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-
|
|
3
|
-
import { t as handleNextAction } from "../next-action-handlers-
|
|
4
|
-
import { n as StripeApplePayAdapter, t as ApplePayMockScenario } from "../stripe-apple-pay-adapter-
|
|
1
|
+
import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-Dc6zwOe1.mjs";
|
|
2
|
+
import { n as AirwallexApplePayMockScenario, t as AirwallexApplePayAdapter } from "../airwallex-apple-pay-adapter-CPz54c9e.mjs";
|
|
3
|
+
import { t as handleNextAction } from "../next-action-handlers-CLOt1wzO.mjs";
|
|
4
|
+
import { n as StripeApplePayAdapter, t as ApplePayMockScenario } from "../stripe-apple-pay-adapter-7rF6xRIG.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/payment-methods/apple-pay.ts
|
|
7
7
|
let preparedStripeState = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../types-
|
|
2
|
-
import "../connect-card-
|
|
3
|
-
import "../connect-tunnel-x-
|
|
4
|
-
import { a as BnplStartResponse, c as createBnplPaymentMethod, i as BnplStartRequest, n as BnplCustomerInfo, o as BnplStatusResponse, r as BnplProviderConfig, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-
|
|
1
|
+
import "../types-B3mjYfOm.mjs";
|
|
2
|
+
import "../connect-card-CZhzK_Tp.mjs";
|
|
3
|
+
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
|
+
import { a as BnplStartResponse, c as createBnplPaymentMethod, i as BnplStartRequest, n as BnplCustomerInfo, o as BnplStatusResponse, r as BnplProviderConfig, s as BnplSubmitOptions, t as BnplCheckoutResponse } from "../bnpl-shared-BQwCBD45.mjs";
|
|
5
5
|
export { BnplCheckoutResponse, BnplCustomerInfo, BnplProviderConfig, BnplStartRequest, BnplStartResponse, BnplStatusResponse, BnplSubmitOptions, createBnplPaymentMethod };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as PaymentMethod } from "../types-
|
|
2
|
-
import { n as CardInputType$1, o as connectToCardIframe, r as CheckoutResponse$1 } from "../connect-card-
|
|
3
|
-
import "../connect-tunnel-x-
|
|
1
|
+
import { r as PaymentMethod } from "../types-B3mjYfOm.mjs";
|
|
2
|
+
import { n as CardInputType$1, o as connectToCardIframe, r as CheckoutResponse$1 } from "../connect-card-CZhzK_Tp.mjs";
|
|
3
|
+
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/payment-methods/card.d.ts
|
|
6
6
|
type CardInputType = CardInputType$1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.d.mts","names":[],"sources":["../../src/payment-methods/card.ts"],"sourcesContent":[],"mappings":";;;;;KAQY,aAAA,GAAgB;KAChB,gBAAA,GAAmB;
|
|
1
|
+
{"version":3,"file":"card.d.mts","names":[],"sources":["../../src/payment-methods/card.ts"],"sourcesContent":[],"mappings":";;;;;KAQY,aAAA,GAAgB;KAChB,gBAAA,GAAmB;KAsG1B,oBAAA,GAAuB,QAAQ,kBAAkB;UAC5C;EAxGE,WAAA,CAAA,EAAA,MAAa;AACzB,CAAA;AAAsD,cA6zBhD,iBAvtBmB,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,MAstBV,CAAA"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import "../
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
6
|
-
import {
|
|
1
|
+
import { n as AnalyticsService } from "../analytics-Blvs2DW7.mjs";
|
|
2
|
+
import "../penpal-CBrj43M5.mjs";
|
|
3
|
+
import { t as TunnelXManager } from "../connect-tunnel-x-5XOct5Tm.mjs";
|
|
4
|
+
import { a as validateFormFields, i as definePaymentMethod, n as collectFraudMetadata, r as createCheckoutIFrame, s as withRequestId, t as $ } from "../utils-Dc6zwOe1.mjs";
|
|
5
|
+
import { t as handleNextAction } from "../next-action-handlers-CLOt1wzO.mjs";
|
|
6
|
+
import { t as connectToCardIframe } from "../connect-card-kXLdSNTL.mjs";
|
|
7
|
+
import { n as initVgsCollect, r as loadVgsCollectScript, t as createVgsCardFields } from "../vgs-collect-loader-CTLSv4qv.mjs";
|
|
7
8
|
|
|
8
9
|
//#region src/payment-methods/card.ts
|
|
9
10
|
/**
|
|
@@ -297,14 +298,23 @@ const defSubmitPayment = (states) => {
|
|
|
297
298
|
};
|
|
298
299
|
/**
|
|
299
300
|
* Fetches a VGS CMP access token from the backend.
|
|
301
|
+
* Uses AbortController with 10s timeout to prevent indefinite hangs on slow networks.
|
|
300
302
|
*/
|
|
303
|
+
const FETCH_COLLECT_TOKEN_TIMEOUT_MS = 1e4;
|
|
301
304
|
const fetchCollectToken = async (apiBaseUrl, secureToken) => {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
305
|
+
const controller = new AbortController();
|
|
306
|
+
const timeoutId = setTimeout(() => controller.abort(), FETCH_COLLECT_TOKEN_TIMEOUT_MS);
|
|
307
|
+
try {
|
|
308
|
+
const resp = await fetch(`${apiBaseUrl}/api/card-setup-intents/${secureToken}/collect-token`, {
|
|
309
|
+
method: "POST",
|
|
310
|
+
headers: { "Content-Type": "application/json" },
|
|
311
|
+
signal: controller.signal
|
|
312
|
+
});
|
|
313
|
+
if (!resp.ok) throw new Error(`Failed to get collect token: ${resp.status}`);
|
|
314
|
+
return (await resp.json()).access_token;
|
|
315
|
+
} finally {
|
|
316
|
+
clearTimeout(timeoutId);
|
|
317
|
+
}
|
|
308
318
|
};
|
|
309
319
|
/**
|
|
310
320
|
* Creates a card via VGS CMP and sends aliases to our backend.
|
|
@@ -360,18 +370,36 @@ const submitVgsCardFields = async (states, tunnelX) => {
|
|
|
360
370
|
};
|
|
361
371
|
}
|
|
362
372
|
let accessToken;
|
|
373
|
+
const collectTokenStart = performance.now();
|
|
363
374
|
try {
|
|
364
375
|
accessToken = await fetchCollectToken(apiBaseUrl, secureToken);
|
|
376
|
+
const collectTokenDuration = Math.round(performance.now() - collectTokenStart);
|
|
377
|
+
AnalyticsService.capture("vgs_collect_token_timing", {
|
|
378
|
+
checkout_session_id: secureToken,
|
|
379
|
+
request_id: checkoutRequestId,
|
|
380
|
+
duration_ms: collectTokenDuration,
|
|
381
|
+
success: true
|
|
382
|
+
});
|
|
365
383
|
} catch (err) {
|
|
384
|
+
const collectTokenDuration = Math.round(performance.now() - collectTokenStart);
|
|
385
|
+
const isAbortError = err instanceof DOMException && err.name === "AbortError";
|
|
386
|
+
AnalyticsService.capture("vgs_collect_token_timing", {
|
|
387
|
+
checkout_session_id: secureToken,
|
|
388
|
+
request_id: checkoutRequestId,
|
|
389
|
+
duration_ms: collectTokenDuration,
|
|
390
|
+
success: false,
|
|
391
|
+
error_type: isAbortError ? "FETCH_TIMEOUT" : "FETCH_ERROR"
|
|
392
|
+
});
|
|
366
393
|
console.error(`${logPrefix} VGS auth token fetch failed:`, stringifyError(err));
|
|
367
|
-
errors.root = "Card authentication failed — please try again";
|
|
394
|
+
errors.root = isAbortError ? "Card authentication timed out — please try again" : "Card authentication failed — please try again";
|
|
368
395
|
return {
|
|
369
396
|
errors,
|
|
370
397
|
isSuccess: false
|
|
371
398
|
};
|
|
372
399
|
}
|
|
373
400
|
let cardResult;
|
|
374
|
-
const VGS_CREATE_CARD_TIMEOUT_MS =
|
|
401
|
+
const VGS_CREATE_CARD_TIMEOUT_MS = 12e4;
|
|
402
|
+
const createCardStart = performance.now();
|
|
375
403
|
try {
|
|
376
404
|
let createCardTimeoutId;
|
|
377
405
|
cardResult = await Promise.race([new Promise((resolve, reject) => {
|
|
@@ -382,10 +410,25 @@ const submitVgsCardFields = async (states, tunnelX) => {
|
|
|
382
410
|
}), new Promise((_, reject) => {
|
|
383
411
|
createCardTimeoutId = setTimeout(() => reject(/* @__PURE__ */ new Error("VGS_TIMEOUT")), VGS_CREATE_CARD_TIMEOUT_MS);
|
|
384
412
|
})]).finally(() => clearTimeout(createCardTimeoutId));
|
|
413
|
+
const createCardDuration = Math.round(performance.now() - createCardStart);
|
|
414
|
+
AnalyticsService.capture("vgs_create_card_timing", {
|
|
415
|
+
checkout_session_id: secureToken,
|
|
416
|
+
request_id: checkoutRequestId,
|
|
417
|
+
duration_ms: createCardDuration,
|
|
418
|
+
success: true
|
|
419
|
+
});
|
|
385
420
|
} catch (err) {
|
|
421
|
+
const createCardDuration = Math.round(performance.now() - createCardStart);
|
|
386
422
|
const errStr = stringifyError(err);
|
|
387
423
|
console.error(`${logPrefix} VGS createCard failed:`, errStr);
|
|
388
424
|
if (err instanceof Error && err.message === "VGS_TIMEOUT") {
|
|
425
|
+
AnalyticsService.capture("vgs_create_card_timing", {
|
|
426
|
+
checkout_session_id: secureToken,
|
|
427
|
+
request_id: checkoutRequestId,
|
|
428
|
+
duration_ms: createCardDuration,
|
|
429
|
+
success: false,
|
|
430
|
+
error_type: "VGS_TIMEOUT"
|
|
431
|
+
});
|
|
389
432
|
errors.root = "Card processing timed out — please try again";
|
|
390
433
|
return {
|
|
391
434
|
errors,
|
|
@@ -398,11 +441,27 @@ const submitVgsCardFields = async (states, tunnelX) => {
|
|
|
398
441
|
const messages = vgsErrors[vgsKey]?.errorMessages;
|
|
399
442
|
errors[fieldKey] = Array.isArray(messages) ? messages[0] : "invalid";
|
|
400
443
|
}
|
|
401
|
-
if (Object.keys(errors).length > 0)
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
444
|
+
if (Object.keys(errors).length > 0) {
|
|
445
|
+
AnalyticsService.capture("vgs_create_card_timing", {
|
|
446
|
+
checkout_session_id: secureToken,
|
|
447
|
+
request_id: checkoutRequestId,
|
|
448
|
+
duration_ms: createCardDuration,
|
|
449
|
+
success: false,
|
|
450
|
+
error_type: "VGS_VALIDATION_ERROR"
|
|
451
|
+
});
|
|
452
|
+
return {
|
|
453
|
+
errors,
|
|
454
|
+
isSuccess: false
|
|
455
|
+
};
|
|
456
|
+
}
|
|
405
457
|
}
|
|
458
|
+
AnalyticsService.capture("vgs_create_card_timing", {
|
|
459
|
+
checkout_session_id: secureToken,
|
|
460
|
+
request_id: checkoutRequestId,
|
|
461
|
+
duration_ms: createCardDuration,
|
|
462
|
+
success: false,
|
|
463
|
+
error_type: "VGS_ERROR"
|
|
464
|
+
});
|
|
406
465
|
errors.root = "Card validation failed — please check your card details and try again";
|
|
407
466
|
return {
|
|
408
467
|
errors,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.mjs","names":["taxIds: string[] | undefined","cleanupVgs: (() => void) | undefined","cleanupDirect: (() => void) | undefined","cdnTimeoutId: ReturnType<typeof setTimeout>","params: Record<string, string>","submitPayment: TInternalFuncs[\"submitPayment\"]","VGS_FIELD_MAP: Record<string, keyof PaymentKitErrors>","accessToken: string","cardResult: VGSCreateCardResponse","createCardTimeoutId: ReturnType<typeof setTimeout>","errors: PaymentKitErrors"],"sources":["../../src/payment-methods/card.ts"],"sourcesContent":["import {\n connectToCardIframe,\n type IFrameConnection,\n type CardInputType as PenpalCardInputType,\n type CheckoutResponse as PenpalCheckoutResponse,\n} from \"../penpal/connect-card\";\n\n// Re-export types for public API\nexport type CardInputType = PenpalCardInputType;\nexport type CheckoutResponse = PenpalCheckoutResponse;\n\nimport { TunnelXManager } from \"../penpal/connect-tunnel-x\";\nimport type { PaymentKitErrors, PaymentKitFields, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport {\n $,\n collectFraudMetadata,\n createCheckoutIFrame,\n definePaymentMethod,\n validateFormFields,\n withRequestId,\n} from \"../utils\";\nimport { handleNextAction } from \"./next-action-handlers\";\nimport { createVgsCardFields, initVgsCollect, loadVgsCollectScript } from \"./vgs-collect-loader\";\n\n/**\n * Splits a full name into first name and last name.\n * First word becomes firstName, rest becomes lastName.\n */\nconst splitName = (fullName: string): { firstName: string; lastName?: string } => {\n const trimmed = fullName.trim();\n const spaceIndex = trimmed.indexOf(\" \");\n if (spaceIndex === -1) {\n return { firstName: trimmed };\n }\n return {\n firstName: trimmed.substring(0, spaceIndex),\n lastName: trimmed.substring(spaceIndex + 1).trim() || undefined,\n };\n};\n\n/**\n * Maps PaymentKitFields to the customerInfo structure expected by the API.\n */\nconst mapFieldsToCustomerInfo = (fields: PaymentKitFields) => {\n const { firstName, lastName } = splitName(fields.customer_name);\n\n const hasBillingAddress =\n fields.customer_country ||\n fields.customer_zip_code ||\n fields.customer_address_line1 ||\n fields.customer_address_line2 ||\n fields.customer_city ||\n fields.customer_state;\n\n const hasShippingAddress =\n fields.shipping_address_line1 ||\n fields.shipping_address_line2 ||\n fields.shipping_city ||\n fields.shipping_state ||\n fields.shipping_zip_code ||\n fields.shipping_country;\n\n let taxIds: string[] | undefined;\n if (fields.customer_tax_ids) {\n try {\n taxIds = JSON.parse(fields.customer_tax_ids);\n } catch {\n taxIds = undefined;\n }\n }\n\n return {\n email: fields.customer_email || undefined,\n firstName,\n lastName,\n businessName: fields.customer_business_name || undefined,\n taxIds: taxIds?.length ? taxIds : undefined,\n billingAddress: hasBillingAddress\n ? {\n country: fields.customer_country || undefined,\n zipCode: fields.customer_zip_code || undefined,\n line1: fields.customer_address_line1 || undefined,\n line2: fields.customer_address_line2 || undefined,\n city: fields.customer_city || undefined,\n state: fields.customer_state || undefined,\n }\n : undefined,\n shippingAddress: hasShippingAddress\n ? {\n line1: fields.shipping_address_line1 || undefined,\n line2: fields.shipping_address_line2 || undefined,\n city: fields.shipping_city || undefined,\n state: fields.shipping_state || undefined,\n zipCode: fields.shipping_zip_code || undefined,\n country: fields.shipping_country || undefined,\n }\n : undefined,\n };\n};\n\ntype CardStates = PaymentKitStates & {\n cardSetupIntentId?: string;\n cardInputConnections: Partial<Record<PenpalCardInputType, IFrameConnection>>;\n vgsForm?: VGSCollectForm;\n vgsFieldsCleanup?: () => void;\n vgsFocusCallbacks?: Partial<Record<PenpalCardInputType, (isFocused: boolean) => void>>;\n vgsMountSelectors?: Partial<Record<PenpalCardInputType, string>>;\n vgsPlaceholders?: Partial<Record<PenpalCardInputType, string>>;\n};\n\ntype CreateElementOptions = Partial<Parameters<typeof connectToCardIframe>[1]> & {\n style?: Record<string, string>;\n placeholder?: string;\n};\n\nconst defCreateElement = (states: CardStates) => {\n const { baseUrl, apiBaseUrl, cardInputConnections, secureToken, timingTracker } = states;\n\n return (type: PenpalCardInputType, options: CreateElementOptions) => {\n const { style, onLoaded, onFocusChange, placeholder } = options;\n\n const mountIFrame = (parentSelector: string) => {\n // Mutable cleanup callbacks — set once mode is determined and mount completes\n let cleanupVgs: (() => void) | undefined;\n let cleanupDirect: (() => void) | undefined;\n // Cancellation flag: prevents deferred doMount from executing after unmount.\n // Needed because React strict mode may call unmount before the deferred\n // _sessionConfigReady promise resolves.\n let cancelled = false;\n\n /**\n * Performs the actual DOM mount after the tokenization mode is known.\n * Runs synchronously when mode is explicitly provided, or after the\n * auto-detect fetch resolves.\n */\n // Store mount selector so VGS init (triggered by card_pan) can read\n // the exp/cvc selectors that were registered by their own createElement calls.\n if (!states.vgsMountSelectors) states.vgsMountSelectors = {};\n states.vgsMountSelectors[type] = parentSelector;\n\n const doMount = () => {\n if (cancelled) return;\n const isVgsMode = states.cardTokenizationMode === \"vgs\";\n console.log(\n `[PaymentKit] card.doMount(${type}) — mode: ${states.cardTokenizationMode}, vgsVaultId: ${states.vgsVaultId ?? \"unset\"}, vgsEnvironment: ${states.vgsEnvironment ?? \"unset\"}`,\n );\n\n // VGS mode: initialize VGS Collect form and mount fields on card_pan\n if (isVgsMode && states.vgsVaultId && states.vgsEnvironment) {\n // Store per-field focus callbacks and placeholders so createVgsCardFields\n // can wire each field to its own callback/placeholder. All three createElement\n // calls complete before the CDN script loads, so all values are available by then.\n if (onFocusChange) {\n if (!states.vgsFocusCallbacks) states.vgsFocusCallbacks = {};\n states.vgsFocusCallbacks[type] = onFocusChange;\n }\n if (placeholder) {\n if (!states.vgsPlaceholders) states.vgsPlaceholders = {};\n states.vgsPlaceholders[type] = placeholder;\n }\n\n if (type === \"card_pan\") {\n const vaultId = states.vgsVaultId;\n const vgsEnv = states.vgsEnvironment;\n\n console.log(`[PaymentKit] VGS mode active — loading VGS Collect CDN for vault ${vaultId} (${vgsEnv})...`);\n const VGS_CDN_TIMEOUT_MS = 15_000;\n let cdnTimeoutId: ReturnType<typeof setTimeout>;\n Promise.race([\n loadVgsCollectScript(),\n new Promise<never>((_, reject) => {\n cdnTimeoutId = setTimeout(() => {\n console.warn(`[PaymentKit] VGS Collect CDN load timed out after ${VGS_CDN_TIMEOUT_MS / 1000}s`);\n reject(new Error(\"VGS Collect CDN load timed out\"));\n }, VGS_CDN_TIMEOUT_MS);\n }),\n ])\n .finally(() => clearTimeout(cdnTimeoutId))\n .then(() => {\n if (cancelled) return;\n console.log(\"[PaymentKit] VGS Collect CDN loaded — initializing form...\");\n const form = initVgsCollect(vaultId, vgsEnv);\n if (cancelled) {\n form.unmount();\n return;\n }\n states.vgsForm = form;\n\n const css = style\n ? Object.fromEntries(\n Object.entries(style).map(([k, v]) => [k.replace(/([A-Z])/g, \"-$1\").toLowerCase(), v]),\n )\n : undefined;\n\n // Read exp/cvc selectors from shared state.\n // Each createElement(\"card_exp/card_cvc\").mount(selector) stores its\n // selector before this async callback runs, so they're available here.\n const expSelector = states.vgsMountSelectors?.card_exp;\n const cvcSelector = states.vgsMountSelectors?.card_cvc;\n if (!expSelector || !cvcSelector) {\n const msg =\n `[PaymentKit] VGS mode requires all three card fields to be mounted. ` +\n `Missing: ${!expSelector ? \"card_exp\" : \"\"}${!expSelector && !cvcSelector ? \", \" : \"\"}${!cvcSelector ? \"card_cvc\" : \"\"}`;\n console.error(msg);\n onLoaded?.();\n return;\n }\n console.log(\n `[PaymentKit] Creating VGS card fields — pan: ${parentSelector}, exp: ${expSelector}, cvc: ${cvcSelector}`,\n );\n states.vgsFieldsCleanup = createVgsCardFields(\n form,\n {\n pan: parentSelector,\n exp: expSelector,\n cvc: cvcSelector,\n },\n css,\n states.vgsFocusCallbacks,\n states.vgsPlaceholders,\n );\n\n console.log(\"[PaymentKit] VGS card fields created successfully\");\n timingTracker.trackInputReady();\n onLoaded?.();\n })\n .catch((err) => {\n console.error(\"[PaymentKit] Failed to load VGS Collect script. Card input will not be available:\", err);\n // Signal loaded so the form exits loading state rather than hanging forever.\n // Card fields won't render, but submit will fail with a clear error.\n onLoaded?.();\n });\n }\n\n // For non-pan fields in VGS mode, signal loaded immediately since\n // VGS handles all three fields from the card_pan mount.\n if (type !== \"card_pan\") {\n onLoaded?.();\n }\n\n cleanupVgs = () => {\n if (type === \"card_pan\" && states.vgsForm) {\n try {\n states.vgsFieldsCleanup?.();\n } catch {\n // VGS may try to remove iframes from containers already removed by React\n }\n states.vgsFieldsCleanup = undefined;\n try {\n states.vgsForm.unmount();\n } catch {\n // VGS unmount may fail if DOM nodes are already detached\n }\n states.vgsForm = undefined;\n }\n };\n return;\n }\n\n // If we got here and mode was \"vgs\", it means VGS config was incomplete\n if (isVgsMode) {\n console.warn(\n `[PaymentKit] VGS mode requested but config incomplete (vgsVaultId: ${states.vgsVaultId ?? \"unset\"}, vgsEnvironment: ${states.vgsEnvironment ?? \"unset\"}) — using direct mode`,\n );\n }\n\n // Direct mode: existing penpal iframe logic\n const parent = $(parentSelector) as HTMLElement;\n\n // Read container padding so the embed input matches the merchant's\n // visual intent. The iframe uses absolute positioning to fill the\n // full container, so the input needs its own padding for alignment.\n const computed = getComputedStyle(parent);\n const containerPadding = computed.padding !== \"0px\" ? computed.padding : undefined;\n const enhancedStyle = {\n ...(style ?? {}),\n height: \"100%\",\n boxSizing: \"border-box\",\n ...(containerPadding ? { padding: containerPadding } : {}),\n };\n\n const params: Record<string, string> = {\n checkout_token: secureToken,\n api_base_url: apiBaseUrl,\n style: JSON.stringify(enhancedStyle),\n };\n\n const iframe = createCheckoutIFrame(type.replace(\"_\", \"-\"), baseUrl, params);\n\n // Use absolute positioning so the iframe covers the full container\n // including any padding the merchant's CSS applies.\n if (computed.position === \"static\") {\n parent.style.position = \"relative\";\n }\n iframe.style.position = \"absolute\";\n iframe.style.inset = \"0\";\n\n // Set cleanup before DOM mutation to avoid leaking the iframe if\n // unmount() is called between appendChild and onload.\n cleanupDirect = () => {\n const connection = cardInputConnections[type];\n connection?.destroy();\n try {\n parent.removeChild(iframe);\n } catch {\n // Parent may already be detached from DOM by React\n }\n states.cardInputConnections[type] = undefined;\n };\n\n parent.appendChild(iframe);\n\n iframe.onload = () => {\n if (type === \"card_pan\") {\n timingTracker.trackInputReady();\n }\n\n const connection = connectToCardIframe(iframe, {\n onLoaded: onLoaded || (() => {}),\n onFocusChange: onFocusChange || (() => {}),\n });\n\n states.cardInputConnections[type] = connection;\n };\n };\n\n // If session config needs auto-detection, wait for it; otherwise mount synchronously\n if (states._sessionConfigReady) {\n states._sessionConfigReady.then(doMount);\n } else {\n doMount();\n }\n\n return {\n unmount: () => {\n cancelled = true;\n cleanupVgs?.();\n cleanupDirect?.();\n },\n };\n };\n\n return { mount: mountIFrame };\n };\n};\n\nconst defSubmitPayment = (states: CardStates) => {\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (fields, options) => {\n // Ensure session config is loaded (no-op if explicitly provided)\n if (states._sessionConfigReady) await states._sessionConfigReady;\n const isVgsMode = states.cardTokenizationMode === \"vgs\";\n\n const { timingTracker, checkoutRequestId } = states;\n\n // Track submit event\n timingTracker.trackSubmit();\n\n // Use the checkout request ID from states (generated on page load)\n const requestOptions = withRequestId(checkoutRequestId);\n\n const tunnelX = await TunnelXManager.createFromPenpalConnection(states.tunnelXConnection);\n\n // Step 1. Validate form values.\n // Form field validation is shared across both modes.\n // In VGS mode, card field validation is handled by VGS Collect (built-in validators).\n // In direct mode, card field validation is handled by penpal iframes.\n const skipCustomerValidation = options?.skipCustomerValidation === true;\n const validateFormResult = skipCustomerValidation ? { isSuccess: true as const } : await validateFormFields(fields);\n if (!isVgsMode) {\n const validateCardResult = await validateCardFields(states);\n if (!(validateCardResult.isSuccess && validateFormResult.isSuccess)) {\n timingTracker.trackFail(null, \"validation_error\", \"Form validation failed\");\n return { errors: { ...validateCardResult.errors, ...validateFormResult.errors } };\n }\n } else if (!validateFormResult.isSuccess) {\n timingTracker.trackFail(null, \"validation_error\", \"Form validation failed\");\n return { errors: validateFormResult.errors };\n }\n\n // Step 2. Create card setup intent if not present\n if (!states.cardSetupIntentId) {\n const res = await tunnelX.publicEndpoints.createCardSetupIntent({\n checkoutToken: states.secureToken,\n });\n states.cardSetupIntentId = res.cardSetupIntentId;\n }\n\n // Step 3. Submit card values.\n if (isVgsMode) {\n // VGS mode: create card via CMP, then send aliases to backend\n console.log(\"[PaymentKit] Submitting card via VGS CMP...\");\n const vgsSubmitResult = await submitVgsCardFields(states, tunnelX);\n if (!vgsSubmitResult.isSuccess) {\n // Include field-level error details for PostHog visibility\n const errorDetail = Object.entries(vgsSubmitResult.errors)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n timingTracker.trackFail(null, \"card_submit_error\", errorDetail || \"VGS card submission failed\");\n return { errors: vgsSubmitResult.errors };\n }\n } else {\n // Direct mode: submit via penpal iframes\n const submitCardResult = await submitCardFields(states);\n if (!submitCardResult.isSuccess) {\n timingTracker.trackFail(null, \"card_submit_error\", \"Card submission failed\");\n return { errors: submitCardResult.errors };\n }\n }\n\n // Step 4. Get card setup intent.\n const cardSetupIntent = await tunnelX.publicEndpoints.getCardSetupIntent({\n cardSetupIntentId: states.cardSetupIntentId,\n checkoutToken: states.secureToken,\n });\n if (!cardSetupIntent.isCardAllSet) {\n const errors = {} as PaymentKitErrors;\n if (!cardSetupIntent.isCardPanSet) errors.card_pan = \"required\";\n if (!cardSetupIntent.isCardExpSet) errors.card_exp = \"required\";\n if (!cardSetupIntent.isCardCvcSet) errors.card_cvc = \"required\";\n timingTracker.trackFail(null, \"card_setup_incomplete\", \"Card details incomplete\");\n return { errors };\n }\n\n console.log(\"Card setup intent is set ✅\", cardSetupIntent);\n console.log(\"Fields\", fields);\n\n // Step 5. Submit card checkout with customer info and fraud metadata\n let currentResult = await tunnelX.publicEndpoints.cardCheckout(\n {\n checkoutToken: states.secureToken,\n publicCardCheckoutRequest: {\n cardSetupIntentId: states.cardSetupIntentId,\n customerInfo: mapFieldsToCustomerInfo(fields),\n fraudMetadata: collectFraudMetadata(),\n },\n },\n requestOptions,\n );\n\n console.log(\"Card checkout result:\", currentResult);\n\n // Step 6. Handle next actions in a loop (supports multiple 3DS challenges)\n // This loop handles the case where one processor fails and we try another\n // that also requires 3DS authentication.\n const MAX_USER_ACTIONS = 5; // Safety limit to prevent infinite loops\n let userActionCount = 0;\n\n while (currentResult.nextAction && userActionCount < MAX_USER_ACTIONS) {\n userActionCount++;\n console.log(`Handling user action ${userActionCount}/${MAX_USER_ACTIONS}...`);\n\n const actionResult = await handleNextAction(currentResult.nextAction);\n\n // Always call verify endpoint so backend can properly conclude the checkout.\n // This is needed even on 3DS failure so the backend can transition from\n // user_actions_requested to card_payment_concluded with proper failure state.\n console.log(\"User action completed, verifying checkout...\");\n const verifyResult = await tunnelX.publicEndpoints.cardCheckoutVerify(\n {\n checkoutToken: states.secureToken,\n },\n requestOptions,\n );\n\n // Check if another action is required (e.g., cascade to next processor with 3DS)\n // This must be checked BEFORE returning error, as cascade may offer a new 3DS challenge\n if (verifyResult.nextAction) {\n if (!actionResult.success) {\n console.log(\"3DS failed but cascade triggered new action, continuing loop...\");\n } else {\n console.log(\"Another user action required, continuing loop...\");\n }\n currentResult = verifyResult;\n continue;\n }\n\n if (!actionResult.success) {\n // 3DS failed and no cascade/retry available - return error\n // Include verifyResult as checkout_response so error_code is available to frontend\n console.log(\"3DS authentication failed, checkout concluded:\", verifyResult);\n timingTracker.trackFail(\n verifyResult.checkoutAttemptId || null,\n verifyResult.errorCode || \"3ds_failed\",\n verifyResult.errorMessageForCustomer || actionResult.error,\n );\n return {\n errors: {\n root: verifyResult.errorMessageForCustomer || actionResult.error,\n checkout_response: verifyResult,\n },\n };\n }\n\n console.log(\"Card checkout verified ✅\", verifyResult);\n\n // No more actions needed, return the result\n timingTracker.trackSuccess(verifyResult.checkoutAttemptId || \"unknown\");\n return { data: verifyResult as { [key: string]: unknown } };\n }\n\n if (userActionCount >= MAX_USER_ACTIONS) {\n console.error(\"Max user actions exceeded\");\n timingTracker.trackFail(null, \"max_actions_exceeded\", \"Too many authentication attempts\");\n return { errors: { root: \"Too many authentication attempts. Please try again.\" } };\n }\n\n // Check if checkout succeeded or failed\n // States: checkout_succeeded (success), payment_failed (failure)\n if (currentResult.state === \"payment_failed\" || currentResult.state === \"checkout_failed\") {\n console.log(\"Card checkout failed:\", currentResult);\n timingTracker.trackFail(\n currentResult.checkoutAttemptId || null,\n currentResult.errorCode || \"payment_failed\",\n currentResult.errorMessageForCustomer || \"Payment failed\",\n );\n // Return the full response as errors so frontend can display error details\n // including error_code, error_message_for_customer, error_message_for_debug\n return {\n errors: {\n root: currentResult.errorMessageForCustomer || \"Payment failed\",\n checkout_response: currentResult,\n },\n };\n }\n\n console.log(\"Card checkout completed ✅\", currentResult);\n timingTracker.trackSuccess(currentResult.checkoutAttemptId || \"unknown\");\n return { data: currentResult as { [key: string]: unknown } };\n };\n return submitPayment;\n};\n\n/**\n * Fetches a VGS CMP access token from the backend.\n */\nconst fetchCollectToken = async (apiBaseUrl: string, secureToken: string): Promise<string> => {\n const resp = await fetch(`${apiBaseUrl}/api/card-setup-intents/${secureToken}/collect-token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n });\n if (!resp.ok) {\n throw new Error(`Failed to get collect token: ${resp.status}`);\n }\n const data = await resp.json();\n return data.access_token;\n};\n\n/**\n * Creates a card via VGS CMP and sends aliases to our backend.\n *\n * Flow:\n * 1. Fetch CMP access token from our backend\n * 2. Call form.createCard() → VGS creates card, returns aliases\n * 3. Send aliases + fraud metadata to our backend via updateCardSetupIntent\n */\n/**\n * Map VGS field-level error keys to PaymentKitErrors field keys.\n *\n * VGS CMP errorCallback uses short field names (\"pan\", \"cvc\", \"exp-date\")\n * matching the CMP field type, NOT the longer CSS-style names. Both forms\n * are mapped here for robustness.\n */\nconst VGS_FIELD_MAP: Record<string, keyof PaymentKitErrors> = {\n // Actual VGS CMP error keys (verified empirically)\n pan: \"card_pan\",\n cvc: \"card_cvc\",\n \"exp-date\": \"card_exp\",\n // Alternative key formats (VGS documentation references)\n \"card-number\": \"card_pan\",\n \"card-security-code\": \"card_cvc\",\n \"card-expiration-date\": \"card_exp\",\n};\n\n/**\n * Safely stringify an error for console logging.\n * VGS errors are plain objects that print as [object Object] without this.\n */\nconst stringifyError = (err: unknown): string => {\n if (err instanceof Error) return err.message;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n};\n\nconst submitVgsCardFields = async (\n states: CardStates,\n tunnelX: Awaited<ReturnType<typeof TunnelXManager.createFromPenpalConnection>>,\n): Promise<{ errors: PaymentKitErrors; isSuccess: boolean }> => {\n const { vgsForm, cardSetupIntentId, secureToken, apiBaseUrl, checkoutRequestId } = states;\n const logPrefix = `[PaymentKit] [${checkoutRequestId}]`;\n const errors = {} as PaymentKitErrors;\n\n if (!vgsForm) {\n errors.card_pan = \"required\";\n return { errors, isSuccess: false };\n }\n\n if (!cardSetupIntentId) {\n errors.root = \"Card setup intent not created\";\n return { errors, isSuccess: false };\n }\n\n // Step 1: Get CMP access token from our backend\n let accessToken: string;\n try {\n accessToken = await fetchCollectToken(apiBaseUrl, secureToken);\n } catch (err) {\n console.error(`${logPrefix} VGS auth token fetch failed:`, stringifyError(err));\n errors.root = \"Card authentication failed — please try again\";\n return { errors, isSuccess: false };\n }\n\n // Step 2: Create card via VGS CMP — returns aliases for PAN/CVC, plain text expiry\n let cardResult: VGSCreateCardResponse;\n const VGS_CREATE_CARD_TIMEOUT_MS = 30_000;\n try {\n let createCardTimeoutId: ReturnType<typeof setTimeout>;\n cardResult = await Promise.race([\n new Promise<VGSCreateCardResponse>((resolve, reject) => {\n vgsForm.createCard(\n {\n auth: accessToken,\n data: { cardholder: {} },\n },\n (_status, cardObject) => resolve(cardObject),\n (error) => reject(error),\n );\n }),\n new Promise<never>((_, reject) => {\n createCardTimeoutId = setTimeout(() => reject(new Error(\"VGS_TIMEOUT\")), VGS_CREATE_CARD_TIMEOUT_MS);\n }),\n ]).finally(() => clearTimeout(createCardTimeoutId));\n } catch (err) {\n const errStr = stringifyError(err);\n console.error(`${logPrefix} VGS createCard failed:`, errStr);\n\n // Distinguish timeout from VGS field validation errors\n if (err instanceof Error && err.message === \"VGS_TIMEOUT\") {\n errors.root = \"Card processing timed out — please try again\";\n return { errors, isSuccess: false };\n }\n\n // VGS errorCallback returns field-level errors as a plain object,\n // e.g. { \"card-number\": { errorMessages: [\"Card number is not valid\"] } }\n // Map them to per-field errors so inline validation shows on the right field.\n if (err && typeof err === \"object\" && !(err instanceof Error)) {\n const vgsErrors = err as Record<string, unknown>;\n for (const [vgsKey, fieldKey] of Object.entries(VGS_FIELD_MAP)) {\n if (vgsKey in vgsErrors) {\n const fieldErr = vgsErrors[vgsKey] as Record<string, unknown> | undefined;\n const messages = fieldErr?.errorMessages;\n errors[fieldKey] = Array.isArray(messages) ? messages[0] : \"invalid\";\n }\n }\n if (Object.keys(errors).length > 0) {\n return { errors, isSuccess: false };\n }\n }\n\n errors.root = \"Card validation failed — please check your card details and try again\";\n return { errors, isSuccess: false };\n }\n\n // Step 3: Extract aliases and expiry from CMP response\n if (!cardResult?.data?.attributes) {\n console.error(`${logPrefix} VGS createCard returned invalid response:`, stringifyError(cardResult));\n errors.root = \"Card processing returned an invalid response — please try again\";\n return { errors, isSuccess: false };\n }\n const { pan_alias, cvc_alias, exp_month, exp_year } = cardResult.data.attributes;\n const fullYear = exp_year < 100 ? 2000 + exp_year : exp_year;\n const formattedExp = `${String(exp_month).padStart(2, \"0\")}/${fullYear}`;\n\n // Capture CMP card ID for network token tracking\n const cmpCardId = cardResult.data.id;\n\n // Step 4: Send aliases + fraud metadata to our backend.\n // CVC is sent as a VGS alias from createCard. Additionally, the CVC is\n // submitted via the vault inbound proxy (REDACT route) as a fallback for\n // the 303 deduplication path where VGS returns an existing card without\n // a fresh cvc_alias.\n try {\n const updateIntentCall = tunnelX.publicEndpoints.updateCardSetupIntent({\n checkoutToken: secureToken,\n cardSetupIntentId: cardSetupIntentId,\n updateCardSetupIntentReq: {\n cardPan: pan_alias,\n cardExp: formattedExp,\n cardCvc: cvc_alias,\n cmpCardId: cmpCardId,\n fraudMetadata: collectFraudMetadata(),\n },\n });\n\n const proxyCvcCall = new Promise<void>((resolve, reject) => {\n if (!vgsForm.submit) {\n reject(new Error(\"VGS form.submit not available\"));\n return;\n }\n vgsForm.submit(\n `/api/card-setup-intents/${secureToken}/${cardSetupIntentId}`,\n {\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: (fields: Record<string, unknown>) => ({ card_cvc: fields.cvc }),\n },\n (_status: number) => resolve(),\n (err: unknown) => reject(err),\n );\n });\n\n await Promise.all([updateIntentCall, proxyCvcCall]);\n } catch (err) {\n console.error(`${logPrefix} updateCardSetupIntent failed:`, stringifyError(err));\n errors.root = \"Failed to save card details — please try again\";\n return { errors, isSuccess: false };\n }\n\n return { errors: {}, isSuccess: true };\n};\n\nconst submitCardFields = async (states: CardStates) => {\n const errors = {} as PaymentKitErrors;\n const { cardSetupIntentId, cardInputConnections } = states;\n\n const submitPromises = Object.entries(cardInputConnections).map(async ([_type, connection]) => {\n const type = _type as PenpalCardInputType;\n\n const remote = await connection.promise;\n const result = await remote.onSubmit(cardSetupIntentId || \"\");\n\n if (\"error\" in result) {\n errors[type] = result.error;\n }\n });\n\n await Promise.allSettled(submitPromises);\n\n return {\n errors,\n isSuccess: Object.keys(errors).length === 0,\n };\n};\n\nconst validateCardFields = async (states: CardStates) => {\n const errors: PaymentKitErrors = {};\n const { cardInputConnections } = states;\n\n const validatePromises = Object.entries(cardInputConnections).map(async ([_type, connection]) => {\n const type = _type as PenpalCardInputType;\n\n if (!connection) {\n errors[type] = \"penpal_not_connected\";\n return;\n }\n\n const remote = await connection.promise;\n const errorMsg = await remote.onValidate();\n\n if (errorMsg) {\n errors[type] = errorMsg;\n }\n });\n\n await Promise.allSettled(validatePromises);\n\n return {\n errors,\n isSuccess: Object.keys(errors).length === 0,\n };\n};\n\nconst CardPaymentMethod = definePaymentMethod((paymentKitStates) => {\n // Object.create() creates prototype delegation: reads fall through to the shared\n // paymentKitStates (preserving auto-detected VGS config), writes stay local.\n // This prevents card-specific properties (cardInputConnections, vgsForm, etc.)\n // from leaking onto the shared paymentKitStates object.\n const localStates = Object.create(paymentKitStates) as CardStates;\n localStates.cardInputConnections = {};\n\n return {\n name: \"card\",\n externalFuncs: {\n createElement: defCreateElement(localStates),\n },\n internalFuncs: {\n submitPayment: defSubmitPayment(localStates),\n cleanup: () => {\n // Clean up VGS form if present\n if (localStates.vgsForm) {\n localStates.vgsFieldsCleanup?.();\n localStates.vgsFieldsCleanup = undefined;\n localStates.vgsForm.unmount();\n localStates.vgsForm = undefined;\n }\n // Clean up all card input iframe connections\n for (const connection of Object.values(localStates.cardInputConnections)) {\n connection?.destroy();\n }\n localStates.cardInputConnections = {};\n },\n },\n };\n});\n\nexport default CardPaymentMethod;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"card.mjs","names":["taxIds: string[] | undefined","cleanupVgs: (() => void) | undefined","cleanupDirect: (() => void) | undefined","cdnTimeoutId: ReturnType<typeof setTimeout>","params: Record<string, string>","submitPayment: TInternalFuncs[\"submitPayment\"]","VGS_FIELD_MAP: Record<string, keyof PaymentKitErrors>","accessToken: string","cardResult: VGSCreateCardResponse","createCardTimeoutId: ReturnType<typeof setTimeout>","errors: PaymentKitErrors"],"sources":["../../src/payment-methods/card.ts"],"sourcesContent":["import {\n connectToCardIframe,\n type IFrameConnection,\n type CardInputType as PenpalCardInputType,\n type CheckoutResponse as PenpalCheckoutResponse,\n} from \"../penpal/connect-card\";\n\n// Re-export types for public API\nexport type CardInputType = PenpalCardInputType;\nexport type CheckoutResponse = PenpalCheckoutResponse;\n\nimport { AnalyticsService } from \"../analytics\";\nimport { TunnelXManager } from \"../penpal/connect-tunnel-x\";\nimport type { PaymentKitErrors, PaymentKitFields, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport {\n $,\n collectFraudMetadata,\n createCheckoutIFrame,\n definePaymentMethod,\n validateFormFields,\n withRequestId,\n} from \"../utils\";\nimport { handleNextAction } from \"./next-action-handlers\";\nimport { createVgsCardFields, initVgsCollect, loadVgsCollectScript } from \"./vgs-collect-loader\";\n\n/**\n * Splits a full name into first name and last name.\n * First word becomes firstName, rest becomes lastName.\n */\nconst splitName = (fullName: string): { firstName: string; lastName?: string } => {\n const trimmed = fullName.trim();\n const spaceIndex = trimmed.indexOf(\" \");\n if (spaceIndex === -1) {\n return { firstName: trimmed };\n }\n return {\n firstName: trimmed.substring(0, spaceIndex),\n lastName: trimmed.substring(spaceIndex + 1).trim() || undefined,\n };\n};\n\n/**\n * Maps PaymentKitFields to the customerInfo structure expected by the API.\n */\nconst mapFieldsToCustomerInfo = (fields: PaymentKitFields) => {\n const { firstName, lastName } = splitName(fields.customer_name);\n\n const hasBillingAddress =\n fields.customer_country ||\n fields.customer_zip_code ||\n fields.customer_address_line1 ||\n fields.customer_address_line2 ||\n fields.customer_city ||\n fields.customer_state;\n\n const hasShippingAddress =\n fields.shipping_address_line1 ||\n fields.shipping_address_line2 ||\n fields.shipping_city ||\n fields.shipping_state ||\n fields.shipping_zip_code ||\n fields.shipping_country;\n\n let taxIds: string[] | undefined;\n if (fields.customer_tax_ids) {\n try {\n taxIds = JSON.parse(fields.customer_tax_ids);\n } catch {\n taxIds = undefined;\n }\n }\n\n return {\n email: fields.customer_email || undefined,\n firstName,\n lastName,\n businessName: fields.customer_business_name || undefined,\n taxIds: taxIds?.length ? taxIds : undefined,\n billingAddress: hasBillingAddress\n ? {\n country: fields.customer_country || undefined,\n zipCode: fields.customer_zip_code || undefined,\n line1: fields.customer_address_line1 || undefined,\n line2: fields.customer_address_line2 || undefined,\n city: fields.customer_city || undefined,\n state: fields.customer_state || undefined,\n }\n : undefined,\n shippingAddress: hasShippingAddress\n ? {\n line1: fields.shipping_address_line1 || undefined,\n line2: fields.shipping_address_line2 || undefined,\n city: fields.shipping_city || undefined,\n state: fields.shipping_state || undefined,\n zipCode: fields.shipping_zip_code || undefined,\n country: fields.shipping_country || undefined,\n }\n : undefined,\n };\n};\n\ntype CardStates = PaymentKitStates & {\n cardSetupIntentId?: string;\n cardInputConnections: Partial<Record<PenpalCardInputType, IFrameConnection>>;\n vgsForm?: VGSCollectForm;\n vgsFieldsCleanup?: () => void;\n vgsFocusCallbacks?: Partial<Record<PenpalCardInputType, (isFocused: boolean) => void>>;\n vgsMountSelectors?: Partial<Record<PenpalCardInputType, string>>;\n vgsPlaceholders?: Partial<Record<PenpalCardInputType, string>>;\n};\n\ntype CreateElementOptions = Partial<Parameters<typeof connectToCardIframe>[1]> & {\n style?: Record<string, string>;\n placeholder?: string;\n};\n\nconst defCreateElement = (states: CardStates) => {\n const { baseUrl, apiBaseUrl, cardInputConnections, secureToken, timingTracker } = states;\n\n return (type: PenpalCardInputType, options: CreateElementOptions) => {\n const { style, onLoaded, onFocusChange, placeholder } = options;\n\n const mountIFrame = (parentSelector: string) => {\n // Mutable cleanup callbacks — set once mode is determined and mount completes\n let cleanupVgs: (() => void) | undefined;\n let cleanupDirect: (() => void) | undefined;\n // Cancellation flag: prevents deferred doMount from executing after unmount.\n // Needed because React strict mode may call unmount before the deferred\n // _sessionConfigReady promise resolves.\n let cancelled = false;\n\n /**\n * Performs the actual DOM mount after the tokenization mode is known.\n * Runs synchronously when mode is explicitly provided, or after the\n * auto-detect fetch resolves.\n */\n // Store mount selector so VGS init (triggered by card_pan) can read\n // the exp/cvc selectors that were registered by their own createElement calls.\n if (!states.vgsMountSelectors) states.vgsMountSelectors = {};\n states.vgsMountSelectors[type] = parentSelector;\n\n const doMount = () => {\n if (cancelled) return;\n const isVgsMode = states.cardTokenizationMode === \"vgs\";\n console.log(\n `[PaymentKit] card.doMount(${type}) — mode: ${states.cardTokenizationMode}, vgsVaultId: ${states.vgsVaultId ?? \"unset\"}, vgsEnvironment: ${states.vgsEnvironment ?? \"unset\"}`,\n );\n\n // VGS mode: initialize VGS Collect form and mount fields on card_pan\n if (isVgsMode && states.vgsVaultId && states.vgsEnvironment) {\n // Store per-field focus callbacks and placeholders so createVgsCardFields\n // can wire each field to its own callback/placeholder. All three createElement\n // calls complete before the CDN script loads, so all values are available by then.\n if (onFocusChange) {\n if (!states.vgsFocusCallbacks) states.vgsFocusCallbacks = {};\n states.vgsFocusCallbacks[type] = onFocusChange;\n }\n if (placeholder) {\n if (!states.vgsPlaceholders) states.vgsPlaceholders = {};\n states.vgsPlaceholders[type] = placeholder;\n }\n\n if (type === \"card_pan\") {\n const vaultId = states.vgsVaultId;\n const vgsEnv = states.vgsEnvironment;\n\n console.log(`[PaymentKit] VGS mode active — loading VGS Collect CDN for vault ${vaultId} (${vgsEnv})...`);\n const VGS_CDN_TIMEOUT_MS = 15_000;\n let cdnTimeoutId: ReturnType<typeof setTimeout>;\n Promise.race([\n loadVgsCollectScript(),\n new Promise<never>((_, reject) => {\n cdnTimeoutId = setTimeout(() => {\n console.warn(`[PaymentKit] VGS Collect CDN load timed out after ${VGS_CDN_TIMEOUT_MS / 1000}s`);\n reject(new Error(\"VGS Collect CDN load timed out\"));\n }, VGS_CDN_TIMEOUT_MS);\n }),\n ])\n .finally(() => clearTimeout(cdnTimeoutId))\n .then(() => {\n if (cancelled) return;\n console.log(\"[PaymentKit] VGS Collect CDN loaded — initializing form...\");\n const form = initVgsCollect(vaultId, vgsEnv);\n if (cancelled) {\n form.unmount();\n return;\n }\n states.vgsForm = form;\n\n const css = style\n ? Object.fromEntries(\n Object.entries(style).map(([k, v]) => [k.replace(/([A-Z])/g, \"-$1\").toLowerCase(), v]),\n )\n : undefined;\n\n // Read exp/cvc selectors from shared state.\n // Each createElement(\"card_exp/card_cvc\").mount(selector) stores its\n // selector before this async callback runs, so they're available here.\n const expSelector = states.vgsMountSelectors?.card_exp;\n const cvcSelector = states.vgsMountSelectors?.card_cvc;\n if (!expSelector || !cvcSelector) {\n const msg =\n `[PaymentKit] VGS mode requires all three card fields to be mounted. ` +\n `Missing: ${!expSelector ? \"card_exp\" : \"\"}${!expSelector && !cvcSelector ? \", \" : \"\"}${!cvcSelector ? \"card_cvc\" : \"\"}`;\n console.error(msg);\n onLoaded?.();\n return;\n }\n console.log(\n `[PaymentKit] Creating VGS card fields — pan: ${parentSelector}, exp: ${expSelector}, cvc: ${cvcSelector}`,\n );\n states.vgsFieldsCleanup = createVgsCardFields(\n form,\n {\n pan: parentSelector,\n exp: expSelector,\n cvc: cvcSelector,\n },\n css,\n states.vgsFocusCallbacks,\n states.vgsPlaceholders,\n );\n\n console.log(\"[PaymentKit] VGS card fields created successfully\");\n timingTracker.trackInputReady();\n onLoaded?.();\n })\n .catch((err) => {\n console.error(\"[PaymentKit] Failed to load VGS Collect script. Card input will not be available:\", err);\n // Signal loaded so the form exits loading state rather than hanging forever.\n // Card fields won't render, but submit will fail with a clear error.\n onLoaded?.();\n });\n }\n\n // For non-pan fields in VGS mode, signal loaded immediately since\n // VGS handles all three fields from the card_pan mount.\n if (type !== \"card_pan\") {\n onLoaded?.();\n }\n\n cleanupVgs = () => {\n if (type === \"card_pan\" && states.vgsForm) {\n try {\n states.vgsFieldsCleanup?.();\n } catch {\n // VGS may try to remove iframes from containers already removed by React\n }\n states.vgsFieldsCleanup = undefined;\n try {\n states.vgsForm.unmount();\n } catch {\n // VGS unmount may fail if DOM nodes are already detached\n }\n states.vgsForm = undefined;\n }\n };\n return;\n }\n\n // If we got here and mode was \"vgs\", it means VGS config was incomplete\n if (isVgsMode) {\n console.warn(\n `[PaymentKit] VGS mode requested but config incomplete (vgsVaultId: ${states.vgsVaultId ?? \"unset\"}, vgsEnvironment: ${states.vgsEnvironment ?? \"unset\"}) — using direct mode`,\n );\n }\n\n // Direct mode: existing penpal iframe logic\n const parent = $(parentSelector) as HTMLElement;\n\n // Read container padding so the embed input matches the merchant's\n // visual intent. The iframe uses absolute positioning to fill the\n // full container, so the input needs its own padding for alignment.\n const computed = getComputedStyle(parent);\n const containerPadding = computed.padding !== \"0px\" ? computed.padding : undefined;\n const enhancedStyle = {\n ...(style ?? {}),\n height: \"100%\",\n boxSizing: \"border-box\",\n ...(containerPadding ? { padding: containerPadding } : {}),\n };\n\n const params: Record<string, string> = {\n checkout_token: secureToken,\n api_base_url: apiBaseUrl,\n style: JSON.stringify(enhancedStyle),\n };\n\n const iframe = createCheckoutIFrame(type.replace(\"_\", \"-\"), baseUrl, params);\n\n // Use absolute positioning so the iframe covers the full container\n // including any padding the merchant's CSS applies.\n if (computed.position === \"static\") {\n parent.style.position = \"relative\";\n }\n iframe.style.position = \"absolute\";\n iframe.style.inset = \"0\";\n\n // Set cleanup before DOM mutation to avoid leaking the iframe if\n // unmount() is called between appendChild and onload.\n cleanupDirect = () => {\n const connection = cardInputConnections[type];\n connection?.destroy();\n try {\n parent.removeChild(iframe);\n } catch {\n // Parent may already be detached from DOM by React\n }\n states.cardInputConnections[type] = undefined;\n };\n\n parent.appendChild(iframe);\n\n iframe.onload = () => {\n if (type === \"card_pan\") {\n timingTracker.trackInputReady();\n }\n\n const connection = connectToCardIframe(iframe, {\n onLoaded: onLoaded || (() => {}),\n onFocusChange: onFocusChange || (() => {}),\n });\n\n states.cardInputConnections[type] = connection;\n };\n };\n\n // If session config needs auto-detection, wait for it; otherwise mount synchronously\n if (states._sessionConfigReady) {\n states._sessionConfigReady.then(doMount);\n } else {\n doMount();\n }\n\n return {\n unmount: () => {\n cancelled = true;\n cleanupVgs?.();\n cleanupDirect?.();\n },\n };\n };\n\n return { mount: mountIFrame };\n };\n};\n\nconst defSubmitPayment = (states: CardStates) => {\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (fields, options) => {\n // Ensure session config is loaded (no-op if explicitly provided)\n if (states._sessionConfigReady) await states._sessionConfigReady;\n const isVgsMode = states.cardTokenizationMode === \"vgs\";\n\n const { timingTracker, checkoutRequestId } = states;\n\n // Track submit event\n timingTracker.trackSubmit();\n\n // Use the checkout request ID from states (generated on page load)\n const requestOptions = withRequestId(checkoutRequestId);\n\n const tunnelX = await TunnelXManager.createFromPenpalConnection(states.tunnelXConnection);\n\n // Step 1. Validate form values.\n // Form field validation is shared across both modes.\n // In VGS mode, card field validation is handled by VGS Collect (built-in validators).\n // In direct mode, card field validation is handled by penpal iframes.\n const skipCustomerValidation = options?.skipCustomerValidation === true;\n const validateFormResult = skipCustomerValidation ? { isSuccess: true as const } : await validateFormFields(fields);\n if (!isVgsMode) {\n const validateCardResult = await validateCardFields(states);\n if (!(validateCardResult.isSuccess && validateFormResult.isSuccess)) {\n timingTracker.trackFail(null, \"validation_error\", \"Form validation failed\");\n return { errors: { ...validateCardResult.errors, ...validateFormResult.errors } };\n }\n } else if (!validateFormResult.isSuccess) {\n timingTracker.trackFail(null, \"validation_error\", \"Form validation failed\");\n return { errors: validateFormResult.errors };\n }\n\n // Step 2. Create card setup intent if not present\n if (!states.cardSetupIntentId) {\n const res = await tunnelX.publicEndpoints.createCardSetupIntent({\n checkoutToken: states.secureToken,\n });\n states.cardSetupIntentId = res.cardSetupIntentId;\n }\n\n // Step 3. Submit card values.\n if (isVgsMode) {\n // VGS mode: create card via CMP, then send aliases to backend\n console.log(\"[PaymentKit] Submitting card via VGS CMP...\");\n const vgsSubmitResult = await submitVgsCardFields(states, tunnelX);\n if (!vgsSubmitResult.isSuccess) {\n // Include field-level error details for PostHog visibility\n const errorDetail = Object.entries(vgsSubmitResult.errors)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n timingTracker.trackFail(null, \"card_submit_error\", errorDetail || \"VGS card submission failed\");\n return { errors: vgsSubmitResult.errors };\n }\n } else {\n // Direct mode: submit via penpal iframes\n const submitCardResult = await submitCardFields(states);\n if (!submitCardResult.isSuccess) {\n timingTracker.trackFail(null, \"card_submit_error\", \"Card submission failed\");\n return { errors: submitCardResult.errors };\n }\n }\n\n // Step 4. Get card setup intent.\n const cardSetupIntent = await tunnelX.publicEndpoints.getCardSetupIntent({\n cardSetupIntentId: states.cardSetupIntentId,\n checkoutToken: states.secureToken,\n });\n if (!cardSetupIntent.isCardAllSet) {\n const errors = {} as PaymentKitErrors;\n if (!cardSetupIntent.isCardPanSet) errors.card_pan = \"required\";\n if (!cardSetupIntent.isCardExpSet) errors.card_exp = \"required\";\n if (!cardSetupIntent.isCardCvcSet) errors.card_cvc = \"required\";\n timingTracker.trackFail(null, \"card_setup_incomplete\", \"Card details incomplete\");\n return { errors };\n }\n\n console.log(\"Card setup intent is set ✅\", cardSetupIntent);\n console.log(\"Fields\", fields);\n\n // Step 5. Submit card checkout with customer info and fraud metadata\n let currentResult = await tunnelX.publicEndpoints.cardCheckout(\n {\n checkoutToken: states.secureToken,\n publicCardCheckoutRequest: {\n cardSetupIntentId: states.cardSetupIntentId,\n customerInfo: mapFieldsToCustomerInfo(fields),\n fraudMetadata: collectFraudMetadata(),\n },\n },\n requestOptions,\n );\n\n console.log(\"Card checkout result:\", currentResult);\n\n // Step 6. Handle next actions in a loop (supports multiple 3DS challenges)\n // This loop handles the case where one processor fails and we try another\n // that also requires 3DS authentication.\n const MAX_USER_ACTIONS = 5; // Safety limit to prevent infinite loops\n let userActionCount = 0;\n\n while (currentResult.nextAction && userActionCount < MAX_USER_ACTIONS) {\n userActionCount++;\n console.log(`Handling user action ${userActionCount}/${MAX_USER_ACTIONS}...`);\n\n const actionResult = await handleNextAction(currentResult.nextAction);\n\n // Always call verify endpoint so backend can properly conclude the checkout.\n // This is needed even on 3DS failure so the backend can transition from\n // user_actions_requested to card_payment_concluded with proper failure state.\n console.log(\"User action completed, verifying checkout...\");\n const verifyResult = await tunnelX.publicEndpoints.cardCheckoutVerify(\n {\n checkoutToken: states.secureToken,\n },\n requestOptions,\n );\n\n // Check if another action is required (e.g., cascade to next processor with 3DS)\n // This must be checked BEFORE returning error, as cascade may offer a new 3DS challenge\n if (verifyResult.nextAction) {\n if (!actionResult.success) {\n console.log(\"3DS failed but cascade triggered new action, continuing loop...\");\n } else {\n console.log(\"Another user action required, continuing loop...\");\n }\n currentResult = verifyResult;\n continue;\n }\n\n if (!actionResult.success) {\n // 3DS failed and no cascade/retry available - return error\n // Include verifyResult as checkout_response so error_code is available to frontend\n console.log(\"3DS authentication failed, checkout concluded:\", verifyResult);\n timingTracker.trackFail(\n verifyResult.checkoutAttemptId || null,\n verifyResult.errorCode || \"3ds_failed\",\n verifyResult.errorMessageForCustomer || actionResult.error,\n );\n return {\n errors: {\n root: verifyResult.errorMessageForCustomer || actionResult.error,\n checkout_response: verifyResult,\n },\n };\n }\n\n console.log(\"Card checkout verified ✅\", verifyResult);\n\n // No more actions needed, return the result\n timingTracker.trackSuccess(verifyResult.checkoutAttemptId || \"unknown\");\n return { data: verifyResult as { [key: string]: unknown } };\n }\n\n if (userActionCount >= MAX_USER_ACTIONS) {\n console.error(\"Max user actions exceeded\");\n timingTracker.trackFail(null, \"max_actions_exceeded\", \"Too many authentication attempts\");\n return { errors: { root: \"Too many authentication attempts. Please try again.\" } };\n }\n\n // Check if checkout succeeded or failed\n // States: checkout_succeeded (success), payment_failed (failure)\n if (currentResult.state === \"payment_failed\" || currentResult.state === \"checkout_failed\") {\n console.log(\"Card checkout failed:\", currentResult);\n timingTracker.trackFail(\n currentResult.checkoutAttemptId || null,\n currentResult.errorCode || \"payment_failed\",\n currentResult.errorMessageForCustomer || \"Payment failed\",\n );\n // Return the full response as errors so frontend can display error details\n // including error_code, error_message_for_customer, error_message_for_debug\n return {\n errors: {\n root: currentResult.errorMessageForCustomer || \"Payment failed\",\n checkout_response: currentResult,\n },\n };\n }\n\n console.log(\"Card checkout completed ✅\", currentResult);\n timingTracker.trackSuccess(currentResult.checkoutAttemptId || \"unknown\");\n return { data: currentResult as { [key: string]: unknown } };\n };\n return submitPayment;\n};\n\n/**\n * Fetches a VGS CMP access token from the backend.\n * Uses AbortController with 10s timeout to prevent indefinite hangs on slow networks.\n */\nconst FETCH_COLLECT_TOKEN_TIMEOUT_MS = 10_000;\n\nconst fetchCollectToken = async (apiBaseUrl: string, secureToken: string): Promise<string> => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), FETCH_COLLECT_TOKEN_TIMEOUT_MS);\n\n try {\n const resp = await fetch(`${apiBaseUrl}/api/card-setup-intents/${secureToken}/collect-token`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n signal: controller.signal,\n });\n if (!resp.ok) {\n throw new Error(`Failed to get collect token: ${resp.status}`);\n }\n const data = await resp.json();\n return data.access_token;\n } finally {\n clearTimeout(timeoutId);\n }\n};\n\n/**\n * Creates a card via VGS CMP and sends aliases to our backend.\n *\n * Flow:\n * 1. Fetch CMP access token from our backend\n * 2. Call form.createCard() → VGS creates card, returns aliases\n * 3. Send aliases + fraud metadata to our backend via updateCardSetupIntent\n */\n/**\n * Map VGS field-level error keys to PaymentKitErrors field keys.\n *\n * VGS CMP errorCallback uses short field names (\"pan\", \"cvc\", \"exp-date\")\n * matching the CMP field type, NOT the longer CSS-style names. Both forms\n * are mapped here for robustness.\n */\nconst VGS_FIELD_MAP: Record<string, keyof PaymentKitErrors> = {\n // Actual VGS CMP error keys (verified empirically)\n pan: \"card_pan\",\n cvc: \"card_cvc\",\n \"exp-date\": \"card_exp\",\n // Alternative key formats (VGS documentation references)\n \"card-number\": \"card_pan\",\n \"card-security-code\": \"card_cvc\",\n \"card-expiration-date\": \"card_exp\",\n};\n\n/**\n * Safely stringify an error for console logging.\n * VGS errors are plain objects that print as [object Object] without this.\n */\nconst stringifyError = (err: unknown): string => {\n if (err instanceof Error) return err.message;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n};\n\nconst submitVgsCardFields = async (\n states: CardStates,\n tunnelX: Awaited<ReturnType<typeof TunnelXManager.createFromPenpalConnection>>,\n): Promise<{ errors: PaymentKitErrors; isSuccess: boolean }> => {\n const { vgsForm, cardSetupIntentId, secureToken, apiBaseUrl, checkoutRequestId } = states;\n const logPrefix = `[PaymentKit] [${checkoutRequestId}]`;\n const errors = {} as PaymentKitErrors;\n\n if (!vgsForm) {\n errors.card_pan = \"required\";\n return { errors, isSuccess: false };\n }\n\n if (!cardSetupIntentId) {\n errors.root = \"Card setup intent not created\";\n return { errors, isSuccess: false };\n }\n\n // Step 1: Get CMP access token from our backend\n let accessToken: string;\n const collectTokenStart = performance.now();\n try {\n accessToken = await fetchCollectToken(apiBaseUrl, secureToken);\n const collectTokenDuration = Math.round(performance.now() - collectTokenStart);\n AnalyticsService.capture(\"vgs_collect_token_timing\", {\n checkout_session_id: secureToken,\n request_id: checkoutRequestId,\n duration_ms: collectTokenDuration,\n success: true,\n });\n } catch (err) {\n const collectTokenDuration = Math.round(performance.now() - collectTokenStart);\n const isAbortError = err instanceof DOMException && err.name === \"AbortError\";\n AnalyticsService.capture(\"vgs_collect_token_timing\", {\n checkout_session_id: secureToken,\n request_id: checkoutRequestId,\n duration_ms: collectTokenDuration,\n success: false,\n error_type: isAbortError ? \"FETCH_TIMEOUT\" : \"FETCH_ERROR\",\n });\n console.error(`${logPrefix} VGS auth token fetch failed:`, stringifyError(err));\n errors.root = isAbortError\n ? \"Card authentication timed out — please try again\"\n : \"Card authentication failed — please try again\";\n return { errors, isSuccess: false };\n }\n\n // Step 2: Create card via VGS CMP — returns aliases for PAN/CVC, plain text expiry\n let cardResult: VGSCreateCardResponse;\n const VGS_CREATE_CARD_TIMEOUT_MS = 120_000;\n const createCardStart = performance.now();\n try {\n let createCardTimeoutId: ReturnType<typeof setTimeout>;\n cardResult = await Promise.race([\n new Promise<VGSCreateCardResponse>((resolve, reject) => {\n vgsForm.createCard(\n {\n auth: accessToken,\n data: { cardholder: {} },\n },\n (_status, cardObject) => resolve(cardObject),\n (error) => reject(error),\n );\n }),\n new Promise<never>((_, reject) => {\n createCardTimeoutId = setTimeout(() => reject(new Error(\"VGS_TIMEOUT\")), VGS_CREATE_CARD_TIMEOUT_MS);\n }),\n ]).finally(() => clearTimeout(createCardTimeoutId));\n\n // Emit timing event on success\n const createCardDuration = Math.round(performance.now() - createCardStart);\n AnalyticsService.capture(\"vgs_create_card_timing\", {\n checkout_session_id: secureToken,\n request_id: checkoutRequestId,\n duration_ms: createCardDuration,\n success: true,\n });\n } catch (err) {\n const createCardDuration = Math.round(performance.now() - createCardStart);\n const errStr = stringifyError(err);\n console.error(`${logPrefix} VGS createCard failed:`, errStr);\n\n // Distinguish timeout from VGS field validation errors\n if (err instanceof Error && err.message === \"VGS_TIMEOUT\") {\n AnalyticsService.capture(\"vgs_create_card_timing\", {\n checkout_session_id: secureToken,\n request_id: checkoutRequestId,\n duration_ms: createCardDuration,\n success: false,\n error_type: \"VGS_TIMEOUT\",\n });\n errors.root = \"Card processing timed out — please try again\";\n return { errors, isSuccess: false };\n }\n\n // VGS errorCallback returns field-level errors as a plain object,\n // e.g. { \"card-number\": { errorMessages: [\"Card number is not valid\"] } }\n // Map them to per-field errors so inline validation shows on the right field.\n if (err && typeof err === \"object\" && !(err instanceof Error)) {\n const vgsErrors = err as Record<string, unknown>;\n for (const [vgsKey, fieldKey] of Object.entries(VGS_FIELD_MAP)) {\n if (vgsKey in vgsErrors) {\n const fieldErr = vgsErrors[vgsKey] as Record<string, unknown> | undefined;\n const messages = fieldErr?.errorMessages;\n errors[fieldKey] = Array.isArray(messages) ? messages[0] : \"invalid\";\n }\n }\n if (Object.keys(errors).length > 0) {\n AnalyticsService.capture(\"vgs_create_card_timing\", {\n checkout_session_id: secureToken,\n request_id: checkoutRequestId,\n duration_ms: createCardDuration,\n success: false,\n error_type: \"VGS_VALIDATION_ERROR\",\n });\n return { errors, isSuccess: false };\n }\n }\n\n // Generic VGS error\n AnalyticsService.capture(\"vgs_create_card_timing\", {\n checkout_session_id: secureToken,\n request_id: checkoutRequestId,\n duration_ms: createCardDuration,\n success: false,\n error_type: \"VGS_ERROR\",\n });\n errors.root = \"Card validation failed — please check your card details and try again\";\n return { errors, isSuccess: false };\n }\n\n // Step 3: Extract aliases and expiry from CMP response\n if (!cardResult?.data?.attributes) {\n console.error(`${logPrefix} VGS createCard returned invalid response:`, stringifyError(cardResult));\n errors.root = \"Card processing returned an invalid response — please try again\";\n return { errors, isSuccess: false };\n }\n const { pan_alias, cvc_alias, exp_month, exp_year } = cardResult.data.attributes;\n const fullYear = exp_year < 100 ? 2000 + exp_year : exp_year;\n const formattedExp = `${String(exp_month).padStart(2, \"0\")}/${fullYear}`;\n\n // Capture CMP card ID for network token tracking\n const cmpCardId = cardResult.data.id;\n\n // Step 4: Send aliases + fraud metadata to our backend.\n // CVC is sent as a VGS alias from createCard. Additionally, the CVC is\n // submitted via the vault inbound proxy (REDACT route) as a fallback for\n // the 303 deduplication path where VGS returns an existing card without\n // a fresh cvc_alias.\n try {\n const updateIntentCall = tunnelX.publicEndpoints.updateCardSetupIntent({\n checkoutToken: secureToken,\n cardSetupIntentId: cardSetupIntentId,\n updateCardSetupIntentReq: {\n cardPan: pan_alias,\n cardExp: formattedExp,\n cardCvc: cvc_alias,\n cmpCardId: cmpCardId,\n fraudMetadata: collectFraudMetadata(),\n },\n });\n\n const proxyCvcCall = new Promise<void>((resolve, reject) => {\n if (!vgsForm.submit) {\n reject(new Error(\"VGS form.submit not available\"));\n return;\n }\n vgsForm.submit(\n `/api/card-setup-intents/${secureToken}/${cardSetupIntentId}`,\n {\n method: \"post\",\n headers: { \"Content-Type\": \"application/json\" },\n data: (fields: Record<string, unknown>) => ({ card_cvc: fields.cvc }),\n },\n (_status: number) => resolve(),\n (err: unknown) => reject(err),\n );\n });\n\n await Promise.all([updateIntentCall, proxyCvcCall]);\n } catch (err) {\n console.error(`${logPrefix} updateCardSetupIntent failed:`, stringifyError(err));\n errors.root = \"Failed to save card details — please try again\";\n return { errors, isSuccess: false };\n }\n\n return { errors: {}, isSuccess: true };\n};\n\nconst submitCardFields = async (states: CardStates) => {\n const errors = {} as PaymentKitErrors;\n const { cardSetupIntentId, cardInputConnections } = states;\n\n const submitPromises = Object.entries(cardInputConnections).map(async ([_type, connection]) => {\n const type = _type as PenpalCardInputType;\n\n const remote = await connection.promise;\n const result = await remote.onSubmit(cardSetupIntentId || \"\");\n\n if (\"error\" in result) {\n errors[type] = result.error;\n }\n });\n\n await Promise.allSettled(submitPromises);\n\n return {\n errors,\n isSuccess: Object.keys(errors).length === 0,\n };\n};\n\nconst validateCardFields = async (states: CardStates) => {\n const errors: PaymentKitErrors = {};\n const { cardInputConnections } = states;\n\n const validatePromises = Object.entries(cardInputConnections).map(async ([_type, connection]) => {\n const type = _type as PenpalCardInputType;\n\n if (!connection) {\n errors[type] = \"penpal_not_connected\";\n return;\n }\n\n const remote = await connection.promise;\n const errorMsg = await remote.onValidate();\n\n if (errorMsg) {\n errors[type] = errorMsg;\n }\n });\n\n await Promise.allSettled(validatePromises);\n\n return {\n errors,\n isSuccess: Object.keys(errors).length === 0,\n };\n};\n\nconst CardPaymentMethod = definePaymentMethod((paymentKitStates) => {\n // Object.create() creates prototype delegation: reads fall through to the shared\n // paymentKitStates (preserving auto-detected VGS config), writes stay local.\n // This prevents card-specific properties (cardInputConnections, vgsForm, etc.)\n // from leaking onto the shared paymentKitStates object.\n const localStates = Object.create(paymentKitStates) as CardStates;\n localStates.cardInputConnections = {};\n\n return {\n name: \"card\",\n externalFuncs: {\n createElement: defCreateElement(localStates),\n },\n internalFuncs: {\n submitPayment: defSubmitPayment(localStates),\n cleanup: () => {\n // Clean up VGS form if present\n if (localStates.vgsForm) {\n localStates.vgsFieldsCleanup?.();\n localStates.vgsFieldsCleanup = undefined;\n localStates.vgsForm.unmount();\n localStates.vgsForm = undefined;\n }\n // Clean up all card input iframe connections\n for (const connection of Object.values(localStates.cardInputConnections)) {\n connection?.destroy();\n }\n localStates.cardInputConnections = {};\n },\n },\n };\n});\n\nexport default CardPaymentMethod;\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { r as PaymentMethod } from "../types-
|
|
2
|
-
import "../connect-card-
|
|
3
|
-
import "../connect-tunnel-x-
|
|
4
|
-
import { a as GooglePayEncryptedToken } from "../airwallex-google-pay-adapter-
|
|
5
|
-
import { n as GooglePayMockScenario } from "../stripe-google-pay-adapter-
|
|
1
|
+
import { r as PaymentMethod } from "../types-B3mjYfOm.mjs";
|
|
2
|
+
import "../connect-card-CZhzK_Tp.mjs";
|
|
3
|
+
import "../connect-tunnel-x-BKtMfoGh.mjs";
|
|
4
|
+
import { a as GooglePayEncryptedToken } from "../airwallex-google-pay-adapter-D-AxVLLq.mjs";
|
|
5
|
+
import { n as GooglePayMockScenario } from "../stripe-google-pay-adapter-B330fRiH.mjs";
|
|
6
6
|
|
|
7
7
|
//#region src/payment-methods/google-pay.d.ts
|
|
8
8
|
type GooglePayCustomerInfo = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-
|
|
2
|
-
import { n as AirwallexGooglePayMockScenario, t as AirwallexGooglePayAdapter } from "../airwallex-google-pay-adapter-
|
|
3
|
-
import { t as handleNextAction } from "../next-action-handlers-
|
|
4
|
-
import { n as StripeGooglePayAdapter, t as GooglePayMockScenario } from "../stripe-google-pay-adapter-
|
|
1
|
+
import { i as definePaymentMethod, n as collectFraudMetadata, o as getOrCreateCheckoutRequestId } from "../utils-Dc6zwOe1.mjs";
|
|
2
|
+
import { n as AirwallexGooglePayMockScenario, t as AirwallexGooglePayAdapter } from "../airwallex-google-pay-adapter-BvlROwj_.mjs";
|
|
3
|
+
import { t as handleNextAction } from "../next-action-handlers-CLOt1wzO.mjs";
|
|
4
|
+
import { n as StripeGooglePayAdapter, t as GooglePayMockScenario } from "../stripe-google-pay-adapter-B346KXt4.mjs";
|
|
5
5
|
|
|
6
6
|
//#region src/payment-methods/google-pay.ts
|
|
7
7
|
async function apiCall(url, options, checkoutRequestId) {
|