{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading"]},"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 Apple 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 Apple 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":{"data-label":"Exception"},"children":["Exception"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Prevention"},"children":["Prevention"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePaySdkLoadFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Apple Pay SDK failed to load. For example, due to network issues, blocked resources, or an incorrect SDK URL."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Verify network connectivity and check CSP policies."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayNotAvailableException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Apple Pay isn't available on device. For example, due to an unsupported browser, no Apple Pay setup, or region restrictions."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check device compatibility before showing button."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayRequiresAppleDeviceException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The CSS method was used on non-Apple device."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Use device detection before enabling the CSS method."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayRequiresSafariException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The CSS method was used on a non-Safari browser."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check browser type before enabling the CSS method."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePaySafariVersionIncompatibleException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Safari version is too old for the CSS method."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check the Safari version compatibility."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayRequiresHttpsException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The CSS method was used on a non-HTTPS connection."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Ensure HTTPS for all Apple Pay implementations."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayMerchantIdentifierRequiredException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The merchant ID is missing from the configuration."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Validate the configuration before initialisation."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayMerchantValidationFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Merchant validation with Apple failed. For example, due to an invalid merchant ID or certificate issues."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Verify Apple Developer Console setup."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayPaymentFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Payment processing failed. For example, due to network issues, invalid payment data, or server errors."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Implement retry logic and validation."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePaySessionCancelledException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The customiser cancelled the Apple Pay session."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Handle gracefully and don't treat this as an error."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayValidationException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Payment request validation failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Validate all required fields before submission."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayPaymentAddressInvalidException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Shipping/billing address validation failed. For example, due to an invalid address format or restricted delivery area."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Implement address validation and clear error messages."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayPaymentMethodInvalidException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Payment method validation failed. For example, due to an unsupported card type or expired payment method."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check supported networks and card validity."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ApplePayCouponCodeInvalidException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Coupon code validation failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Implement real-time coupon validation."]}]}]}]}]},{"$$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('Apple Pay error:', {\n      name: error.name,\n      message: error.message,\n      code: error.code,\n      stack: error.stack,\n      timestamp: new Date().toISOString()\n    });\n\n    // Handle specific error types\n    switch (error.constructor.name) {\n      case 'ApplePayNotAvailableException':\n        showUserMessage('Apple Pay is not available on this device. Please use an alternative payment method.');\n        showAlternativePaymentMethods();\n        break;\n\n      case 'ApplePayMerchantValidationFailedException':\n        showUserMessage('Payment system temporarily unavailable. Please try again in a few moments.');\n        logCriticalError('Merchant validation failed', error);\n        break;\n\n      case 'ApplePayRequiresHttpsException':\n        showUserMessage('Secure connection required. Please ensure you are using HTTPS.');\n        redirectToHttps();\n        break;\n\n      case 'ApplePaySessionCancelledException':\n        // User cancelled - don't show error\n        trackEvent('apple_pay_cancelled');\n        break;\n\n      case 'ApplePayPaymentFailedException':\n        showUserMessage('Payment failed. Please check your payment information and try again.');\n        offerRetryOption();\n        break;\n\n      default:\n        showUserMessage('An unexpected error occurred. Please try again or contact support.');\n        logUnknownError(error);\n    }\n  }\n};\n\nfunction showUserMessage(message) {\n  // Show user-friendly error 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\nfunction logCriticalError(context, error) {\n  // Send to error monitoring service\n  errorReporting.captureException(error, { context });\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":"apple-pay-button-isnt-showing","__idx":6},"children":["Apple 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 Apple 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 Apple Pay availability\nconsole.log('Checking Apple Pay availability...');\n\nif (!window.ApplePaySession) {\n  console.error('ApplePaySession not available - not supported browser');\n  return;\n}\n\nif (!ApplePaySession.canMakePayments()) {\n  console.error('Apple Pay cannot make payments - no setup or unsupported device');\n  return;\n}\n\n// Step 2: Check specific networks\nconst supportedNetworks = ['visa', 'masterCard', 'amex', 'discover'];\nif (!ApplePaySession.canMakePayments(supportedNetworks)) {\n  console.warn('Apple Pay available but no supported cards configured');\n}\n\n// Step 3: Verify merchant configuration\nconst merchantId = sdkConfig.session.allowedFundingTypes.wallets.applePay.merchantId;\nif (!merchantId) {\n  console.error('Merchant ID is missing');\n  return;\n}\n\nif (!merchantId.startsWith('merchant.')) {\n  console.error('Invalid merchant ID format:', merchantId);\n  return;\n}\n\n// Step 4: Check HTTPS requirement\nif (location.protocol !== 'https:' && location.hostname !== 'localhost') {\n  console.error('Apple Pay requires HTTPS in production');\n  return;\n}\n\nconsole.log('All Apple Pay requirements met');\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: Graceful fallback\nfunction initializeApplePay() {\n  if (checkApplePayAvailability()) {\n    renderApplePayButton();\n  } else {\n    renderAlternativePaymentMethods();\n  }\n}\n\nfunction checkApplePayAvailability() {\n  return window.ApplePaySession && \n         ApplePaySession.canMakePayments() &&\n         isHttps() &&\n         hasMerchantId();\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","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"merchant-validation-failures","__idx":9},"children":["Merchant validation failures"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["An error occurs during the Apple Pay session initialisation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["\"Merchant validation failed\" error messages are displayed."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The payment sheet doesn't appear after button tap."]}]},{"$$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":"// Check merchant ID configuration\nconst diagnostics = {\n  merchantId: sdkConfig.session.allowedFundingTypes.wallets.applePay.merchantId,\n  domain: window.location.hostname,\n  protocol: window.location.protocol,\n  userAgent: navigator.userAgent\n};\n\nconsole.log('Merchant Validation Diagnostics:', diagnostics);\n\n// Test merchant validation endpoint\nasync function testMerchantValidation() {\n  try {\n    const testURL = 'https://apple-pay-gateway.apple.com/paymentservices/startSession';\n    const response = await fetch('/api/validate-merchant', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({\n        validationURL: testURL,\n        merchantId: diagnostics.merchantId,\n        displayName: 'Test Store',\n        domain: diagnostics.domain\n      })\n    });\n    \n    if (!response.ok) {\n      console.error('Merchant validation test failed:', response.status);\n    } else {\n      console.log('Merchant validation test passed');\n    }\n  } catch (error) {\n    console.error('Merchant validation test error:', error);\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-1","__idx":11},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify the Apple Developer Console setup:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Checklist for Apple Developer Console\nconst merchantSetupChecklist = {\n  merchantIdCreated: true,           // Created in Apple Developer Console\n  merchantIdFormat: 'merchant.com.yourcompany.store', // Correct format\n  certificateGenerated: true,        // Payment processing certificate created\n  certificateInstalled: true,        // Certificate installed on server\n  domainRegistered: true,           // Domain registered for merchant ID\n  domainVerified: true              // Domain verification file uploaded\n};\n\nconsole.log('Merchant setup checklist:', merchantSetupChecklist);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Perform server-side merchant validation:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Example server-side validation (Node.js)\napp.post('/api/validate-merchant', async (req, res) => {\n  const { validationURL, merchantId, displayName, domain } = req.body;\n  \n  try {\n    // Load merchant certificate and key\n    const merchantCert = fs.readFileSync('path/to/merchant.crt');\n    const merchantKey = fs.readFileSync('path/to/merchant.key');\n    \n    // Create validation payload\n    const payload = {\n      merchantIdentifier: merchantId,\n      displayName: displayName,\n      initiative: 'web',\n      initiativeContext: domain\n    };\n    \n    // Make request to Apple\n    const response = await axios.post(validationURL, payload, {\n      httpsAgent: new https.Agent({\n        cert: merchantCert,\n        key: merchantKey\n      }),\n      headers: {\n        'Content-Type': 'application/json'\n      }\n    });\n    \n    res.json(response.data);\n  } catch (error) {\n    console.error('Merchant validation failed:', error);\n    res.status(500).json({ error: 'Merchant validation failed' });\n  }\n});\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement client-side retry logic:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"async function validateMerchantWithRetry(validationURL, maxRetries = 3) {\n  for (let attempt = 1; attempt <= maxRetries; attempt++) {\n    try {\n      const merchantSession = await this.unityService.createPaymentMethod(\n        PaymentMethod.ApplePay,\n        validationURL,\n        this.config.merchantDisplayName,\n        window.location.hostname\n      );\n      return merchantSession;\n    } catch (error) {\n      console.warn(`Merchant validation attempt ${attempt} failed:`, error);\n      \n      if (attempt === maxRetries) {\n        throw new Error(`Merchant validation failed after ${maxRetries} attempts`);\n      }\n      \n      // Wait before retrying (exponential backoff)\n      await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));\n    }\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 Apple Pay sheet appears but payment fails."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The customer sees a generic error message."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The 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 payment authorisation with detailed logging\nthis.applePaySession.onpaymentauthorized = async (event) => {\n  console.log('Payment authorisation started:', {\n    paymentToken: event.payment.token ? 'Present' : 'Missing',\n    billingContact: event.payment.billingContact ? 'Present' : 'Missing',\n    shippingContact: event.payment.shippingContact ? 'Present' : 'Missing',\n    paymentMethod: event.payment.paymentMethod\n  });\n  \n  try {\n    // Validate payment data\n    this.validatePaymentData(event.payment);\n    \n    // Process payment\n    const result = await this.processPaymentWithDiagnostics(event.payment);\n    \n    if (result.success) {\n      console.log('Payment successful:', result.transactionId);\n      this.applePaySession.completePayment({ status: ApplePaySession.STATUS_SUCCESS });\n    } else {\n      console.error('Payment failed:', result.error);\n      this.applePaySession.completePayment({ status: ApplePaySession.STATUS_FAILURE });\n    }\n  } catch (error) {\n    console.error('Payment authorisation error:', error);\n    this.applePaySession.completePayment({ status: ApplePaySession.STATUS_FAILURE });\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-2","__idx":14},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Perform Enhanced validation:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"function validatePaymentData(payment) {\n  const validations = [\n    {\n      check: () => payment.token && payment.token.paymentData,\n      error: 'Payment token is missing or invalid'\n    },\n    {\n      check: () => payment.token.transactionIdentifier,\n      error: 'Transaction identifier is missing'\n    },\n    {\n      check: () => payment.billingContact,\n      error: 'Billing contact 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\nasync function processPaymentWithDiagnostics(payment) {\n  const startTime = Date.now();\n  \n  try {\n    // Create transaction request with additional metadata\n    const transactionRequest = {\n      merchantTransactionId: generateUniqueId(),\n      amount: this.config.paymentRequest.total.amount,\n      currency: this.config.paymentRequest.currencyCode,\n      paymentToken: payment.token.paymentData,\n      billingContact: payment.billingContact,\n      shippingContact: payment.shippingContact,\n      metadata: {\n        userAgent: navigator.userAgent,\n        timestamp: new Date().toISOString(),\n        sessionId: this.sessionId\n      }\n    };\n    \n    const result = await this.unityService.transactionAsync(transactionRequest);\n    const processingTime = Date.now() - startTime;\n    \n    console.log('Payment processing completed:', {\n      success: result.success,\n      processingTime: `${processingTime}ms`,\n      transactionId: result.transactionId\n    });\n    \n    return result;\n  } catch (error) {\n    const processingTime = Date.now() - startTime;\n    console.error('Payment processing failed:', {\n      error: error.message,\n      processingTime: `${processingTime}ms`,\n      stack: error.stack\n    });\n    throw error;\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement network error handling:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"async function processPaymentWithRetry(payment, maxRetries = 2) {\n  for (let attempt = 1; attempt <= maxRetries; attempt++) {\n    try {\n      return await this.processPayment(payment);\n    } catch (error) {\n      console.warn(`Payment attempt ${attempt} failed:`, error.message);\n      \n      if (this.isRetryableError(error) && attempt < maxRetries) {\n        console.log(`Retrying payment (attempt ${attempt + 1}/${maxRetries})`);\n        await this.delay(1000 * attempt); // Progressive delay\n        continue;\n      }\n      \n      throw error;\n    }\n  }\n}\n\nfunction isRetryableError(error) {\n  const retryableErrors = [\n    'Network error',\n    'Timeout',\n    'Service temporarily unavailable',\n    'Rate limit exceeded'\n  ];\n  \n  return retryableErrors.some(retryableError => \n    error.message.toLowerCase().includes(retryableError.toLowerCase())\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":"css-method-issues","__idx":15},"children":["CSS method issues"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The custom styled button doesn't trigger Apple Pay."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The button appears but clicking it has no effect."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["There are errors about browser compatibility."]}]},{"$$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":"function diagnoseCSSMethodCompatibility() {\n  const diagnostics = {\n    browser: getBrowserInfo(),\n    device: getDeviceInfo(),\n    https: location.protocol === 'https:',\n    applePaySupport: !!window.ApplePaySession,\n    canMakePayments: window.ApplePaySession ? ApplePaySession.canMakePayments() : false\n  };\n  \n  console.log('CSS method compatibility:', diagnostics);\n  \n  const requirements = [\n    {\n      name: 'HTTPS required',\n      met: diagnostics.https || location.hostname === 'localhost',\n      required: true\n    },\n    {\n      name: 'Apple device',\n      met: diagnostics.device.isApple,\n      required: true\n    },\n    {\n      name: 'Safari browser',\n      met: diagnostics.browser.isSafari,\n      required: true\n    },\n    {\n      name: 'Safari version 11.1+',\n      met: diagnostics.browser.version >= 11.1,\n      required: true\n    }\n  ];\n  \n  const unmetRequirements = requirements.filter(req => req.required && !req.met);\n  \n  if (unmetRequirements.length > 0) {\n    console.error('CSS method requirements not met:', unmetRequirements);\n    return false;\n  }\n  \n  return true;\n}\n\nfunction getBrowserInfo() {\n  const userAgent = navigator.userAgent;\n  const isSafari = /Safari/.test(userAgent) && !(/Chrome|Chromium|Edge|OPR/.test(userAgent));\n  \n  let version = 0;\n  if (isSafari) {\n    const versionMatch = userAgent.match(/Version\\/(\\d+)\\.(\\d+)/);\n    if (versionMatch) {\n      version = parseFloat(`${versionMatch[1]}.${versionMatch[2]}`);\n    }\n  }\n  \n  return { isSafari, version };\n}\n\nfunction getDeviceInfo() {\n  const userAgent = navigator.userAgent;\n  const isApple = /Mac|iPhone|iPad|iPod/.test(userAgent);\n  \n  return { isApple };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-3","__idx":17},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement browser detection and fallback:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"function initializeApplePayButton() {\n  if (shouldUseCSSMethod()) {\n    if (diagnoseCSSMethodCompatibility()) {\n      initializeCSSMethod();\n    } else {\n      showCompatibilityError();\n    }\n  } else {\n    initializeOfficialSDK();\n  }\n}\n\nfunction shouldUseCSSMethod() {\n  // Only use CSS method when specifically required\n  return config.usingCss === true;\n}\n\nfunction initializeCSSMethod() {\n  const config = {\n    usingCss: true,\n    style: {\n      template: `\n        <button class=\"apple-pay-button\" type=\"button\" data-apple-pay=\"true\">\n          <span class=\"apple-pay-icon\"></span>\n          <span class=\"apple-pay-text\">Pay with Apple Pay</span>\n        </button>\n      `,\n      templateCSS: `\n        .apple-pay-button {\n          background: #000;\n          color: #fff;\n          border: none;\n          border-radius: 4px;\n          height: 44px;\n          width: 100%;\n          display: flex;\n          align-items: center;\n          justify-content: center;\n          font-family: -apple-system, BlinkMacSystemFont, sans-serif;\n          font-size: 16px;\n          font-weight: 500;\n          cursor: pointer;\n          transition: background-color 0.2s ease;\n        }\n        \n        .apple-pay-button:hover {\n          background: #333;\n        }\n        \n        .apple-pay-button:active {\n          background: #555;\n        }\n        \n        .apple-pay-button:disabled {\n          opacity: 0.6;\n          cursor: not-allowed;\n        }\n        \n        .apple-pay-icon {\n          margin-right: 8px;\n        }\n      `\n    }\n  };\n  \n  const applePayComponent = new ApplePayButtonComponent(sdkConfig, config);\n  applePayComponent.mount('apple-pay-container');\n}\n\nfunction showCompatibilityError() {\n  const errorMessage = `\n    <div class=\"apple-pay-error\">\n      <h4>Apple Pay Not Available</h4>\n      <p>Apple Pay with custom styling requires:</p>\n      <ul>\n        <li>Safari browser</li>\n        <li>Apple device (Mac, iPhone, iPad)</li>\n        <li>HTTPS connection</li>\n        <li>Safari version 11.1 or later</li>\n      </ul>\n      <p>Please use a supported browser or device.</p>\n    </div>\n  `;\n  \n  document.getElementById('apple-pay-container').innerHTML = errorMessage;\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement progressive enhancement:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"function initializeWithProgressiveEnhancement() {\n  // Start with most compatible method\n  if (window.ApplePaySession && ApplePaySession.canMakePayments()) {\n    try {\n      // Try official SDK first\n      initializeOfficialSDK();\n    } catch (error) {\n      console.warn('Official SDK failed, trying CSS method:', error);\n      \n      if (diagnoseCSSMethodCompatibility()) {\n        initializeCSSMethod();\n      } else {\n        showAlternativePaymentMethods();\n      }\n    }\n  } else {\n    showAlternativePaymentMethods();\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 snippet:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enable comprehensive logging\nwindow.applePayDebug = {\n  logLevel: 'verbose',\n  logPaymentData: false, // Never log actual payment tokens\n  logNetworkRequests: true\n};\n\n// Debug helper functions\nconst debugApplePay = {\n  checkEnvironment() {\n    console.group('🔍 Apple 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('Apple Pay Session Available:', !!window.ApplePaySession);\n    console.log('Can Make Payments:', window.ApplePaySession ? ApplePaySession.canMakePayments() : false);\n    console.groupEnd();\n  },\n  \n  logPaymentRequest(request) {\n    console.group('📋 Payment Request');\n    console.log('Country Code:', request.countryCode);\n    console.log('Currency Code:', request.currencyCode);\n    console.log('Total Amount:', request.total.amount);\n    console.log('Supported Networks:', request.supportedNetworks);\n    console.log('Merchant Capabilities:', request.merchantCapabilities);\n    console.groupEnd();\n  },\n  \n  monitorSession(session) {\n    const originalCompletePayment = session.completePayment;\n    session.completePayment = function(result) {\n      console.log('💳 Payment Completed with status:', result.status);\n      return originalCompletePayment.call(this, result);\n    };\n  }\n};\n\n// Use in your implementation\ndebugApplePay.checkEnvironment();\ndebugApplePay.logPaymentRequest(paymentRequest);\ndebugApplePay.monitorSession(applePaySession);\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 Apple 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: 'Apple Pay support',\n      test: () => !!window.ApplePaySession,\n      fix: 'Apple Pay is not supported in this browser'\n    },\n    {\n      name: 'Payment capability',\n      test: () => ApplePaySession.canMakePayments(),\n      fix: 'Apple Pay is not set up on this device'\n    },\n    {\n      name: 'Merchant ID',\n      test: () => !!config.merchantId && config.merchantId.startsWith('merchant.'),\n      fix: 'Verify merchant ID configuration'\n    },\n    {\n      name: 'Network connectivity',\n      test: async () => {\n        try {\n          await fetch('/api/health-check', { method: 'HEAD' });\n          return true;\n        } catch {\n          return false;\n        }\n      },\n      fix: 'Check network connection'\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\n// Use before initialisation\nasync function initializeApplePay() {\n  const preflightPassed = await performPreflightChecks();\n  \n  if (preflightPassed) {\n    // Safe to initialise Apple Pay\n    const applePayComponent = new ApplePayButtonComponent(sdkConfig, config);\n    applePayComponent.mount('apple-pay-container');\n  } else {\n    // Show alternative payment methods\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      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  trackApplePayEvent(eventType, data) {\n    // Track Apple 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 Apple Pay component\nconst config = {\n  onError: (error) => {\n    errorMonitoring.captureError(error, { component: 'ApplePay' });\n  },\n  \n  onPaymentAuthorized: (payment) => {\n    errorMonitoring.trackApplePayEvent('payment_authorized', {\n      amount: payment.total.amount,\n      currency: payment.currencyCode\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":"Apple Pay button isn't showing","id":"apple-pay-button-isnt-showing","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps","depth":4},{"value":"Solutions","id":"solutions","depth":4},{"value":"Merchant validation failures","id":"merchant-validation-failures","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":"CSS method issues","id":"css-method-issues","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-03-24T15:21:03.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/web/apple-pay/troubleshooting","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}