{"version":3,"file":"google-pay.mjs","names":["airwallexMockScenario: AirwallexGooglePayMockScenario","config: AirwallexGooglePayConfig","requestBody: GooglePayConfirmRequest","submitPayment: TInternalFuncs[\"submitPayment\"]","effectiveOptions: GooglePaySubmitOptions","autoPrepareConfig: AutoPrepareConfig | null","onGooglePayReadyCallbacks: ((isReady: boolean) => void)[]","pendingAutoPrepareArgs: { apiBaseUrl: string; secureToken: string; environment: string } | null","pendingPrepareResolvers: (() => void)[]"],"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  /** Processor external ID — optional when using auto-prepare (SDK fetches from checkout session) */\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(\n  options: GooglePaySubmitOptions,\n  autoPrepareConfig: AutoPrepareConfig | null,\n): PaymentKitErrors | null {\n  // processorId is optional when autoPrepareConfig provides it\n  if (!options?.processorId && !autoPrepareConfig?.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\n// =============================================================================\n// Auto-Prepare Types\n// =============================================================================\n\ntype CheckoutSessionConfig = {\n  express_checkout_processor_id?: string | null;\n  express_checkout_processor_type?: string | null;\n};\n\ntype AutoPrepareConfig = {\n  processorId: string;\n  processorType?: \"stripe\" | \"airwallex\";\n};\n\n/**\n * Check if Google Pay is available on this device/browser.\n * Uses the Google Pay API's isReadyToPay() method.\n */\nasync function checkGooglePayAvailability(): Promise<boolean> {\n  // Check if Google Pay API is loaded\n  if (!window.google?.payments?.api?.PaymentsClient) {\n    console.log(\"[GooglePay] Google Pay API not loaded\");\n    return false;\n  }\n\n  try {\n    // Per Google Pay docs, TEST mode is appropriate for isReadyToPay() availability checks.\n    // The actual payment flow uses the production environment configured in submit().\n    const client = new window.google.payments.api.PaymentsClient({\n      environment: \"TEST\",\n    });\n\n    const request = {\n      apiVersion: 2,\n      apiVersionMinor: 0,\n      allowedPaymentMethods: [\n        {\n          type: \"CARD\" as const,\n          parameters: {\n            allowedAuthMethods: [\"PAN_ONLY\", \"CRYPTOGRAM_3DS\"] as (\"PAN_ONLY\" | \"CRYPTOGRAM_3DS\")[],\n            allowedCardNetworks: [\"VISA\", \"MASTERCARD\", \"AMEX\", \"DISCOVER\", \"JCB\"] as (\n              | \"VISA\"\n              | \"MASTERCARD\"\n              | \"AMEX\"\n              | \"DISCOVER\"\n              | \"JCB\"\n            )[],\n          },\n        },\n      ],\n    };\n\n    const response = await client.isReadyToPay(request);\n    return response.result;\n  } catch (error) {\n    console.error(\"[GooglePay] availability check error:\", error);\n    return false;\n  }\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; payerEmail?: string; 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 and payer email for passing to backend\n  return { success: true, token: paymentResult.token, payerEmail: paymentResult.payerEmail };\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  payerEmail?: string,\n): Promise<GooglePayResult> {\n  let userActionCount = 0;\n\n  // Step 1: Initial confirm with token\n  let response = await callConfirmEndpoint(\n    apiBaseUrl,\n    secureToken,\n    googlePayToken,\n    mockScenarioStr,\n    checkoutRequestId,\n    payerEmail,\n  );\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, getAutoPrepareConfig: () => AutoPrepareConfig | null) => {\n  const submitPayment: TInternalFuncs[\"submitPayment\"] = async (_fields, options) => {\n    const { apiBaseUrl, secureToken, environment } = states;\n    const gpayOptions = options as GooglePaySubmitOptions;\n    const autoPrepareConfig = getAutoPrepareConfig();\n\n    // Validate options\n    const validationError = validateOptions(gpayOptions, autoPrepareConfig);\n    if (validationError) {\n      return { errors: validationError };\n    }\n\n    // Use autoPrepareConfig as fallback for processorId\n    const effectiveOptions: GooglePaySubmitOptions = {\n      ...gpayOptions,\n      processorId: gpayOptions.processorId || autoPrepareConfig?.processorId || \"\",\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        effectiveOptions,\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          airwallexResult.payerEmail,\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  const { apiBaseUrl, secureToken, environment } = paymentKitStates;\n\n  // Per-instance auto-prepare state — isolated from other GooglePayPaymentMethod instances.\n  let autoPrepareConfig: AutoPrepareConfig | null = null;\n  let onGooglePayReadyCallbacks: ((isReady: boolean) => void)[] = [];\n  let isGooglePayReadyState = false;\n  let autoPrepareInProgress = false;\n  // Incremented by cleanup() so that in-flight prepares can detect staleness and skip writes.\n  let cleanupGeneration = 0;\n  // Stores pending retry args when notifyAmountChanged is called while a prepare is in flight.\n  let pendingAutoPrepareArgs: { apiBaseUrl: string; secureToken: string; environment: string } | null = null;\n  // Resolvers waiting for a queued retry to complete (for correct notifyAmountChanged await).\n  let pendingPrepareResolvers: (() => void)[] = [];\n\n  function instanceSetGooglePayReady(ready: boolean): void {\n    isGooglePayReadyState = ready;\n    for (const cb of onGooglePayReadyCallbacks) cb(ready);\n  }\n\n  function instanceClearPreparedGooglePay(): void {\n    instanceSetGooglePayReady(false);\n  }\n\n  async function instanceAutoPrepare(apBase: string, sToken: string, env: string): Promise<void> {\n    if (autoPrepareInProgress) {\n      // A prepare is already in flight; queue a retry and return a promise that resolves after it.\n      pendingAutoPrepareArgs = { apiBaseUrl: apBase, secureToken: sToken, environment: env };\n      return new Promise<void>((resolve) => pendingPrepareResolvers.push(resolve));\n    }\n    autoPrepareInProgress = true;\n    // Capture generation so we can detect if cleanup() is called while we await.\n    const capturedGeneration = cleanupGeneration;\n    instanceSetGooglePayReady(false);\n\n    try {\n      const result = await apiCall<CheckoutSessionConfig>(`${apBase}/api/checkout-sessions/token/${sToken}`, {\n        method: \"GET\",\n      });\n\n      if (cleanupGeneration !== capturedGeneration) return;\n\n      if (result.error || !result.data) {\n        console.warn(\"[GooglePay] Auto-prepare: failed to fetch session config:\", result.error);\n        return;\n      }\n\n      const processorId = result.data.express_checkout_processor_id;\n      if (!processorId) {\n        console.log(\"[GooglePay] Auto-prepare: no express checkout processor configured\");\n        return;\n      }\n\n      const processorTypeRaw = result.data.express_checkout_processor_type;\n      const processorType =\n        processorTypeRaw === \"airwallex\" || processorTypeRaw === \"stripe\" ? processorTypeRaw : undefined;\n\n      autoPrepareConfig = { processorId, processorType };\n\n      const isAvailable = await checkGooglePayAvailability();\n\n      if (cleanupGeneration !== capturedGeneration) return;\n\n      instanceSetGooglePayReady(isAvailable);\n    } catch (err) {\n      if (cleanupGeneration === capturedGeneration) {\n        console.error(\"[GooglePay] Auto-prepare failed:\", err);\n      }\n    } finally {\n      autoPrepareInProgress = false;\n      const stale = cleanupGeneration !== capturedGeneration;\n      const pending = pendingAutoPrepareArgs;\n      const resolvers = pendingPrepareResolvers.splice(0);\n      if (!stale && pending) {\n        pendingAutoPrepareArgs = null;\n        // Run the retry and resolve all callers that were waiting for it.\n        instanceAutoPrepare(pending.apiBaseUrl, pending.secureToken, pending.environment).then(() => {\n          for (const r of resolvers) r();\n        });\n      } else {\n        pendingAutoPrepareArgs = null;\n        for (const r of resolvers) r();\n      }\n    }\n  }\n\n  // Start auto-prepare immediately so the button is ready before first user interaction.\n  instanceAutoPrepare(apiBaseUrl, secureToken, environment).catch((err) =>\n    console.error(\"[GooglePay] Unhandled init error:\", err),\n  );\n\n  return {\n    name: \"google_pay\",\n    externalFuncs: {\n      /**\n       * Register a callback to be notified when Google Pay becomes ready (or stops being ready).\n       * Fires immediately with the current state, then on every state change.\n       * Multiple registrations are all notified — none are silently overwritten.\n       *\n       * @example\n       * paymentKit.google_pay.onGooglePayReady((isReady) => {\n       *   googlePayButton.disabled = !isReady;\n       * });\n       */\n      onGooglePayReady: (callback: (isReady: boolean) => void): void => {\n        onGooglePayReadyCallbacks.push(callback);\n        // Fire immediately with current state so caller doesn't miss a completed prepare.\n        callback(isGooglePayReadyState);\n      },\n\n      /**\n       * Notify the SDK that the payment amount has changed (e.g. coupon applied).\n       * The SDK will disable Google Pay, re-prepare with the new amount, then re-enable.\n       * The returned promise resolves when re-prepare is fully complete.\n       *\n       * @example\n       * await paymentKit.google_pay.notifyAmountChanged();\n       */\n      notifyAmountChanged: (): Promise<void> => {\n        instanceClearPreparedGooglePay();\n        autoPrepareConfig = null;\n        return instanceAutoPrepare(apiBaseUrl, secureToken, environment);\n      },\n    },\n    internalFuncs: {\n      submitPayment: defSubmitPayment(paymentKitStates, () => autoPrepareConfig),\n      cleanup: () => {\n        cleanupGeneration++;\n        onGooglePayReadyCallbacks = [];\n        isGooglePayReadyState = false;\n        autoPrepareConfig = null;\n        pendingAutoPrepareArgs = null;\n        pendingPrepareResolvers = [];\n        autoPrepareInProgress = false;\n      },\n    },\n  };\n});\n\nexport { GooglePayMockScenario };\n\nexport default GooglePayPaymentMethod;\n"],"mappings":"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"}