{"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 card payment components."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"common-issues","__idx":1},"children":["Common issues"]},{"$$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":"Issue"},"children":["Issue"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Description"},"children":["Description"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Next steps"},"children":["Next steps"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Component not rendering."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Card input fields don't appear in the container."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that the container ID exists in the DOM."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check that the component is properly mounted after ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pxpSdk.create()"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure the SDK is fully initialised before creating components."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check browser console for JavaScript errors."]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Validation errors."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Card number or other fields show validation errors."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify card number format (Luhn algorithm check)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check expiry date is in the future."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure CVV length matches card type (3 digits for most, 4 for Amex)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Validate that all required fields are filled."]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["3DS challenge not appearing."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["3D Secure authentication modal doesn't show."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that 3DS is enabled in the Unity Portal."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check that the card supports 3DS."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure iframes are not blocked by browser/CSP."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify network connectivity to authentication server."]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Tokenisation fails."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Card tokenisation fails before transaction."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check Unity API connectivity."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify session data is valid and not expired."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure HMAC signature is correctly generated."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check that card data is properly formatted."]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Styling issues."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Custom styles not applying to components."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify CSS selectors match component structure."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check that styles are loaded after component mounts."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["customComponentCss"]}," config for iframe-based fields."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure no conflicting global styles."]}]}]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Submit button disabled."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Submit button remains disabled even with valid data."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check that all required components are created and mounted."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that all fields pass validation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onFieldValid"]}," events are firing."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check for JavaScript errors preventing state updates."]}]}]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"error-codes-and-exceptions","__idx":2},"children":["Error codes and exceptions"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"component-exceptions","__idx":3},"children":["Component exceptions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The card components throw 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":"Error Code"},"children":["Error Code"]},{"$$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":["SDK0200"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ComponentException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Generic component error."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Validate configuration before component creation."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0201"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ComponentContainerNotFoundException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The container element doesn't exist in the DOM."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Ensure container exists before calling ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mount()"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0202"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ComponentNameEmptyException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Component name is missing or empty."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Always provide valid component type to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["create()"]},"."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0301"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TokenizeCardException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Card tokenisation failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Verify API connectivity and session validity."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0400"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ThreeDSecureException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["3D Secure authentication error."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check 3DS configuration and network access."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0401"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["PreInitiateAuthenticationException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Pre-authentication request failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Verify transaction data and session."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0402"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["InitiateAuthenticationException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Authentication initiation failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Check 3DS server connectivity."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0403"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AuthenticationRequiredException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["3DS authentication required but not completed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Implement 3DS flow properly."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0404"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AuthenticationChallengeException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Challenge presentation failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Ensure iframe access and proper event handling."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0405"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["AuthenticationRejected Exception"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Card issuer rejected authentication."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Inform customer to contact their bank."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0500"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["NetworkException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Network connectivity error."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Implement retry logic and check internet connection."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["SDK0501"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ValidationException"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Field validation failed."]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Display specific validation messages to user."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-component-rendering","__idx":4},"children":["Troubleshooting component rendering"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"card-components-not-appearing","__idx":5},"children":["Card components not appearing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptoms:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Empty containers where card fields should be."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["No visible input fields for card number, expiry, CVV."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Console errors about missing containers."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps","__idx":6},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Step 1: Verify DOM is ready\nconsole.log('Checking DOM readiness...');\nconst container = document.getElementById('card-number-container');\nif (!container) {\n  console.error('Container not found in DOM');\n} else {\n  console.log('Container exists:', container);\n}\n\n// Step 2: Verify SDK initialisation\nconsole.log('Checking SDK initialisation...');\nif (typeof pxpSdk === 'undefined') {\n  console.error('PxpCheckout SDK not initialised');\n} else {\n  console.log('SDK initialised successfully');\n}\n\n// Step 3: Check component creation\ntry {\n  const cardNumber = pxpSdk.create('card-number');\n  console.log('Card number component created:', cardNumber);\n  \n  // Try to mount\n  cardNumber.mount('card-number-container');\n  console.log('Card number component mounted successfully');\n} catch (error) {\n  console.error('Component creation/mount failed:', error);\n}\n\n// Step 4: Check for iframe creation\nsetTimeout(() => {\n  const iframe = container.querySelector('iframe');\n  if (iframe) {\n    console.log('Iframe created successfully');\n  } else {\n    console.error('No iframe found - component may not have mounted');\n  }\n}, 500);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions","__idx":7},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Ensure proper DOM timing:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// ❌ Bad - Mount before DOM is ready\nconst cardNumber = pxpSdk.create('card-number');\ncardNumber.mount('card-number-container'); // May fail if DOM not ready\n\n// ✅ Good - Wait for DOM\ndocument.addEventListener('DOMContentLoaded', () => {\n  const cardNumber = pxpSdk.create('card-number');\n  cardNumber.mount('card-number-container');\n});\n\n// ✅ Better - Check container exists\nfunction mountCardComponent() {\n  const container = document.getElementById('card-number-container');\n  \n  if (!container) {\n    console.error('Container not found, retrying...');\n    setTimeout(mountCardComponent, 100);\n    return;\n  }\n  \n  const cardNumber = pxpSdk.create('card-number');\n  cardNumber.mount('card-number-container');\n}\n\n// ✅ Best - Use framework lifecycle hooks\n// React\nuseEffect(() => {\n  if (containerRef.current && pxpSdk) {\n    const cardNumber = pxpSdk.create('card-number');\n    cardNumber.mount(containerRef.current);\n    \n    return () => cardNumber.unmount();\n  }\n}, [pxpSdk]);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Handle SDK initialisation errors:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"let pxpSdk;\n\ntry {\n  pxpSdk = PxpCheckout.initialize({\n    environment: 'production',\n    session: sessionData,\n    ownerId: 'MERCHANT-1',\n    ownerType: 'MerchantGroup'\n  });\n  \n  console.log('SDK initialised successfully');\n} catch (error) {\n  console.error('SDK initialisation failed:', error);\n  \n  // Show user-friendly error\n  showError('Payment system unavailable. Please try again later.');\n  \n  // Log to monitoring service\n  logError('SDK_INIT_FAILED', error);\n  \n  return; // Don't proceed with component creation\n}\n\n// Now safe to create components\nconst cardNumber = pxpSdk.create('card-number');\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Verify container visibility:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"function diagnoseContainerVisibility() {\n  const container = document.getElementById('card-number-container');\n  \n  if (!container) {\n    console.error('Container not found');\n    return false;\n  }\n  \n  const styles = window.getComputedStyle(container);\n  const diagnostics = {\n    display: styles.display,\n    visibility: styles.visibility,\n    opacity: styles.opacity,\n    width: styles.width,\n    height: styles.height,\n    position: styles.position,\n    isInViewport: isElementInViewport(container)\n  };\n  \n  console.log('Container diagnostics:', diagnostics);\n  \n  // Check for common issues\n  if (styles.display === 'none') {\n    console.warn('Container has display:none - component won\\'t be visible');\n  }\n  \n  if (parseInt(styles.width) === 0 || parseInt(styles.height) === 0) {\n    console.warn('Container has zero dimensions');\n  }\n  \n  return true;\n}\n\nfunction isElementInViewport(el) {\n  const rect = el.getBoundingClientRect();\n  return (\n    rect.top >= 0 &&\n    rect.left >= 0 &&\n    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n    rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n  );\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-validation","__idx":8},"children":["Troubleshooting validation"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"card-number-validation-fails","__idx":9},"children":["Card number validation fails"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptoms:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Valid card numbers show as invalid."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Error messages appear immediately on input."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Unable to proceed with payment."]}]},{"$$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":"// Test card validation logic\nfunction testCardValidation(cardNumber) {\n  console.group('Card Validation Test');\n  console.log('Testing card number:', cardNumber);\n  \n  // Check Luhn algorithm\n  const isLuhnValid = validateLuhn(cardNumber);\n  console.log('Luhn valid:', isLuhnValid);\n  \n  // Check card type\n  const cardType = detectCardType(cardNumber);\n  console.log('Detected card type:', cardType);\n  \n  // Check length\n  const lengthValid = validateCardLength(cardNumber, cardType);\n  console.log('Length valid:', lengthValid);\n  \n  console.groupEnd();\n  \n  return isLuhnValid && lengthValid;\n}\n\nfunction validateLuhn(cardNumber) {\n  const digits = cardNumber.replace(/\\D/g, '');\n  let sum = 0;\n  let isEven = false;\n  \n  for (let i = digits.length - 1; i >= 0; i--) {\n    let digit = parseInt(digits[i]);\n    \n    if (isEven) {\n      digit *= 2;\n      if (digit > 9) {\n        digit -= 9;\n      }\n    }\n    \n    sum += digit;\n    isEven = !isEven;\n  }\n  \n  return sum % 10 === 0;\n}\n\nfunction detectCardType(cardNumber) {\n  const patterns = {\n    visa: /^4/,\n    mastercard: /^5[1-5]|^2[2-7]/,\n    amex: /^3[47]/,\n    discover: /^6(?:011|5)/,\n    diners: /^3(?:0[0-5]|[68])/,\n    jcb: /^35/\n  };\n  \n  for (const [type, pattern] of Object.entries(patterns)) {\n    if (pattern.test(cardNumber)) {\n      return type;\n    }\n  }\n  \n  return 'unknown';\n}\n\nfunction validateCardLength(cardNumber, cardType) {\n  const expectedLengths = {\n    visa: [13, 16, 19],\n    mastercard: [16],\n    amex: [15],\n    discover: [16, 19],\n    diners: [14],\n    jcb: [16, 19]\n  };\n  \n  const digits = cardNumber.replace(/\\D/g, '');\n  const expected = expectedLengths[cardType] || [16];\n  \n  return expected.includes(digits.length);\n}\n\n// Test with various card numbers\ntestCardValidation('4111111111111111'); // Valid Visa\ntestCardValidation('5555555555554444'); // Valid Mastercard\ntestCardValidation('378282246310005');  // Valid Amex\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-1","__idx":11},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Listen to validation events:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const cardNumberConfig = {\n  onChange: (event) => {\n    console.log('Card number changed:', {\n      complete: event.complete,\n      valid: event.valid,\n      brand: event.brand,\n      error: event.error\n    });\n    \n    // Update UI based on validation\n    if (event.error) {\n      showFieldError('card-number', event.error.message);\n    } else {\n      clearFieldError('card-number');\n    }\n    \n    // Update submit button state\n    updateSubmitButton();\n  },\n  \n  onFieldValid: () => {\n    console.log('Card number is valid');\n    highlightField('card-number', 'valid');\n  },\n  \n  onFieldInvalid: (error) => {\n    console.log('Card number is invalid:', error);\n    highlightField('card-number', 'invalid');\n  }\n};\n\nconst cardNumber = pxpSdk.create('card-number', cardNumberConfig);\ncardNumber.mount('card-number-container');\n\nfunction showFieldError(fieldName, message) {\n  const errorElement = document.getElementById(`${fieldName}-error`);\n  if (errorElement) {\n    errorElement.textContent = message;\n    errorElement.style.display = 'block';\n  }\n}\n\nfunction clearFieldError(fieldName) {\n  const errorElement = document.getElementById(`${fieldName}-error`);\n  if (errorElement) {\n    errorElement.textContent = '';\n    errorElement.style.display = 'none';\n  }\n}\n\nfunction highlightField(fieldName, state) {\n  const container = document.getElementById(`${fieldName}-container`);\n  if (container) {\n    container.classList.remove('valid', 'invalid');\n    if (state !== 'neutral') {\n      container.classList.add(state);\n    }\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Implement custom validation:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Add business-specific validation rules\nconst cardSubmitConfig = {\n  beforeSubmit: () => {\n    // Custom validation before tokenisation\n    const validationErrors = [];\n    \n    // Check if card is in excluded BIN list\n    const cardNumber = getCardNumberValue();\n    if (isExcludedBIN(cardNumber)) {\n      validationErrors.push('This card type is not accepted');\n    }\n    \n    // Check amount limits for card type\n    const amount = getTransactionAmount();\n    const cardType = detectCardType(cardNumber);\n    if (amount > getMaxAmountForCard Type(cardType)) {\n      validationErrors.push(`Amount exceeds limit for ${cardType} cards`);\n    }\n    \n    // Show errors if any\n    if (validationErrors.length > 0) {\n      showValidationErrors(validationErrors);\n      return false; // Prevent submission\n    }\n    \n    return true; // Allow submission\n  },\n  \n  onSubmitError: (error) => {\n    if (error.ErrorCode === 'SDK0501') {\n      // Validation error from SDK\n      console.error('Validation error:', error.message);\n      showError(error.message);\n    }\n  }\n};\n\nfunction isExcludedBIN(cardNumber) {\n  const excludedBINs = ['123456', '654321']; // Example\n  const bin = cardNumber.substring(0, 6);\n  return excludedBINs.includes(bin);\n}\n\nfunction getMaxAmountForCardType(cardType) {\n  const limits = {\n    amex: 10000,\n    visa: 15000,\n    mastercard: 15000,\n    discover: 10000\n  };\n  return limits[cardType] || 5000;\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"expiry-date-validation-issues","__idx":12},"children":["Expiry date validation issues"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptoms:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Valid future dates show as invalid."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Past dates are accepted."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Format errors with MM/YY input."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-2","__idx":13},"children":["Solutions"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const expiryConfig = {\n  onChange: (event) => {\n    if (!event.valid && event.complete) {\n      // Card is expired\n      showFieldError('expiry', 'Card has expired. Please use a different card.');\n    } else if (event.error) {\n      showFieldError('expiry', event.error.message);\n    } else {\n      clearFieldError('expiry');\n    }\n  },\n  \n  // Additional validation\n  customValidation: (month, year) => {\n    const now = new Date();\n    const currentMonth = now.getMonth() + 1; // 0-indexed\n    const currentYear = now.getFullYear() % 100; // Last 2 digits\n    \n    // Check if card expires within 30 days\n    if (year === currentYear && month === currentMonth) {\n      showFieldWarning('expiry', 'Card expires soon. Consider using a different card.');\n    }\n    \n    // Check if expiry is too far in future (potential typo)\n    if (year > currentYear + 10) {\n      showFieldWarning('expiry', 'Please verify the expiry date.');\n    }\n  }\n};\n\nfunction showFieldWarning(fieldName, message) {\n  const warningElement = document.getElementById(`${fieldName}-warning`);\n  if (warningElement) {\n    warningElement.textContent = message;\n    warningElement.style.display = 'block';\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-3d-secure","__idx":14},"children":["Troubleshooting 3D Secure"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"3ds-challenge-iframe-not-loading","__idx":15},"children":["3DS challenge iframe not loading"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptoms:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["3DS challenge window doesn't appear."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Transaction fails with authentication error."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Console shows iframe loading errors."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-2","__idx":16},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"function diagnose3DSSetup() {\n  console.group('3DS Diagnostic Check');\n  \n  // Check CSP settings\n  const csp = document.querySelector('meta[http-equiv=\"Content-Security-Policy\"]');\n  console.log('CSP meta tag:', csp ? csp.content : 'Not found');\n  \n  // Check if iframes are blocked\n  try {\n    const testIframe = document.createElement('iframe');\n    testIframe.src = 'about:blank';\n    document.body.appendChild(testIframe);\n    console.log('Iframe creation: Allowed');\n    document.body.removeChild(testIframe);\n  } catch (error) {\n    console.error('Iframe creation: Blocked', error);\n  }\n  \n  // Check network connectivity to 3DS servers\n  checkThreeDSConnectivity();\n  \n  console.groupEnd();\n}\n\nasync function checkThreeDSConnectivity() {\n  const threeDSServers = [\n    'https://threeds2.example.com',\n    // Add your actual 3DS server URLs\n  ];\n  \n  for (const server of threeDSServers) {\n    try {\n      const response = await fetch(server, { method: 'HEAD', mode: 'no-cors' });\n      console.log(`3DS Server ${server}: Reachable`);\n    } catch (error) {\n      console.error(`3DS Server ${server}: Not reachable`, error);\n    }\n  }\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":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Update Content Security Policy:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"html","header":{"controls":{"copy":{}}},"source":"<!-- Add 3DS servers to CSP -->\n<meta http-equiv=\"Content-Security-Policy\" \n      content=\"frame-src 'self' https://threeds2.example.com https://*.3dsecure.io;\">\n","lang":"html"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Handle 3DS events properly:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const cardSubmitConfig = {\n  onSubmit: () => {\n    console.log('Payment submission started');\n    showLoadingIndicator('Processing payment...');\n  },\n  \n  on3DSInitiated: () => {\n    console.log('3DS authentication initiated');\n    showLoadingIndicator('Verifying your card...');\n  },\n  \n  on3DSChallengePresented: () => {\n    console.log('3DS challenge presented to user');\n    hideLoadingIndicator();\n    showMessage('Please complete authentication in the popup');\n  },\n  \n  on3DSComplete: (result) => {\n    console.log('3DS authentication completed:', result);\n    \n    if (result.authenticated) {\n      showLoadingIndicator('Completing payment...');\n    } else {\n      showError('Authentication failed. Please try again or use a different card.');\n    }\n  },\n  \n  onPostAuthorisation: (result) => {\n    console.log('Payment authorised:', result);\n    hideLoadingIndicator();\n    \n    // Redirect to success page\n    window.location.href = `/success?id=${result.systemTransactionId}`;\n  },\n  \n  onSubmitError: (error) => {\n    console.error('Payment failed:', error);\n    hideLoadingIndicator();\n    \n    if (error.ErrorCode === 'SDK0505') {\n      showError('Card authentication failed. Please contact your bank or try a different card.');\n    } else {\n      showError(`Payment failed: ${error.message}`);\n    }\n  }\n};\n\nconst cardSubmit = pxpSdk.create('card-submit', cardSubmitConfig);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Implement 3DS timeout handling:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"let threeDSTimeout;\n\nconst cardSubmitConfig = {\n  on3DSChallengePresented: () => {\n    // Set 5-minute timeout for 3DS challenge\n    threeDSTimeout = setTimeout(() => {\n      console.warn('3DS challenge timeout');\n      showError('Authentication timed out. Please try again.');\n      \n      // Cancel the transaction\n      cancelPayment();\n    }, 5 * 60 * 1000);\n  },\n  \n  on3DSComplete: () => {\n    // Clear timeout when 3DS completes\n    if (threeDSTimeout) {\n      clearTimeout(threeDSTimeout);\n      threeDSTimeout = null;\n    }\n  },\n  \n  onSubmitError: () => {\n    // Clear timeout on error\n    if (threeDSTimeout) {\n      clearTimeout(threeDSTimeout);\n      threeDSTimeout = null;\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-tokenisation","__idx":18},"children":["Troubleshooting tokenisation"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"tokenisation-failures","__idx":19},"children":["Tokenisation failures"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptoms:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Payment fails before reaching transaction stage."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Error: \"Unable to tokenise card\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Network errors in console."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"diagnostic-steps-3","__idx":20},"children":["Diagnostic steps"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"async function diagnoseTokenisation() {\n  console.group('Tokenisation Diagnostic');\n  \n  // Check session validity\n  const sessionData = pxpSdk.getSession();\n  console.log('Session data:', {\n    sessionId: sessionData.sessionId ? 'Present' : 'Missing',\n    expiresAt: sessionData.expiresAt,\n    isExpired: sessionData.expiresAt ? new Date(sessionData.expiresAt) < new Date() : 'Unknown'\n  });\n  \n  // Check HMAC signature\n  const hmac = sessionData.hmacSignature;\n  console.log('HMAC signature:', hmac ? 'Present' : 'Missing');\n  \n  // Check API connectivity\n  try {\n    const response = await fetch('https://api.pxp.io/health', { mode: 'no-cors' });\n    console.log('API connectivity: OK');\n  } catch (error) {\n    console.error('API connectivity: Failed', error);\n  }\n  \n  // Check token vault URL\n  const tokenVaultUrl = pxpSdk.getConfig().tokenVaultUrl;\n  console.log('Token Vault URL:', tokenVaultUrl);\n  \n  console.groupEnd();\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-4","__idx":21},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Handle session expiration:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const cardSubmitConfig = {\n  beforeSubmit: async () => {\n    // Check if session is about to expire\n    const session = pxpSdk.getSession();\n    const expiresAt = new Date(session.expiresAt);\n    const now = new Date();\n    const minutesUntilExpiry = (expiresAt - now) / (1000 * 60);\n    \n    if (minutesUntilExpiry < 5) {\n      console.log('Session expiring soon, refreshing...');\n      \n      try {\n        // Request new session from backend\n        const newSession = await fetch('/api/create-session').then(r => r.json());\n        \n        // Reinitialise SDK with new session\n        pxpSdk.updateSession(newSession);\n        \n        console.log('Session refreshed successfully');\n        return true;\n      } catch (error) {\n        console.error('Failed to refresh session:', error);\n        showError('Your session has expired. Please refresh the page.');\n        return false;\n      }\n    }\n    \n    return true;\n  },\n  \n  onSubmitError: async (error) => {\n    if (error.message.includes('session') || error.message.includes('expired')) {\n      // Session expired during submission\n      showError('Your session has expired. Refreshing...');\n      \n      // Refresh page after short delay\n      setTimeout(() => {\n        window.location.reload();\n      }, 2000);\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Implement retry logic:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"async function submitPaymentWithRetry(maxRetries = 3) {\n  for (let attempt = 1; attempt <= maxRetries; attempt++) {\n    try {\n      console.log(`Payment attempt ${attempt}/${maxRetries}`);\n      \n      // Trigger card submit\n      const result = await cardSubmit.submit();\n      \n      console.log('Payment successful:', result);\n      return result;\n      \n    } catch (error) {\n      console.error(`Attempt ${attempt} failed:`, error);\n      \n      // Check if error is retryable\n      if (isRetryableError(error) && attempt < maxRetries) {\n        const delay = Math.min(1000 * Math.pow(2, attempt), 5000);\n        console.log(`Retrying in ${delay}ms...`);\n        await new Promise(resolve => setTimeout(resolve, delay));\n        continue;\n      }\n      \n      // Non-retryable error or max retries reached\n      throw error;\n    }\n  }\n}\n\nfunction isRetryableError(error) {\n  const retryableCodes = ['SDK0500', 'SDK0301']; // Network, tokenisation\n  const retryableMessages = ['network', 'timeout', 'temporarily unavailable'];\n  \n  return retryableCodes.includes(error.ErrorCode) ||\n         retryableMessages.some(msg => error.message.toLowerCase().includes(msg));\n}\n\n// Use in submit button handler\ndocument.getElementById('submit-button').addEventListener('click', async () => {\n  try {\n    showLoadingIndicator();\n    const result = await submitPaymentWithRetry();\n    handleSuccess(result);\n  } catch (error) {\n    handleError(error);\n  } finally {\n    hideLoadingIndicator();\n  }\n});\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting-styling","__idx":22},"children":["Troubleshooting styling"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"custom-styles-not-applying","__idx":23},"children":["Custom styles not applying"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Symptoms:"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Component styling doesn't match design."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["CSS changes have no effect."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Inconsistent appearance across components."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"solutions-5","__idx":24},"children":["Solutions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use customComponentCss for iframe fields:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const cardNumberConfig = {\n  customComponentCss: {\n    base: {\n      fontSize: '16px',\n      fontFamily: '\"Helvetica Neue\", Helvetica, sans-serif',\n      color: '#32325d',\n      '::placeholder': {\n        color: '#aab7c4'\n      }\n    },\n    invalid: {\n      color: '#fa755a',\n      iconColor: '#fa755a'\n    },\n    valid: {\n      color: '#32cd32'\n    }\n  }\n};\n\nconst cardNumber = pxpSdk.create('card-number', cardNumberConfig);\ncardNumber.mount('card-number-container');\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Style containers consistently:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":"/* Container styling (applies to all components) */\n.card-field-container {\n  margin-bottom: 16px;\n  position: relative;\n}\n\n.card-field-container label {\n  display: block;\n  margin-bottom: 8px;\n  font-weight: 600;\n  color: #32325d;\n  font-size: 14px;\n}\n\n.card-field-container .field-wrapper {\n  border: 1px solid #e0e0e0;\n  border-radius: 4px;\n  padding: 12px;\n  background: #fff;\n  transition: all 0.2s ease;\n}\n\n.card-field-container .field-wrapper:focus-within {\n  border-color: #5469d4;\n  box-shadow: 0 0 0 3px rgba(84, 105, 212, 0.1);\n}\n\n.card-field-container.invalid .field-wrapper {\n  border-color: #fa755a;\n}\n\n.card-field-container.valid .field-wrapper {\n  border-color: #32cd32;\n}\n\n.card-field-container .error-message {\n  color: #fa755a;\n  font-size: 13px;\n  margin-top: 4px;\n  display: none;\n}\n\n.card-field-container.invalid .error-message {\n  display: block;\n}\n","lang":"css"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Apply consistent styling across all fields:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Create shared styling config\nconst sharedFieldStyles = {\n  customComponentCss: {\n    base: {\n      fontSize: '16px',\n      fontFamily: '\"Helvetica Neue\", Helvetica, sans-serif',\n      color: '#32325d',\n      lineHeight: '24px',\n      '::placeholder': {\n        color: '#aab7c4'\n      },\n      ':-webkit-autofill': {\n        color: '#32325d'\n      }\n    },\n    invalid: {\n      color: '#fa755a',\n      iconColor: '#fa755a'\n    },\n    valid: {\n      color: '#32cd32'\n    }\n  }\n};\n\n// Apply to all card fields\nconst cardNumber = pxpSdk.create('card-number', sharedFieldStyles);\nconst cardExpiry = pxpSdk.create('card-expiry', sharedFieldStyles);\nconst cardCvv = pxpSdk.create('card-cvv', sharedFieldStyles);\nconst cardName = pxpSdk.create('card-holder-name', sharedFieldStyles);\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":"Heading","attributes":{"level":3,"id":"enable-verbose-logging","__idx":26},"children":["Enable verbose logging"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Enable debug mode globally\nwindow.pxpDebug = {\n  enabled: true,\n  logLevel: 'verbose',\n  logComponents: true,\n  logNetworkRequests: true\n};\n\n// Custom logger\nconst logger = {\n  group(label) {\n    if (window.pxpDebug?.enabled) {\n      console.group(`🔍 ${label}`);\n    }\n  },\n  \n  groupEnd() {\n    if (window.pxpDebug?.enabled) {\n      console.groupEnd();\n    }\n  },\n  \n  log(message, data) {\n    if (window.pxpDebug?.enabled) {\n      console.log(`[PXP] ${message}`, data || '');\n    }\n  },\n  \n  error(message, error) {\n    console.error(`[PXP ERROR] ${message}`, error);\n  }\n};\n\n// Use in your code\nlogger.group('Card Component Setup');\nlogger.log('Creating card number component');\nconst cardNumber = pxpSdk.create('card-number');\nlogger.log('Mounting to container', 'card-number-container');\ncardNumber.mount('card-number-container');\nlogger.groupEnd();\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"comprehensive-event-monitoring","__idx":27},"children":["Comprehensive event monitoring"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Monitor all component events\nfunction monitorComponentEvents(component, componentName) {\n  const events = ['onChange', 'onFocus', 'onBlur', 'onFieldValid', 'onFieldInvalid'];\n  \n  events.forEach(eventName => {\n    if (component[eventName]) {\n      const originalHandler = component[eventName];\n      component[eventName] = function(...args) {\n        console.log(`[${componentName}] ${eventName}`, args);\n        if (originalHandler) {\n          return originalHandler.apply(this, args);\n        }\n      };\n    }\n  });\n  \n  return component;\n}\n\n// Use for debugging\nconst cardNumber = monitorComponentEvents(\n  pxpSdk.create('card-number'),\n  'CardNumber'\n);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"network-request-debugging","__idx":28},"children":["Network request debugging"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Intercept and log all API requests\nconst originalFetch = window.fetch;\nwindow.fetch = async function(...args) {\n  const [url, options] = args;\n  \n  // Log request\n  console.group('🌐 Network Request');\n  console.log('URL:', url);\n  console.log('Method:', options?.method || 'GET');\n  console.log('Headers:', options?.headers);\n  console.groupEnd();\n  \n  try {\n    const response = await originalFetch.apply(this, args);\n    \n    // Log response\n    console.group('✅ Network Response');\n    console.log('URL:', url);\n    console.log('Status:', response.status);\n    console.log('Status Text:', response.statusText);\n    console.groupEnd();\n    \n    return response;\n  } catch (error) {\n    console.group('❌ Network Error');\n    console.log('URL:', url);\n    console.error('Error:', error);\n    console.groupEnd();\n    \n    throw error;\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prevention-and-best-practices","__idx":29},"children":["Prevention and best practices"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"proactive-error-prevention","__idx":30},"children":["Proactive error prevention"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Pre-flight checks before initialisation\nasync function performPreflightChecks() {\n  const checks = [\n    {\n      name: 'Session data validity',\n      test: () => validateSessionData(),\n      fix: 'Request new session from backend'\n    },\n    {\n      name: 'DOM containers exist',\n      test: () => checkContainersExist(),\n      fix: 'Ensure containers are in the DOM before mounting'\n    },\n    {\n      name: 'Network connectivity',\n      test: async () => await checkNetworkConnectivity(),\n      fix: 'Check internet connection'\n    },\n    {\n      name: 'No conflicting scripts',\n      test: () => checkForConflicts(),\n      fix: 'Remove conflicting payment libraries'\n    }\n  ];\n  \n  const results = [];\n  for (const check of checks) {\n    try {\n      const passed = await check.test();\n      results.push({ ...check, passed });\n      \n      if (!passed) {\n        console.warn(`❌ ${check.name}: ${check.fix}`);\n      } else {\n        console.log(`✅ ${check.name}`);\n      }\n    } catch (error) {\n      console.error(`❌ ${check.name} failed:`, error);\n      results.push({ ...check, passed: false, error });\n    }\n  }\n  \n  return results.every(r => r.passed);\n}\n\nfunction validateSessionData() {\n  const sessionData = getSessionData();\n  return sessionData && \n         sessionData.sessionId && \n         sessionData.hmacSignature &&\n         new Date(sessionData.expiresAt) > new Date();\n}\n\nfunction checkContainersExist() {\n  const requiredContainers = [\n    'card-number-container',\n    'card-expiry-container',\n    'card-cvv-container',\n    'card-submit-container'\n  ];\n  \n  return requiredContainers.every(id => document.getElementById(id) !== null);\n}\n\nasync function checkNetworkConnectivity() {\n  try {\n    await fetch('/api/health-check', { method: 'HEAD' });\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nfunction checkForConflicts() {\n  const conflictingScripts = ['stripe', 'braintree', 'square'];\n  return !conflictingScripts.some(script => window[script]);\n}\n\n// Use before initialisation\nasync function initializePaymentForm() {\n  const preflightPassed = await performPreflightChecks();\n  \n  if (!preflightPassed) {\n    showError('Unable to initialise payment form. Please refresh the page.');\n    return;\n  }\n  \n  // Safe to proceed\n  createCardComponents();\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"error-monitoring-and-analytics","__idx":31},"children":["Error monitoring and analytics"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Comprehensive error tracking\nconst errorTracking = {\n  capture(error, context) {\n    const errorData = {\n      message: error.message,\n      code: error.ErrorCode,\n      stack: error.stack,\n      context: context,\n      timestamp: new Date().toISOString(),\n      userAgent: navigator.userAgent,\n      url: location.href,\n      sessionId: getSessionId(),\n      userId: getUserId()\n    };\n    \n    // Send to error monitoring service\n    this.sendToMonitoring(errorData);\n    \n    // Track in analytics\n    this.trackInAnalytics('payment_error', {\n      error_code: error.ErrorCode,\n      error_type: error.name,\n      context: context\n    });\n  },\n  \n  sendToMonitoring(data) {\n    // Example: Sentry, LogRocket, etc.\n    if (window.Sentry) {\n      Sentry.captureException(new Error(data.message), {\n        extra: data\n      });\n    }\n  },\n  \n  trackInAnalytics(event, properties) {\n    // Example: Google Analytics, Mixpanel, etc.\n    if (window.gtag) {\n      gtag('event', event, properties);\n    }\n  }\n};\n\n// Use in component configuration\nconst cardSubmitConfig = {\n  onSubmitError: (error) => {\n    errorTracking.capture(error, 'card_submit');\n    showUserFriendlyError(error);\n  }\n};\n","lang":"typescript"},"children":[]}]},"headings":[{"value":"Troubleshooting","id":"troubleshooting","depth":1},{"value":"Common issues","id":"common-issues","depth":2},{"value":"Error codes and exceptions","id":"error-codes-and-exceptions","depth":2},{"value":"Component exceptions","id":"component-exceptions","depth":3},{"value":"Troubleshooting component rendering","id":"troubleshooting-component-rendering","depth":2},{"value":"Card components not appearing","id":"card-components-not-appearing","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps","depth":4},{"value":"Solutions","id":"solutions","depth":4},{"value":"Troubleshooting validation","id":"troubleshooting-validation","depth":2},{"value":"Card number validation fails","id":"card-number-validation-fails","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-1","depth":4},{"value":"Solutions","id":"solutions-1","depth":4},{"value":"Expiry date validation issues","id":"expiry-date-validation-issues","depth":3},{"value":"Solutions","id":"solutions-2","depth":4},{"value":"Troubleshooting 3D Secure","id":"troubleshooting-3d-secure","depth":2},{"value":"3DS challenge iframe not loading","id":"3ds-challenge-iframe-not-loading","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-2","depth":4},{"value":"Solutions","id":"solutions-3","depth":4},{"value":"Troubleshooting tokenisation","id":"troubleshooting-tokenisation","depth":2},{"value":"Tokenisation failures","id":"tokenisation-failures","depth":3},{"value":"Diagnostic steps","id":"diagnostic-steps-3","depth":4},{"value":"Solutions","id":"solutions-4","depth":4},{"value":"Troubleshooting styling","id":"troubleshooting-styling","depth":2},{"value":"Custom styles not applying","id":"custom-styles-not-applying","depth":3},{"value":"Solutions","id":"solutions-5","depth":4},{"value":"Debugging tools and techniques","id":"debugging-tools-and-techniques","depth":2},{"value":"Enable verbose logging","id":"enable-verbose-logging","depth":3},{"value":"Comprehensive event monitoring","id":"comprehensive-event-monitoring","depth":3},{"value":"Network request debugging","id":"network-request-debugging","depth":3},{"value":"Prevention and best practices","id":"prevention-and-best-practices","depth":2},{"value":"Proactive error prevention","id":"proactive-error-prevention","depth":3},{"value":"Error monitoring and analytics","id":"error-monitoring-and-analytics","depth":3}],"frontmatter":{"seo":{"title":"Troubleshooting"}},"lastModified":"2026-04-15T15:24:26.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/web/card/troubleshooting","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}