{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition"]},"type":"markdown"},"seo":{"title":"Troubleshooting","description":"Transform your commerce with PXP's unified platform—seamless payments, real-time insights, and global growth in one powerful integration.","lang":"en-UK","siteUrl":"https://developer.pxp.io","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"troubleshooting","__idx":0},"children":["Troubleshooting"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Learn how to diagnose and fix common issues with the Google Pay web component."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"exception-types-and-error-codes","__idx":1},"children":["Exception types and error codes"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"component-exceptions","__idx":2},"children":["Component exceptions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Google Pay web component throws specific exceptions for different error scenarios:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"width":"40%","data-label":"Exception"},"children":["Exception "]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Error Code"},"children":["Error Code"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GooglePayLoadFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0704"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Google Pay API failed to load. For example, due to network issues, blocked resources, or CSP restrictions."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GooglePayNotReadyException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0701"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Google Pay isn't ready on this device or browser. For example, unsupported browser, no Google account, or no payment methods configured."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GooglePayClientNotInitializedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0703"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Google Pay client was not properly initialised before attempting a payment."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GooglePayConfigurationValidationFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0705"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Configuration validation failed. For example, missing required fields, invalid payment method configuration, or incorrect format."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GooglePayPaymentFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0702"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Payment processing failed. For example, due to network issues, declined payment, or server errors."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GooglePayDecryptAndTokenVaultFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0706"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Payment token decryption or vault storage failed. Check gateway configuration and token handling."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UnsupportedFundingTypeGooglePaySdkException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["SDK0110"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Google Pay is not included in the allowed funding types for this session."]}]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Payment cancellation by the user is not thrown as an exception. Instead, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCancel"]}," callback to handle user cancellations gracefully."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"error-handling-best-practices","__idx":3},"children":["Error handling best practices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"comprehensive-error-handler","__idx":4},"children":["Comprehensive error handler"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const config = {\n  onError: (error) => {\n    // Log error for debugging\n    console.error('Google Pay error:', {\n      name: error.name,\n      message: error.message,\n      code: error.ErrorCode, // Note: Capital 'E' in ErrorCode\n      stack: error.stack,\n      timestamp: new Date().toISOString()\n    });\n\n    // Handle specific error types by exception name\n    if (error.name === 'GooglePayNotReadyException') {\n      showUserMessage('Google Pay is not available on this device. Please use an alternative payment method.');\n      showAlternativePaymentMethods();\n      \n    } else if (error.name === 'GooglePayConfigurationValidationFailedException') {\n      showUserMessage('Payment system temporarily unavailable. Please try again in a few moments.');\n      logCriticalError('Configuration validation error', error);\n      \n    } else if (error.name === 'GooglePayClientNotInitializedException') {\n      showUserMessage('Payment system not ready. Please refresh and try again.');\n      logCriticalError('Client not initialized', error);\n      \n    } else if (error.name === 'GooglePayLoadFailedException') {\n      showUserMessage('Unable to load payment system. Please check your connection and try again.');\n      offerRetryOption();\n      \n    } else if (error.name === 'GooglePayPaymentFailedException') {\n      showUserMessage('Payment failed. Please check your payment information and try again.');\n      offerRetryOption();\n      \n    } else if (error.name === 'GooglePayDecryptAndTokenVaultFailedException') {\n      showUserMessage('Payment processing error. Please try again.');\n      logCriticalError('Token vault error', error);\n      \n    } else {\n      showUserMessage('An unexpected error occurred. Please try again or contact support.');\n      logUnknownError(error);\n    }\n  },\n  \n  // Handle user cancellation separately (not an exception)\n  onCancel: () => {\n    console.log('User cancelled Google Pay');\n    trackEvent('google_pay_cancelled');\n  }\n};\n\nfunction showUserMessage(message) {\n  const errorDiv = document.createElement('div');\n  errorDiv.className = 'error-message';\n  errorDiv.textContent = message;\n  document.getElementById('payment-container').appendChild(errorDiv);\n  \n  // Auto-dismiss after 5 seconds\n  setTimeout(() => {\n    errorDiv.remove();\n  }, 5000);\n}\n\nfunction logCriticalError(context, error) {\n  // Send to error monitoring service\n  if (window.errorReporting) {\n    window.errorReporting.captureException(error, { context });\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-common-issues","__idx":5},"children":["Troubleshooting common issues"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"google-pay-button-isnt-showing","__idx":6},"children":["Google Pay button isn't showing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The button element is hidden or not rendered."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["There's an empty container where the button should appear."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No Google Pay option is visible to customers."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps","__idx":7},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Step 1: Check Google Pay availability\nconsole.log('Checking Google Pay availability...');\n\n// Check if Google Pay API is loaded\nif (!window.google || !window.google.payments || !window.google.payments.api) {\n  console.error('Google Pay API not loaded');\n  console.log('Ensure the Google Pay script is included and loaded');\n  return;\n}\n\n// Step 2: Check browser compatibility\nconst browserInfo = {\n  userAgent: navigator.userAgent,\n  isChrome: /Chrome\\/(\\d+)/.test(navigator.userAgent),\n  isSafari: /Safari\\//.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent),\n  isFirefox: /Firefox\\/(\\d+)/.test(navigator.userAgent)\n};\nconsole.log('Browser info:', browserInfo);\n\n// Step 3: Check HTTPS\nif (location.protocol !== 'https:' && location.hostname !== 'localhost') {\n  console.error('Google Pay requires HTTPS in production');\n  return;\n}\n\n// Step 4: Verify payment method configuration\nconst paymentMethod = config.paymentDataRequest.allowedPaymentMethods[0];\n  \nif (!paymentMethod || !paymentMethod.parameters) {\n  console.error('Payment method configuration is missing');\n  return;\n}\n\nconsole.log('Allowed card networks:', paymentMethod.parameters.allowedCardNetworks);\nconsole.log('Allowed auth methods:', paymentMethod.parameters.allowedAuthMethods);\n\n// Note: The SDK automatically configures tokenizationSpecification from the session\n\n// Step 5: Test Google Pay readiness\ntry {\n  const paymentsClient = new google.payments.api.PaymentsClient({\n    environment: 'TEST'\n  });\n  \n  const isReadyToPayRequest = {\n    apiVersion: 2,\n    apiVersionMinor: 0,\n    allowedPaymentMethods: config.paymentDataRequest.allowedPaymentMethods\n  };\n  \n  paymentsClient.isReadyToPay(isReadyToPayRequest)\n    .then(response => {\n      if (response.result) {\n        console.log('✅ Google Pay is ready');\n      } else {\n        console.warn('⚠️ Google Pay is not ready - user may not have payment methods configured');\n      }\n    })\n    .catch(error => {\n      console.error('❌ Google Pay readiness check failed:', error);\n    });\n    \n} catch (error) {\n  console.error('Failed to check Google Pay readiness:', error);\n}\n\nconsole.log('All diagnostic checks complete');\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions","__idx":8},"children":["Solutions"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Graceful fallback\nfunction initializeGooglePay() {\n  if (checkGooglePayAvailability()) {\n    renderGooglePayButton();\n  } else {\n    console.log('Google Pay not available, showing alternatives');\n    renderAlternativePaymentMethods();\n  }\n}\n\nfunction checkGooglePayAvailability() {\n  return window.google && \n         window.google.payments && \n         window.google.payments.api &&\n         isHttps() &&\n         hasValidPaymentMethods();\n}\n\nfunction isHttps() {\n  return location.protocol === 'https:' || location.hostname === 'localhost';\n}\n\nfunction hasValidPaymentMethods() {\n  const paymentMethods = config.paymentDataRequest?.allowedPaymentMethods;\n  return paymentMethods && \n         paymentMethods.length > 0 && \n         paymentMethods[0].parameters?.allowedCardNetworks?.length > 0;\n}\n\nfunction renderAlternativePaymentMethods() {\n  const container = document.getElementById('payment-buttons');\n  container.innerHTML = `\n    <button class=\"credit-card-button\">Pay with Credit Card</button>\n    <button class=\"paypal-button\">Pay with PayPal</button>\n  `;\n}\n\n// Solution 2: Progressive loading\nfunction loadGooglePayWithFallback() {\n  const timeout = setTimeout(() => {\n    console.warn('Google Pay API loading timeout');\n    renderAlternativePaymentMethods();\n  }, 5000); // 5 second timeout\n  \n  // Load Google Pay API\n  const script = document.createElement('script');\n  script.src = 'https://pay.google.com/gp/p/js/pay.js';\n  script.async = true;\n  \n  script.onload = () => {\n    clearTimeout(timeout);\n    console.log('Google Pay API loaded successfully');\n    initializeGooglePay();\n  };\n  \n  script.onerror = () => {\n    clearTimeout(timeout);\n    console.error('Failed to load Google Pay API');\n    renderAlternativePaymentMethods();\n  };\n  \n  document.head.appendChild(script);\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"payment-sheet-not-opening","__idx":9},"children":["Payment sheet not opening"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Button is visible and clickable but nothing happens."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No error messages are shown."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Payment sheet doesn't appear after button click."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-1","__idx":10},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enhanced button click handler with diagnostics\nconst googlePayConfig = {\n  onGooglePaymentButtonClicked: async (event) => {\n    console.group('🔍 Google Pay Button Click Diagnostics');\n    \n    // Check 1: Verify button was actually clicked\n    console.log('Button clicked:', event);\n    \n    // Check 2: Verify configuration\n    console.log('Payment request config:', googlePayConfig.paymentDataRequest);\n    \n    // Check 3: Verify Google Pay client\n    if (!window.google || !window.google.payments || !window.google.payments.api) {\n      console.error('❌ Google Pay API not available');\n      console.groupEnd();\n      return;\n    }\n    \n    // Check 4: Test payment data request\n    try {\n      const paymentsClient = new google.payments.api.PaymentsClient({\n        environment: pxpSdk.environment === 'live' ? 'PRODUCTION' : 'TEST'\n      });\n      \n      // Validate payment data request\n      console.log('Testing payment data request...');\n      const testRequest = {\n        apiVersion: 2,\n        apiVersionMinor: 0,\n        allowedPaymentMethods: googlePayConfig.paymentDataRequest.allowedPaymentMethods\n      };\n      \n      const readyToPay = await paymentsClient.isReadyToPay(testRequest);\n      console.log('Ready to pay:', readyToPay);\n      \n      if (!readyToPay.result) {\n        console.error('❌ Google Pay not ready - no payment methods configured');\n      }\n      \n    } catch (error) {\n      console.error('❌ Payment request test failed:', error);\n    }\n    \n    console.groupEnd();\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-1","__idx":11},"children":["Solutions"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Add validation before opening sheet\nconst googlePayConfig = {\n  onCustomValidation: async () => {\n    console.log('Running custom validation...');\n    \n    const validations = [\n      {\n        name: 'Email',\n        test: () => {\n          const email = document.getElementById('email')?.value;\n          return email && email.includes('@');\n        },\n        message: 'Please enter a valid email address'\n      },\n      {\n        name: 'Terms',\n        test: () => document.getElementById('terms')?.checked,\n        message: 'Please accept terms and conditions'\n      },\n      {\n        name: 'Amount',\n        test: () => {\n          const amount = parseFloat(googlePayConfig.paymentDataRequest.transactionInfo.totalPrice);\n          return amount > 0;\n        },\n        message: 'Invalid payment amount'\n      }\n    ];\n    \n    for (const validation of validations) {\n      if (!validation.test()) {\n        console.error(`Validation failed: ${validation.name}`);\n        showError(validation.message);\n        return false;\n      }\n      console.log(`✅ ${validation.name} validation passed`);\n    }\n    \n    return true;\n  }\n};\n\n// Solution 2: Handle configuration errors\nfunction createGooglePayButton() {\n  try {\n    // Validate configuration before creating button\n    validateGooglePayConfiguration(googlePayConfig);\n    \n    const googlePayButton = pxpSdk.create('google-pay-button', googlePayConfig);\n    googlePayButton.mount('google-pay-container');\n    \n    console.log('✅ Google Pay button created successfully');\n    \n  } catch (error) {\n    console.error('❌ Failed to create Google Pay button:', error);\n    \n    if (error.name === 'GooglePayConfigurationValidationFailedException') {\n      showError('Payment configuration error. Please contact support.');\n      logConfigurationError(error);\n    } else {\n      showError('Unable to initialise Google Pay. Please try again.');\n    }\n    \n    // Show alternative payment methods\n    showAlternativePaymentMethods();\n  }\n}\n\nfunction validateGooglePayConfiguration(config) {\n  if (!config.paymentDataRequest) {\n    throw new Error('paymentDataRequest is required');\n  }\n  \n  if (!config.paymentDataRequest.transactionInfo) {\n    throw new Error('transactionInfo is required');\n  }\n  \n  if (!config.paymentDataRequest.allowedPaymentMethods || \n      config.paymentDataRequest.allowedPaymentMethods.length === 0) {\n    throw new Error('allowedPaymentMethods is required');\n  }\n  \n  const amount = parseFloat(config.paymentDataRequest.transactionInfo.totalPrice);\n  if (isNaN(amount) || amount <= 0) {\n    throw new Error('Invalid transaction amount');\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"payment-authorisation-failures","__idx":12},"children":["Payment authorisation failures"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The Google Pay sheet appears but payment fails."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Customer sees a generic error message."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Transaction doesn't complete successfully."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-2","__idx":13},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enhanced authorisation handler with detailed logging\nconst googlePayConfig = {\n  onPreAuthorisation: async (data) => {\n    console.group('💳 Payment Authorisation Diagnostics');\n    \n    console.log('Pre-authorisation data:', {\n      hasData: !!data,\n      billingAddress: data?.billingAddress ? 'Present' : 'Missing',\n      timestamp: new Date().toISOString()\n    });\n    \n    try {\n      // Validate amount\n      const amount = getOrderTotal();\n      console.log('Transaction amount:', amount);\n      \n      if (amount <= 0) {\n        console.error('❌ Invalid amount:', amount);\n        throw new Error('Invalid transaction amount');\n      }\n      \n      // Check inventory\n      console.log('Checking inventory...');\n      const inventoryAvailable = await checkInventory();\n      console.log('Inventory available:', inventoryAvailable);\n      \n      if (!inventoryAvailable) {\n        console.error('❌ Inventory not available');\n        throw new Error('Items no longer available');\n      }\n      \n      console.log('✅ Pre-authorisation checks passed');\n      console.groupEnd();\n      \n      return {\n        riskScreeningData: {\n          performRiskScreening: true,\n          userIp: \"192.168.1.100\",\n          account: {\n            id: \"user_12345678\",\n            creationDateTime: \"2024-01-15T10:30:00.000Z\"\n          },\n          fulfillments: [{\n            type: \"Shipped\",\n            recipientPerson: {\n              phoneNumber: \"+1234567890\"\n            }\n          }]\n        }\n      };\n      \n    } catch (error) {\n      console.error('❌ Pre-authorisation failed:', error);\n      console.groupEnd();\n      return null; // Cancel payment\n    }\n  },\n  \n  onPostAuthorisation: async (result, paymentData) => {\n    console.group('📊 Payment Authorisation Result');\n    \n    const isSuccess = 'merchantTransactionId' in result;\n    console.log('Result type:', isSuccess ? 'Success (MerchantSubmitResult)' : 'Failure (FailedSubmitResult)');\n    console.log('Transaction IDs:', {\n      merchantTransactionId: result.merchantTransactionId,\n      systemTransactionId: result.systemTransactionId\n    });\n    \n    if (!isSuccess && 'errorCode' in result) {\n      console.error('Payment not authorised:', {\n        errorCode: result.errorCode,\n        errorReason: result.errorReason,\n        correlationId: result.correlationId\n      });\n    } else if (isSuccess) {\n      console.log('Payment authorised successfully');\n    }\n    \n    console.groupEnd();\n    \n    // Handle result...\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-2","__idx":14},"children":["Solutions"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Enhanced validation\nfunction validatePaymentData(paymentData) {\n  const validations = [\n    {\n      check: () => paymentData && Object.keys(paymentData).length > 0,\n      error: 'Payment data is missing'\n    },\n    {\n      check: () => {\n        const amount = getOrderTotal();\n        return amount > 0 && amount < 1000000;\n      },\n      error: 'Invalid payment amount'\n    },\n    {\n      check: () => getCurrentCustomerEmail(),\n      error: 'Customer email is required'\n    }\n  ];\n  \n  for (const validation of validations) {\n    if (!validation.check()) {\n      throw new Error(validation.error);\n    }\n  }\n}\n\n// Solution 2: Implement retry logic\nasync function processPaymentWithRetry(paymentData, maxRetries = 2) {\n  for (let attempt = 1; attempt <= maxRetries; attempt++) {\n    try {\n      console.log(`Payment attempt ${attempt} of ${maxRetries}`);\n      \n      const result = await processPayment(paymentData);\n      \n      console.log('Payment processed successfully');\n      return result;\n      \n    } catch (error) {\n      console.warn(`Payment attempt ${attempt} failed:`, error.message);\n      \n      if (isRetryableError(error) && attempt < maxRetries) {\n        console.log(`Retrying payment...`);\n        await delay(1000 * attempt); // Progressive delay\n        continue;\n      }\n      \n      console.error('Payment failed after all retries');\n      throw error;\n    }\n  }\n}\n\nfunction isRetryableError(error) {\n  const retryableErrors = [\n    'network error',\n    'timeout',\n    'temporary failure',\n    'service unavailable'\n  ];\n  \n  return retryableErrors.some(retryableError => \n    error.message.toLowerCase().includes(retryableError)\n  );\n}\n\nfunction delay(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"shipping-address-errors","__idx":15},"children":["Shipping address errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Customer selects shipping address but sees error."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Unable to calculate shipping costs."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Address validation failures."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-3","__idx":16},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const googlePayConfig = {\n  onPaymentDataChanged: async (intermediatePaymentData) => {\n    console.group('📍 Shipping Address Diagnostics');\n    \n    const address = intermediatePaymentData.shippingAddress;\n    console.log('Shipping address:', address);\n    \n    if (!address) {\n      console.warn('⚠️ No shipping address provided');\n      console.groupEnd();\n      return {};\n    }\n    \n    // Validate address fields\n    const requiredFields = ['countryCode', 'postalCode', 'administrativeArea'];\n    const missingFields = requiredFields.filter(field => !address[field]);\n    \n    if (missingFields.length > 0) {\n      console.error('❌ Missing address fields:', missingFields);\n    } else {\n      console.log('✅ All required address fields present');\n    }\n    \n    // Test shipping calculation\n    try {\n      console.log('Testing shipping calculation...');\n      const shippingCost = await calculateShippingCost(address);\n      console.log('Shipping cost calculated:', shippingCost);\n    } catch (error) {\n      console.error('❌ Shipping calculation failed:', error);\n    }\n    \n    console.groupEnd();\n    \n    // Return actual response...\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-3","__idx":17},"children":["Solutions"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const googlePayConfig = {\n  onPaymentDataChanged: async (intermediatePaymentData) => {\n    try {\n      const address = intermediatePaymentData.shippingAddress;\n      \n      if (!address) {\n        return {};\n      }\n      \n      // Validate address completeness\n      if (!address.countryCode || !address.postalCode) {\n        return {\n          error: {\n            reason: 'SHIPPING_ADDRESS_INVALID',\n            message: 'Please enter a complete address',\n            intent: 'SHIPPING_ADDRESS'\n          }\n        };\n      }\n      \n      // Check if we ship to this country\n      const allowedCountries = ['US', 'CA', 'GB', 'FR', 'DE'];\n      if (!allowedCountries.includes(address.countryCode)) {\n        return {\n          error: {\n            reason: 'SHIPPING_ADDRESS_UNSERVICEABLE',\n            message: `We do not ship to ${address.countryCode}`,\n            intent: 'SHIPPING_ADDRESS'\n          }\n        };\n      }\n      \n      // Calculate shipping with error handling\n      let shippingCost = 0;\n      try {\n        shippingCost = await calculateShippingCost(address);\n      } catch (error) {\n        console.error('Shipping calculation failed:', error);\n        return {\n          error: {\n            reason: 'SHIPPING_ADDRESS_INVALID',\n            message: 'Unable to calculate shipping. Please try again.',\n            intent: 'SHIPPING_ADDRESS'\n          }\n        };\n      }\n      \n      const baseAmount = getBaseAmount();\n      const tax = calculateTax(address, baseAmount);\n      const newTotal = baseAmount + tax + shippingCost;\n      \n      // Update SDK amount\n      pxpSdk.updateAmount(newTotal);\n      \n      return {\n        newTransactionInfo: {\n          totalPriceStatus: 'FINAL',\n          totalPrice: newTotal.toFixed(2),\n          displayItems: [\n            { label: 'Subtotal', type: 'LINE_ITEM', price: baseAmount.toFixed(2) },\n            { label: 'Shipping', type: 'LINE_ITEM', price: shippingCost.toFixed(2) },\n            { label: 'Tax', type: 'TAX', price: tax.toFixed(2) }\n          ]\n        }\n      };\n      \n    } catch (error) {\n      console.error('Payment data changed error:', error);\n      return {\n        error: {\n          reason: 'SHIPPING_ADDRESS_INVALID',\n          message: 'An error occurred. Please try again.',\n          intent: 'SHIPPING_ADDRESS'\n        }\n      };\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"debugging-tools-and-techniques","__idx":18},"children":["Debugging tools and techniques"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To get more detailed information about errors, use this comprehensive debugging setup:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enable comprehensive logging\nwindow.googlePayDebug = {\n  logLevel: 'verbose',\n  logPaymentData: false, // Never log actual payment tokens\n  logNetworkRequests: true\n};\n\n// Debug helper functions\nconst debugGooglePay = {\n  checkEnvironment() {\n    console.group('🔍 Google Pay Environment Check');\n    console.log('Protocol:', location.protocol);\n    console.log('Hostname:', location.hostname);\n    console.log('User Agent:', navigator.userAgent);\n    console.log('Google Pay API Available:', !!(window.google && window.google.payments));\n    console.log('Environment:', pxpSdk.environment);\n    console.groupEnd();\n  },\n  \n  logPaymentRequest(request) {\n    console.group('📋 Payment Request Configuration');\n    console.log('Allowed Payment Methods:', request.allowedPaymentMethods);\n    console.log('Transaction Info:', request.transactionInfo);\n    console.log('Merchant Info:', request.merchantInfo);\n    console.log('Callback Intents:', request.callbackIntents);\n    console.groupEnd();\n  },\n  \n  logConfiguration(config) {\n    console.group('⚙️ Google Pay Configuration');\n    const paymentMethod = config.paymentDataRequest.allowedPaymentMethods[0];\n    console.log('Allowed Card Networks:', paymentMethod?.parameters?.allowedCardNetworks);\n    console.log('Auth Methods:', paymentMethod?.parameters?.allowedAuthMethods);\n    console.log('Billing Address Required:', paymentMethod?.parameters?.billingAddressRequired);\n    console.log('Total Price:', config.paymentDataRequest.transactionInfo?.totalPrice);\n    console.log('Currency:', config.paymentDataRequest.transactionInfo?.currencyCode);\n    console.log('Country Code:', config.paymentDataRequest.transactionInfo?.countryCode);\n    // Note: tokenizationSpecification is configured automatically by the SDK\n    console.groupEnd();\n  },\n  \n  testReadiness: async function(config) {\n    console.group('🧪 Google Pay Readiness Test');\n    \n    try {\n      const paymentsClient = new google.payments.api.PaymentsClient({\n        environment: pxpSdk.environment === 'live' ? 'PRODUCTION' : 'TEST'\n      });\n      \n      const isReadyToPayRequest = {\n        apiVersion: 2,\n        apiVersionMinor: 0,\n        allowedPaymentMethods: config.paymentDataRequest.allowedPaymentMethods\n      };\n      \n      const response = await paymentsClient.isReadyToPay(isReadyToPayRequest);\n      \n      if (response.result) {\n        console.log('✅ Google Pay is ready to accept payments');\n        console.log('Payment methods available:', response.paymentMethodPresent);\n      } else {\n        console.warn('⚠️ Google Pay not ready - user may need to add payment methods');\n      }\n      \n    } catch (error) {\n      console.error('❌ Readiness test failed:', error);\n    }\n    \n    console.groupEnd();\n  }\n};\n\n// Use in your implementation\ndebugGooglePay.checkEnvironment();\ndebugGooglePay.logConfiguration(googlePayConfig);\nawait debugGooglePay.testReadiness(googlePayConfig);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prevention-and-best-practices","__idx":19},"children":["Prevention and best practices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"proactive-error-prevention","__idx":20},"children":["Proactive error prevention"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Pre-flight checks before initialising Google Pay\nasync function performPreflightChecks() {\n  const checks = [\n    {\n      name: 'HTTPS check',\n      test: () => location.protocol === 'https:' || location.hostname === 'localhost',\n      fix: 'Ensure your site is served over HTTPS'\n    },\n    {\n      name: 'Google Pay API loaded',\n      test: () => !!(window.google && window.google.payments && window.google.payments.api),\n      fix: 'Ensure Google Pay API script is loaded'\n    },\n    {\n      name: 'Payment methods configured',\n      test: () => {\n        const pm = googlePayConfig.paymentDataRequest?.allowedPaymentMethods?.[0];\n        return pm?.parameters?.allowedCardNetworks?.length > 0;\n      },\n      fix: 'Configure at least one payment method with allowed card networks'\n    },\n    {\n      name: 'Valid transaction amount',\n      test: () => {\n        const amount = parseFloat(googlePayConfig.paymentDataRequest.transactionInfo.totalPrice);\n        return !isNaN(amount) && amount > 0;\n      },\n      fix: 'Ensure transaction amount is valid'\n    },\n    {\n      name: 'Browser compatibility',\n      test: () => checkBrowserCompatibility(),\n      fix: 'Use a supported browser'\n    }\n  ];\n  \n  const results = [];\n  for (const check of checks) {\n    const passed = await check.test();\n    results.push({ name: check.name, passed, fix: check.fix });\n    \n    if (!passed) {\n      console.warn(`❌ ${check.name}: ${check.fix}`);\n    } else {\n      console.log(`✅ ${check.name}`);\n    }\n  }\n  \n  return results.every(result => result.passed);\n}\n\nfunction checkBrowserCompatibility() {\n  const ua = navigator.userAgent;\n  \n  // Chrome 61+\n  if (/Chrome\\/(\\d+)/.test(ua)) {\n    return parseInt(RegExp.$1) >= 61;\n  }\n  \n  // Safari 12.1+\n  if (/Version\\/(\\d+)/.test(ua) && /Safari/.test(ua)) {\n    return parseInt(RegExp.$1) >= 12;\n  }\n  \n  // Firefox 62+\n  if (/Firefox\\/(\\d+)/.test(ua)) {\n    return parseInt(RegExp.$1) >= 62;\n  }\n  \n  return false;\n}\n\n// Use before initialisation\nasync function initializeGooglePay() {\n  const preflightPassed = await performPreflightChecks();\n  \n  if (preflightPassed) {\n    const googlePayButton = pxpSdk.create('google-pay-button', googlePayConfig);\n    googlePayButton.mount('google-pay-container');\n  } else {\n    showFallbackPaymentOptions();\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"monitoring-and-alerting","__idx":21},"children":["Monitoring and alerting"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Error monitoring setup\nconst errorMonitoring = {\n  captureError(error, context) {\n    // Send to your error tracking service\n    const errorData = {\n      message: error.message,\n      name: error.name,\n      errorCode: error.ErrorCode,\n      stack: error.stack,\n      context: context,\n      userAgent: navigator.userAgent,\n      url: location.href,\n      timestamp: new Date().toISOString(),\n      userId: getCurrentUserId(),\n      sessionId: getSessionId()\n    };\n    \n    // Example: Send to Sentry, LogRocket, etc.\n    this.sendToErrorService(errorData);\n  },\n  \n  trackGooglePayEvent(eventType, data) {\n    // Track Google Pay specific events\n    const eventData = {\n      type: eventType,\n      data: data,\n      timestamp: new Date().toISOString(),\n      sessionId: getSessionId()\n    };\n    \n    this.sendToAnalytics(eventData);\n  }\n};\n\n// Integration with Google Pay component\nconst config = {\n  onError: (error) => {\n    errorMonitoring.captureError(error, { component: 'GooglePay' });\n  },\n  \n  onPostAuthorisation: (result, paymentData) => {\n    const isSuccess = 'merchantTransactionId' in result;\n    errorMonitoring.trackGooglePayEvent('payment_completed', {\n      success: isSuccess,\n      transactionId: result.merchantTransactionId\n    });\n  }\n};\n","lang":"typescript"},"children":[]}]},"headings":[{"value":"Troubleshooting","id":"troubleshooting","depth":1},{"value":"Exception types and error codes","id":"exception-types-and-error-codes","depth":2},{"value":"Component exceptions","id":"component-exceptions","depth":3},{"value":"Error handling best practices","id":"error-handling-best-practices","depth":2},{"value":"Comprehensive error handler","id":"comprehensive-error-handler","depth":3},{"value":"Troubleshooting common issues","id":"troubleshooting-common-issues","depth":2},{"value":"Google Pay button isn't showing","id":"google-pay-button-isnt-showing","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps","depth":4},{"value":"Solutions","id":"solutions","depth":4},{"value":"Payment sheet not opening","id":"payment-sheet-not-opening","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-1","depth":4},{"value":"Solutions","id":"solutions-1","depth":4},{"value":"Payment authorisation failures","id":"payment-authorisation-failures","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-2","depth":4},{"value":"Solutions","id":"solutions-2","depth":4},{"value":"Shipping address errors","id":"shipping-address-errors","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-3","depth":4},{"value":"Solutions","id":"solutions-3","depth":4},{"value":"Debugging tools and techniques","id":"debugging-tools-and-techniques","depth":2},{"value":"Prevention and best practices","id":"prevention-and-best-practices","depth":2},{"value":"Proactive error prevention","id":"proactive-error-prevention","depth":3},{"value":"Monitoring and alerting","id":"monitoring-and-alerting","depth":3}],"frontmatter":{"seo":{"title":"Troubleshooting"}},"lastModified":"2026-04-22T11:40:18.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/web/google-pay/troubleshooting","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}