{"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          iframe.remove();\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\n/**\n * Terminal failure states for a card checkout. Mirrors the backend checkout-attempt state machine\n * (app/modules/checkout/checkout_attempt/checkout_attempt_state_machine.py — the only terminal\n * success state is `checkout_succeeded`). A checkout in one of these states must be surfaced to the\n * merchant as an error so `onError` — not `onSuccess` — fires.\n *\n * Note: 3DS authentication *passing* does NOT imply the charge succeeded — a pass-then-decline\n * concludes with `payment_failed` and no further `nextAction`. Other non-terminal states (e.g.\n * `payment_started` from an async \"pending\" charge that carries no `nextAction`) are intentionally\n * left to the success/data path here, preserving existing behavior for the non-3DS flow.\n */\nconst CHECKOUT_FAILURE_STATES = new Set([\"payment_failed\", \"checkout_failed\"]);\n\nconst isCheckoutFailure = (result: CheckoutResponse): boolean => CHECKOUT_FAILURE_STATES.has(result.state);\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\n      ? { isSuccess: true as const, errors: {} as PaymentKitErrors }\n      : 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    // Include processor_fraud_info with airwallex_device_id for fraud fingerprinting\n    const fraudMetadata = {\n      ...collectFraudMetadata(),\n      processorFraudInfo: {\n        airwallexDeviceId: states.checkoutRequestId,\n      },\n    };\n    let currentResult = await tunnelX.publicEndpoints.cardCheckout(\n      {\n        checkoutToken: states.secureToken,\n        publicCardCheckoutRequest: {\n          cardSetupIntentId: states.cardSetupIntentId,\n          customerInfo: mapFieldsToCustomerInfo(fields),\n          fraudMetadata,\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      // 3DS auth passed AND no further action — but the charge may still have been declined.\n      // Gate the success return on the checkout state so a pass-then-decline\n      // (state=payment_failed) reports onError instead of a false onSuccess.\n      if (isCheckoutFailure(verifyResult)) {\n        console.log(\"Card checkout concluded in a failure state after 3DS:\", verifyResult);\n        timingTracker.trackFail(\n          verifyResult.checkoutAttemptId || null,\n          verifyResult.errorCode || \"payment_failed\",\n          verifyResult.errorMessageForCustomer || \"Payment failed\",\n        );\n        return {\n          errors: {\n            root: verifyResult.errorMessageForCustomer || \"Payment failed\",\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 (isCheckoutFailure(currentResult)) {\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\n  if (!cvc_alias) {\n    console.warn(\n      `${logPrefix} VGS createCard response missing cvc_alias (303 dedup):`,\n      JSON.stringify(cardResult.data.attributes),\n    );\n  }\n\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        ...(cvc_alias ? { 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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"}