{"version":3,"file":"airwallex-google-pay-adapter-BvlROwj_.mjs","names":["baseMethod: AllowedPaymentMethod","request: IsReadyToPayRequest","request: PaymentDataRequest"],"sources":["../src/payment-methods/airwallex-google-pay-adapter.ts"],"sourcesContent":["/**\n * Airwallex Google Pay Adapter\n *\n * Uses Google Pay 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 Google Pay API is available\n * 2. createPaymentDataRequest() - Configures the payment request\n * 3. canMakePayment() - Checks if user can pay with Google Pay\n * 4. showPaymentSheet() - Shows Google Pay sheet and returns encrypted token\n *\n * Mock scenarios are supported for E2E testing without real Google Pay.\n */\n\nexport enum AirwallexGooglePayMockScenario {\n  None = \"none\",\n  Success = \"success\",\n  Cancelled = \"cancelled\",\n}\n\n// Google Pay API types\n// See: https://developers.google.com/pay/api/web/reference/request-objects\ndeclare global {\n  interface Window {\n    google?: {\n      payments: {\n        api: {\n          PaymentsClient: new (config: GooglePayClientConfig) => GooglePaymentsClient;\n        };\n      };\n    };\n  }\n}\n\ninterface GooglePayClientConfig {\n  environment: \"TEST\" | \"PRODUCTION\";\n}\n\ninterface GooglePaymentsClient {\n  isReadyToPay(request: IsReadyToPayRequest): Promise<IsReadyToPayResponse>;\n  loadPaymentData(request: PaymentDataRequest): Promise<PaymentData>;\n}\n\ninterface IsReadyToPayRequest {\n  apiVersion: number;\n  apiVersionMinor: number;\n  allowedPaymentMethods: AllowedPaymentMethod[];\n}\n\ninterface IsReadyToPayResponse {\n  result: boolean;\n}\n\ninterface AllowedPaymentMethod {\n  type: \"CARD\";\n  parameters: {\n    allowedAuthMethods: (\"PAN_ONLY\" | \"CRYPTOGRAM_3DS\")[];\n    allowedCardNetworks: (\"VISA\" | \"MASTERCARD\" | \"AMEX\" | \"DISCOVER\" | \"JCB\")[];\n  };\n  tokenizationSpecification?: TokenizationSpecification;\n}\n\ninterface TokenizationSpecification {\n  type: \"PAYMENT_GATEWAY\";\n  parameters: {\n    gateway: string;\n    gatewayMerchantId: string;\n  };\n}\n\ninterface PaymentDataRequest extends IsReadyToPayRequest {\n  merchantInfo: {\n    merchantId?: string;\n    merchantName: string;\n  };\n  transactionInfo: {\n    totalPriceStatus: \"FINAL\" | \"ESTIMATED\";\n    totalPrice: string;\n    currencyCode: string;\n    countryCode: string;\n  };\n  emailRequired?: boolean;\n}\n\ninterface PaymentData {\n  email?: string;\n  paymentMethodData: {\n    type: string;\n    tokenizationData: {\n      type: string;\n      token: string; // JSON string containing the encrypted payment token\n    };\n    info?: {\n      cardNetwork: string;\n      cardDetails: string;\n    };\n  };\n}\n\n// Google Pay encrypted token structure (what's inside tokenizationData.token)\nexport interface GooglePayEncryptedToken {\n  protocolVersion: string;\n  signature: string;\n  intermediateSigningKey: {\n    signedKey: string;\n    signatures: string[];\n  };\n  signedMessage: string;\n}\n\nexport interface AirwallexGooglePayConfig {\n  merchantId: string; // Business name for display\n  gatewayMerchantId: string; // Airwallex account ID (acct_xxxx)\n  amountDisplay: string; // Formatted amount for Google Pay (e.g., \"100.00\" for USD, \"1000\" for JPY)\n  currency: string; // e.g., \"usd\"\n  country: string; // e.g., \"US\"\n  isProduction?: boolean; // Default: false (TEST environment)\n  googleMerchantId?: string; // Google-assigned merchant ID for production (BCR2DN...)\n}\n\nexport type AirwallexShowPaymentResult =\n  | { success: true; token: GooglePayEncryptedToken; payerEmail?: string }\n  | { success: false; cancelled: true }\n  | { success: false; error: string };\n\nexport class AirwallexGooglePayAdapter {\n  private client: GooglePaymentsClient | null = null;\n  private config: AirwallexGooglePayConfig | null = null;\n  private mockScenario: AirwallexGooglePayMockScenario;\n\n  constructor(mockScenario?: AirwallexGooglePayMockScenario) {\n    this.mockScenario = mockScenario ?? AirwallexGooglePayMockScenario.None;\n  }\n\n  /**\n   * Initialize the Google Pay client.\n   * Returns true if Google Pay API is available.\n   */\n  initialize(config: AirwallexGooglePayConfig): boolean {\n    // Mock scenarios bypass real Google Pay initialization\n    if (this.mockScenario !== AirwallexGooglePayMockScenario.None) {\n      console.log(\"[MockGooglePay:Airwallex] initialize called (mock mode)\");\n      this.config = config;\n      return true;\n    }\n\n    if (!window.google?.payments?.api?.PaymentsClient) {\n      console.error(\"[GooglePay:Airwallex] Google Pay API not loaded\");\n      return false;\n    }\n\n    this.config = config;\n    this.client = new window.google.payments.api.PaymentsClient({\n      environment: config.isProduction ? \"PRODUCTION\" : \"TEST\",\n    });\n\n    return this.client !== null;\n  }\n\n  /**\n   * Build the allowed payment methods configuration for Google Pay.\n   */\n  private getAllowedPaymentMethods(includeTokenization: boolean): AllowedPaymentMethod[] {\n    if (!this.config) {\n      throw new Error(\"Config not set. Call initialize() first.\");\n    }\n\n    const baseMethod: AllowedPaymentMethod = {\n      type: \"CARD\",\n      parameters: {\n        allowedAuthMethods: [\"PAN_ONLY\", \"CRYPTOGRAM_3DS\"],\n        allowedCardNetworks: [\"VISA\", \"MASTERCARD\", \"AMEX\", \"DISCOVER\", \"JCB\"],\n      },\n    };\n\n    if (includeTokenization) {\n      baseMethod.tokenizationSpecification = {\n        type: \"PAYMENT_GATEWAY\",\n        parameters: {\n          gateway: \"airwallex\",\n          gatewayMerchantId: this.config.gatewayMerchantId,\n        },\n      };\n    }\n\n    return [baseMethod];\n  }\n\n  /**\n   * Check if the user can make a payment with Google Pay.\n   */\n  async canMakePayment(): Promise<boolean> {\n    // Mock scenarios always return true\n    if (this.mockScenario !== AirwallexGooglePayMockScenario.None) {\n      console.log(\"[MockGooglePay:Airwallex] canMakePayment: true (mock mode)\");\n      return true;\n    }\n\n    if (!this.client) {\n      return false;\n    }\n\n    try {\n      const request: IsReadyToPayRequest = {\n        apiVersion: 2,\n        apiVersionMinor: 0,\n        allowedPaymentMethods: this.getAllowedPaymentMethods(false),\n      };\n\n      const response = await this.client.isReadyToPay(request);\n      return response.result;\n    } catch (error) {\n      console.error(\"[GooglePay:Airwallex] canMakePayment error:\", error);\n      return false;\n    }\n  }\n\n  /**\n   * Show the Google Pay payment sheet and return the encrypted token.\n   */\n  async showPaymentSheet(): Promise<AirwallexShowPaymentResult> {\n    // Handle mock scenarios\n    if (this.mockScenario === AirwallexGooglePayMockScenario.Success) {\n      console.log(\"[MockGooglePay:Airwallex] showPaymentSheet: returning mock success token\");\n      // Return a mock token that the backend will recognize as mock\n      const mockToken: GooglePayEncryptedToken = {\n        protocolVersion: \"ECv2\",\n        signature: \"MOCK_SIGNATURE\",\n        intermediateSigningKey: {\n          signedKey: \"MOCK_SIGNED_KEY\",\n          signatures: [\"MOCK_SIGNATURE\"],\n        },\n        signedMessage: \"MOCK_SIGNED_MESSAGE\",\n      };\n      return { success: true, token: mockToken, payerEmail: \"mock@example.com\" };\n    }\n\n    if (this.mockScenario === AirwallexGooglePayMockScenario.Cancelled) {\n      console.log(\"[MockGooglePay:Airwallex] showPaymentSheet: returning mock cancelled\");\n      return { success: false, cancelled: true };\n    }\n\n    // Real Google Pay flow\n    if (!this.client || !this.config) {\n      return { success: false, error: \"Google Pay not initialized\" };\n    }\n\n    try {\n      const totalPrice = this.config.amountDisplay;\n\n      const request: PaymentDataRequest = {\n        apiVersion: 2,\n        apiVersionMinor: 0,\n        allowedPaymentMethods: this.getAllowedPaymentMethods(true),\n        merchantInfo: {\n          merchantName: this.config.merchantId,\n          // merchantId is required in PRODUCTION environment\n          // It's the Google-assigned merchant ID from Google Pay Business Console\n          ...(this.config.isProduction && this.config.googleMerchantId\n            ? { merchantId: this.config.googleMerchantId }\n            : {}),\n        },\n        transactionInfo: {\n          totalPriceStatus: \"FINAL\",\n          totalPrice: totalPrice,\n          currencyCode: this.config.currency.toUpperCase(),\n          countryCode: this.config.country.toUpperCase(),\n        },\n        emailRequired: true,\n      };\n\n      const paymentData = await this.client.loadPaymentData(request);\n\n      // Parse the encrypted token from the response\n      const tokenString = paymentData.paymentMethodData.tokenizationData.token;\n      const token: GooglePayEncryptedToken = JSON.parse(tokenString);\n\n      return { success: true, token, payerEmail: paymentData.email };\n    } catch (error) {\n      // Google Pay API throws an error when user cancels\n      if (error instanceof Error && error.message?.includes(\"CANCELED\")) {\n        return { success: false, cancelled: true };\n      }\n\n      // Check for statusCode which indicates user cancelled\n      const gpayError = error as { statusCode?: string };\n      if (gpayError.statusCode === \"CANCELED\") {\n        return { success: false, cancelled: true };\n      }\n\n      console.error(\"[GooglePay:Airwallex] Payment sheet error:\", error);\n      const errorMessage = error instanceof Error ? error.message : \"Unknown error\";\n      return { success: false, error: errorMessage };\n    }\n  }\n}\n"],"mappings":"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"}