{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","br","details"]},"type":"markdown"},"seo":{"title":"Events","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":"events","__idx":0},"children":["Events"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement callbacks to customise your Apple Pay payment flow for Web."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Components emit events based on user interaction or validation. You can use these to implement callback functions, which allow you to inject your own business logic and user experience customisations into the payment flow at critical moments. They ensure that while the SDK handles the complex technical aspects of payment processing, you retain full control over the customer experience and can seamlessly integrate payments into your broader business workflows and systems."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Callbacks enable you to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Validate business rules before payments proceed."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Display custom error, failure, or success messages."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Tailor user interfaces to match your brand's look and feel."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Integrate with your own systems for fraud detection or customer management."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Control exactly how your customers experience both successful and failed transactions."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Handle Apple Pay specific browser and device requirements."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"sdk-data-callbacks","__idx":2},"children":["SDK data callbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Apple Pay component requires an SDK initialisation callback to gather shopper information during transaction processing:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onGetShopper"]}," (required):"]}," Called to retrieve current shopper data (ID, email, name, etc.) for transaction submission to the backend."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback ensures the Apple Pay component always uses the latest customer data from your application state, forms, or APIs when processing payments."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"apple-pay-specific-events","__idx":3},"children":["Apple Pay-specific events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All Apple Pay-specific events are optional and can be mixed and matched based on your business needs."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The SDK initialisation callback (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onGetShopper"]},") works alongside Apple Pay-specific callbacks to provide a complete payment experience. SDK callbacks handle backend transaction data, while Apple Pay callbacks handle the payment sheet interactions."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"optional-apple-pay-events","__idx":4},"children":["Optional Apple Pay events"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpostauthorisation","__idx":5},"children":["onPostAuthorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered after the customer authorises the payment with Touch ID, Face ID, or passcode, providing transaction identifiers."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Retrieve full authorisation result from your backend using the transaction identifiers."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Redirect customers to a success page with order confirmation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update stock levels for purchased items."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Send order confirmation emails to customers."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Record successful transactions for business intelligence."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data","__idx":6},"children":["Event data"]},{"$$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":"Event data"},"children":["Event data"]},{"$$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":["data"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Object containing transaction identifiers."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.merchantTransactionId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Your unique identifier for the transaction. Use this to retrieve full authorisation details from the Unity backend."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data.systemTransactionId"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The unique PXP system transaction identifier."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation","__idx":7},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onPostAuthorisation: async (data) => {\n  console.log('Payment authorisation completed');\n  console.log('Merchant Transaction ID:', data.merchantTransactionId);\n  console.log('System Transaction ID:', data.systemTransactionId);\n  \n  // Get authorisation result from merchant backend\n  const authorisationResult = await getAuthorisationResultFromGateway(\n    data.merchantTransactionId, \n    data.systemTransactionId\n  );\n  \n  if (authorisationResult.status === 'Authorised') {\n    // Update inventory\n    await updateInventory(data.merchantTransactionId);\n    \n    // Send confirmation email\n    await sendConfirmationEmail(\n      authorisationResult.customerEmail, \n      data.merchantTransactionId\n    );\n    \n    // Track analytics\n    trackPurchase(data.merchantTransactionId, authorisationResult.amount);\n    \n    // Redirect to success page\n    window.location.href = `/payment-success?txn=${data.merchantTransactionId}`;\n  } else if (authorisationResult.status === 'Declined') {\n    console.error('Payment declined:', authorisationResult.reason);\n    showErrorMessage('Payment declined. Please try again or use a different payment method.');\n  } else {\n    console.error('Payment exception:', authorisationResult.reason);\n    showErrorMessage('Payment processing error. Please contact support.');\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpreauthorisation","__idx":8},"children":["onPreAuthorisation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered before payment authorisation, allowing you to provide authorisation configuration or control whether to proceed."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update the authorisation decision in your backend."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Integrate with Kount or other fraud detection services."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Perform AVS (Address Verification System) checks."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Apply business rules based on transaction amount or customer history."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check product availability before processing payment."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Control whether to proceed with authorisation by returning null."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After evaluating transaction details, use the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/apis/session/other/modify-session"},"children":["Modify session"]}," API to update the authorisation decision on your backend before returning from this callback. Set ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"allowTransaction\": true"]}," in the session data to proceed with the transaction."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-1","__idx":9},"children":["Event data"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback receives no parameters."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-1","__idx":10},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["To proceed with authorisation:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onPreAuthorisation: async () => {\n  // Perform pre-payment validation\n  const deviceSessionId = await getKountSessionId();\n  const isHighRisk = await checkCustomerRiskProfile();\n  const customerTier = await getCustomerTier();\n  \n  // Get billing address if AVS is enabled\n  const billingAddress = await getBillingAddress();\n  \n  // Update authorisation decision to true in backend via Modify Session API\n  await updateSessionAuthorisationDecision(true);\n  \n  return {\n    addressVerification: billingAddress ? {\n      countryCode: billingAddress.countryCode,\n      houseNumberOrName: billingAddress.address,\n      postalCode: billingAddress.postalCode,\n      city: billingAddress.city,\n      state: billingAddress.state\n    } : undefined,\n    riskScreeningData: {\n      deviceSessionId: deviceSessionId,\n      performRiskScreening: true,\n      userIp: \"192.168.1.100\",\n      account: {\n        id: \"user_12345678\",\n        creationDateTime: \"2024-01-15T10:30:00.000Z\"\n      },\n      items: [{\n        price: 140.00,\n        quantity: 1,\n        category: \"Electronics\"\n      }],\n      fulfillments: [{\n        type: \"Shipped\",\n        shipping: {\n          shippingMethod: \"Express\"\n        },\n        recipientPerson: {\n          phoneNumber: \"+1234567890\",\n          email: \"customer@example.com\"\n        }\n      }]\n    }\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["If you don't want to proceed with authorisation:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onPreAuthorisation: async () => {\n  // Check if authorisation should proceed\n  const shouldProceed = await checkAuthorizationDecision();\n  \n  if (!shouldProceed) {\n    // Update authorisation decision to false in backend via Modify Session API\n    await updateSessionAuthorisationDecision(false);\n    // Stop the authorisation process\n    return null;\n  }\n  \n  // Update authorisation decision to true in backend via Modify Session API\n  await updateSessionAuthorisationDecision(true);\n  \n  // Return authorisation configuration\n  return {\n    riskScreeningData: {\n      performRiskScreening: true,\n      userIp: \"192.168.1.100\",\n      account: {\n        id: \"user_12345678\",\n        creationDateTime: \"2024-01-15T10:30:00.000Z\"\n      },\n      fulfillments: [{\n        type: \"Shipped\",\n        recipientPerson: {\n          phoneNumber: \"+1234567890\"\n        }\n      }]\n    }\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onerror","__idx":11},"children":["onError"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when an error occurs during the Apple Pay payment process."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Log errors for debugging and monitoring."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Display user-friendly error messages"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Offer alternative payment methods."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Implement automatic retry for transient errors."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-2","__idx":12},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["error"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["Error"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error object containing details about what went wrong."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.message"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A human-readable error description."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.name"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error type."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.code"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The error code for programmatic handling."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.stack"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The stack trace for debugging."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-2","__idx":13},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onError: (error) => {\n  console.error('Apple Pay error:', error);\n  \n  // Log error for debugging\n  logError('apple-pay-error', {\n    message: error.message,\n    code: error.code,\n    timestamp: new Date().toISOString()\n  });\n  \n  // Handle different error types\n  if (error.message.includes('User cancelled')) {\n    // Silent handling - user intentionally cancelled\n    return;\n  } else if (error.message.includes('Network')) {\n    showUserMessage('Network error. Please check your connection and try again.');\n    // Offer offline payment options\n  } else if (error.message.includes('Merchant validation')) {\n    showUserMessage('Payment system temporarily unavailable. Please try again later.');\n    // Alert support team\n    notifySupport('Apple Pay merchant validation failed');\n  } else {\n    showUserMessage('Payment failed. Please try again or use a different payment method.');\n    // Show alternative payment options\n    showAlternativePaymentMethods();\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"oncancel","__idx":14},"children":["onCancel"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the customer cancels the Apple Pay payment flow."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Track cancellation rates for conversion optimisation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Show helpful messages or alternative options."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Save the customer's cart for later completion."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Trigger email campaigns for abandoned checkouts."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-3","__idx":15},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["error"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["Error"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Error object indicating cancellation reason (optional)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.message"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The cancellation reason."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error.code"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The cancellation code, for tracking purposes."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-3","__idx":16},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onCancel: (error) => {\n  console.log('Apple Pay cancelled:', error);\n  \n  // Track cancellation for analytics\n  trackEvent('apple-pay-cancelled', {\n    reason: error?.message || 'unknown',\n    timestamp: new Date().toISOString(),\n    cartValue: getCurrentCartValue()\n  });\n  \n  // Preserve cart for later\n  saveCartForLater();\n  \n  // Show helpful message\n  showMessage('No worries! Your items are saved. You can complete your purchase anytime.', 'info');\n  \n  // Offer alternatives\n  setTimeout(() => {\n    showAlternativePaymentOptions();\n  }, 2000);\n  \n  // Optional: Trigger abandoned cart email sequence\n  scheduleAbandonedCartEmail(customer.email, 30); // 30 minutes delay\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onshippingcontactselected","__idx":17},"children":["onShippingContactSelected"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the customer selects or changes their shipping address in the Apple Pay sheet. Use this to calculate shipping costs and validate delivery availability."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Calculate shipping costs based on distance, weight, and destination."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify addresses against postal service databases."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update tax rates based on the shipping destination."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Show available delivery options for the location."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the customer changes their shipping address, use the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/apis/session/other/modify-session"},"children":["Modify session"]}," API to update the transaction amount on your backend. Update the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["amounts"]}," object with the new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["currencyCode"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transactionValue"]}," to reflect updated shipping costs and taxes."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-4","__idx":18},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["contact"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["ApplePayPaymentContact"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The customer's shipping contact information."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The shipping address details."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress.street"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The street address."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress.city"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The city name."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress.state"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The state or province."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress.postalCode"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The ZIP or postal code."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress.country"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The country name."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.postalAddress.countryCode"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The ISO country code."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.name"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The contact name."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.name.givenName"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The first name."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.name.familyName"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The last name."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.phoneNumber"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The phone number."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["contact.emailAddress"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The email address."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-4","__idx":19},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onShippingContactSelected: async (contact) => {\n  console.log('Shipping contact selected:', contact);\n  \n  try {\n    // Validate shipping address\n    const isValidAddress = await validateAddress(contact.postalAddress);\n    if (!isValidAddress) {\n      return {\n        errors: [{\n          code: 'shippingContactInvalid',\n          contactField: 'postalAddress',\n          message: 'Please enter a valid shipping address'\n        }]\n      };\n    }\n    \n    // Calculate shipping and tax\n    const shippingCost = await calculateShipping(contact.postalAddress);\n    const taxAmount = await calculateTax(contact.postalAddress, baseAmount);\n    const newTotal = baseAmount + taxAmount + shippingCost;\n    \n    // Get available shipping methods\n    const shippingMethods = await getShippingMethods(contact.postalAddress);\n    \n    return {\n      newTotal: {\n        label: 'Total',\n        amount: newTotal.toFixed(2)\n      },\n      newLineItems: [\n        { label: 'Subtotal', amount: baseAmount.toFixed(2) },\n        { label: 'Tax', amount: taxAmount.toFixed(2) },\n        { label: 'Shipping', amount: shippingCost.toFixed(2) }\n      ],\n      newShippingMethods: shippingMethods\n    };\n  } catch (error) {\n    console.error('Shipping calculation failed:', error);\n    return {\n      errors: [{\n        code: 'shippingContactInvalid',\n        message: 'Unable to calculate shipping. Please try again.'\n      }]\n    };\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onshippingmethodselected","__idx":20},"children":["onShippingMethodSelected"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the customer selects a different shipping method in the Apple Pay sheet."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update the total price based on the shipping method selection."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Show the expected delivery dates for the selected method."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Highlight benefits of premium shipping options."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check real-time availability for express options."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the customer selects a different shipping method, use the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/apis/session/other/modify-session"},"children":["Modify session"]}," API to update the transaction amount on your backend. Update the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["amounts"]}," object with the new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["currencyCode"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transactionValue"]}," to reflect the selected shipping method cost."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-5","__idx":21},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["method"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["ApplePayShippingMethod"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The selected shipping method."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["method.identifier"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A unique identifier for the shipping method."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["method.label"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The display name (e.g., \"Standard Shipping\")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["method.detail"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Additional details (e.g., \"5-7 business days\")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["method.amount"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The shipping cost as a decimal string."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-5","__idx":22},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onShippingMethodSelected: async (method) => {\n  console.log('Shipping method selected:', method);\n  \n  // Update total based on selected shipping method\n  const baseAmount = 20.00;\n  const tax = 5.00;\n  const shippingCost = parseFloat(method.amount);\n  \n  // Add insurance for express shipping\n  let insurance = 0;\n  if (method.identifier === 'express' && baseAmount > 50) {\n    insurance = 2.99;\n  }\n  \n  // Calculate carbon offset for eco-conscious customers\n  const carbonOffset = method.identifier === 'standard' ? 0.50 : 0;\n  \n  const newTotal = baseAmount + tax + shippingCost + insurance + carbonOffset;\n  \n  // Track shipping method selection\n  trackEvent('shipping-method-selected', {\n    method: method.identifier,\n    cost: shippingCost,\n    orderValue: baseAmount\n  });\n  \n  return {\n    newTotal: {\n      label: 'Total',\n      amount: newTotal.toFixed(2)\n    },\n    newLineItems: [\n      { label: 'Subtotal', amount: baseAmount.toFixed(2) },\n      { label: 'Tax', amount: tax.toFixed(2) },\n      { label: `Shipping (${method.label})`, amount: shippingCost.toFixed(2) },\n      ...(insurance > 0 ? [{ label: 'Shipping Insurance', amount: insurance.toFixed(2) }] : []),\n      ...(carbonOffset > 0 ? [{ label: 'Carbon Offset', amount: carbonOffset.toFixed(2) }] : [])\n    ]\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"onpaymentmethodselected","__idx":23},"children":["onPaymentMethodSelected"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the customer changes their payment method (different card) within the Apple Pay sheet."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Apply different fees based on the card type."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Offer different rewards based on the payment method."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Apply additional verification for high-risk cards."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Route payments through optimal payment processors."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-6","__idx":24},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["paymentMethod"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["ApplePayPaymentMethod"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The selected payment method."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.displayName"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The card display name (e.g., \"Visa ••••1234\")."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.network"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The card network (visa, masterCard, amex, discover)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.type"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The card type."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.paymentPass"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["object"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The card details."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.paymentPass.primaryAccountIdentifier"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The primary account identifier."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.paymentPass.primaryAccountNumberSuffix"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The last four digits of the card."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.paymentPass.deviceAccountIdentifier"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The device-specific account ID."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["paymentMethod.paymentPass.deviceAccountNumberSuffix"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The device account suffix."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-6","__idx":25},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onPaymentMethodSelected: async (paymentMethod) => {\n  console.log('Payment method selected:', paymentMethod);\n  \n  const baseAmount = 20.00;\n  const tax = 5.00;\n  let processingFee = 0;\n  let reward = 0;\n  \n  // Apply different fees based on card type\n  if (paymentMethod.type === 'credit') {\n    processingFee = 2.99; // Credit card processing fee\n  } else if (paymentMethod.type === 'debit') {\n    processingFee = 0.99; // Lower fee for debit\n  }\n  \n  // Offer rewards for specific networks\n  if (paymentMethod.network === 'amex') {\n    reward = 1.00; // American Express cashback offer\n  }\n  \n  // Track payment method selection\n  trackEvent('payment-method-selected', {\n    network: paymentMethod.network,\n    type: paymentMethod.type,\n    lastFour: paymentMethod.paymentPass?.primaryAccountNumberSuffix\n  });\n  \n  const newTotal = baseAmount + tax + processingFee - reward;\n  \n  return {\n    newTotal: {\n      label: 'Total',\n      amount: Math.max(0, newTotal).toFixed(2)\n    },\n    newLineItems: [\n      { label: 'Subtotal', amount: baseAmount.toFixed(2) },\n      { label: 'Tax', amount: tax.toFixed(2) },\n      ...(processingFee > 0 ? [{ label: `${paymentMethod.type} Fee`, amount: processingFee.toFixed(2) }] : []),\n      ...(reward > 0 ? [{ label: `${paymentMethod.network} Reward`, amount: `-${reward.toFixed(2)}` }] : [])\n    ]\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"oncouponcodechanged","__idx":26},"children":["onCouponCodeChanged"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This callback is triggered when the customer enters or changes a coupon code in the Apple Pay sheet (available on supported Safari versions)."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use it to:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Apply percentage or fixed amount discounts."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Validate customer-specific coupon codes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Track effectiveness of marketing campaigns."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Apply discounts to clear specific inventory."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After validating the coupon code, use the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/apis/session/other/modify-session"},"children":["Modify session"]}," API to update the transaction amount on your backend. Update the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["amounts"]}," object with the new ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["currencyCode"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transactionValue"]}," to reflect the applied discount."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"event-data-7","__idx":27},"children":["Event data"]},{"$$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":"Parameter"},"children":["Parameter"]},{"$$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":["couponCode"]},{"$$mdtype":"Tag","name":"Break","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Details","attributes":{},"children":["string"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The coupon code entered by the customer."]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example-implementation-7","__idx":28},"children":["Example implementation"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onCouponCodeChanged: async (couponCode) => {\n  console.log('Coupon code entered:', couponCode);\n  \n  try {\n    // Validate coupon code\n    const discount = await validateCouponCode(couponCode);\n    \n    if (discount.valid && !discount.expired) {\n      const baseAmount = 20.00;\n      const tax = 5.00;\n      \n      // Calculate discount amount\n      let discountAmount = 0;\n      if (discount.type === 'percentage') {\n        discountAmount = baseAmount * (discount.value / 100);\n      } else if (discount.type === 'fixed') {\n        discountAmount = discount.value;\n      }\n      \n      // Apply minimum purchase requirement\n      if (discount.minimumPurchase && baseAmount < discount.minimumPurchase) {\n        return {\n          errors: [{\n            code: 'couponCodeInvalid',\n            message: `Minimum purchase of $${discount.minimumPurchase} required`\n          }]\n        };\n      }\n      \n      // Cap discount at maximum amount\n      discountAmount = Math.min(discountAmount, discount.maxDiscount || discountAmount);\n      \n      const newTotal = Math.max(0, baseAmount + tax - discountAmount);\n      \n      // Track coupon usage\n      trackEvent('coupon-applied', {\n        code: couponCode,\n        discountType: discount.type,\n        discountAmount: discountAmount,\n        orderValue: baseAmount\n      });\n      \n      return {\n        newTotal: {\n          label: 'Total',\n          amount: newTotal.toFixed(2)\n        },\n        newLineItems: [\n          { label: 'Subtotal', amount: baseAmount.toFixed(2) },\n          { label: 'Tax', amount: tax.toFixed(2) },\n          { label: `Discount (${couponCode})`, amount: `-${discountAmount.toFixed(2)}` }\n        ]\n      };\n    } else {\n      // Handle invalid or expired coupon\n      const errorMessage = discount.expired \n        ? 'This coupon code has expired' \n        : 'Invalid coupon code';\n        \n      return {\n        errors: [{\n          code: 'couponCodeInvalid',\n          message: errorMessage\n        }]\n      };\n    }\n  } catch (error) {\n    console.error('Coupon validation failed:', error);\n    return {\n      errors: [{\n        code: 'couponCodeInvalid',\n        message: 'Unable to validate coupon code. Please try again.'\n      }]\n    };\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"event-data-structures","__idx":29},"children":["Event data structures"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"contact-object","__idx":30},"children":["Contact object"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The contact object contains customer address and contact information:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"interface ApplePayContact {\n  postalAddress?: {\n    street?: string;\n    city?: string;\n    state?: string;\n    postalCode?: string;\n    country?: string;\n    countryCode?: string;\n  };\n  name?: {\n    givenName?: string;\n    familyName?: string;\n  };\n  phoneNumber?: string;\n  emailAddress?: string;\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"payment-method-object","__idx":31},"children":["Payment method object"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The payment method object contains information about the selected payment card:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"interface ApplePayPaymentMethod {\n  displayName?: string;\n  network?: string;\n  type?: 'debit' | 'credit' | 'prepaid' | 'store';\n  paymentPass?: {\n    primaryAccountIdentifier?: string;\n    primaryAccountNumberSuffix?: string;\n    deviceAccountIdentifier?: string;\n    deviceAccountNumberSuffix?: string;\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"update-response-object","__idx":32},"children":["Update response object"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Event callbacks can return update objects to modify the Apple Pay sheet:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"interface ApplePayUpdateResponse {\n  newTotal?: {\n    label: string;\n    amount: string;\n  };\n  newLineItems?: Array<{\n    label: string;\n    amount: string;\n  }>;\n  newShippingMethods?: Array<{\n    identifier: string;\n    label: string;\n    detail?: string;\n    amount: string;\n  }>;\n  errors?: Array<{\n    code: string;\n    contactField?: string;\n    message: string;\n  }>;\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"error-handling-in-events","__idx":33},"children":["Error handling in events"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Event callbacks should handle errors gracefully and provide appropriate feedback to customers:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const applePayConfig = {\n  onShippingContactSelected: async (contact) => {\n    try {\n      // Validate shipping address\n      const isValid = await validateShippingAddress(contact.postalAddress);\n      \n      if (!isValid) {\n        return {\n          errors: [{\n            code: 'shippingContactInvalid',\n            contactField: 'postalAddress',\n            message: 'We cannot ship to this address'\n          }]\n        };\n      }\n      \n      // Calculate shipping\n      const shippingCost = await calculateShipping(contact.postalAddress);\n      return {\n        newTotal: {\n          label: 'Total',\n          amount: (baseAmount + shippingCost).toFixed(2)\n        }\n      };\n      \n    } catch (error) {\n      console.error('Shipping calculation failed:', error);\n      return {\n        errors: [{\n          code: 'shippingContactInvalid',\n          message: 'Unable to calculate shipping. Please try again.'\n        }]\n      };\n    }\n  },\n  \n  onPostAuthorisation: async (data) => {\n    try {\n      // Retrieve authorisation result from backend\n      const result = await getAuthorisationResultFromGateway(\n        data.merchantTransactionId,\n        data.systemTransactionId\n      );\n      \n      if (result.status === 'Authorised') {\n        // Handle success\n        window.location.href = `/payment-success?txn=${data.merchantTransactionId}`;\n      } else {\n        // Handle declined payment\n        showUserMessage('Payment declined. Please try again or use a different payment method.');\n      }\n    } catch (error) {\n      console.error('Failed to retrieve authorisation result:', error);\n      showUserMessage('Unable to confirm payment status. Please contact support.');\n    }\n  },\n  \n  onError: (error) => {\n    // Log error for debugging\n    console.error('Apple Pay error:', error);\n    \n    // Show user-friendly message\n    if (error.message.includes('Network')) {\n      showUserMessage('Network error. Please check your connection and try again.');\n    } else if (error.message.includes('Merchant validation')) {\n      showUserMessage('Payment system temporarily unavailable. Please try again later.');\n    } else {\n      showUserMessage('Payment failed. Please try again or use a different payment method.');\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"advanced-event-usage","__idx":34},"children":["Advanced event usage"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"browser-compatibility-checking","__idx":35},"children":["Browser compatibility checking"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Always check Apple Pay availability before initialising:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Check if Apple Pay is available in the browser\nif (window.ApplePaySession && ApplePaySession.canMakePayments()) {\n  // Initialise Apple Pay component\n  const applePayComponent = pxpCheckoutSdk.create('apple-pay-button', applePayConfig);\n} else {\n  // Show alternative payment methods\n  console.log('Apple Pay not available in this browser');\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"recurring-payments","__idx":36},"children":["Recurring payments"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For recurring payments, use the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]}," callback to set up subscription data:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onPreAuthorisation: async () => {\n  // Check if transaction should proceed\n  const transactionDecision = await getAuthorisationDecision();\n  \n  if (!transactionDecision) {\n    // Update authorisation decision to false in backend via Modify Session API\n    await updateSessionAuthorisationDecision(false);\n    return null; // Do not proceed\n  }\n  \n  // Update authorisation decision to true in backend via Modify Session API\n  await updateSessionAuthorisationDecision(true);\n  \n  return {\n    riskScreeningData: {\n      deviceSessionId: await getDeviceSessionId(),\n      performRiskScreening: true,\n      userIp: \"192.168.1.100\",\n      account: {\n        id: \"user_12345678\",\n        creationDateTime: \"2024-01-15T10:30:00.000Z\"\n      },\n      items: [{\n        price: 9.99,\n        quantity: 1,\n        category: \"Subscription\"\n      }],\n      fulfillments: [{\n        type: \"Digital\",\n        recipientPerson: {\n          phoneNumber: \"+1234567890\"\n        }\n      }],\n      transaction: {\n        subtotal: 9.99\n      }\n    }\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"fraud-detection","__idx":37},"children":["Fraud detection"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Integrate with fraud detection services in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["onPreAuthorisation"]}," callback:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"onPreAuthorisation: async () => {\n  // Check if transaction should proceed\n  const transactionDecision = await getAuthorisationDecision();\n  \n  if (!transactionDecision) {\n    // Update authorisation decision to false in backend via Modify Session API\n    await updateSessionAuthorisationDecision(false);\n    return null; // Do not proceed\n  }\n  \n  // Get cart items for risk analysis\n  const cartItems = await getCartItems();\n  const shippingAddress = await getShippingAddress();\n  const customer = await getCustomer();\n  \n  // Update authorisation decision to true in backend via Modify Session API\n  await updateSessionAuthorisationDecision(true);\n  \n  return {\n    riskScreeningData: {\n      performRiskScreening: true,\n      deviceSessionId: await getDeviceSessionId(),\n      userIp: \"192.168.1.100\",\n      account: {\n        id: \"user_12345678\",\n        creationDateTime: \"2024-01-15T10:30:00.000Z\"\n      },\n      items: cartItems.map(item => ({\n        price: item.price,\n        quantity: item.quantity,\n        category: item.category,\n        sku: item.sku\n      })),\n      fulfillments: [{\n        type: 'Shipped',\n        shipping: {\n          shippingMethod: 'Standard'\n        },\n        recipientPerson: {\n          name: {\n            first: customer.firstName,\n            family: customer.lastName\n          },\n          email: customer.email,\n          phoneNumber: customer.phone,\n          address: {\n            line1: shippingAddress.street,\n            city: shippingAddress.city,\n            region: shippingAddress.state,\n            countryCode: shippingAddress.countryCode,\n            postalCode: shippingAddress.postalCode\n          }\n        }\n      }],\n      transaction: {\n        subtotal: cartItems.reduce((sum, item) => sum + (item.price * item.quantity), 0)\n      }\n    }\n  };\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"handling-different-rendering-methods","__idx":38},"children":["Handling different rendering methods"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Web SDK supports two rendering methods with consistent event handling:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Official Apple Pay SDK method (recommended)\nconst officialConfig = {\n  usingCss: false, // Use Apple's official button\n  onPostAuthorisation: async (data) => {\n    // Retrieve authorisation result from backend\n    const result = await getAuthorisationResultFromGateway(\n      data.merchantTransactionId, \n      data.systemTransactionId\n    );\n    // Handle authorisation result\n  }\n};\n\n// Custom CSS method (more restrictive browser support)\nconst cssConfig = {\n  usingCss: true, // Use custom styled button\n  style: {\n    template: '<button class=\"custom-apple-pay\">Pay with Apple Pay</button>',\n    templateCSS: '.custom-apple-pay { /* custom styles */ }'\n  },\n  onPostAuthorisation: async (data) => {\n    // Same event handling regardless of rendering method\n    const result = await getAuthorisationResultFromGateway(\n      data.merchantTransactionId, \n      data.systemTransactionId\n    );\n    // Handle authorisation result\n  }\n};\n","lang":"typescript"},"children":[]}]},"headings":[{"value":"Events","id":"events","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"SDK data callbacks","id":"sdk-data-callbacks","depth":2},{"value":"Apple Pay-specific events","id":"apple-pay-specific-events","depth":2},{"value":"Optional Apple Pay events","id":"optional-apple-pay-events","depth":2},{"value":"onPostAuthorisation","id":"onpostauthorisation","depth":3},{"value":"Event data","id":"event-data","depth":4},{"value":"Example implementation","id":"example-implementation","depth":4},{"value":"onPreAuthorisation","id":"onpreauthorisation","depth":3},{"value":"Event data","id":"event-data-1","depth":4},{"value":"Example implementation","id":"example-implementation-1","depth":4},{"value":"onError","id":"onerror","depth":3},{"value":"Event data","id":"event-data-2","depth":4},{"value":"Example implementation","id":"example-implementation-2","depth":4},{"value":"onCancel","id":"oncancel","depth":3},{"value":"Event data","id":"event-data-3","depth":4},{"value":"Example implementation","id":"example-implementation-3","depth":4},{"value":"onShippingContactSelected","id":"onshippingcontactselected","depth":3},{"value":"Event data","id":"event-data-4","depth":4},{"value":"Example implementation","id":"example-implementation-4","depth":4},{"value":"onShippingMethodSelected","id":"onshippingmethodselected","depth":3},{"value":"Event data","id":"event-data-5","depth":4},{"value":"Example implementation","id":"example-implementation-5","depth":4},{"value":"onPaymentMethodSelected","id":"onpaymentmethodselected","depth":3},{"value":"Event data","id":"event-data-6","depth":4},{"value":"Example implementation","id":"example-implementation-6","depth":4},{"value":"onCouponCodeChanged","id":"oncouponcodechanged","depth":3},{"value":"Event data","id":"event-data-7","depth":4},{"value":"Example implementation","id":"example-implementation-7","depth":4},{"value":"Event data structures","id":"event-data-structures","depth":2},{"value":"Contact object","id":"contact-object","depth":3},{"value":"Payment method object","id":"payment-method-object","depth":3},{"value":"Update response object","id":"update-response-object","depth":3},{"value":"Error handling in events","id":"error-handling-in-events","depth":2},{"value":"Advanced event usage","id":"advanced-event-usage","depth":2},{"value":"Browser compatibility checking","id":"browser-compatibility-checking","depth":3},{"value":"Recurring payments","id":"recurring-payments","depth":3},{"value":"Fraud detection","id":"fraud-detection","depth":3},{"value":"Handling different rendering methods","id":"handling-different-rendering-methods","depth":3}],"frontmatter":{"seo":{"title":"Events"}},"lastModified":"2026-04-22T11:40:18.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/web/apple-pay/events","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}