{"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 Paze 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 Paze 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":["PazeLoadFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1200"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The Paze SDK 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":["PazeInitializationFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1206"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1207"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze SDK initialisation failed, or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["canCheckout()"]}," did not return an eligibility result."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeConfigurationValidationFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1202-1205"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1222-1232"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Configuration validation failed. For example, due to a missing client ID, invalid lengths, or incorrect billing preferences."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeDynamicIdentityRequiredException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1208"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Dynamic presentment requires both email and phone number to be provided."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeIdentityValidationFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1209"]},"-",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1212"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Email or phone number validation failed. Check format and length requirements."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCurrencyNotSupportedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1213"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze only supports ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["USD"]}," currency. The provided currency isn't supported."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazePaymentFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1214"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze checkout or wallet flow failed before authorisation. For example, due to network issues or an error returned by the Paze SDK."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeTransactionFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1235"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Transaction submission failed. The exception includes a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["submitResult"]}," with error details. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]}," receives the same failure data."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeIncompleteCheckoutException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1221"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["complete()"]}," was called before ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkout()"]}," finished successfully."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCheckoutResponseMissingException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1215"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze checkout did not return a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkoutResponse"]}," for a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["COMPLETE"]}," result."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCompleteResponseMissingException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1216"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["complete()"]}," did not return a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completeResponse"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCheckoutDecodeFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1217"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Unable to decode the Paze ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["checkoutResponse"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCompleteDecodeFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1218"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Unable to decode the Paze ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completeResponse"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeCompleteSecuredPayloadMissingException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1219"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["completeResponse"]}," did not contain a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["securedPayload"]}," for decryption."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeDecryptFailedException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1233"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Token decryption failed. Check session configuration and Paze wallet settings in Unity Portal."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeAccountInaccessibleException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1220"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze wallet account exists but is not accessible to the merchant."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PazeInvalidRequestException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1234"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Invalid request parameters or configuration returned by the Paze SDK."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["UnsupportedFundingTypePazeSdkException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0118"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Paze 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":["User cancellation through ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutIncomplete"]}," is not thrown as an exception. Use the callback to handle 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":"p","attributes":{},"children":["Use a single component configuration that routes ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onError"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutIncomplete"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]}," to appropriate user messaging and logging:"]},{"$$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('Paze 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 === 'PazeLoadFailedException') {\n      showUserMessage('Unable to load Paze. Please check your connection and try again.');\n      offerAlternativePaymentMethods();\n      \n    } else if (error.name === 'PazeCurrencyNotSupportedException') {\n      showUserMessage('Paze is only available for USD transactions. Please use an alternative payment method.');\n      showAlternativePaymentMethods();\n      \n    } else if (error.name === 'PazeIdentityValidationFailedException') {\n      showUserMessage('Please provide a valid email address to use Paze.');\n      highlightEmailField();\n      \n    } else if (error.name === 'PazeDynamicIdentityRequiredException') {\n      showUserMessage('Please provide both email address and phone number to use Paze.');\n      highlightIdentityFields();\n      \n    } else if (error.name === 'PazeConfigurationValidationFailedException') {\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 === 'PazePaymentFailedException') {\n      showUserMessage('Payment failed. Please check your payment information and try again.');\n      offerRetryOption();\n      \n    } else if (error.name === 'PazeDecryptFailedException') {\n      showUserMessage('Payment processing error. Please try again.');\n      logCriticalError('Token decryption error', error);\n      \n    } else if (error.name === 'PazeAccountInaccessibleException') {\n      showUserMessage('Unable to access your Paze wallet. Please use an alternative payment method.');\n      showAlternativePaymentMethods();\n      \n    } else if (error.name === 'PazeInitializationFailedException') {\n      showUserMessage('Payment system not ready. Please refresh and try again.');\n      logCriticalError('Paze initialization 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 checkout cancellation separately (not an exception)\n  onCheckoutIncomplete: (result) => {\n    console.log('Paze checkout cancelled or incomplete');\n    trackEvent('paze_checkout_cancelled');\n    showUserMessage('Payment was cancelled. You can try again when ready.');\n  },\n  \n  // Handle submission errors (FailedSubmitResult, PazeTransactionFailedException, or BaseSdkException)\n  onSubmitError: (submitError) => {\n    console.error('Paze submission error:', submitError);\n\n    const failed = 'submitResult' in submitError\n      ? submitError.submitResult\n      : 'errorCode' in submitError\n        ? submitError\n        : null;\n\n    if (failed?.errorCode === 'DECLINED') {\n      showUserMessage('Payment was declined. Please try a different payment method.');\n    } else if (failed?.errorReason?.toLowerCase().includes('insufficient funds')) {\n      showUserMessage('Insufficient funds. Please try a different payment method.');\n    } else if ('ErrorCode' in submitError) {\n      showUserMessage(submitError.message);\n    } else {\n      showUserMessage('Payment failed. Please try again or use a different payment method.');\n    }\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\nfunction offerAlternativePaymentMethods() {\n  document.getElementById('paze-container').style.display = 'none';\n  document.getElementById('alternative-payments').style.display = 'block';\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"portal-and-session-setup","__idx":5},"children":["Portal and session setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use this section when Paze is not appearing in the Unity Portal, missing from your session response, or failing during component initialisation with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1202"]},". For portal setup steps, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/web/paze/onboarding"},"children":["Onboarding"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"paze-service-not-visible-on-site","__idx":6},"children":["Paze service not visible on site"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptom:"]}," The Paze service does not appear in your site's Services tab."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Solution:"]}," Enable Paze at the merchant group level first (",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/web/paze/onboarding#step-1-ensure-paze-is-enabled-at-the-merchant-group-level"},"children":["Onboarding, Step 1"]},"), then return to the site configuration."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"missing-client-id-in-session","__idx":7},"children":["Missing client ID in session"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptom:"]}," Session response does not include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["allowedFundingTypes.wallets.paze.clientId"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Solution:"]}]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify the client ID is saved in ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Paze Account Settings"]}," for the correct site."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Create a new session after saving portal changes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Confirm you are using the correct site name in your session request."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"sdk1202-error-on-mount","__idx":8},"children":["SDK1202 error on mount"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptom:"]}," Component fails with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Missing session.allowedFundingTypes.wallets.paze.clientId"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Solution:"]}," The session was created before Paze was configured, or Paze is not enabled for the site. Complete ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/web/paze/onboarding#step-3-configure-paze-on-your-site"},"children":["Onboarding, Steps 3–4"]},", then re-create the session."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-common-issues","__idx":9},"children":["Troubleshooting common issues"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"paze-button-isnt-showing","__idx":10},"children":["Paze 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 Paze option is visible to customers."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps","__idx":11},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Run these checks in your browser console to narrow down why the button is not visible:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Step 1: Check Paze SDK availability\nconsole.log('Checking Paze SDK availability...');\n\n// Check if Paze SDK is loaded\nif (!window.DIGITAL_WALLET_SDK || !window.DIGITAL_WALLET_SDK.canCheckout) {\n  console.error('Paze SDK not loaded');\n  console.log('Ensure the Paze SDK script is included and loaded');\n  return;\n}\n\n// Step 2: Verify session configuration\nconst sessionPazeConfig = sessionData?.allowedFundingTypes?.wallets?.paze;\nif (!sessionPazeConfig) {\n  console.error('Paze not configured in session');\n  console.log('Verify Paze is enabled in Unity Portal and included in session response');\n  return;\n}\n\nconsole.log('Session Paze config:', {\n  clientId: sessionPazeConfig.clientId ? 'Present' : 'Missing',\n  profileId: sessionPazeConfig.profileId ? 'Present' : 'Not set'\n});\n\n// Step 3: 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 4: Check HTTPS\nif (location.protocol !== 'https:' && location.hostname !== 'localhost') {\n  console.error('Paze requires HTTPS in production');\n  return;\n}\n\n// Step 5: Verify component configuration\nconst pazeConfig = {\n  buttonRenderMode: config.buttonRenderMode,\n  emailAddress: config.emailAddress,\n  phoneNumber: config.phoneNumber\n};\n\nconsole.log('Paze component config:', pazeConfig);\n\nif (config.buttonRenderMode === 'dynamic') {\n  if (!config.emailAddress || !config.phoneNumber) {\n    console.error('Dynamic presentment requires both emailAddress and phoneNumber');\n    return;\n  }\n}\n\n// Step 6: Test presentment\ntry {\n  console.log('Testing Paze presentment...');\n  // Presentment check happens automatically during component creation\n  // Monitor onPresentmentResolved callback\n} catch (error) {\n  console.error('Paze presentment test failed:', error);\n}\n\nconsole.log('All diagnostic checks complete');\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions","__idx":12},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use these patterns to hide Paze gracefully when it is unavailable and to validate identity before dynamic presentment:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Graceful fallback when Paze not available\nfunction initializePaze() {\n  if (checkPazeAvailability()) {\n    renderPazeButton();\n  } else {\n    console.log('Paze not available, showing alternatives');\n    renderAlternativePaymentMethods();\n  }\n}\n\nfunction checkPazeAvailability() {\n  return window.DIGITAL_WALLET_SDK && \n         window.DIGITAL_WALLET_SDK.canCheckout &&\n         sessionData?.allowedFundingTypes?.wallets?.paze?.clientId &&\n         isHttps() &&\n         hasValidConfiguration();\n}\n\nfunction isHttps() {\n  return location.protocol === 'https:' || location.hostname === 'localhost';\n}\n\nfunction hasValidConfiguration() {\n  if (!config.buttonRenderMode) return false;\n\n  if (config.buttonRenderMode === 'dynamic') {\n    return config.emailAddress &&\n           validateEmail(config.emailAddress) &&\n           config.phoneNumber &&\n           /^1\\d{10}$/.test(config.phoneNumber);\n  }\n\n  if (config.emailAddress && !validateEmail(config.emailAddress)) return false;\n  if (config.phoneNumber && !/^1\\d{10}$/.test(config.phoneNumber)) return false;\n\n  return true;\n}\n\nfunction validateEmail(email) {\n  const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  return emailRegex.test(email) && email.length <= 128;\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=\"google-pay-button\">Pay with Google Pay</button>\n  `;\n}\n\n// Solution 2: Validate identity for dynamic presentment\nfunction initializePazeWithValidation() {\n  const email = document.getElementById('customer-email')?.value;\n  const phone = document.getElementById('customer-phone')?.value;\n\n  if (!email || !phone) {\n    console.warn('Dynamic presentment requires both email and phone number');\n    document.getElementById('paze-container').style.display = 'none';\n    document.getElementById('identity-required-message').style.display = 'block';\n    return;\n  }\n\n  if (!validateEmail(email)) {\n    console.error('Invalid email format:', email);\n    showError('Please enter a valid email address');\n    return;\n  }\n\n  if (!/^1\\d{10}$/.test(phone)) {\n    console.error('Invalid phone format:', phone);\n    showError('Please enter a valid US phone number without +, for example 15551234567');\n    return;\n  }\n\n  const pazeButton = pxpSdk.create('paze-button', {\n    buttonRenderMode: 'dynamic',\n    emailAddress: email,\n    phoneNumber: phone,\n    onPresentmentResolved: (isVisible) => {\n      if (!isVisible) {\n        console.log('No Paze wallet found for this email');\n        document.getElementById('paze-container').style.display = 'none';\n      }\n    },\n    onError: (error) => {\n      console.error('Paze error:', error);\n      handlePazeError(error);\n    }\n  });\n  \n  pazeButton.mount('paze-container');\n}\n\n// Solution 3: Progressive loading with timeout\nfunction loadPazeWithFallback() {\n  const timeout = setTimeout(() => {\n    console.warn('Paze SDK loading timeout');\n    renderAlternativePaymentMethods();\n  }, 5000); // 5 second timeout\n  \n  // Check if Paze SDK is already loaded\n  if (window.DIGITAL_WALLET_SDK) {\n    clearTimeout(timeout);\n    initializePaze();\n    return;\n  }\n  \n  // Wait for Paze SDK to load\n  const checkInterval = setInterval(() => {\n    if (window.DIGITAL_WALLET_SDK) {\n      clearInterval(checkInterval);\n      clearTimeout(timeout);\n      console.log('Paze SDK loaded successfully');\n      initializePaze();\n    }\n  }, 100);\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"wallet-presentment-not-resolving","__idx":13},"children":["Wallet presentment not resolving"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved"]}," callback never fires."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Button remains in loading state indefinitely."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No visibility determination for Paze button."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["static"]}," mode, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPresentmentResolved(true)"]}," fires after successful initialisation. In ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["dynamic"]}," mode, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["isVisible"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["false"]}," when ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["canCheckout()"]}," reports the shopper has no eligible Paze wallet."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-1","__idx":14},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Add logging callbacks to trace initialisation, presentment, and validation errors:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enhanced presentment diagnostics\nconst pazeConfig = {\n  buttonRenderMode: 'static',\n  emailAddress: 'customer@example.com',\n  \n  onInit: () => {\n    console.log('✅ Paze component initialized');\n  },\n  \n  onPresentmentResolved: (isVisible) => {\n    console.group('🔍 Paze Presentment Diagnostics');\n    \n    console.log('Presentment resolved:', {\n      isVisible,\n      timestamp: new Date().toISOString()\n    });\n    \n    if (!isVisible) {\n      console.log('ℹ️ Reasons wallet might not be visible:');\n      console.log('- No Paze wallet registered for this email');\n      console.log('- Email not verified in Paze system');\n      console.log('- Paze service temporarily unavailable');\n    }\n    \n    console.groupEnd();\n  },\n  \n  onError: (error) => {\n    console.error('Presentment error:', error);\n    \n    if (error.ErrorCode === 'SDK1206' || error.ErrorCode === 'SDK1207') {\n      console.error('Paze initialization failed');\n      console.log('Check: clientId in session configuration');\n      console.log('Check: Network connectivity to Paze servers');\n    } else if (error.ErrorCode === 'SDK1209' || error.ErrorCode === 'SDK1210') {\n      console.error('Email validation failed:', error.message);\n      console.log('Check: Email format (RFC 5322)');\n      console.log('Check: Email length (max 128 characters)');\n    }\n  }\n};\n\n// Add timeout for presentment\nlet presentmentTimeout = setTimeout(() => {\n  console.warn('Presentment timeout after 10 seconds');\n  console.log('Paze presentment did not resolve in expected time');\n  // Hide button or show alternative\n  document.getElementById('paze-container').style.display = 'none';\n}, 10000);\n\n// Clear timeout when presentment resolves\npazeConfig.onPresentmentResolved = (isVisible) => {\n  clearTimeout(presentmentTimeout);\n  // ... rest of handler\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-1","__idx":15},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement a presentment timeout and validate identity before creating the component:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Implement presentment timeout and fallback\nfunction createPazeWithTimeout() {\n  let presentmentResolved = false;\n  \n  const pazeButton = pxpSdk.create('paze-button', {\n    buttonRenderMode: 'static',\n    emailAddress: customerEmail,\n    \n    onPresentmentResolved: (isVisible) => {\n      presentmentResolved = true;\n      \n      if (isVisible) {\n        console.log('Paze wallet available');\n        document.getElementById('paze-container').style.display = 'block';\n      } else {\n        console.log('No Paze wallet found');\n        document.getElementById('paze-container').style.display = 'none';\n        document.getElementById('paze-unavailable-message').style.display = 'block';\n      }\n    },\n    \n    onError: (error) => {\n      presentmentResolved = true;\n      console.error('Paze presentment error:', error);\n      document.getElementById('paze-container').style.display = 'none';\n    }\n  });\n  \n  pazeButton.mount('paze-container');\n  \n  // Timeout fallback\n  setTimeout(() => {\n    if (!presentmentResolved) {\n      console.warn('Paze presentment timeout - hiding button');\n      document.getElementById('paze-container').style.display = 'none';\n    }\n  }, 10000);\n}\n\n// Solution 2: Validate email before creating component\nfunction createPazeWithValidation() {\n  const email = getCustomerEmail();\n  \n  // Validate email format\n  if (!email || !validatePazeEmail(email)) {\n    console.error('Invalid email for Paze');\n    return;\n  }\n  \n  console.log('Creating Paze button with validated email:', email);\n  \n  const pazeButton = pxpSdk.create('paze-button', {\n    buttonRenderMode: 'static',\n    emailAddress: email,\n    onPresentmentResolved: handlePresentment\n  });\n  \n  pazeButton.mount('paze-container');\n}\n\nfunction validatePazeEmail(email) {\n  // Check format (RFC 5322 compliant)\n  const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  if (!emailRegex.test(email)) {\n    console.error('Email format invalid');\n    return false;\n  }\n  \n  // Check length\n  if (email.length > 128) {\n    console.error('Email too long (max 128 characters)');\n    return false;\n  }\n  \n  return true;\n}\n\nfunction handlePresentment(isVisible) {\n  if (isVisible) {\n    // Show Paze button\n    document.getElementById('paze-container').classList.add('visible');\n    trackEvent('paze_wallet_available');\n  } else {\n    // Hide Paze, offer alternatives\n    document.getElementById('paze-container').style.display = 'none';\n    document.getElementById('alternative-payment-methods').style.display = 'block';\n    trackEvent('paze_wallet_not_available');\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"checkout-fails-or-gets-cancelled","__idx":16},"children":["Checkout fails or gets cancelled"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Customer clicks Paze button but checkout doesn't complete."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onCheckoutIncomplete"]}," fires unexpectedly."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Paze wallet opens but customer can't complete payment."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-2","__idx":17},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Instrument the checkout callbacks to log each step and capture the incomplete reason:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Comprehensive checkout flow diagnostics\nconst pazeConfig = {\n  buttonRenderMode: 'static',\n  emailAddress: 'customer@example.com',\n  \n  onPazeButtonClicked: (event) => {\n    console.group('🔍 Paze Checkout Flow');\n    console.log('Step 1: Button clicked');\n    console.log('Email:', config.emailAddress);\n    console.log('Currency:', pxpSdk.getConfig().transactionData.currency);\n    console.log('Amount:', pxpSdk.getConfig().transactionData.amount);\n  },\n  \n  onCheckoutComplete: (result) => {\n    console.log('Step 2: Checkout complete');\n    console.log('Result:', result.result);\n    console.log('Session ID:', result.checkoutDecodedResponse?.sessionId);\n    console.log('Card network:', result.checkoutDecodedResponse?.maskedCard?.paymentCardNetwork);\n    console.groupEnd();\n    \n    return true;\n  },\n  \n  onCheckoutIncomplete: (result) => {\n    console.warn('Checkout incomplete or cancelled');\n    console.log('Reason:', result.reason);\n    console.log('Session ID:', result.checkoutDecodedResponse?.sessionId);\n    console.groupEnd();\n    \n    if (result.reason?.toLowerCase().includes('cancel')) {\n      trackEvent('paze_user_cancelled');\n    } else {\n      trackEvent('paze_checkout_error', { reason: result.reason });\n    }\n  },\n  \n  onError: (error) => {\n    console.error('Checkout error:', error);\n    console.groupEnd();\n    \n    if (error.ErrorCode === 'SDK1213') {\n      console.error('Currency not supported - Paze only supports USD');\n    } else if (error.ErrorCode === 'SDK1214') {\n      console.error('Checkout failed:', error.message);\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-2","__idx":18},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Validate currency before mounting the component and handle incomplete checkout with clear customer messaging:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Currency validation before checkout\nfunction initializePazeWithCurrencyCheck() {\n  const currency = pxpSdk.getConfig().transactionData.currency;\n  \n  if (currency !== 'USD') {\n    console.warn('Paze only supports USD, current currency:', currency);\n    document.getElementById('paze-container').style.display = 'none';\n    document.getElementById('currency-notice').textContent = \n      `Paze is only available for USD transactions. Current currency: ${currency}`;\n    return;\n  }\n  \n  const pazeButton = pxpSdk.create('paze-button', {\n    buttonRenderMode: 'static',\n    emailAddress: customerEmail,\n    onCheckoutComplete: handleCheckoutComplete,\n    onCheckoutIncomplete: handleCheckoutIncomplete\n  });\n  \n  pazeButton.mount('paze-container');\n}\n\nfunction handleCheckoutComplete(result) {\n  console.log('Paze checkout successful');\n  \n  // Show success indicator\n  showCheckoutSuccess();\n  \n  // Proceed with decryption\n  return true;\n}\n\nfunction handleCheckoutIncomplete(result) {\n  console.log('Checkout incomplete:', result.reason);\n  \n  if (result.reason?.toLowerCase().includes('cancel')) {\n    showMessage('Payment cancelled. You can try again when ready.');\n  } else {\n    showMessage('Unable to complete checkout. Please try a different payment method.');\n    showAlternativePaymentMethods();\n  }\n}\n\n// Solution 2: Implement checkout timeout handling\nfunction createPazeWithCheckoutTimeout() {\n  let checkoutTimeout;\n  \n  const pazeButton = pxpSdk.create('paze-button', {\n    buttonRenderMode: 'static',\n    emailAddress: customerEmail,\n    \n    onPazeButtonClicked: () => {\n      console.log('Starting checkout, setting 5 minute timeout');\n      \n      // Set 5-minute timeout for checkout\n      checkoutTimeout = setTimeout(() => {\n        console.warn('Checkout timeout - 5 minutes elapsed');\n        showMessage('Checkout timed out. Please try again.');\n        hideLoadingIndicator();\n      }, 5 * 60 * 1000);\n      \n      showLoadingIndicator('Opening Paze wallet...');\n    },\n    \n    onCheckoutComplete: (result) => {\n      clearTimeout(checkoutTimeout);\n      console.log('Checkout completed successfully');\n      return true;\n    },\n    \n    onCheckoutIncomplete: (result) => {\n      clearTimeout(checkoutTimeout);\n      console.log('Checkout incomplete');\n      hideLoadingIndicator();\n    },\n    \n    onError: (error) => {\n      clearTimeout(checkoutTimeout);\n      console.error('Checkout error:', error);\n      hideLoadingIndicator();\n    }\n  });\n  \n  pazeButton.mount('paze-container');\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"token-decryption-fails","__idx":19},"children":["Token decryption fails"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The symptoms of this are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Checkout completes but payment doesn't process."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostDecryption"]}," never fires."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Error: \"Token decryption failed\" (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK1233"]},")."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-3","__idx":20},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Log each stage of the decryption flow to see whether SDK-managed or manual decryption is failing:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Decryption flow diagnostics\nconst pazeConfig = {\n  buttonRenderMode: 'static',\n  emailAddress: 'customer@example.com',\n  \n  onCheckoutComplete: (result) => {\n    console.group('🔐 Decryption Flow Diagnostics');\n    console.log('Step 1: Checkout complete, preparing for decryption');\n    return true;\n  },\n  \n  onPreDecryption: () => {\n    console.log('Step 2: Pre-decryption');\n    console.log('Decryption method: SDK-managed (automatic)');\n    \n    // Check session encryption key\n    const session = pxpSdk.getConfig().session;\n    console.log('Session encryption key present:', !!session.encryptionKey);\n    \n    return true;\n  },\n  \n  onPostDecryption: (decryptedPayload) => {\n    console.log('Step 3: Post-decryption');\n    console.log('Decryption successful');\n    console.log('Network token present:', !!decryptedPayload.fundingData?.networkToken);\n    console.groupEnd();\n  },\n  \n  onError: (error) => {\n    console.error('Decryption error:', error);\n    console.groupEnd();\n    \n    if (error.ErrorCode === 'SDK1233') {\n      console.error('Token decryption failed');\n      console.log('Check: Session encryption key');\n      console.log('Check: Gateway configuration in Unity Portal');\n      console.log('Check: Network connectivity');\n    } else if (error.ErrorCode === 'SDK1219') {\n      console.error('Secured payload missing from complete response');\n    }\n  }\n};\n\n// Manual decryption diagnostics\nconst manualDecryptionConfig = {\n  onPreDecryption: () => {\n    console.log('Manual decryption mode enabled');\n    return false;\n  },\n  \n  onComplete: async (result) => {\n    console.group('Manual Decryption Diagnostics');\n    const securedPayload = result.completeDecodedResponse?.securedPayload;\n    console.log('Secured payload received');\n    console.log('Has secured payload:', !!securedPayload);\n    console.log('Payload ID:', result.completeDecodedResponse?.payloadId);\n    \n    try {\n      // Forward securedPayload to your backend (never call PXP decrypt API from the browser)\n      console.log('Calling merchant decrypt endpoint...');\n      const response = await fetch('/api/paze/decrypt', {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ securedPayload })\n      });\n      \n      console.log('Decryption API response status:', response.status);\n      \n      if (!response.ok) {\n        console.error('Decryption API failed:', await response.text());\n      } else {\n        console.log('Manual decryption successful');\n      }\n      \n    } catch (error) {\n      console.error('Manual decryption error:', error);\n    }\n    \n    console.groupEnd();\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-3","__idx":21},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify the session before decryption, recover from session expiry, and handle manual decryption with retries. For the PXP decrypt-token API, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/checkout/components/web/paze/implementation#backend-decryption"},"children":["Backend decryption"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Verify session encryption key\nfunction verifySessionForPaze() {\n  const session = pxpSdk.getConfig().session;\n  \n  if (!session.encryptionKey) {\n    console.error('Session encryption key missing');\n    showError('Payment system configuration error. Please refresh and try again.');\n    return false;\n  }\n  \n  if (!session.sessionId) {\n    console.error('Session ID missing');\n    showError('Session invalid. Please refresh and try again.');\n    return false;\n  }\n  \n  // Check session expiry when your backend includes sessionExpiry in the session response\n  if (session.sessionExpiry) {\n    const expiresAt = new Date(session.sessionExpiry);\n    const now = new Date();\n\n    if (expiresAt < now) {\n      console.error('Session expired');\n      showError('Session expired. Please refresh and try again.');\n      setTimeout(() => window.location.reload(), 2000);\n      return false;\n    }\n  }\n  \n  console.log('Session validated for Paze decryption');\n  return true;\n}\n\n// Solution 2: Implement decryption error recovery\nconst pazeConfig = {\n  onPreDecryption: () => {\n    // Verify session before decryption\n    if (!verifySessionForPaze()) {\n      return false;\n    }\n    \n    return true;\n  },\n  \n  onError: async (error) => {\n    if (error.ErrorCode === 'SDK1233') {\n      console.error('Decryption failed, attempting recovery');\n      \n      // Check if session needs refresh\n      const session = pxpSdk.getConfig().session;\n      if (session.sessionExpiry) {\n        const expiresAt = new Date(session.sessionExpiry);\n        const now = new Date();\n        const minutesUntilExpiry = (expiresAt - now) / (1000 * 60);\n\n        if (minutesUntilExpiry < 5) {\n          showMessage('Session expired. Refreshing...');\n          \n          try {\n            const newSession = await fetch('/api/sessions').then(r => r.json());\n\n            // Reinitialise the SDK with the refreshed session\n            pxpSdk = PxpCheckout.initialize({\n              ...existingSdkConfig,\n              session: newSession\n            });\n            \n            showMessage('Please try your payment again.');\n            return;\n          } catch (refreshError) {\n            showError('Unable to refresh session. Please reload the page.');\n            return;\n          }\n        }\n      }\n\n      showError('Decryption failed. Please try again or use a different payment method.');\n    }\n  }\n};\n\n// Solution 3: Manual decryption with error handling\nconst manualDecryptionConfig = {\n  onPreDecryption: () => {\n    return false;\n  },\n  \n  onComplete: async (result) => {\n    try {\n      showLoadingIndicator('Processing payment...');\n      \n      const securedPayload = result.completeDecodedResponse?.securedPayload;\n      \n      // Validate payload\n      if (!securedPayload) {\n        throw new Error('Secured payload missing');\n      }\n      \n      // Call your backend decrypt endpoint with retry\n      const decryptedData = await retryDecryption({ securedPayload }, 3);\n      \n      console.log('Manual decryption successful');\n      \n      // Submit payment with decrypted data\n      const paymentResult = await submitPayment(decryptedData);\n      \n      if (paymentResult.success) {\n        window.location.href = '/success';\n      } else {\n        showError('Payment failed: ' + paymentResult.error);\n      }\n      \n    } catch (error) {\n      console.error('Manual decryption failed:', error);\n      showError('Unable to process payment. Please try again or use a different payment method.');\n    } finally {\n      hideLoadingIndicator();\n    }\n  }\n};\n\nasync function retryDecryption(result, maxAttempts) {\n  for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n    try {\n      console.log(`Decryption attempt ${attempt}/${maxAttempts}`);\n      \n      const response = await fetch('/api/paze/decrypt', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          'X-HMAC-Signature': await generateHmacSignature(result.securedPayload)\n        },\n        body: JSON.stringify({\n          securedPayload: result.securedPayload\n        })\n      });\n      \n      if (!response.ok) {\n        throw new Error(`Decryption API returned ${response.status}`);\n      }\n      \n      return await response.json();\n      \n    } catch (error) {\n      console.warn(`Attempt ${attempt} failed:`, error.message);\n      \n      if (attempt < maxAttempts) {\n        // Exponential backoff\n        await delay(Math.min(1000 * Math.pow(2, attempt), 5000));\n      } else {\n        throw error;\n      }\n    }\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":"payment-authorisation-failures","__idx":22},"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":["Decryption succeeds but authorisation fails."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]}," receives a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["state"]}," other than ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorised"]}," (when configured)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]}," fires for HTTP or validation failures."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Transaction declined or rejected."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Configure ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPostAuthorisation"]}," on the component to receive authorisation outcomes. HTTP failures route to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onSubmitError"]}," instead."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-4","__idx":23},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Log transaction data before submit and inspect the authorisation response state:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Authorisation flow diagnostics\nconst pazeConfig = {\n  onPreAuthorisation: async () => {\n    console.group('💳 Payment authorisation diagnostics');\n    console.log('Step 1: Pre-authorisation');\n    \n    // Check transaction data\n    const transactionData = pxpSdk.getConfig().transactionData;\n    console.log('Transaction data:', {\n      amount: transactionData.amount,\n      currency: transactionData.currency,\n      merchantTransactionId: transactionData.merchantTransactionId\n    });\n    \n    // Validate amount\n    if (transactionData.amount <= 0) {\n      console.error('Invalid amount:', transactionData.amount);\n      return false; // Cancel authorisation\n    }\n    \n    console.log('Pre-authorisation checks passed');\n    \n    return {\n      riskScreeningData: {\n        performRiskScreening: true,\n        userIp: \"192.168.1.100\"\n      }\n    };\n  },\n  \n  onPostAuthorisation: (data) => {\n    console.log('Step 2: Post-authorisation');\n    \n    const isSuccess = data.state === 'Authorised';\n    console.log('Result type:', isSuccess ? 'Success' : 'Failure');\n    \n    if (isSuccess) {\n      console.log('Authorisation successful');\n      console.log('Merchant transaction ID:', data.merchantTransactionId);\n      console.log('System transaction ID:', data.systemTransactionId);\n    } else {\n      console.error('Authorisation failed');\n      console.error('State:', data.state);\n      console.error('Provider response code:', data.providerResponseCode);\n      console.error('State data code:', data.stateDataCode);\n      \n      if (data.state === 'Declined') {\n        console.error('Payment declined by issuer');\n      }\n    }\n    \n    console.groupEnd();\n  },\n  \n  onSubmitError: (submitError) => {\n    const failed = 'submitResult' in submitError\n      ? submitError.submitResult\n      : 'errorCode' in submitError\n        ? submitError\n        : null;\n\n    console.error('Submit error:', failed ?? submitError);\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-4","__idx":24},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify successful authorisation on your backend before fulfilling the order and track declined states separately from submission errors:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Solution 1: Comprehensive authorization handling\nconst pazeConfig = {\n  onPostAuthorisation: async (data) => {\n    if (data.state === 'Authorised') {\n      console.log('Payment authorized successfully');\n      \n      // Verify on backend before fulfilling\n      const verified = await verifyPaymentOnBackend({\n        systemTransactionId: data.systemTransactionId,\n        merchantTransactionId: data.merchantTransactionId\n      });\n      \n      if (verified.success) {\n        showSuccessMessage('Payment successful!');\n        setTimeout(() => {\n          window.location.href = `/success?orderId=${verified.orderId}`;\n        }, 2000);\n      } else {\n        showError('Payment verification failed. Please contact support.');\n      }\n      \n    } else {\n      showError(`Payment failed: ${data.state || 'Unknown error'}`);\n      trackEvent('paze_authorization_failed', {\n        state: data.state,\n        providerResponseCode: data.providerResponseCode\n      });\n      \n      // Show alternative payment methods\n      showAlternativePaymentMethods();\n    }\n  },\n  \n  onSubmitError: (submitError) => {\n    console.error('Payment submission error:', submitError);\n\n    const message = 'submitResult' in submitError\n      ? submitError.submitResult.errorReason\n      : 'errorCode' in submitError\n        ? submitError.errorReason\n        : submitError.message;\n\n    showError(message || 'Unable to process payment. Please try again.');\n    trackEvent('paze_submit_error', {\n      errorCode: 'submitResult' in submitError\n        ? submitError.submitResult.errorCode\n        : 'errorCode' in submitError\n          ? submitError.errorCode\n          : submitError.ErrorCode\n    });\n  }\n};\n\nasync function verifyPaymentOnBackend(transactionData) {\n  try {\n    const response = await fetch('/api/verify-payment', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(transactionData)\n    });\n    \n    return await response.json();\n  } catch (error) {\n    console.error('Backend verification failed:', error);\n    return { success: false, error: error.message };\n  }\n}\n\n// Solution 2: Implement retry logic for transient failures\nasync function handleAuthorizationWithRetry(data) {\n  if (data.state !== 'Authorised') {\n    // Use onSubmitError for submission-level failures; check state for authorisation outcome\n    trackEvent('paze_authorization_failed', {\n      state: data.state,\n      providerResponseCode: data.providerResponseCode\n    });\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"debugging-tools-and-techniques","__idx":25},"children":["Debugging tools and techniques"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To get more detailed information about errors, enable verbose logging and run environment checks before reproducing an issue:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enable comprehensive logging\nwindow.pazeDebug = {\n  logLevel: 'verbose',\n  logPaymentData: false, // Never log actual payment tokens\n  logNetworkRequests: true,\n  logPresentment: true,\n  logDecryption: false // Security: never log decryption details\n};\n\n// Debug helper functions\nconst debugPaze = {\n  checkEnvironment() {\n    console.group('🔍 Paze Environment Check');\n    console.log('Protocol:', location.protocol);\n    console.log('Hostname:', location.hostname);\n    console.log('User Agent:', navigator.userAgent);\n    console.log('Paze SDK Available:', !!(window.DIGITAL_WALLET_SDK));\n    console.log('Environment:', pxpSdk.environment);\n    console.log('Currency:', pxpSdk.getConfig().transactionData.currency);\n    console.groupEnd();\n  },\n  \n  logConfiguration(config) {\n    console.group('⚙️ Paze Configuration');\n    console.log('Button Render Mode:', config.buttonRenderMode);\n    console.log('Email Address:', config.emailAddress ? '***@***.***' : 'Not provided'); // Masked\n    console.log('Phone Number:', config.phoneNumber ? '***-***-****' : 'Not provided'); // Masked\n    console.log('Billing Preference:', config.billingPreference);\n    console.log('Accepted Card Networks:', config.acceptedPaymentCardNetworks);\n    console.log('Perform AVS:', config.performAVS);\n    console.log('Cobrand:', config.cobrand);\n    console.groupEnd();\n  },\n  \n  logSessionConfig() {\n    console.group('📋 Session Paze Configuration');\n    const pazeConfig = pxpSdk.getConfig().session?.allowedFundingTypes?.wallets?.paze;\n    \n    if (!pazeConfig) {\n      console.error('❌ Paze not configured in session');\n    } else {\n      console.log('✅ Paze configuration present');\n      console.log('Client ID:', pazeConfig.clientId ? 'Present' : 'Missing');\n      console.log('Profile ID:', pazeConfig.profileId ? 'Present' : 'Not set');\n    }\n    console.groupEnd();\n  },\n  \n  testPazeSDK() {\n    console.group('Paze SDK test');\n    \n    if (!window.DIGITAL_WALLET_SDK) {\n      console.error('Paze SDK not loaded');\n      console.log('Check: Script tag is present in HTML');\n      console.log('Check: Network requests for Paze SDK');\n    } else {\n      console.log('Paze SDK loaded');\n      console.log('DIGITAL_WALLET_SDK.canCheckout available:', typeof window.DIGITAL_WALLET_SDK.canCheckout === 'function');\n      console.log('DIGITAL_WALLET_SDK.checkout available:', typeof window.DIGITAL_WALLET_SDK.checkout === 'function');\n    }\n    \n    console.groupEnd();\n  },\n  \n  logPresentmentFlow(config) {\n    console.group('Paze Presentment Flow');\n    console.log('Email:', config.emailAddress ? '***@***.***' : 'Not provided');\n    console.log('Phone:', config.phoneNumber ? '***-***-****' : 'Not provided');\n    console.log('Render mode:', config.buttonRenderMode);\n    \n    console.log('Waiting for presentment resolution...');\n    console.groupEnd();\n  }\n};\n\n// Use in your implementation\ndebugPaze.checkEnvironment();\ndebugPaze.logSessionConfig();\ndebugPaze.testPazeSDK();\ndebugPaze.logConfiguration(pazeConfig);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prevention-and-best-practices","__idx":26},"children":["Prevention and best practices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"proactive-error-prevention","__idx":27},"children":["Proactive error prevention"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Run pre-flight checks before creating the Paze button to catch configuration issues early:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Pre-flight checks before initializing Paze\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: 'Paze SDK loaded',\n      test: () => !!(window.DIGITAL_WALLET_SDK && window.DIGITAL_WALLET_SDK.canCheckout),\n      fix: 'Ensure Paze SDK script is loaded'\n    },\n    {\n      name: 'Session Paze configuration',\n      test: () => {\n        const pazeConfig = pxpSdk.getConfig().session?.allowedFundingTypes?.wallets?.paze;\n        return pazeConfig?.clientId;\n      },\n      fix: 'Enable Paze in Unity Portal and ensure it\\'s in session response'\n    },\n    {\n      name: 'Currency is USD',\n      test: () => pxpSdk.getConfig().transactionData.currency === 'USD',\n      fix: 'Paze only supports USD currency'\n    },\n    {\n      name: 'Identity fields for dynamic presentment',\n      test: () => {\n        if (pazeConfig.buttonRenderMode !== 'dynamic') return true;\n\n        const email = pazeConfig.emailAddress;\n        const phone = pazeConfig.phoneNumber;\n        return email &&\n               /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email) &&\n               email.length <= 128 &&\n               phone &&\n               /^1\\d{10}$/.test(phone);\n      },\n      fix: 'Dynamic presentment requires valid emailAddress and phoneNumber (US E.164 without +, 11 digits)'\n    },\n    {\n      name: 'Valid transaction amount',\n      test: () => {\n        const amount = pxpSdk.getConfig().transactionData.amount;\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 (Chrome 80+, Safari 13.1+, Firefox 75+, Edge 80+)'\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 80+\n  if (/Chrome\\/(\\d+)/.test(ua)) {\n    return parseInt(RegExp.$1) >= 80;\n  }\n  \n  // Safari 13.1+\n  if (/Version\\/(\\d+)\\.(\\d+)/.test(ua) && /Safari/.test(ua)) {\n    const major = parseInt(RegExp.$1);\n    const minor = parseInt(RegExp.$2);\n    return major > 13 || (major === 13 && minor >= 1);\n  }\n  \n  // Firefox 75+\n  if (/Firefox\\/(\\d+)/.test(ua)) {\n    return parseInt(RegExp.$1) >= 75;\n  }\n  \n  // Edge 80+\n  if (/Edg\\/(\\d+)/.test(ua)) {\n    return parseInt(RegExp.$1) >= 80;\n  }\n  \n  return false;\n}\n\n// Use before initialisation\nasync function initializePaze() {\n  const preflightPassed = await performPreflightChecks();\n  \n  if (preflightPassed) {\n    const pazeButton = pxpSdk.create('paze-button', pazeConfig);\n    pazeButton.mount('paze-container');\n  } else {\n    console.warn('Preflight checks failed, showing alternative payment methods');\n    showFallbackPaymentOptions();\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"monitoring-and-alerting","__idx":28},"children":["Monitoring and alerting"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Wire Paze callbacks into your error monitoring and analytics services:"]},{"$$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    // Alert on critical errors\n    if (this.isCriticalError(error)) {\n      this.alertOpsTeam(errorData);\n    }\n  },\n  \n  isCriticalError(error) {\n    const criticalCodes = [\n      'SDK1200', // SDK load failed\n      'SDK1206', // Initialisation failed\n      'SDK1233'  // Decryption failed\n    ];\n    \n    return criticalCodes.includes(error.ErrorCode);\n  },\n  \n  trackPazeEvent(eventType, data) {\n    // Track Paze 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  sendToErrorService(data) {\n    // Example: Sentry\n    if (window.Sentry) {\n      Sentry.captureException(new Error(data.message), {\n        extra: data\n      });\n    }\n  },\n  \n  sendToAnalytics(data) {\n    // Example: Google Analytics\n    if (window.gtag) {\n      gtag('event', data.type, data.data);\n    }\n  },\n  \n  alertOpsTeam(errorData) {\n    // Send alert to operations team\n    fetch('/api/alerts', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify(errorData)\n    });\n  }\n};\n\n// Integration with Paze component\nconst config = {\n  onError: (error) => {\n    errorMonitoring.captureError(error, { component: 'Paze' });\n    handlePazeError(error);\n  },\n  \n  onPresentmentResolved: (isVisible) => {\n    errorMonitoring.trackPazeEvent('presentment_resolved', {\n      isVisible\n    });\n  },\n  \n  onCheckoutComplete: (result) => {\n    errorMonitoring.trackPazeEvent('checkout_complete', {\n      sessionId: result.checkoutDecodedResponse?.sessionId,\n      cardNetwork: result.checkoutDecodedResponse?.maskedCard?.paymentCardNetwork\n    });\n    return true;\n  },\n  \n  onPostAuthorisation: (data) => {\n    errorMonitoring.trackPazeEvent('payment_completed', {\n      success: data.state === 'Authorised',\n      merchantTransactionId: data.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":"Portal and session setup","id":"portal-and-session-setup","depth":2},{"value":"Paze service not visible on site","id":"paze-service-not-visible-on-site","depth":3},{"value":"Missing client ID in session","id":"missing-client-id-in-session","depth":3},{"value":"SDK1202 error on mount","id":"sdk1202-error-on-mount","depth":3},{"value":"Troubleshooting common issues","id":"troubleshooting-common-issues","depth":2},{"value":"Paze button isn't showing","id":"paze-button-isnt-showing","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps","depth":4},{"value":"Solutions","id":"solutions","depth":4},{"value":"Wallet presentment not resolving","id":"wallet-presentment-not-resolving","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-1","depth":4},{"value":"Solutions","id":"solutions-1","depth":4},{"value":"Checkout fails or gets cancelled","id":"checkout-fails-or-gets-cancelled","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-2","depth":4},{"value":"Solutions","id":"solutions-2","depth":4},{"value":"Token decryption fails","id":"token-decryption-fails","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-3","depth":4},{"value":"Solutions","id":"solutions-3","depth":4},{"value":"Payment authorisation failures","id":"payment-authorisation-failures","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-4","depth":4},{"value":"Solutions","id":"solutions-4","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-06-22T12:35:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/web/paze/troubleshooting","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}