@payment-kit-js/vanilla 0.5.8 → 0.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{airwallex-apple-pay-adapter-I_pnNYdy.d.mts → airwallex-apple-pay-adapter-BCYt7Jzc.d.mts} +2 -1
  2. package/dist/airwallex-apple-pay-adapter-BCYt7Jzc.d.mts.map +1 -0
  3. package/dist/{airwallex-apple-pay-adapter-BE15xREr.mjs → airwallex-apple-pay-adapter-BFsoDoSf.mjs} +6 -2
  4. package/dist/airwallex-apple-pay-adapter-BFsoDoSf.mjs.map +1 -0
  5. package/dist/cdn/paymentkit.js +1250 -129
  6. package/dist/cdn/paymentkit.js.map +4 -4
  7. package/dist/cdn/paymentkit.min.js +10 -10
  8. package/dist/cdn/paymentkit.min.js.map +4 -4
  9. package/dist/index.d.mts.map +1 -1
  10. package/dist/index.mjs +7 -1
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/payment-methods/airwallex-apple-pay-adapter.d.mts +1 -1
  13. package/dist/payment-methods/airwallex-apple-pay-adapter.mjs +1 -1
  14. package/dist/payment-methods/apple-pay.d.mts +15 -1
  15. package/dist/payment-methods/apple-pay.d.mts.map +1 -1
  16. package/dist/payment-methods/apple-pay.mjs +45 -13
  17. package/dist/payment-methods/apple-pay.mjs.map +1 -1
  18. package/dist/payment-methods/card.d.mts.map +1 -1
  19. package/dist/payment-methods/card.mjs +120 -21
  20. package/dist/payment-methods/card.mjs.map +1 -1
  21. package/dist/payment-methods/google-pay.d.mts +18 -1
  22. package/dist/payment-methods/google-pay.d.mts.map +1 -1
  23. package/dist/payment-methods/google-pay.mjs +28 -9
  24. package/dist/payment-methods/google-pay.mjs.map +1 -1
  25. package/dist/payment-methods/stripe-google-pay-adapter.d.mts +1 -1
  26. package/dist/payment-methods/stripe-google-pay-adapter.mjs +1 -1
  27. package/dist/payment-methods/vgs-collect-loader.d.mts +1 -1
  28. package/dist/payment-methods/vgs-collect-loader.mjs +1 -1
  29. package/dist/{stripe-google-pay-adapter-CqcUEoM3.mjs → stripe-google-pay-adapter-3cx0KNjK.mjs} +7 -2
  30. package/dist/stripe-google-pay-adapter-3cx0KNjK.mjs.map +1 -0
  31. package/dist/{stripe-google-pay-adapter-C3NCBSO3.d.mts → stripe-google-pay-adapter-Bdox4xBq.d.mts} +2 -1
  32. package/dist/stripe-google-pay-adapter-Bdox4xBq.d.mts.map +1 -0
  33. package/dist/{vgs-collect-loader-3Z4IWCA6.mjs → vgs-collect-loader-BZj36d8r.mjs} +28 -9
  34. package/dist/vgs-collect-loader-BZj36d8r.mjs.map +1 -0
  35. package/package.json +2 -2
  36. package/dist/airwallex-apple-pay-adapter-BE15xREr.mjs.map +0 -1
  37. package/dist/airwallex-apple-pay-adapter-I_pnNYdy.d.mts.map +0 -1
  38. package/dist/stripe-google-pay-adapter-C3NCBSO3.d.mts.map +0 -1
  39. package/dist/stripe-google-pay-adapter-CqcUEoM3.mjs.map +0 -1
  40. package/dist/vgs-collect-loader-3Z4IWCA6.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"google-pay.mjs","names":["airwallexMockScenario: AirwallexGooglePayMockScenario","config: AirwallexGooglePayConfig","requestBody: GooglePayConfirmRequest","submitPayment: TInternalFuncs[\"submitPayment\"]"],"sources":["../../src/payment-methods/google-pay.ts"],"sourcesContent":["import type { PaymentKitErrors, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport { collectFraudMetadata, definePaymentMethod, getOrCreateCheckoutRequestId } from \"../utils\";\nimport {\n AirwallexGooglePayAdapter,\n type AirwallexGooglePayConfig,\n AirwallexGooglePayMockScenario,\n type GooglePayEncryptedToken,\n} from \"./airwallex-google-pay-adapter\";\nimport { handleNextAction } from \"./next-action-handlers\";\nimport { GooglePayMockScenario, StripeGooglePayAdapter } from \"./stripe-google-pay-adapter\";\n\n// Google Pay-specific types\nexport type GooglePayCustomerInfo = {\n first_name: string;\n last_name: string;\n};\n\nexport type GooglePayStartRequest = {\n processor_id: string;\n customer_info: GooglePayCustomerInfo;\n fraud_metadata: {\n ipAddress?: string;\n browserInfo?: { [key: string]: unknown };\n processorFraudInfo?: { [key: string]: unknown };\n };\n mock_scenario?: string;\n};\n\nexport type GooglePayStartResponse = {\n checkout_attempt_id: string;\n amount: number;\n amount_display: string; // Formatted for Google Pay (e.g., \"100.00\" for USD, \"1000\" for JPY)\n currency: string;\n country: string;\n\n // Processor discriminator\n processor: \"stripe\" | \"airwallex\";\n\n // Environment flag\n is_sandbox?: boolean;\n\n // Stripe-specific fields (when processor=\"stripe\")\n client_secret?: string;\n stripe_pk?: string;\n\n // Airwallex-specific fields (when processor=\"airwallex\")\n merchant_name?: string;\n airwallex_account_id?: string;\n google_merchant_id?: string; // Google-assigned merchant ID for production (BCR2DN...)\n};\n\nexport type GooglePayConfirmRequest = {\n google_pay_token?: GooglePayEncryptedToken; // Required for Airwallex\n mock_scenario?: string;\n};\n\n// Airwallex 3DS next action type (matches backend snake_case response)\nexport type Airwallex3dsNextAction = {\n type: \"airwallex_3ds\";\n url: string;\n method: string;\n payment_intent_id: string;\n};\n\nexport type GooglePayConfirmResponse = {\n charge_status: \"success\" | \"fail\" | \"pending\";\n transaction_id?: string;\n error_message?: string;\n checkout_attempt_id: string;\n next_action?: Airwallex3dsNextAction; // Present when charge_status=\"pending\" for 3DS\n};\n\nexport type GooglePaySubmitOptions = {\n processorId: string;\n customerInfo: GooglePayCustomerInfo;\n mockScenario?: GooglePayMockScenario;\n};\n\ntype GooglePayResult =\n | { data: { [key: string]: unknown }; errors?: never }\n | { data?: never; errors: PaymentKitErrors };\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\nasync function apiCall<T>(\n url: string,\n options: RequestInit,\n checkoutRequestId?: string,\n): Promise<{ data?: T; error?: string }> {\n // Add x-request-id header if provided\n const headers = new Headers(options.headers);\n if (checkoutRequestId) {\n headers.set(\"x-request-id\", checkoutRequestId);\n }\n\n const response = await fetch(url, { ...options, headers });\n if (!response.ok) {\n let errorMessage = `Request failed (${response.status})`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.detail || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n return { error: errorMessage };\n }\n return { data: await response.json() };\n}\n\nfunction validateOptions(options: GooglePaySubmitOptions): PaymentKitErrors | null {\n if (!options?.processorId) {\n return { processor_id: \"Processor ID is required\" };\n }\n // Customer name is optional — Google Pay collects it from the payment sheet\n return null;\n}\n\nfunction getMockScenarioStr(mockScenario?: GooglePayMockScenario): string | undefined {\n return mockScenario && mockScenario !== GooglePayMockScenario.None ? mockScenario : undefined;\n}\n\nasync function callStartEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n options: GooglePaySubmitOptions,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<{ data?: GooglePayStartResponse; error?: string }> {\n return apiCall<GooglePayStartResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/google-pay/start`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n processor_id: options.processorId,\n customer_info: options.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n mock_scenario: mockScenarioStr,\n } as GooglePayStartRequest),\n },\n checkoutRequestId,\n );\n}\n\n// =============================================================================\n// Stripe Flow\n// =============================================================================\n\nfunction initializeStripeAdapter(\n stripePk: string,\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): { adapter?: StripeGooglePayAdapter; error?: string } {\n const adapter = new StripeGooglePayAdapter(mockScenario);\n\n if (!adapter.initialize(stripePk)) {\n return { error: 'Stripe.js not loaded. Add <script src=\"https://js.stripe.com/v3/\"></script> to your page.' };\n }\n\n const prConfig = {\n country: startData.country,\n currency: startData.currency.toLowerCase(),\n total: { label: \"Total\", amount: startData.amount },\n requestPayerName: true,\n requestPayerEmail: true,\n };\n adapter.createPaymentRequest(prConfig);\n return { adapter };\n}\n\nasync function runStripeFlow(\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): Promise<{ success: boolean; error?: string }> {\n if (!startData.stripe_pk || !startData.client_secret) {\n return { success: false, error: \"Stripe credentials not provided\" };\n }\n\n // Initialize Stripe adapter\n const { adapter, error: adapterError } = initializeStripeAdapter(startData.stripe_pk, startData, mockScenario);\n if (!adapter) {\n return { success: false, error: adapterError };\n }\n\n // Check availability\n const isAvailable = await adapter.canMakePayment();\n\n if (!isAvailable) {\n return { success: false, error: \"Google Pay not available on this device\" };\n }\n\n // Show payment sheet\n const paymentResult = await adapter.showPaymentSheet();\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { success: false, error: \"Google Pay cancelled by user\" };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { success: false, error: errorMessage };\n }\n\n // Confirm with Stripe SDK\n const confirmResult = await adapter.confirmCardSetup(startData.client_secret, paymentResult.paymentMethodId);\n\n if (!confirmResult.success) {\n paymentResult.complete(\"fail\");\n return { success: false, error: \"error\" in confirmResult ? confirmResult.error : \"Card setup failed\" };\n }\n\n paymentResult.complete(\"success\");\n return { success: true };\n}\n\n// =============================================================================\n// Airwallex Flow\n// =============================================================================\n\nfunction initializeAirwallexAdapter(\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): {\n adapter?: AirwallexGooglePayAdapter;\n error?: string;\n} {\n if (!startData.merchant_name || !startData.airwallex_account_id) {\n return { error: \"Airwallex Google Pay credentials not provided\" };\n }\n\n // Convert GooglePayMockScenario to AirwallexGooglePayMockScenario\n let airwallexMockScenario: AirwallexGooglePayMockScenario = AirwallexGooglePayMockScenario.None;\n if (mockScenario === GooglePayMockScenario.Success) {\n airwallexMockScenario = AirwallexGooglePayMockScenario.Success;\n } else if (mockScenario === GooglePayMockScenario.Cancelled) {\n airwallexMockScenario = AirwallexGooglePayMockScenario.Cancelled;\n }\n\n const adapter = new AirwallexGooglePayAdapter(airwallexMockScenario);\n\n const config: AirwallexGooglePayConfig = {\n merchantId: startData.merchant_name,\n gatewayMerchantId: startData.airwallex_account_id,\n amountDisplay: startData.amount_display,\n currency: startData.currency,\n country: startData.country,\n isProduction: startData.is_sandbox === false,\n googleMerchantId: startData.google_merchant_id,\n };\n\n if (!adapter.initialize(config)) {\n return {\n error:\n 'Google Pay API not loaded. Add <script src=\"https://pay.google.com/gp/p/js/pay.js\"></script> to your page.',\n };\n }\n\n return { adapter };\n}\n\nasync function runAirwallexFlow(\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): Promise<{ success: boolean; token?: GooglePayEncryptedToken; error?: string }> {\n // Initialize Airwallex adapter\n const { adapter, error: adapterError } = initializeAirwallexAdapter(startData, mockScenario);\n if (!adapter) {\n return { success: false, error: adapterError };\n }\n\n // Check availability\n const isAvailable = await adapter.canMakePayment();\n\n if (!isAvailable) {\n return { success: false, error: \"Google Pay not available on this device\" };\n }\n\n // Show payment sheet\n const paymentResult = await adapter.showPaymentSheet();\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { success: false, error: \"Google Pay cancelled by user\" };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { success: false, error: errorMessage };\n }\n\n // Return the token for passing to backend\n return { success: true, token: paymentResult.token };\n}\n\n// =============================================================================\n// Confirm & Verify Endpoints\n// =============================================================================\n\n/**\n * Call /confirm endpoint - processes Google Pay token (Airwallex) or records setup (Stripe).\n * For Airwallex, may return next_action if 3DS is required.\n */\nasync function callConfirmEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n googlePayToken?: GooglePayEncryptedToken,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<GooglePayConfirmResponse> {\n const requestBody: GooglePayConfirmRequest = {\n mock_scenario: mockScenarioStr,\n };\n\n if (googlePayToken) {\n requestBody.google_pay_token = googlePayToken;\n }\n\n const result = await apiCall<GooglePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/google-pay/confirm`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(requestBody),\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message: result.error || \"Failed to confirm payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\n/**\n * Call /verify endpoint - verifies 3DS completion for Airwallex.\n * Called after user completes 3DS challenge. May return another next_action for retry.\n */\nasync function callVerifyEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n checkoutRequestId?: string,\n): Promise<GooglePayConfirmResponse> {\n const result = await apiCall<GooglePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/google-pay/verify`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message: result.error || \"Failed to verify payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\n/**\n * Convert GooglePayConfirmResponse to GooglePayResult for return to caller.\n */\nfunction toGooglePayResult(response: GooglePayConfirmResponse, secureToken: string): GooglePayResult {\n if (response.charge_status === \"success\") {\n return {\n data: {\n id: response.transaction_id,\n checkoutAttemptId: response.checkout_attempt_id,\n checkoutSessionId: secureToken,\n state: \"checkout_succeeded\",\n },\n };\n }\n return { errors: { google_pay: response.error_message || \"Payment failed\" } };\n}\n\n// =============================================================================\n// Stripe Confirm (Simple - No 3DS Loop)\n// =============================================================================\n\n/**\n * Confirm Stripe Google Pay - simple flow without 3DS loop.\n * Stripe.js handles 3DS internally during confirmCardSetup().\n */\nasync function confirmStripeGooglePay(\n apiBaseUrl: string,\n secureToken: string,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<GooglePayResult> {\n const response = await callConfirmEndpoint(apiBaseUrl, secureToken, undefined, mockScenarioStr, checkoutRequestId);\n return toGooglePayResult(response, secureToken);\n}\n\n// =============================================================================\n// Airwallex Confirm with 3DS Loop\n// =============================================================================\n\nconst MAX_USER_ACTIONS = 5;\n\n/**\n * Confirm Airwallex Google Pay with 3DS loop support.\n *\n * Flow:\n * 1. Call /confirm with token → may return next_action (3DS)\n * 2. If next_action: handle 3DS, then call /verify\n * 3. Loop if /verify returns another next_action (3DS retry)\n * 4. Return final result\n *\n * This mirrors the card.ts pattern for consistency.\n */\nasync function confirmAirwallexGooglePay(\n apiBaseUrl: string,\n secureToken: string,\n googlePayToken: GooglePayEncryptedToken,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<GooglePayResult> {\n let userActionCount = 0;\n\n // Step 1: Initial confirm with token\n let response = await callConfirmEndpoint(apiBaseUrl, secureToken, googlePayToken, mockScenarioStr, checkoutRequestId);\n\n // Step 2: Handle 3DS loop (if required)\n while (response.charge_status === \"pending\" && response.next_action && userActionCount < MAX_USER_ACTIONS) {\n userActionCount++;\n\n // Handle 3DS challenge\n const actionResult = await handleNextAction(response.next_action);\n\n // Always call verify endpoint so backend can conclude properly\n // (even if 3DS failed, backend needs to know)\n const verifyResponse = await callVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId);\n\n // Check if another 3DS action is required (retry scenario)\n if (verifyResponse.charge_status === \"pending\" && verifyResponse.next_action) {\n if (!actionResult.success) {\n console.log(\"[GooglePay:Airwallex] 3DS failed but retry available, continuing loop...\");\n }\n response = verifyResponse;\n continue;\n }\n\n // No more actions - check final result\n if (!actionResult.success) {\n // 3DS failed and no retry available\n return {\n errors: {\n google_pay: verifyResponse.error_message || actionResult.error || \"3DS authentication failed\",\n },\n };\n }\n\n // 3DS succeeded - return verify result\n return toGooglePayResult(verifyResponse, secureToken);\n }\n\n // Check for max attempts exceeded\n if (userActionCount >= MAX_USER_ACTIONS) {\n return { errors: { google_pay: \"Too many authentication attempts. Please try again.\" } };\n }\n\n // No 3DS required - return initial confirm result\n return toGooglePayResult(response, secureToken);\n}\n\n// =============================================================================\n// Main Submit Function\n// =============================================================================\n\nconst defSubmitPayment = (states: PaymentKitStates) => {\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n const { apiBaseUrl, secureToken, environment } = states;\n const gpayOptions = options as GooglePaySubmitOptions;\n\n // Validate options\n const validationError = validateOptions(gpayOptions);\n if (validationError) {\n return { errors: validationError };\n }\n\n try {\n const mockScenarioStr = getMockScenarioStr(gpayOptions.mockScenario);\n\n // Get or create checkout request ID for correlating all API calls\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[GooglePay] Using checkout_request_id: ${checkoutRequestId}`);\n\n // Step 1: Start Google Pay flow - backend selects processor\n const startResult = await callStartEndpoint(\n apiBaseUrl,\n secureToken,\n gpayOptions,\n mockScenarioStr,\n checkoutRequestId,\n );\n if (startResult.error || !startResult.data) {\n return { errors: { google_pay: startResult.error || \"Failed to start Google Pay\" } };\n }\n\n const startData = startResult.data;\n\n // Step 2 & 3: Run processor-specific flow and confirm\n if (startData.processor === \"stripe\") {\n // Stripe flow: Uses Stripe.js PaymentRequest API (handles 3DS internally)\n const stripeResult = await runStripeFlow(startData, gpayOptions.mockScenario);\n if (!stripeResult.success) {\n return { errors: { google_pay: stripeResult.error } };\n }\n // Confirm with backend (no token needed, Stripe handled it)\n return await confirmStripeGooglePay(apiBaseUrl, secureToken, mockScenarioStr, checkoutRequestId);\n }\n\n if (startData.processor === \"airwallex\") {\n // Airwallex flow: Uses Google Pay API directly, may need 3DS\n const airwallexResult = await runAirwallexFlow(startData, gpayOptions.mockScenario);\n if (!airwallexResult.success) {\n return { errors: { google_pay: airwallexResult.error } };\n }\n if (!airwallexResult.token) {\n return { errors: { google_pay: \"Google Pay token not received\" } };\n }\n // Confirm with 3DS loop support\n return await confirmAirwallexGooglePay(\n apiBaseUrl,\n secureToken,\n airwallexResult.token,\n mockScenarioStr,\n checkoutRequestId,\n );\n }\n\n return { errors: { google_pay: `Unsupported processor: ${startData.processor}` } };\n } catch (error) {\n return { errors: { google_pay: `Google Pay error: ${error}` } };\n }\n };\n\n return submitPayment;\n};\n\n// =============================================================================\n// Payment Method Definition\n// =============================================================================\n\nconst GooglePayPaymentMethod = definePaymentMethod((paymentKitStates) => {\n return {\n name: \"google_pay\",\n externalFuncs: {},\n internalFuncs: {\n submitPayment: defSubmitPayment(paymentKitStates),\n cleanup: () => {},\n },\n };\n});\n\nexport { GooglePayMockScenario };\n\nexport default GooglePayPaymentMethod;\n"],"mappings":"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"}
1
+ {"version":3,"file":"google-pay.mjs","names":["airwallexMockScenario: AirwallexGooglePayMockScenario","config: AirwallexGooglePayConfig","requestBody: GooglePayConfirmRequest","submitPayment: TInternalFuncs[\"submitPayment\"]"],"sources":["../../src/payment-methods/google-pay.ts"],"sourcesContent":["import type { PaymentKitErrors, PaymentKitStates, TInternalFuncs } from \"../types\";\nimport { collectFraudMetadata, definePaymentMethod, getOrCreateCheckoutRequestId } from \"../utils\";\nimport {\n AirwallexGooglePayAdapter,\n type AirwallexGooglePayConfig,\n AirwallexGooglePayMockScenario,\n type GooglePayEncryptedToken,\n} from \"./airwallex-google-pay-adapter\";\nimport { handleNextAction } from \"./next-action-handlers\";\nimport { GooglePayMockScenario, StripeGooglePayAdapter } from \"./stripe-google-pay-adapter\";\n\n// Google Pay-specific types\nexport type GooglePayCustomerInfo = {\n first_name: string;\n last_name: string;\n email?: string;\n};\n\nexport type GooglePayStartRequest = {\n processor_id: string;\n customer_info: GooglePayCustomerInfo;\n fraud_metadata: {\n ipAddress?: string;\n browserInfo?: { [key: string]: unknown };\n processorFraudInfo?: { [key: string]: unknown };\n };\n mock_scenario?: string;\n};\n\nexport type GooglePayStartResponse = {\n checkout_attempt_id: string;\n amount: number;\n amount_display: string; // Formatted for Google Pay (e.g., \"100.00\" for USD, \"1000\" for JPY)\n currency: string;\n country: string;\n\n // Processor discriminator\n processor: \"stripe\" | \"airwallex\";\n\n // Environment flag\n is_sandbox?: boolean;\n\n // Stripe-specific fields (when processor=\"stripe\")\n client_secret?: string;\n stripe_pk?: string;\n\n // Airwallex-specific fields (when processor=\"airwallex\")\n merchant_name?: string;\n airwallex_account_id?: string;\n google_merchant_id?: string; // Google-assigned merchant ID for production (BCR2DN...)\n};\n\nexport type GooglePayConfirmRequest = {\n google_pay_token?: GooglePayEncryptedToken; // Required for Airwallex\n payer_email?: string; // Email from payment sheet (Stripe Google Pay)\n mock_scenario?: string;\n};\n\n// Airwallex 3DS next action type (matches backend snake_case response)\nexport type Airwallex3dsNextAction = {\n type: \"airwallex_3ds\";\n url: string;\n method: string;\n payment_intent_id: string;\n};\n\nexport type GooglePayConfirmResponse = {\n charge_status: \"success\" | \"fail\" | \"pending\";\n transaction_id?: string;\n error_code?: string;\n error_message?: string;\n error_message_for_customer?: string;\n error_message_for_debug?: string;\n checkout_attempt_id: string;\n checkout_session_id?: string;\n next_action?: Airwallex3dsNextAction; // Present when charge_status=\"pending\" for 3DS\n payment_intent_id?: string;\n customer_id?: string;\n payment_method_id?: string;\n processor_used?: string;\n subscription_id?: string;\n invoice_id?: string;\n invoice_number?: number;\n card_brand?: string;\n card_last4?: string;\n card_exp_month?: number;\n card_exp_year?: number;\n};\n\nexport type GooglePaySubmitOptions = {\n processorId: string;\n customerInfo: GooglePayCustomerInfo;\n mockScenario?: GooglePayMockScenario;\n};\n\ntype GooglePayResult =\n | { data: { [key: string]: unknown }; errors?: never }\n | { data?: never; errors: PaymentKitErrors };\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\nasync function apiCall<T>(\n url: string,\n options: RequestInit,\n checkoutRequestId?: string,\n): Promise<{ data?: T; error?: string }> {\n // Add x-request-id header if provided\n const headers = new Headers(options.headers);\n if (checkoutRequestId) {\n headers.set(\"x-request-id\", checkoutRequestId);\n }\n\n const response = await fetch(url, { ...options, headers });\n if (!response.ok) {\n let errorMessage = `Request failed (${response.status})`;\n try {\n const errorData = await response.json();\n errorMessage = errorData.detail || errorMessage;\n } catch {\n errorMessage = response.statusText || errorMessage;\n }\n return { error: errorMessage };\n }\n return { data: await response.json() };\n}\n\nfunction validateOptions(options: GooglePaySubmitOptions): PaymentKitErrors | null {\n if (!options?.processorId) {\n return { processor_id: \"Processor ID is required\" };\n }\n // Customer name is optional — Google Pay collects it from the payment sheet\n return null;\n}\n\nfunction getMockScenarioStr(mockScenario?: GooglePayMockScenario): string | undefined {\n return mockScenario && mockScenario !== GooglePayMockScenario.None ? mockScenario : undefined;\n}\n\nasync function callStartEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n options: GooglePaySubmitOptions,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<{ data?: GooglePayStartResponse; error?: string }> {\n return apiCall<GooglePayStartResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/google-pay/start`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n processor_id: options.processorId,\n customer_info: options.customerInfo,\n fraud_metadata: collectFraudMetadata(),\n mock_scenario: mockScenarioStr,\n } as GooglePayStartRequest),\n },\n checkoutRequestId,\n );\n}\n\n// =============================================================================\n// Stripe Flow\n// =============================================================================\n\nfunction initializeStripeAdapter(\n stripePk: string,\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): { adapter?: StripeGooglePayAdapter; error?: string } {\n const adapter = new StripeGooglePayAdapter(mockScenario);\n\n if (!adapter.initialize(stripePk)) {\n return { error: 'Stripe.js not loaded. Add <script src=\"https://js.stripe.com/v3/\"></script> to your page.' };\n }\n\n const prConfig = {\n country: startData.country,\n currency: startData.currency.toLowerCase(),\n total: { label: \"Total\", amount: startData.amount },\n requestPayerName: true,\n requestPayerEmail: true,\n };\n adapter.createPaymentRequest(prConfig);\n return { adapter };\n}\n\nasync function runStripeFlow(\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): Promise<{ success: boolean; error?: string; payerEmail?: string }> {\n if (!startData.stripe_pk || !startData.client_secret) {\n return { success: false, error: \"Stripe credentials not provided\" };\n }\n\n // Initialize Stripe adapter\n const { adapter, error: adapterError } = initializeStripeAdapter(startData.stripe_pk, startData, mockScenario);\n if (!adapter) {\n return { success: false, error: adapterError };\n }\n\n // Check availability\n const isAvailable = await adapter.canMakePayment();\n\n if (!isAvailable) {\n return { success: false, error: \"Google Pay not available on this device\" };\n }\n\n // Show payment sheet\n const paymentResult = await adapter.showPaymentSheet();\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { success: false, error: \"Google Pay cancelled by user\" };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { success: false, error: errorMessage };\n }\n\n // Confirm with Stripe SDK\n const confirmResult = await adapter.confirmCardSetup(startData.client_secret, paymentResult.paymentMethodId);\n\n if (!confirmResult.success) {\n paymentResult.complete(\"fail\");\n return { success: false, error: \"error\" in confirmResult ? confirmResult.error : \"Card setup failed\" };\n }\n\n paymentResult.complete(\"success\");\n return { success: true, payerEmail: paymentResult.payerEmail };\n}\n\n// =============================================================================\n// Airwallex Flow\n// =============================================================================\n\nfunction initializeAirwallexAdapter(\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): {\n adapter?: AirwallexGooglePayAdapter;\n error?: string;\n} {\n if (!startData.merchant_name || !startData.airwallex_account_id) {\n return { error: \"Airwallex Google Pay credentials not provided\" };\n }\n\n // Convert GooglePayMockScenario to AirwallexGooglePayMockScenario\n let airwallexMockScenario: AirwallexGooglePayMockScenario = AirwallexGooglePayMockScenario.None;\n if (mockScenario === GooglePayMockScenario.Success) {\n airwallexMockScenario = AirwallexGooglePayMockScenario.Success;\n } else if (mockScenario === GooglePayMockScenario.Cancelled) {\n airwallexMockScenario = AirwallexGooglePayMockScenario.Cancelled;\n }\n\n const adapter = new AirwallexGooglePayAdapter(airwallexMockScenario);\n\n const config: AirwallexGooglePayConfig = {\n merchantId: startData.merchant_name,\n gatewayMerchantId: startData.airwallex_account_id,\n amountDisplay: startData.amount_display,\n currency: startData.currency,\n country: startData.country,\n isProduction: startData.is_sandbox === false,\n googleMerchantId: startData.google_merchant_id,\n };\n\n if (!adapter.initialize(config)) {\n return {\n error:\n 'Google Pay API not loaded. Add <script src=\"https://pay.google.com/gp/p/js/pay.js\"></script> to your page.',\n };\n }\n\n return { adapter };\n}\n\nasync function runAirwallexFlow(\n startData: GooglePayStartResponse,\n mockScenario?: GooglePayMockScenario,\n): Promise<{ success: boolean; token?: GooglePayEncryptedToken; error?: string }> {\n // Initialize Airwallex adapter\n const { adapter, error: adapterError } = initializeAirwallexAdapter(startData, mockScenario);\n if (!adapter) {\n return { success: false, error: adapterError };\n }\n\n // Check availability\n const isAvailable = await adapter.canMakePayment();\n\n if (!isAvailable) {\n return { success: false, error: \"Google Pay not available on this device\" };\n }\n\n // Show payment sheet\n const paymentResult = await adapter.showPaymentSheet();\n\n if (!paymentResult.success) {\n if (\"cancelled\" in paymentResult && paymentResult.cancelled) {\n return { success: false, error: \"Google Pay cancelled by user\" };\n }\n const errorMessage = \"error\" in paymentResult ? paymentResult.error : \"Unknown error\";\n return { success: false, error: errorMessage };\n }\n\n // Return the token for passing to backend\n return { success: true, token: paymentResult.token };\n}\n\n// =============================================================================\n// Confirm & Verify Endpoints\n// =============================================================================\n\n/**\n * Call /confirm endpoint - processes Google Pay token (Airwallex) or records setup (Stripe).\n * For Airwallex, may return next_action if 3DS is required.\n */\nasync function callConfirmEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n googlePayToken?: GooglePayEncryptedToken,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n payerEmail?: string,\n): Promise<GooglePayConfirmResponse> {\n const requestBody: GooglePayConfirmRequest = {\n mock_scenario: mockScenarioStr,\n };\n\n if (googlePayToken) {\n requestBody.google_pay_token = googlePayToken;\n }\n\n if (payerEmail) {\n requestBody.payer_email = payerEmail;\n }\n\n const result = await apiCall<GooglePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/google-pay/confirm`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(requestBody),\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message: result.error || \"Failed to confirm payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\n/**\n * Call /verify endpoint - verifies 3DS completion for Airwallex.\n * Called after user completes 3DS challenge. May return another next_action for retry.\n */\nasync function callVerifyEndpoint(\n apiBaseUrl: string,\n secureToken: string,\n checkoutRequestId?: string,\n): Promise<GooglePayConfirmResponse> {\n const result = await apiCall<GooglePayConfirmResponse>(\n `${apiBaseUrl}/api/checkout/${secureToken}/google-pay/verify`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n },\n checkoutRequestId,\n );\n\n if (result.error || !result.data) {\n return {\n charge_status: \"fail\",\n error_message: result.error || \"Failed to verify payment\",\n checkout_attempt_id: \"\",\n };\n }\n\n return result.data;\n}\n\n/**\n * Convert GooglePayConfirmResponse to GooglePayResult for return to caller.\n */\nfunction toGooglePayResult(response: GooglePayConfirmResponse, secureToken: string): GooglePayResult {\n if (response.charge_status === \"success\") {\n return {\n data: {\n id: response.transaction_id,\n checkoutAttemptId: response.checkout_attempt_id,\n checkoutSessionId: response.checkout_session_id ?? secureToken,\n state: \"checkout_succeeded\",\n paymentIntentId: response.payment_intent_id,\n customerId: response.customer_id,\n paymentMethodId: response.payment_method_id,\n processorUsed: response.processor_used,\n subscriptionId: response.subscription_id,\n invoiceId: response.invoice_id,\n invoiceNumber: response.invoice_number,\n cardBrand: response.card_brand,\n cardLast4: response.card_last4,\n cardExpMonth: response.card_exp_month,\n cardExpYear: response.card_exp_year,\n errorCode: response.error_code,\n errorMessageForCustomer: response.error_message_for_customer,\n errorMessageForDebug: response.error_message_for_debug,\n nextAction: response.next_action,\n },\n };\n }\n return {\n errors: {\n google_pay:\n response.error_message_for_customer ||\n response.error_message_for_debug ||\n response.error_message ||\n \"Payment failed\",\n },\n };\n}\n\n// =============================================================================\n// Stripe Confirm (Simple - No 3DS Loop)\n// =============================================================================\n\n/**\n * Confirm Stripe Google Pay - simple flow without 3DS loop.\n * Stripe.js handles 3DS internally during confirmCardSetup().\n */\nasync function confirmStripeGooglePay(\n apiBaseUrl: string,\n secureToken: string,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n payerEmail?: string,\n): Promise<GooglePayResult> {\n const response = await callConfirmEndpoint(\n apiBaseUrl,\n secureToken,\n undefined,\n mockScenarioStr,\n checkoutRequestId,\n payerEmail,\n );\n return toGooglePayResult(response, secureToken);\n}\n\n// =============================================================================\n// Airwallex Confirm with 3DS Loop\n// =============================================================================\n\nconst MAX_USER_ACTIONS = 5;\n\n/**\n * Confirm Airwallex Google Pay with 3DS loop support.\n *\n * Flow:\n * 1. Call /confirm with token → may return next_action (3DS)\n * 2. If next_action: handle 3DS, then call /verify\n * 3. Loop if /verify returns another next_action (3DS retry)\n * 4. Return final result\n *\n * This mirrors the card.ts pattern for consistency.\n */\nasync function confirmAirwallexGooglePay(\n apiBaseUrl: string,\n secureToken: string,\n googlePayToken: GooglePayEncryptedToken,\n mockScenarioStr?: string,\n checkoutRequestId?: string,\n): Promise<GooglePayResult> {\n let userActionCount = 0;\n\n // Step 1: Initial confirm with token\n let response = await callConfirmEndpoint(apiBaseUrl, secureToken, googlePayToken, mockScenarioStr, checkoutRequestId);\n\n // Step 2: Handle 3DS loop (if required)\n while (response.charge_status === \"pending\" && response.next_action && userActionCount < MAX_USER_ACTIONS) {\n userActionCount++;\n\n // Handle 3DS challenge\n const actionResult = await handleNextAction(response.next_action);\n\n // Always call verify endpoint so backend can conclude properly\n // (even if 3DS failed, backend needs to know)\n const verifyResponse = await callVerifyEndpoint(apiBaseUrl, secureToken, checkoutRequestId);\n\n // Check if another 3DS action is required (retry scenario)\n if (verifyResponse.charge_status === \"pending\" && verifyResponse.next_action) {\n if (!actionResult.success) {\n console.log(\"[GooglePay:Airwallex] 3DS failed but retry available, continuing loop...\");\n }\n response = verifyResponse;\n continue;\n }\n\n // No more actions - check final result\n if (!actionResult.success) {\n // 3DS failed and no retry available\n return {\n errors: {\n google_pay: verifyResponse.error_message || actionResult.error || \"3DS authentication failed\",\n },\n };\n }\n\n // 3DS succeeded - return verify result\n return toGooglePayResult(verifyResponse, secureToken);\n }\n\n // Check for max attempts exceeded\n if (userActionCount >= MAX_USER_ACTIONS) {\n return { errors: { google_pay: \"Too many authentication attempts. Please try again.\" } };\n }\n\n // No 3DS required - return initial confirm result\n return toGooglePayResult(response, secureToken);\n}\n\n// =============================================================================\n// Main Submit Function\n// =============================================================================\n\nconst defSubmitPayment = (states: PaymentKitStates) => {\n const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n const { apiBaseUrl, secureToken, environment } = states;\n const gpayOptions = options as GooglePaySubmitOptions;\n\n // Validate options\n const validationError = validateOptions(gpayOptions);\n if (validationError) {\n return { errors: validationError };\n }\n\n try {\n const mockScenarioStr = getMockScenarioStr(gpayOptions.mockScenario);\n\n // Get or create checkout request ID for correlating all API calls\n const checkoutRequestId = getOrCreateCheckoutRequestId(environment);\n console.log(`[GooglePay] Using checkout_request_id: ${checkoutRequestId}`);\n\n // Step 1: Start Google Pay flow - backend selects processor\n const startResult = await callStartEndpoint(\n apiBaseUrl,\n secureToken,\n gpayOptions,\n mockScenarioStr,\n checkoutRequestId,\n );\n if (startResult.error || !startResult.data) {\n return { errors: { google_pay: startResult.error || \"Failed to start Google Pay\" } };\n }\n\n const startData = startResult.data;\n\n // Step 2 & 3: Run processor-specific flow and confirm\n if (startData.processor === \"stripe\") {\n // Stripe flow: Uses Stripe.js PaymentRequest API (handles 3DS internally)\n const stripeResult = await runStripeFlow(startData, gpayOptions.mockScenario);\n if (!stripeResult.success) {\n return { errors: { google_pay: stripeResult.error } };\n }\n // Confirm with backend (no token needed, Stripe handled it)\n return await confirmStripeGooglePay(\n apiBaseUrl,\n secureToken,\n mockScenarioStr,\n checkoutRequestId,\n stripeResult.payerEmail,\n );\n }\n\n if (startData.processor === \"airwallex\") {\n // Airwallex flow: Uses Google Pay API directly, may need 3DS\n const airwallexResult = await runAirwallexFlow(startData, gpayOptions.mockScenario);\n if (!airwallexResult.success) {\n return { errors: { google_pay: airwallexResult.error } };\n }\n if (!airwallexResult.token) {\n return { errors: { google_pay: \"Google Pay token not received\" } };\n }\n // Confirm with 3DS loop support\n return await confirmAirwallexGooglePay(\n apiBaseUrl,\n secureToken,\n airwallexResult.token,\n mockScenarioStr,\n checkoutRequestId,\n );\n }\n\n return { errors: { google_pay: `Unsupported processor: ${startData.processor}` } };\n } catch (error) {\n return { errors: { google_pay: `Google Pay error: ${error}` } };\n }\n };\n\n return submitPayment;\n};\n\n// =============================================================================\n// Payment Method Definition\n// =============================================================================\n\nconst GooglePayPaymentMethod = definePaymentMethod((paymentKitStates) => {\n return {\n name: \"google_pay\",\n externalFuncs: {},\n internalFuncs: {\n submitPayment: defSubmitPayment(paymentKitStates),\n cleanup: () => {},\n },\n };\n});\n\nexport { GooglePayMockScenario };\n\nexport default GooglePayPaymentMethod;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { a as StripeGooglePayAdapter, i as ShowPaymentSheetResult, n as GooglePayMockScenario, r as PaymentRequestConfig, t as ConfirmResult } from "../stripe-google-pay-adapter-C3NCBSO3.mjs";
1
+ import { a as StripeGooglePayAdapter, i as ShowPaymentSheetResult, n as GooglePayMockScenario, r as PaymentRequestConfig, t as ConfirmResult } from "../stripe-google-pay-adapter-Bdox4xBq.mjs";
2
2
  export { ConfirmResult, GooglePayMockScenario, PaymentRequestConfig, ShowPaymentSheetResult, StripeGooglePayAdapter };
@@ -1,3 +1,3 @@
1
- import { n as StripeGooglePayAdapter, t as GooglePayMockScenario } from "../stripe-google-pay-adapter-CqcUEoM3.mjs";
1
+ import { n as StripeGooglePayAdapter, t as GooglePayMockScenario } from "../stripe-google-pay-adapter-3cx0KNjK.mjs";
2
2
 
3
3
  export { GooglePayMockScenario, StripeGooglePayAdapter };
@@ -22,7 +22,7 @@ declare function createVgsCardFields(form: VGSCollectForm, mountPoints: {
22
22
  pan: string;
23
23
  exp: string;
24
24
  cvc: string;
25
- }, css?: Record<string, string>, onFocusChangeCallbacks?: Partial<Record<string, (isFocused: boolean) => void>>, placeholders?: Partial<Record<string, string>>): void;
25
+ }, css?: Record<string, string>, onFocusChangeCallbacks?: Partial<Record<string, (isFocused: boolean) => void>>, placeholders?: Partial<Record<string, string>>): () => void;
26
26
  //#endregion
27
27
  export { createVgsCardFields, initVgsCollect, loadVgsCollectScript };
28
28
  //# sourceMappingURL=vgs-collect-loader.d.mts.map
@@ -1,3 +1,3 @@
1
- import { n as initVgsCollect, r as loadVgsCollectScript, t as createVgsCardFields } from "../vgs-collect-loader-3Z4IWCA6.mjs";
1
+ import { n as initVgsCollect, r as loadVgsCollectScript, t as createVgsCardFields } from "../vgs-collect-loader-BZj36d8r.mjs";
2
2
 
3
3
  export { createVgsCardFields, initVgsCollect, loadVgsCollectScript };
@@ -85,10 +85,14 @@ var StripeGooglePayAdapter = class {
85
85
  }
86
86
  return new Promise((resolve) => {
87
87
  this.paymentRequest.on("paymentmethod", (event) => {
88
- console.log("[GooglePay] showPaymentSheet: paymentmethod event", { paymentMethodId: event.paymentMethod.id });
88
+ console.log("[GooglePay] showPaymentSheet: paymentmethod event", {
89
+ paymentMethodId: event.paymentMethod.id,
90
+ payerEmail: event.payerEmail
91
+ });
89
92
  resolve({
90
93
  success: true,
91
94
  paymentMethodId: event.paymentMethod.id,
95
+ payerEmail: event.payerEmail ?? void 0,
92
96
  complete: (status) => {
93
97
  console.log("[GooglePay] complete called:", status);
94
98
  event.complete(status);
@@ -111,6 +115,7 @@ var StripeGooglePayAdapter = class {
111
115
  return {
112
116
  success: true,
113
117
  paymentMethodId: "pm_mock_123456789",
118
+ payerEmail: "mock@example.com",
114
119
  complete: (status) => console.log(`[MockGooglePay] complete: ${status}`)
115
120
  };
116
121
  case GooglePayMockScenario.Cancelled:
@@ -160,4 +165,4 @@ var StripeGooglePayAdapter = class {
160
165
 
161
166
  //#endregion
162
167
  export { StripeGooglePayAdapter as n, GooglePayMockScenario as t };
163
- //# sourceMappingURL=stripe-google-pay-adapter-CqcUEoM3.mjs.map
168
+ //# sourceMappingURL=stripe-google-pay-adapter-3cx0KNjK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe-google-pay-adapter-3cx0KNjK.mjs","names":[],"sources":["../src/payment-methods/stripe-google-pay-adapter.ts"],"sourcesContent":["import type { PaymentRequest, PaymentRequestPaymentMethodEvent, Stripe, StripeConstructor } from \"@stripe/stripe-js\";\n\n// Stripe.js must be loaded via script tag for PCI compliance\ndeclare global {\n interface Window {\n Stripe?: StripeConstructor;\n }\n}\n\nexport interface PaymentRequestConfig {\n country: string;\n currency: string;\n total: { label: string; amount: number };\n requestPayerName: boolean;\n requestPayerEmail: boolean;\n}\n\nexport type ShowPaymentSheetResult =\n | {\n success: true;\n paymentMethodId: string;\n payerEmail?: string;\n complete: (status: \"success\" | \"fail\") => void;\n }\n | { success: false; cancelled: true }\n | { success: false; error: string };\n\nexport type ConfirmResult = { success: true } | { success: false; error: string };\n\nexport enum GooglePayMockScenario {\n None = \"none\",\n Success = \"success\",\n Cancelled = \"cancelled\",\n}\n\nexport class StripeGooglePayAdapter {\n private stripe: Stripe | null = null;\n private paymentRequest: PaymentRequest | null = null;\n private mockScenario: GooglePayMockScenario;\n\n constructor(mockScenario?: GooglePayMockScenario) {\n this.mockScenario = mockScenario ?? GooglePayMockScenario.None;\n }\n\n initialize(publishableKey: string): boolean {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] initialize called\");\n if (!window.Stripe) {\n console.log(\"[GooglePay] Stripe.js not loaded\");\n return false;\n }\n this.stripe = window.Stripe(publishableKey);\n const success = this.stripe !== null;\n console.log(\"[GooglePay] initialize result:\", success);\n return success;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] initialize called\");\n console.log(\"[MockGooglePay] initialize result:\", true);\n return true;\n }\n }\n }\n\n createPaymentRequest(config: PaymentRequestConfig): void {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] createPaymentRequest called\", config);\n if (!this.stripe) {\n throw new Error(\"Stripe not initialized\");\n }\n this.paymentRequest = this.stripe.paymentRequest(config);\n console.log(\"[GooglePay] paymentRequest created\");\n return;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] createPaymentRequest called\", config);\n return;\n }\n }\n }\n\n async canMakePayment(): Promise<boolean> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] canMakePayment called\");\n if (!this.paymentRequest) {\n console.log(\"[GooglePay] canMakePayment: no paymentRequest\");\n return false;\n }\n const result = await this.paymentRequest.canMakePayment();\n const isAvailable = result?.googlePay ?? false;\n console.log(\"[GooglePay] canMakePayment result:\", { result, isAvailable });\n return isAvailable;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] canMakePayment called\");\n console.log(\"[MockGooglePay] canMakePayment result:\", { result: { googlePay: true }, isAvailable: true });\n return true;\n }\n }\n }\n\n async showPaymentSheet(): Promise<ShowPaymentSheetResult> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] showPaymentSheet called\");\n if (!this.paymentRequest) {\n console.log(\"[GooglePay] showPaymentSheet: no paymentRequest\");\n return { success: false, error: \"Payment request not created\" };\n }\n\n return new Promise((resolve) => {\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.on(\"paymentmethod\", (event: PaymentRequestPaymentMethodEvent) => {\n console.log(\"[GooglePay] showPaymentSheet: paymentmethod event\", {\n paymentMethodId: event.paymentMethod.id,\n payerEmail: event.payerEmail,\n });\n resolve({\n success: true,\n paymentMethodId: event.paymentMethod.id,\n payerEmail: event.payerEmail ?? undefined,\n complete: (status) => {\n console.log(\"[GooglePay] complete called:\", status);\n event.complete(status);\n },\n });\n });\n\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.on(\"cancel\", () => {\n console.log(\"[GooglePay] showPaymentSheet: cancelled by user\");\n resolve({ success: false, cancelled: true });\n });\n\n console.log(\"[GooglePay] showing payment sheet...\");\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.show();\n });\n }\n case GooglePayMockScenario.Success: {\n console.log(\"[MockGooglePay] showPaymentSheet: success\");\n await new Promise((resolve) => setTimeout(resolve, 500));\n return {\n success: true,\n paymentMethodId: \"pm_mock_123456789\",\n payerEmail: \"mock@example.com\",\n complete: (status) => console.log(`[MockGooglePay] complete: ${status}`),\n };\n }\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] showPaymentSheet: cancelled\");\n await new Promise((resolve) => setTimeout(resolve, 500));\n return { success: false, cancelled: true };\n }\n }\n }\n\n async confirmCardSetup(clientSecret: string, paymentMethodId: string): Promise<ConfirmResult> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] confirmCardSetup called\", {\n clientSecret: `${clientSecret.slice(0, 20)}...`,\n paymentMethodId,\n });\n if (!this.stripe) {\n console.log(\"[GooglePay] confirmCardSetup: Stripe not initialized\");\n return { success: false, error: \"Stripe not initialized\" };\n }\n\n const { error } = await this.stripe.confirmCardSetup(clientSecret, {\n payment_method: paymentMethodId,\n });\n\n if (error) {\n console.log(\"[GooglePay] confirmCardSetup error:\", error);\n return { success: false, error: error.message ?? \"Card setup failed\" };\n }\n\n console.log(\"[GooglePay] confirmCardSetup success\");\n return { success: true };\n }\n case GooglePayMockScenario.Success: {\n console.log(\"[MockGooglePay] confirmCardSetup called\", { clientSecret, paymentMethodId });\n return { success: true };\n }\n case GooglePayMockScenario.Cancelled: {\n throw new Error(\"confirmCardSetup should not be called when scenario is Cancelled\");\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -19,6 +19,7 @@ interface PaymentRequestConfig {
19
19
  type ShowPaymentSheetResult = {
20
20
  success: true;
21
21
  paymentMethodId: string;
22
+ payerEmail?: string;
22
23
  complete: (status: "success" | "fail") => void;
23
24
  } | {
24
25
  success: false;
@@ -51,4 +52,4 @@ declare class StripeGooglePayAdapter {
51
52
  }
52
53
  //#endregion
53
54
  export { StripeGooglePayAdapter as a, ShowPaymentSheetResult as i, GooglePayMockScenario as n, PaymentRequestConfig as r, ConfirmResult as t };
54
- //# sourceMappingURL=stripe-google-pay-adapter-C3NCBSO3.d.mts.map
55
+ //# sourceMappingURL=stripe-google-pay-adapter-Bdox4xBq.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripe-google-pay-adapter-Bdox4xBq.d.mts","names":[],"sources":["../src/payment-methods/stripe-google-pay-adapter.ts"],"sourcesContent":[],"mappings":";;;;;IAAqH,MAAA,CAAA,EAKxG,iBALwG;EAAA;;AAKvF,UAIb,oBAAA,CAJa;EAAA,OAAA,EAAA,MAAA;EAIb,QAAA,EAAA,MAAA;EAQL,KAAA,EAAA;IAUA,KAAA,EAAA,MAAa;IAEb,MAAA,EAAA,MAAA;EAMC,CAAA;EAKgB,gBAAA,EAAA,OAAA;EA0BE,iBAAA,EAAA,OAAA;;AAyCK,KA1FxB,sBAAA,GA0FwB;EAAR,OAAA,EAAA,IAAA;EAwDqD,eAAA,EAAA,MAAA;EAAR,UAAA,CAAA,EAAA,MAAA;EAAO,QAAA,EAAA,CAAA,MAAA,EAAA,SAAA,GAAA,MAAA,EAAA,GAAA,IAAA;;;;;;;;KAxIpE,aAAA;;;;;;aAEA,qBAAA;;;;;cAMC,sBAAA;;;;6BAKgB;;+BA0BE;oBAmBL;sBAsBE,QAAQ;mEAwDqC,QAAQ"}
@@ -63,6 +63,16 @@ function createVgsCardFields(form, mountPoints, css, onFocusChangeCallbacks, pla
63
63
  "box-sizing": "border-box",
64
64
  ...containerPadding && containerPadding !== "0px" ? { padding: containerPadding } : {}
65
65
  };
66
+ for (const selector of [
67
+ mountPoints.pan,
68
+ mountPoints.exp,
69
+ mountPoints.cvc
70
+ ]) {
71
+ const container = document.querySelector(selector);
72
+ if (!container) continue;
73
+ const staleIframes = container.querySelectorAll("iframe");
74
+ for (const iframe of staleIframes) iframe.remove();
75
+ }
66
76
  const panField = form.cardNumberField(mountPoints.pan, {
67
77
  placeholder: placeholders?.card_pan ?? "Card number",
68
78
  validations: ["required", "validCardNumber"],
@@ -88,6 +98,8 @@ function createVgsCardFields(form, mountPoints, css, onFocusChangeCallbacks, pla
88
98
  validations: ["required", "validCardSecurityCode"],
89
99
  css: fieldCss
90
100
  });
101
+ const observers = [];
102
+ const containers = [];
91
103
  for (const selector of [
92
104
  mountPoints.pan,
93
105
  mountPoints.exp,
@@ -95,6 +107,7 @@ function createVgsCardFields(form, mountPoints, css, onFocusChangeCallbacks, pla
95
107
  ]) {
96
108
  const container = document.querySelector(selector);
97
109
  if (!container) continue;
110
+ containers.push(container);
98
111
  const styleIframe = (iframe) => {
99
112
  const containerEl = container;
100
113
  if (getComputedStyle(containerEl).position === "static") containerEl.style.position = "relative";
@@ -104,18 +117,17 @@ function createVgsCardFields(form, mountPoints, css, onFocusChangeCallbacks, pla
104
117
  iframe.style.height = "100%";
105
118
  iframe.style.border = "none";
106
119
  };
107
- const existing = container.querySelector("iframe");
108
- if (existing) styleIframe(existing);
109
- else new MutationObserver((_, obs) => {
120
+ const observer = new MutationObserver(() => {
110
121
  const iframe = container.querySelector("iframe");
111
- if (iframe) {
112
- styleIframe(iframe);
113
- obs.disconnect();
114
- }
115
- }).observe(container, {
122
+ if (iframe && iframe.style.position !== "absolute") styleIframe(iframe);
123
+ });
124
+ observer.observe(container, {
116
125
  childList: true,
117
126
  subtree: true
118
127
  });
128
+ observers.push(observer);
129
+ const existing = container.querySelector("iframe");
130
+ if (existing && existing.style.position !== "absolute") styleIframe(existing);
119
131
  }
120
132
  if (onFocusChangeCallbacks) {
121
133
  const fieldMap = [
@@ -131,8 +143,15 @@ function createVgsCardFields(form, mountPoints, css, onFocusChangeCallbacks, pla
131
143
  }
132
144
  }
133
145
  }
146
+ return () => {
147
+ for (const observer of observers) observer.disconnect();
148
+ for (const container of containers) {
149
+ const iframes = container.querySelectorAll("iframe");
150
+ for (const iframe of iframes) iframe.remove();
151
+ }
152
+ };
134
153
  }
135
154
 
136
155
  //#endregion
137
156
  export { initVgsCollect as n, loadVgsCollectScript as r, createVgsCardFields as t };
138
- //# sourceMappingURL=vgs-collect-loader-3Z4IWCA6.mjs.map
157
+ //# sourceMappingURL=vgs-collect-loader-BZj36d8r.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vgs-collect-loader-BZj36d8r.mjs","names":["loadPromise: Promise<void> | null","observers: MutationObserver[]","containers: Element[]","fieldMap: [VGSCollectField, string][]"],"sources":["../src/payment-methods/vgs-collect-loader.ts"],"sourcesContent":["const VGS_COLLECT_CDN = \"https://js.verygoodvault.com/vgs-collect/3.2.1/vgs-collect.js\";\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads VGS Collect JS from CDN. Idempotent — subsequent calls return the same promise.\n */\nexport function loadVgsCollectScript(): Promise<void> {\n if (loadPromise) {\n console.log(\"[PaymentKit] VGS Collect CDN load already in progress — reusing promise\");\n return loadPromise;\n }\n\n loadPromise = new Promise<void>((resolve, reject) => {\n if (typeof window !== \"undefined\" && window.VGSCollect) {\n console.log(\"[PaymentKit] VGS Collect JS already available on window\");\n resolve();\n return;\n }\n\n console.log(`[PaymentKit] Loading VGS Collect JS from CDN: ${VGS_COLLECT_CDN}`);\n const script = document.createElement(\"script\");\n script.src = VGS_COLLECT_CDN;\n script.async = true;\n script.onload = () => {\n console.log(\"[PaymentKit] VGS Collect JS loaded successfully from CDN\");\n resolve();\n };\n script.onerror = () => {\n console.error(`[PaymentKit] Failed to load VGS Collect JS from CDN: ${VGS_COLLECT_CDN}`);\n loadPromise = null;\n reject(new Error(\"Failed to load VGS Collect JS\"));\n };\n document.head.appendChild(script);\n });\n\n return loadPromise;\n}\n\n/**\n * Initializes a VGS Collect form instance.\n */\nexport function initVgsCollect(vaultId: string, environment: string): VGSCollectForm {\n if (!window.VGSCollect) {\n throw new Error(\"VGS Collect JS not loaded. Call loadVgsCollectScript() first.\");\n }\n return window.VGSCollect.create(vaultId, environment, () => {});\n}\n\n/**\n * Creates and mounts VGS Collect card fields using CMP-specific field methods.\n *\n * Uses cardNumberField(), cardExpirationDateField(), cardCVCField() which are\n * required for the CMP createCard() flow. After mounting, call form.createCard()\n * to create a card in the VGS vault, which returns aliases for PAN and CVC.\n *\n * @param form - VGS Collect form instance\n * @param mountPoints - CSS selectors for PAN, expiry, and CVC containers\n * @param css - Optional CSS to apply to VGS Collect iframe fields\n */\nexport function createVgsCardFields(\n form: VGSCollectForm,\n mountPoints: { pan: string; exp: string; cvc: string },\n css?: Record<string, string>,\n onFocusChangeCallbacks?: Partial<Record<string, (isFocused: boolean) => void>>,\n placeholders?: Partial<Record<string, string>>,\n): () => void {\n // Read container padding so the VGS input content matches the merchant's\n // visual intent. The iframe uses absolute positioning (inset: 0) to fill\n // the full container, so the input needs its own padding for alignment.\n const sampleContainer = document.querySelector(mountPoints.pan) as HTMLElement | null;\n const containerPadding = sampleContainer ? getComputedStyle(sampleContainer).padding : undefined;\n\n const baseCss = css ?? {\n \"font-size\": \"1rem\",\n color: \"#18181b\",\n \"font-family\": \"ui-sans-serif, system-ui, sans-serif\",\n };\n\n const fieldCss = {\n ...baseCss,\n height: \"100%\",\n \"box-sizing\": \"border-box\",\n ...(containerPadding && containerPadding !== \"0px\" ? { padding: containerPadding } : {}),\n };\n\n // Remove stale iframes from previous VGS form mounts to prevent overlap.\n // VGS's form.unmount() does not remove iframes from the DOM.\n // IMPORTANT: This must run BEFORE VGS field methods below, because VGS may\n // insert new iframes synchronously — removing after would destroy fresh iframes.\n for (const selector of [mountPoints.pan, mountPoints.exp, mountPoints.cvc]) {\n const container = document.querySelector(selector);\n if (!container) continue;\n const staleIframes = container.querySelectorAll(\"iframe\");\n for (const iframe of staleIframes) {\n iframe.remove();\n }\n }\n\n const panField = form.cardNumberField(mountPoints.pan, {\n placeholder: placeholders?.card_pan ?? \"Card number\",\n validations: [\"required\", \"validCardNumber\"],\n css: fieldCss,\n });\n\n const expField = form.field(mountPoints.exp, {\n type: \"card-expiration-date\",\n name: \"exp-date\",\n placeholder: placeholders?.card_exp ?? \"MM / YY\",\n yearLength: 2,\n serializers: [{ name: \"separate\", options: { monthName: \"month\", yearName: \"year\" } }],\n validations: [\"required\", \"validCardExpirationDate\"],\n css: fieldCss,\n });\n\n const cvcField = form.cardCVCField(mountPoints.cvc, {\n placeholder: placeholders?.card_cvc ?? \"123\",\n validations: [\"required\", \"validCardSecurityCode\"],\n css: fieldCss,\n });\n\n // Track observers for cleanup\n const observers: MutationObserver[] = [];\n const containers: Element[] = [];\n\n // VGS Collect doesn't set width/height on its iframes, so they may not\n // fill the merchant's container. Force them to stretch like direct-mode iframes.\n // Iframes may be inserted asynchronously, so use MutationObserver as a fallback.\n for (const selector of [mountPoints.pan, mountPoints.exp, mountPoints.cvc]) {\n const container = document.querySelector(selector);\n if (!container) continue;\n containers.push(container);\n\n const styleIframe = (iframe: HTMLIFrameElement) => {\n // Use absolute positioning so the iframe covers the full container\n // including any padding the merchant's CSS applies.\n const containerEl = container as HTMLElement;\n if (getComputedStyle(containerEl).position === \"static\") {\n containerEl.style.position = \"relative\";\n }\n iframe.style.position = \"absolute\";\n iframe.style.inset = \"0\";\n iframe.style.width = \"100%\";\n iframe.style.height = \"100%\";\n iframe.style.border = \"none\";\n };\n\n // Always set up a MutationObserver to catch asynchronously inserted iframes.\n // VGS inserts iframes after field creation, so we need the observer even if\n // no iframe exists yet.\n const observer = new MutationObserver(() => {\n const iframe = container.querySelector(\"iframe\") as HTMLIFrameElement | null;\n if (iframe && iframe.style.position !== \"absolute\") {\n styleIframe(iframe);\n }\n });\n observer.observe(container, { childList: true, subtree: true });\n observers.push(observer);\n\n // Style any iframe VGS may have inserted synchronously during field creation.\n // The MutationObserver only fires on future mutations, so this handles the\n // case where VGS inserts the iframe before the observer is attached.\n const existing = container.querySelector(\"iframe\") as HTMLIFrameElement | null;\n if (existing && existing.style.position !== \"absolute\") {\n styleIframe(existing);\n }\n }\n\n if (onFocusChangeCallbacks) {\n const fieldMap: [VGSCollectField, string][] = [\n [panField, \"card_pan\"],\n [expField, \"card_exp\"],\n [cvcField, \"card_cvc\"],\n ];\n for (const [field, key] of fieldMap) {\n const cb = onFocusChangeCallbacks[key];\n if (cb) {\n field.on(\"focus\", () => cb(true));\n field.on(\"blur\", () => cb(false));\n }\n }\n }\n\n // Return cleanup function to disconnect observers and remove iframes\n return () => {\n for (const observer of observers) {\n observer.disconnect();\n }\n for (const container of containers) {\n const iframes = container.querySelectorAll(\"iframe\");\n for (const iframe of iframes) {\n iframe.remove();\n }\n }\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payment-kit-js/vanilla",
3
- "version": "0.5.8",
3
+ "version": "0.5.10",
4
4
  "main": "./dist/index.mjs",
5
5
  "types": "./dist/index.d.mts",
6
6
  "module": "./dist/index.mjs",
@@ -48,5 +48,5 @@
48
48
  "tsdown": "^0.15.10",
49
49
  "typescript": "^5.9.3"
50
50
  },
51
- "stableVersion": "0.5.8"
51
+ "stableVersion": "0.5.10"
52
52
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"airwallex-apple-pay-adapter-BE15xREr.mjs","names":["paymentRequest: ApplePayJS.ApplePayPaymentRequest","token: ApplePayEncryptedToken"],"sources":["../src/payment-methods/airwallex-apple-pay-adapter.ts"],"sourcesContent":["/**\n * Airwallex Apple Pay Adapter\n *\n * Uses native ApplePaySession API directly (not Stripe.js) to show the payment sheet\n * and extract the encrypted payment token for Airwallex processing.\n *\n * Flow:\n * 1. initialize() - Checks if ApplePaySession is available\n * 2. canMakePayment() - Checks if user can pay with Apple Pay\n * 3. showPaymentSheet() - Shows Apple Pay sheet with merchant validation callback\n *\n * The key difference from Stripe's approach is that we use the native\n * ApplePaySession API and handle merchant validation via Airwallex's\n * payment_session/start API which validates with Apple.\n *\n * Mock scenarios are supported for E2E testing without real Apple Pay.\n */\n\n/// <reference types=\"@types/applepayjs\" />\n\nexport enum AirwallexApplePayMockScenario {\n None = \"none\",\n Success = \"success\",\n Cancelled = \"cancelled\",\n}\n\n// Apple Pay token structure from payment.token\nexport interface ApplePayEncryptedToken {\n paymentData: {\n version?: string;\n data: string;\n signature: string;\n header: {\n ephemeralPublicKey: string;\n publicKeyHash: string;\n transactionId: string;\n };\n };\n paymentMethod: {\n displayName: string;\n network: string;\n type: string;\n };\n transactionIdentifier: string;\n}\n\nexport interface AirwallexApplePayConfig {\n amount: number; // Amount in atomic units (cents)\n currency: string; // e.g., \"USD\"\n country: string; // e.g., \"US\"\n merchantName?: string; // Display name on Apple Pay sheet\n}\n\nexport type AirwallexApplePayShowResult =\n | { success: true; token: ApplePayEncryptedToken; complete: (status: \"success\" | \"fail\") => void }\n | { success: false; cancelled: true }\n | { success: false; error: string };\n\n// Merchant validation callback type - called during onvalidatemerchant\nexport type MerchantValidationCallback = (\n validationUrl: string,\n) => Promise<{ merchantSession?: object; error?: string }>;\n\nexport class AirwallexApplePayAdapter {\n private config: AirwallexApplePayConfig | null = null;\n private mockScenario: AirwallexApplePayMockScenario;\n\n constructor(mockScenario?: AirwallexApplePayMockScenario) {\n this.mockScenario = mockScenario ?? AirwallexApplePayMockScenario.None;\n }\n\n /**\n * Initialize the adapter with payment configuration.\n * Returns true if Apple Pay is available on this device.\n */\n initialize(config: AirwallexApplePayConfig): boolean {\n // Mock scenarios bypass real Apple Pay initialization\n if (this.mockScenario !== AirwallexApplePayMockScenario.None) {\n console.log(\"[MockApplePay:Airwallex] initialize called (mock mode)\");\n this.config = config;\n return true;\n }\n\n // Check if ApplePaySession is available (Safari on iOS/macOS only)\n if (typeof window === \"undefined\" || !window.ApplePaySession) {\n console.error(\"[ApplePay:Airwallex] ApplePaySession not available (not Safari or unsupported device)\");\n return false;\n }\n\n this.config = config;\n return true;\n }\n\n /**\n * Check if the user can make a payment with Apple Pay.\n * Returns true if Apple Pay is set up on this device.\n */\n async canMakePayment(): Promise<boolean> {\n // Mock scenarios always return true\n if (this.mockScenario !== AirwallexApplePayMockScenario.None) {\n console.log(\"[MockApplePay:Airwallex] canMakePayment: true (mock mode)\");\n return true;\n }\n\n if (!window.ApplePaySession) {\n return false;\n }\n\n try {\n const canMake = window.ApplePaySession.canMakePayments();\n console.log(\"[ApplePay:Airwallex] canMakePayments:\", canMake);\n return canMake;\n } catch (error) {\n console.error(\"[ApplePay:Airwallex] canMakePayment error:\", error);\n return false;\n }\n }\n\n /**\n * Convert atomic units (cents) to display format for Apple Pay.\n * Apple Pay expects a string like \"10.00\" for $10.00.\n */\n private formatAmount(amountAtom: number, currency: string): string {\n // Most currencies use 2 decimal places, some like JPY use 0\n const zeroDecimalCurrencies = [\n \"BIF\",\n \"CLP\",\n \"DJF\",\n \"GNF\",\n \"ISK\",\n \"JPY\",\n \"KMF\",\n \"KRW\",\n \"PYG\",\n \"RWF\",\n \"UGX\",\n \"VND\",\n \"VUV\",\n \"XAF\",\n \"XOF\",\n \"XPF\",\n ];\n const isZeroDecimal = zeroDecimalCurrencies.includes(currency.toUpperCase());\n\n if (isZeroDecimal) {\n return amountAtom.toString();\n }\n\n return (amountAtom / 100).toFixed(2);\n }\n\n /**\n * Show the Apple Pay payment sheet and return the encrypted token.\n *\n * This uses the native ApplePaySession API with a two-step flow:\n * 1. onvalidatemerchant - Called by Apple to validate the merchant\n * The callback should call our backend which calls Airwallex's payment_session/start\n * 2. onpaymentauthorized - Called when user authorizes with Face ID/Touch ID\n * Returns the encrypted token for processing\n *\n * @param onMerchantValidation - Callback to validate merchant with backend\n * @returns Promise with token or error\n */\n async showPaymentSheet(onMerchantValidation: MerchantValidationCallback): Promise<AirwallexApplePayShowResult> {\n // Handle mock scenarios\n if (this.mockScenario === AirwallexApplePayMockScenario.Success) {\n console.log(\"[MockApplePay:Airwallex] showPaymentSheet: returning mock success token\");\n const mockToken: ApplePayEncryptedToken = {\n paymentData: {\n version: \"EC_v1\",\n data: \"MOCK_ENCRYPTED_DATA\",\n signature: \"MOCK_SIGNATURE\",\n header: {\n ephemeralPublicKey: \"MOCK_PUBLIC_KEY\",\n publicKeyHash: \"MOCK_HASH\",\n transactionId: \"mock_txn_123\",\n },\n },\n paymentMethod: {\n displayName: \"Visa 4242\",\n network: \"Visa\",\n type: \"debit\",\n },\n transactionIdentifier: \"MOCK_TXN_ID\",\n };\n return {\n success: true,\n token: mockToken,\n complete: (status) => console.log(`[MockApplePay:Airwallex] complete: ${status}`),\n };\n }\n\n if (this.mockScenario === AirwallexApplePayMockScenario.Cancelled) {\n console.log(\"[MockApplePay:Airwallex] showPaymentSheet: returning mock cancelled\");\n return { success: false, cancelled: true };\n }\n\n // Real Apple Pay flow\n if (!this.config) {\n return { success: false, error: \"Apple Pay not initialized\" };\n }\n\n if (!window.ApplePaySession) {\n return { success: false, error: \"ApplePaySession not available\" };\n }\n\n const config = this.config;\n const amount = this.formatAmount(config.amount, config.currency);\n\n // Create the Apple Pay payment request\n const paymentRequest: ApplePayJS.ApplePayPaymentRequest = {\n countryCode: config.country.toUpperCase(),\n currencyCode: config.currency.toUpperCase(),\n supportedNetworks: [\"visa\", \"masterCard\", \"amex\", \"discover\"],\n merchantCapabilities: [\"supports3DS\"],\n total: {\n label: config.merchantName || \"Total\",\n amount: amount,\n type: \"final\",\n },\n };\n\n return new Promise((resolve) => {\n try {\n // Create ApplePaySession (version 3 is widely supported)\n // biome-ignore lint/style/noNonNullAssertion: ApplePaySession is guaranteed to exist (checked in canMakePayments)\n const session = new window.ApplePaySession!(3, paymentRequest);\n\n // Capture status constants at creation time (before optional chaining could yield undefined)\n // biome-ignore lint/style/noNonNullAssertion: ApplePaySession existence verified above\n const STATUS_SUCCESS = window.ApplePaySession!.STATUS_SUCCESS;\n // biome-ignore lint/style/noNonNullAssertion: ApplePaySession existence verified above\n const STATUS_FAILURE = window.ApplePaySession!.STATUS_FAILURE;\n\n // Handle merchant validation\n session.onvalidatemerchant = async (event: ApplePayJS.ApplePayValidateMerchantEvent) => {\n console.log(\"[ApplePay:Airwallex] onvalidatemerchant called\", event.validationURL);\n\n try {\n const validationResult = await onMerchantValidation(event.validationURL);\n\n if (validationResult.error || !validationResult.merchantSession) {\n console.error(\"[ApplePay:Airwallex] Merchant validation failed:\", validationResult.error);\n session.abort();\n resolve({\n success: false,\n error: validationResult.error || \"Merchant validation failed\",\n });\n return;\n }\n\n // Complete merchant validation with the session from Apple\n session.completeMerchantValidation(validationResult.merchantSession);\n console.log(\"[ApplePay:Airwallex] Merchant validation completed\");\n } catch (error) {\n console.error(\"[ApplePay:Airwallex] Merchant validation error:\", error);\n session.abort();\n resolve({\n success: false,\n error: `Merchant validation error: ${error}`,\n });\n }\n };\n\n // Handle payment authorization (user approved with Face ID/Touch ID)\n session.onpaymentauthorized = (event: ApplePayJS.ApplePayPaymentAuthorizedEvent) => {\n console.log(\"[ApplePay:Airwallex] onpaymentauthorized called\");\n\n // Extract the encrypted token\n const payment = event.payment;\n const token: ApplePayEncryptedToken = {\n paymentData: payment.token.paymentData as ApplePayEncryptedToken[\"paymentData\"],\n paymentMethod: {\n displayName: payment.token.paymentMethod.displayName,\n network: payment.token.paymentMethod.network,\n type: payment.token.paymentMethod.type,\n },\n transactionIdentifier: payment.token.transactionIdentifier,\n };\n\n // Create the complete callback that the caller will use after confirming\n const complete = (status: \"success\" | \"fail\") => {\n console.log(\"[ApplePay:Airwallex] completing session with status:\", status);\n const appleStatus = status === \"success\" ? STATUS_SUCCESS : STATUS_FAILURE;\n session.completePayment({ status: appleStatus });\n };\n\n resolve({\n success: true,\n token,\n complete,\n });\n };\n\n // Handle cancellation\n session.oncancel = () => {\n console.log(\"[ApplePay:Airwallex] oncancel - user cancelled\");\n resolve({ success: false, cancelled: true });\n };\n\n // Start the session - this shows the Apple Pay sheet\n console.log(\"[ApplePay:Airwallex] Starting Apple Pay session\");\n session.begin();\n } catch (error) {\n console.error(\"[ApplePay:Airwallex] Session creation error:\", error);\n resolve({\n success: false,\n error: `Failed to create Apple Pay session: ${error}`,\n });\n }\n });\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"airwallex-apple-pay-adapter-I_pnNYdy.d.mts","names":[],"sources":["../src/payment-methods/airwallex-apple-pay-adapter.ts"],"sourcesContent":[],"mappings":";;AAoBA;AAOA;AAmBA;AAOA;AAMA;AAIA;;;;;;;;;;;aA3CY,6BAAA;;;;;UAOK,sBAAA;;;;;;;;;;;;;;;;;;UAmBA,uBAAA;;;;;;KAOL,2BAAA;;SACgB;;;;;;;;;KAKhB,0BAAA,8BAEP;;;;cAEQ,wBAAA;;;6BAIgB;;;;;qBAQR;;;;;oBAsBK;;;;;;;;;;;;;;;;;;yCAkEqB,6BAA6B,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"stripe-google-pay-adapter-C3NCBSO3.d.mts","names":[],"sources":["../src/payment-methods/stripe-google-pay-adapter.ts"],"sourcesContent":[],"mappings":";;;;;IAAqH,MAAA,CAAA,EAKxG,iBALwG;EAAA;;AAKvF,UAIb,oBAAA,CAJa;EAAA,OAAA,EAAA,MAAA;EAIb,QAAA,EAAA,MAAA;EAQL,KAAA,EAAA;IAKA,KAAA,EAAA,MAAa;IAEb,MAAA,EAAA,MAAA;EAMC,CAAA;EAKgB,gBAAA,EAAA,OAAA;EA0BE,iBAAA,EAAA,OAAA;;AAyCK,KArFxB,sBAAA,GAqFwB;EAAR,OAAA,EAAA,IAAA;EAqDqD,eAAA,EAAA,MAAA;EAAR,QAAA,EAAA,CAAA,MAAA,EAAA,SAAA,GAAA,MAAA,EAAA,GAAA,IAAA;CAAO,GAAA;;;;;;;KArIpE,aAAA;;;;;;aAEA,qBAAA;;;;;cAMC,sBAAA;;;;6BAKgB;;+BA0BE;oBAmBL;sBAsBE,QAAQ;mEAqDqC,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"stripe-google-pay-adapter-CqcUEoM3.mjs","names":[],"sources":["../src/payment-methods/stripe-google-pay-adapter.ts"],"sourcesContent":["import type { PaymentRequest, PaymentRequestPaymentMethodEvent, Stripe, StripeConstructor } from \"@stripe/stripe-js\";\n\n// Stripe.js must be loaded via script tag for PCI compliance\ndeclare global {\n interface Window {\n Stripe?: StripeConstructor;\n }\n}\n\nexport interface PaymentRequestConfig {\n country: string;\n currency: string;\n total: { label: string; amount: number };\n requestPayerName: boolean;\n requestPayerEmail: boolean;\n}\n\nexport type ShowPaymentSheetResult =\n | { success: true; paymentMethodId: string; complete: (status: \"success\" | \"fail\") => void }\n | { success: false; cancelled: true }\n | { success: false; error: string };\n\nexport type ConfirmResult = { success: true } | { success: false; error: string };\n\nexport enum GooglePayMockScenario {\n None = \"none\",\n Success = \"success\",\n Cancelled = \"cancelled\",\n}\n\nexport class StripeGooglePayAdapter {\n private stripe: Stripe | null = null;\n private paymentRequest: PaymentRequest | null = null;\n private mockScenario: GooglePayMockScenario;\n\n constructor(mockScenario?: GooglePayMockScenario) {\n this.mockScenario = mockScenario ?? GooglePayMockScenario.None;\n }\n\n initialize(publishableKey: string): boolean {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] initialize called\");\n if (!window.Stripe) {\n console.log(\"[GooglePay] Stripe.js not loaded\");\n return false;\n }\n this.stripe = window.Stripe(publishableKey);\n const success = this.stripe !== null;\n console.log(\"[GooglePay] initialize result:\", success);\n return success;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] initialize called\");\n console.log(\"[MockGooglePay] initialize result:\", true);\n return true;\n }\n }\n }\n\n createPaymentRequest(config: PaymentRequestConfig): void {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] createPaymentRequest called\", config);\n if (!this.stripe) {\n throw new Error(\"Stripe not initialized\");\n }\n this.paymentRequest = this.stripe.paymentRequest(config);\n console.log(\"[GooglePay] paymentRequest created\");\n return;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] createPaymentRequest called\", config);\n return;\n }\n }\n }\n\n async canMakePayment(): Promise<boolean> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] canMakePayment called\");\n if (!this.paymentRequest) {\n console.log(\"[GooglePay] canMakePayment: no paymentRequest\");\n return false;\n }\n const result = await this.paymentRequest.canMakePayment();\n const isAvailable = result?.googlePay ?? false;\n console.log(\"[GooglePay] canMakePayment result:\", { result, isAvailable });\n return isAvailable;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] canMakePayment called\");\n console.log(\"[MockGooglePay] canMakePayment result:\", { result: { googlePay: true }, isAvailable: true });\n return true;\n }\n }\n }\n\n async showPaymentSheet(): Promise<ShowPaymentSheetResult> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] showPaymentSheet called\");\n if (!this.paymentRequest) {\n console.log(\"[GooglePay] showPaymentSheet: no paymentRequest\");\n return { success: false, error: \"Payment request not created\" };\n }\n\n return new Promise((resolve) => {\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.on(\"paymentmethod\", (event: PaymentRequestPaymentMethodEvent) => {\n console.log(\"[GooglePay] showPaymentSheet: paymentmethod event\", {\n paymentMethodId: event.paymentMethod.id,\n });\n resolve({\n success: true,\n paymentMethodId: event.paymentMethod.id,\n complete: (status) => {\n console.log(\"[GooglePay] complete called:\", status);\n event.complete(status);\n },\n });\n });\n\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.on(\"cancel\", () => {\n console.log(\"[GooglePay] showPaymentSheet: cancelled by user\");\n resolve({ success: false, cancelled: true });\n });\n\n console.log(\"[GooglePay] showing payment sheet...\");\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.show();\n });\n }\n case GooglePayMockScenario.Success: {\n console.log(\"[MockGooglePay] showPaymentSheet: success\");\n await new Promise((resolve) => setTimeout(resolve, 500));\n return {\n success: true,\n paymentMethodId: \"pm_mock_123456789\",\n complete: (status) => console.log(`[MockGooglePay] complete: ${status}`),\n };\n }\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] showPaymentSheet: cancelled\");\n await new Promise((resolve) => setTimeout(resolve, 500));\n return { success: false, cancelled: true };\n }\n }\n }\n\n async confirmCardSetup(clientSecret: string, paymentMethodId: string): Promise<ConfirmResult> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] confirmCardSetup called\", {\n clientSecret: `${clientSecret.slice(0, 20)}...`,\n paymentMethodId,\n });\n if (!this.stripe) {\n console.log(\"[GooglePay] confirmCardSetup: Stripe not initialized\");\n return { success: false, error: \"Stripe not initialized\" };\n }\n\n const { error } = await this.stripe.confirmCardSetup(clientSecret, {\n payment_method: paymentMethodId,\n });\n\n if (error) {\n console.log(\"[GooglePay] confirmCardSetup error:\", error);\n return { success: false, error: error.message ?? \"Card setup failed\" };\n }\n\n console.log(\"[GooglePay] confirmCardSetup success\");\n return { success: true };\n }\n case GooglePayMockScenario.Success: {\n console.log(\"[MockGooglePay] confirmCardSetup called\", { clientSecret, paymentMethodId });\n return { success: true };\n }\n case GooglePayMockScenario.Cancelled: {\n throw new Error(\"confirmCardSetup should not be called when scenario is Cancelled\");\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"vgs-collect-loader-3Z4IWCA6.mjs","names":["loadPromise: Promise<void> | null","fieldMap: [VGSCollectField, string][]"],"sources":["../src/payment-methods/vgs-collect-loader.ts"],"sourcesContent":["const VGS_COLLECT_CDN = \"https://js.verygoodvault.com/vgs-collect/3.2.1/vgs-collect.js\";\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads VGS Collect JS from CDN. Idempotent — subsequent calls return the same promise.\n */\nexport function loadVgsCollectScript(): Promise<void> {\n if (loadPromise) {\n console.log(\"[PaymentKit] VGS Collect CDN load already in progress — reusing promise\");\n return loadPromise;\n }\n\n loadPromise = new Promise<void>((resolve, reject) => {\n if (typeof window !== \"undefined\" && window.VGSCollect) {\n console.log(\"[PaymentKit] VGS Collect JS already available on window\");\n resolve();\n return;\n }\n\n console.log(`[PaymentKit] Loading VGS Collect JS from CDN: ${VGS_COLLECT_CDN}`);\n const script = document.createElement(\"script\");\n script.src = VGS_COLLECT_CDN;\n script.async = true;\n script.onload = () => {\n console.log(\"[PaymentKit] VGS Collect JS loaded successfully from CDN\");\n resolve();\n };\n script.onerror = () => {\n console.error(`[PaymentKit] Failed to load VGS Collect JS from CDN: ${VGS_COLLECT_CDN}`);\n loadPromise = null;\n reject(new Error(\"Failed to load VGS Collect JS\"));\n };\n document.head.appendChild(script);\n });\n\n return loadPromise;\n}\n\n/**\n * Initializes a VGS Collect form instance.\n */\nexport function initVgsCollect(vaultId: string, environment: string): VGSCollectForm {\n if (!window.VGSCollect) {\n throw new Error(\"VGS Collect JS not loaded. Call loadVgsCollectScript() first.\");\n }\n return window.VGSCollect.create(vaultId, environment, () => {});\n}\n\n/**\n * Creates and mounts VGS Collect card fields using CMP-specific field methods.\n *\n * Uses cardNumberField(), cardExpirationDateField(), cardCVCField() which are\n * required for the CMP createCard() flow. After mounting, call form.createCard()\n * to create a card in the VGS vault, which returns aliases for PAN and CVC.\n *\n * @param form - VGS Collect form instance\n * @param mountPoints - CSS selectors for PAN, expiry, and CVC containers\n * @param css - Optional CSS to apply to VGS Collect iframe fields\n */\nexport function createVgsCardFields(\n form: VGSCollectForm,\n mountPoints: { pan: string; exp: string; cvc: string },\n css?: Record<string, string>,\n onFocusChangeCallbacks?: Partial<Record<string, (isFocused: boolean) => void>>,\n placeholders?: Partial<Record<string, string>>,\n) {\n // Read container padding so the VGS input content matches the merchant's\n // visual intent. The iframe uses absolute positioning (inset: 0) to fill\n // the full container, so the input needs its own padding for alignment.\n const sampleContainer = document.querySelector(mountPoints.pan) as HTMLElement | null;\n const containerPadding = sampleContainer ? getComputedStyle(sampleContainer).padding : undefined;\n\n const baseCss = css ?? {\n \"font-size\": \"1rem\",\n color: \"#18181b\",\n \"font-family\": \"ui-sans-serif, system-ui, sans-serif\",\n };\n\n const fieldCss = {\n ...baseCss,\n height: \"100%\",\n \"box-sizing\": \"border-box\",\n ...(containerPadding && containerPadding !== \"0px\" ? { padding: containerPadding } : {}),\n };\n\n const panField = form.cardNumberField(mountPoints.pan, {\n placeholder: placeholders?.card_pan ?? \"Card number\",\n validations: [\"required\", \"validCardNumber\"],\n css: fieldCss,\n });\n\n const expField = form.field(mountPoints.exp, {\n type: \"card-expiration-date\",\n name: \"exp-date\",\n placeholder: placeholders?.card_exp ?? \"MM / YY\",\n yearLength: 2,\n serializers: [{ name: \"separate\", options: { monthName: \"month\", yearName: \"year\" } }],\n validations: [\"required\", \"validCardExpirationDate\"],\n css: fieldCss,\n });\n\n const cvcField = form.cardCVCField(mountPoints.cvc, {\n placeholder: placeholders?.card_cvc ?? \"123\",\n validations: [\"required\", \"validCardSecurityCode\"],\n css: fieldCss,\n });\n\n // VGS Collect doesn't set width/height on its iframes, so they may not\n // fill the merchant's container. Force them to stretch like direct-mode iframes.\n // Iframes may be inserted asynchronously, so use MutationObserver as a fallback.\n for (const selector of [mountPoints.pan, mountPoints.exp, mountPoints.cvc]) {\n const container = document.querySelector(selector);\n if (!container) continue;\n\n const styleIframe = (iframe: HTMLIFrameElement) => {\n // Use absolute positioning so the iframe covers the full container\n // including any padding the merchant's CSS applies.\n const containerEl = container as HTMLElement;\n if (getComputedStyle(containerEl).position === \"static\") {\n containerEl.style.position = \"relative\";\n }\n iframe.style.position = \"absolute\";\n iframe.style.inset = \"0\";\n iframe.style.width = \"100%\";\n iframe.style.height = \"100%\";\n iframe.style.border = \"none\";\n };\n\n const existing = container.querySelector(\"iframe\") as HTMLIFrameElement | null;\n if (existing) {\n styleIframe(existing);\n } else {\n const observer = new MutationObserver((_, obs) => {\n const iframe = container.querySelector(\"iframe\") as HTMLIFrameElement | null;\n if (iframe) {\n styleIframe(iframe);\n obs.disconnect();\n }\n });\n observer.observe(container, { childList: true, subtree: true });\n }\n }\n\n if (onFocusChangeCallbacks) {\n const fieldMap: [VGSCollectField, string][] = [\n [panField, \"card_pan\"],\n [expField, \"card_exp\"],\n [cvcField, \"card_cvc\"],\n ];\n for (const [field, key] of fieldMap) {\n const cb = onFocusChangeCallbacks[key];\n if (cb) {\n field.on(\"focus\", () => cb(true));\n field.on(\"blur\", () => cb(false));\n }\n }\n }\n}\n"],"mappings":"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"}