{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["sub-heading","admonition","endpoint"]},"type":"markdown"},"seo":{"title":"Recurring payments","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":"recurring-payments","__idx":0},"children":["Recurring payments"]},{"$$mdtype":"Tag","name":"SubHeading","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Perform Apple Pay recurring, deferred, and automatic reload transactions for Web."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"overview","__idx":1},"children":["Overview"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Apple Pay supports three types of recurring payment scenarios:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Recurring payments:"]}," For subscription-based payments where the customer signs up and pays initially, and you then automatically charge them at specified intervals (monthly, yearly, etc.). Apple Pay handles the subscription lifecycle with proper customer consent."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Deferred payments:"]}," For transactions where authorisation happens now, but payment is processed later (e.g., hotel bookings, pre-orders). Apple Pay provides secure payment promises."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Automatic reload payments:"]}," For topping up stored value accounts when balance falls below a threshold (e.g., gift cards, transit cards). Apple Pay manages the reload triggers automatically."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All Apple Pay recurring payment types provide enhanced security, customer control, and transparent billing through Apple's ecosystem."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["While Apple Pay provides the UI and customer consent flow for recurring payments, PXP does not provide an automatic payment scheduler. You must implement your own scheduling system to initiate subsequent charges (recurring billing, deferred payments, and automatic reloads) via the Transactions API."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"recurring-payments-1","__idx":2},"children":["Recurring payments"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-set-up-the-sdk-config","__idx":3},"children":["Step 1: Set up the SDK config"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To set up a recurring Apple Pay payment, you need to include recurring payment configuration in your Apple Pay component setup."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Configure subscription transaction data\nconst transactionData = {\n  amount: 9.99,\n  currency: 'USD',\n  entryType: 'Ecom',\n  intent: {\n    card: 'Purchase'\n  },\n  merchantTransactionId: 'sub-setup-123',\n  merchantTransactionDate: () => new Date().toISOString(),\n  shopper: {\n    email: 'customer@example.com',\n    firstName: 'John',\n    lastName: 'Doe'\n  }\n};\n\n// Create complete SDK configuration\nconst sdkConfig = {\n  environment: 'test',\n  session: {\n    sessionId: 'your-session-id',\n    allowedFundingTypes: {\n      wallets: {\n        applePay: {\n          merchantId: 'merchant.com.yourcompany'\n        }\n      }\n    }\n  },\n  transactionData,           // ← This connects Step 1 to Step 2\n  // ... other SDK settings\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-create-your-apple-pay-component-with-recurring-configuration","__idx":4},"children":["Step 2: Create your Apple Pay component with recurring configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Next, you're going to use your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sdkConfig"]}," to create the Apple Pay component with recurring payment configuration. When the customer authorises with Apple Pay, the recurring payments will start."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const applePayComponent = pxpSdk.create('apple-pay-button', {\n  merchantDisplayName: 'Subscription Service',\n  paymentDescription: 'Monthly Premium Subscription',\n  usingCss: false,\n  \n  style: {\n    type: 'subscribe',  // Use subscribe button type\n    buttonstyle: 'black',\n    height: '50px',\n    borderRadius: '8px'\n  },\n  \n  paymentRequest: {\n    countryCode: 'US',\n    currencyCode: 'USD',\n    merchantCapabilities: ['supports3DS', 'supportsEMV'],\n    supportedNetworks: ['visa', 'masterCard', 'amex'],\n    total: {\n      label: 'First Month',\n      amount: '9.99'\n    },\n    \n    // Recurring payment configuration\n    recurringPaymentRequest: {\n      paymentDescription: 'Monthly Premium Subscription',\n      regularBilling: {\n        label: 'Monthly Subscription',\n        amount: '9.99',\n        recurringPaymentIntervalUnit: 'month',\n        recurringPaymentIntervalCount: 1,\n        recurringPaymentStartDate: '2024-02-01T00:00:00Z',\n        recurringPaymentEndDate: '2025-01-31T23:59:59Z' // Optional end date\n      },\n      managementURL: 'https://yoursite.com/manage-subscription',\n      tokenNotificationURL: 'https://yoursite.com/webhook/subscription' // Optional\n    }\n  },\n\n  onPostAuthorisation: async (data) => {\n    console.log('Recurring Apple Pay subscription processing');\n    console.log('Merchant Transaction ID:', data.merchantTransactionId);\n    \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      console.log('Recurring Apple Pay subscription started!');\n      console.log('Transaction ID:', result.transactionId);\n      \n      // Store recurring payment information\n      storeRecurringPayment({\n        transactionId: result.transactionId,\n        merchantTransactionId: merchantTransactionId,\n        customerId: 'customer@example.com',\n        subscriptionType: 'monthly',\n        amount: 9.99,\n        currency: 'USD',\n        startDate: '2024-02-01',\n        endDate: '2025-01-31'\n      });\n      \n      // Redirect to success page\n      window.location.href = '/subscription-success';\n    }\n  },\n\n  onError: (error) => {\n    console.error('Apple Pay subscription error:', error);\n    showError('Failed to start subscription. Please try again.');\n  }\n});\n\napplePayComponent.mount('apple-pay-container');\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"advanced-recurring-payment-with-trial-period","__idx":5},"children":["Advanced recurring payment with trial period"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For subscriptions with trial periods, you can configure both trial and regular billing:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const applePayConfig = {\n  merchantDisplayName: 'SaaS Platform',\n  paymentDescription: 'Annual Subscription with Trial',\n  paymentRequest: {\n    countryCode: 'US',\n    currencyCode: 'USD',\n    merchantCapabilities: ['supports3DS', 'supportsEMV'],\n    supportedNetworks: ['visa', 'masterCard', 'amex'],\n    total: {\n      label: 'Trial Period',\n      amount: '0.00'  // Free trial\n    },\n    recurringPaymentRequest: {\n      paymentDescription: 'Annual SaaS Subscription',\n      regularBilling: {\n        label: 'Annual Subscription',\n        amount: '299.99',\n        recurringPaymentIntervalUnit: 'year',\n        recurringPaymentIntervalCount: 1,\n        recurringPaymentStartDate: '2024-02-01T00:00:00Z'\n      },\n      trialBilling: {\n        label: '14-Day Free Trial',\n        amount: '0.00',\n        recurringPaymentIntervalUnit: 'day',\n        recurringPaymentIntervalCount: 14,\n        recurringPaymentStartDate: '2024-01-15T00:00:00Z',\n        recurringPaymentEndDate: '2024-01-29T23:59:59Z'\n      },\n      managementURL: 'https://yoursite.com/manage-subscription',\n      tokenNotificationURL: 'https://yoursite.com/webhook/subscription'\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"charging-subsequent-recurring-payments","__idx":6},"children":["Charging subsequent recurring payments"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After setting up the initial recurring payment, you must initiate subsequent charges from your backend using the Transactions API. The SDK creates a payment token during the initial setup that you can use for future charges."]},{"$$mdtype":"Tag","name":"Endpoint","attributes":{"method":"POST"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["/v1/transactions"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the following request to charge a customer for a subsequent recurring payment. You'll need the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["gatewayTokenId"]}," from the initial transaction."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"merchant\": \"MERCHANT-1\",\n  \"site\": \"SITE-1\",\n  \"merchantTransactionId\": \"sub-charge-456\",\n  \"merchantTransactionDate\": \"2025-02-27T08:51:02.826Z\",\n  \"transactionMethod\": {\n    \"intent\": \"Purchase\",\n    \"entryType\": \"Ecom\",\n    \"fundingType\": \"Card\"\n  },\n  \"fundingData\": {\n    \"card\": {\n      \"gatewayTokenId\": \"5fbd77ce-02c1-40ed-94bc-1016660b7512\"\n    }\n  },\n  \"amounts\": {\n    \"transaction\": 9.99,\n    \"currencyCode\": \"USD\"\n  },\n  \"recurring\": {\n    \"processingModel\": \"MerchantInitiatedSubsequentRecurring\"\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["gatewayTokenId"]}," is returned in the initial transaction response and should be stored in your system along with the subscription details. You'll use this token for all subsequent recurring charges until the subscription expires or is cancelled."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/guides/transactions/initiate-transactions"},"children":["Learn more about initiating transactions via API"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"deferred-payments","__idx":7},"children":["Deferred payments"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-set-up-deferred-payment-configuration","__idx":8},"children":["Step 1: Set up deferred payment configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For deferred payments (e.g., hotel bookings or pre-orders), configure the payment to be charged at a future date:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const deferredApplePayConfig = {\n  merchantDisplayName: 'Travel Agency',\n  paymentDescription: 'Hotel Booking',\n  paymentRequest: {\n    countryCode: 'US',\n    currencyCode: 'USD',\n    merchantCapabilities: ['supports3DS', 'supportsEMV'],\n    supportedNetworks: ['visa', 'masterCard', 'amex'],\n    total: {\n      label: 'Hotel Booking',\n      amount: '200.00'\n    },\n    \n    // Deferred payment configuration\n    deferredPaymentRequest: {\n      paymentDescription: 'Hotel Booking - Payment Due at Check-in',\n      deferredBilling: {\n        label: 'Hotel Payment',\n        amount: '200.00',\n        deferredPaymentDate: '2024-06-15T15:00:00Z' // Check-in date\n      },\n      managementURL: 'https://yoursite.com/manage-booking',\n      freeCancellationDate: '2024-06-10T23:59:59Z', // Optional cancellation deadline\n      tokenNotificationURL: 'https://yoursite.com/webhook/deferred-payment'\n    }\n  },\n\n  onPostAuthorisation: async (data) => {\n    console.log('Deferred Apple Pay payment processing');\n    console.log('Merchant transaction ID:', data.merchantTransactionId);\n    \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      console.log('Deferred Apple Pay payment authorised!');\n      \n      // Store deferred payment information\n      storeDeferredPayment({\n        authorizationId: result.transactionId,\n        merchantTransactionId: merchantTransactionId,\n        customerId: result.customerEmail,\n        bookingReference: 'HTL-' + Date.now(),\n        amount: 200.00,\n        currency: 'USD',\n        chargeDate: '2024-06-15T15:00:00Z',\n        cancellationDeadline: '2024-06-10T23:59:59Z'\n      });\n      \n      // Send confirmation\n      window.location.href = '/booking-confirmed';\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-handle-deferred-payment-execution","__idx":9},"children":["Step 2: Handle deferred payment execution"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When the deferred payment date arrives, you'll need to process the actual charge:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// This would typically run in a background job on the deferred payment date\nasync function processDeferredPayment(deferredPaymentId) {\n  try {\n    const deferredPayment = await getDeferredPayment(deferredPaymentId);\n    \n    // Process the actual charge using the stored Apple Pay token\n    const chargeResult = await chargeDeferredApplePayment({\n      originalToken: deferredPayment.applePayToken,\n      amount: deferredPayment.amount,\n      currency: deferredPayment.currency,\n      merchantTransactionId: `deferred-${deferredPaymentId}`\n    });\n    \n    if (chargeResult.success) {\n      console.log('Deferred payment charged successfully');\n      await updateDeferredPaymentStatus(deferredPaymentId, 'CHARGED');\n      await sendPaymentConfirmation(deferredPayment.customerId);\n    } else {\n      console.error('Deferred payment failed:', chargeResult.error);\n      await updateDeferredPaymentStatus(deferredPaymentId, 'FAILED');\n      await sendPaymentFailureNotification(deferredPayment.customerId);\n    }\n  } catch (error) {\n    console.error('Error processing deferred payment:', error);\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"automatic-reload-payments","__idx":10},"children":["Automatic reload payments"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-1-set-up-automatic-reload-configuration","__idx":11},"children":["Step 1: Set up automatic reload configuration"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For automatic reload payments (e.g., gift cards, transit cards), configure the reload trigger and amount:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const autoReloadApplePayConfig = {\n  merchantDisplayName: 'Gift Card Store',\n  paymentDescription: 'Gift Card Purchase',\n  paymentRequest: {\n    countryCode: 'US',\n    currencyCode: 'USD',\n    merchantCapabilities: ['supports3DS', 'supportsEMV'],\n    supportedNetworks: ['visa', 'masterCard', 'amex'],\n    total: {\n      label: 'Gift Card',\n      amount: '50.00'\n    },\n    \n    // Automatic reload configuration\n    automaticReloadPaymentRequest: {\n      paymentDescription: 'Automatic Reload for Gift Card',\n      automaticReloadBilling: {\n        label: 'Auto Reload',\n        amount: '25.00',\n        automaticReloadPaymentThresholdAmount: '10.00' // Reload when balance drops below $10\n      },\n      managementURL: 'https://yoursite.com/manage-gift-card',\n      tokenNotificationURL: 'https://yoursite.com/webhook/auto-reload'\n    }\n  },\n\n  onPostAuthorisation: async (data) => {\n    console.log('Apple Pay automatic reload processing');\n    console.log('Merchant transaction ID:', data.merchantTransactionId);\n    \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      console.log('Apple Pay automatic reload set up!');\n      \n      // Store automatic reload configuration\n      storeAutoReloadConfig({\n        transactionId: result.transactionId,\n        merchantTransactionId: merchantTransactionId,\n        customerId: result.customerEmail,\n        giftCardId: 'GC-' + Date.now(),\n        initialAmount: 50.00,\n        reloadAmount: 25.00,\n        thresholdAmount: 10.00,\n        currency: 'USD'\n      });\n      \n      // Redirect to gift card details\n      window.location.href = '/gift-card-success';\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"step-2-handle-automatic-reload-triggers","__idx":12},"children":["Step 2: Handle automatic reload triggers"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Monitor account balances and trigger automatic reloads when thresholds are reached:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// This would typically run as a scheduled job to check balances\nasync function checkAutoReloadTriggers() {\n  const autoReloadAccounts = await getActiveAutoReloadAccounts();\n  \n  for (const account of autoReloadAccounts) {\n    const currentBalance = await getAccountBalance(account.giftCardId);\n    \n    if (currentBalance <= account.thresholdAmount) {\n      try {\n        console.log(`Triggering auto-reload for account ${account.giftCardId}`);\n        \n        // Process automatic reload using stored Apple Pay token\n        const reloadResult = await processAutoReload({\n          originalToken: account.applePayToken,\n          amount: account.reloadAmount,\n          currency: account.currency,\n          accountId: account.giftCardId,\n          merchantTransactionId: `reload-${account.giftCardId}-${Date.now()}`\n        });\n        \n        if (reloadResult.success) {\n          // Update account balance\n          await updateAccountBalance(\n            account.giftCardId, \n            currentBalance + account.reloadAmount\n          );\n          \n          // Send notification to customer\n          await sendAutoReloadNotification(account.customerId, {\n            amount: account.reloadAmount,\n            newBalance: currentBalance + account.reloadAmount,\n            transactionId: reloadResult.transactionId\n          });\n          \n          console.log('Auto-reload completed successfully');\n        } else {\n          console.error('Auto-reload failed:', reloadResult.error);\n          await sendAutoReloadFailureNotification(account.customerId);\n        }\n      } catch (error) {\n        console.error('Error processing auto-reload:', error);\n      }\n    }\n  }\n}\n\n// Run every hour to check for reload triggers\nsetInterval(checkAutoReloadTriggers, 60 * 60 * 1000);\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"combined-payment-types","__idx":13},"children":["Combined payment types"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can combine multiple payment types in a single Apple Pay transaction:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const combinedApplePayConfig = {\n  merchantDisplayName: 'Premium Service',\n  paymentDescription: 'Premium Subscription with Auto-Reload',\n  paymentRequest: {\n    countryCode: 'US',\n    currencyCode: 'USD',\n    merchantCapabilities: ['supports3DS', 'supportsEMV'],\n    supportedNetworks: ['visa', 'masterCard', 'amex'],\n    total: {\n      label: 'First Payment',\n      amount: '29.99'\n    },\n    \n    // Recurring payment for subscription\n    recurringPaymentRequest: {\n      paymentDescription: 'Monthly Premium Subscription',\n      regularBilling: {\n        label: 'Monthly Premium',\n        amount: '29.99',\n        recurringPaymentIntervalUnit: 'month',\n        recurringPaymentIntervalCount: 1,\n        recurringPaymentStartDate: '2024-01-01T00:00:00Z',\n        recurringPaymentEndDate: '2024-12-31T23:59:59Z'\n      },\n      managementURL: 'https://yoursite.com/manage-subscription',\n      tokenNotificationURL: 'https://yoursite.com/webhook/subscription'\n    },\n    \n    // Automatic reload for credits\n    automaticReloadPaymentRequest: {\n      paymentDescription: 'Auto Reload Credits',\n      automaticReloadBilling: {\n        label: 'Credit Reload',\n        amount: '10.00',\n        automaticReloadPaymentThresholdAmount: '5.00'\n      },\n      managementURL: 'https://yoursite.com/manage-credits'\n    }\n  },\n\n  onPostAuthorisation: async (data) => {\n    console.log('Combined Apple Pay payment processing');\n    console.log('Merchant Transaction ID:', data.merchantTransactionId);\n    \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      console.log('Combined Apple Pay payment configured!');\n      \n      // Store both recurring and auto-reload configurations\n      storeCombinedPaymentConfig({\n        transactionId: result.transactionId,\n        merchantTransactionId: merchantTransactionId,\n        customerId: result.customerEmail,\n        subscription: {\n          amount: 29.99,\n          interval: 'monthly',\n          startDate: '2024-01-01',\n          endDate: '2024-12-31'\n        },\n        autoReload: {\n          reloadAmount: 10.00,\n          thresholdAmount: 5.00\n        }\n      });\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"customer-consent-and-management","__idx":14},"children":["Customer consent and management"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"apple-pay-consent-component","__idx":15},"children":["Apple Pay consent component"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For recurring payments, you should also implement a consent component to clearly communicate the recurring nature of the payment:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Create Apple Pay consent component\nconst applePayConsentComponent = pxpSdk.create('apple-pay-consent', {\n  label: 'I agree to store my Device Primary Account Number (DPAN) for recurring payments and authorise monthly charges of $9.99',\n  checkedColor: '#007AFF',\n  uncheckedColor: '#8E8E93',\n  size: 20.0,\n  checked: false\n});\n\n// Connect consent to Apple Pay button\nconst applePayConfig = {\n  // ... other configuration\n  applePayConsentComponent: applePayConsentComponent,\n  \n  // Alternative: Use callback for consent\n  onGetConsent: () => {\n    return document.getElementById('recurring-consent-checkbox').checked;\n  }\n};\n\napplePayConsentComponent.mount('consent-container');\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"customer-management-urls","__idx":16},"children":["Customer management URLs"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Apple Pay requires management URLs for recurring payments where customers can:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["View upcoming charges."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Modify subscription details."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Cancel subscriptions."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Update payment information."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Example management page functionality\nclass SubscriptionManager {\n  async getSubscriptions(customerId) {\n    return await fetch(`/api/customers/${customerId}/subscriptions`);\n  }\n  \n  async cancelSubscription(subscriptionId) {\n    // Cancel with Apple Pay\n    await this.notifyApplePayCancellation(subscriptionId);\n    \n    // Cancel in your system\n    return await fetch(`/api/subscriptions/${subscriptionId}/cancel`, {\n      method: 'POST'\n    });\n  }\n  \n  async updateSubscription(subscriptionId, updates) {\n    // Update subscription details\n    return await fetch(`/api/subscriptions/${subscriptionId}`, {\n      method: 'PATCH',\n      body: JSON.stringify(updates)\n    });\n  }\n  \n  private async notifyApplePayCancellation(subscriptionId) {\n    // Implement Apple Pay notification for cancellation\n    // This ensures Apple Pay is aware of the cancellation\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"error-handling-and-edge-cases","__idx":17},"children":["Error handling and edge cases"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"recurring-payment-failures","__idx":18},"children":["Recurring payment failures"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Handle various failure scenarios for recurring payments:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"const applePayConfig = {\n  onError: (error) => {\n    console.error('Apple Pay recurring payment error:', error);\n    \n    if (error.message.includes('recurring')) {\n      showError('Unable to set up recurring payments. Please try again.');\n    } else if (error.message.includes('deferred')) {\n      showError('Unable to authorise future payment. Please try again.');\n    } else if (error.message.includes('reload')) {\n      showError('Unable to set up automatic reload. Please try again.');\n    } else {\n      showError('Payment setup failed. Please try again.');\n    }\n  },\n\n  onPostAuthorisation: async (data) => {\n    console.log('Merchant transaction ID:', data.merchantTransactionId);\n    \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 specific recurring payment failures\n      switch (result.errorCode) {\n        case 'RECURRING_NOT_SUPPORTED':\n          showError('Recurring payments are not supported for this card.');\n          break;\n        case 'DEFERRED_NOT_SUPPORTED':\n          showError('Deferred payments are not supported for this card.');\n          break;\n        case 'AUTO_RELOAD_NOT_SUPPORTED':\n          showError('Automatic reload is not supported for this card.');\n          break;\n        case 'INSUFFICIENT_FUNDS':\n          showError('Insufficient funds for recurring payment setup.');\n          break;\n        default:\n          showError('Payment authorisation failed. Please try again.');\n      }\n    }\n  }\n};\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"webhook-handling","__idx":19},"children":["Webhook handling"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implement webhooks to handle Apple Pay notifications for recurring payments:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"// Express.js webhook handler example\napp.post('/webhook/apple-pay', express.json(), (req, res) => {\n  const { type, data } = req.body;\n  \n  switch (type) {\n    case 'RECURRING_PAYMENT_CHARGED':\n      handleRecurringPaymentCharged(data);\n      break;\n    case 'RECURRING_PAYMENT_FAILED':\n      handleRecurringPaymentFailed(data);\n      break;\n    case 'SUBSCRIPTION_CANCELLED':\n      handleSubscriptionCancelled(data);\n      break;\n    case 'AUTO_RELOAD_TRIGGERED':\n      handleAutoReloadTriggered(data);\n      break;\n    case 'DEFERRED_PAYMENT_DUE':\n      handleDeferredPaymentDue(data);\n      break;\n    default:\n      console.log('Unknown webhook type:', type);\n  }\n  \n  res.status(200).send('OK');\n});\n\nasync function handleRecurringPaymentCharged(data) {\n  // Update subscription status\n  await updateSubscriptionStatus(data.subscriptionId, 'ACTIVE');\n  \n  // Send receipt to customer\n  await sendRecurringPaymentReceipt(data.customerId, data);\n  \n  // Update customer balance/access\n  await updateCustomerAccess(data.customerId, data.subscriptionType);\n}\n\nasync function handleRecurringPaymentFailed(data) {\n  // Update subscription status\n  await updateSubscriptionStatus(data.subscriptionId, 'PAYMENT_FAILED');\n  \n  // Send payment failure notification\n  await sendPaymentFailureNotification(data.customerId, {\n    reason: data.failureReason,\n    nextAttempt: data.nextRetryDate\n  });\n  \n  // Implement grace period or suspend access\n  await suspendCustomerAccess(data.customerId, data.subscriptionType);\n}\n","lang":"typescript"},"children":[]}]},"headings":[{"value":"Recurring payments","id":"recurring-payments","depth":1},{"value":"Overview","id":"overview","depth":2},{"value":"Recurring payments","id":"recurring-payments-1","depth":2},{"value":"Step 1: Set up the SDK config","id":"step-1-set-up-the-sdk-config","depth":3},{"value":"Step 2: Create your Apple Pay component with recurring configuration","id":"step-2-create-your-apple-pay-component-with-recurring-configuration","depth":3},{"value":"Advanced recurring payment with trial period","id":"advanced-recurring-payment-with-trial-period","depth":3},{"value":"Charging subsequent recurring payments","id":"charging-subsequent-recurring-payments","depth":3},{"value":"Deferred payments","id":"deferred-payments","depth":2},{"value":"Step 1: Set up deferred payment configuration","id":"step-1-set-up-deferred-payment-configuration","depth":3},{"value":"Step 2: Handle deferred payment execution","id":"step-2-handle-deferred-payment-execution","depth":3},{"value":"Automatic reload payments","id":"automatic-reload-payments","depth":2},{"value":"Step 1: Set up automatic reload configuration","id":"step-1-set-up-automatic-reload-configuration","depth":3},{"value":"Step 2: Handle automatic reload triggers","id":"step-2-handle-automatic-reload-triggers","depth":3},{"value":"Combined payment types","id":"combined-payment-types","depth":2},{"value":"Customer consent and management","id":"customer-consent-and-management","depth":2},{"value":"Apple Pay consent component","id":"apple-pay-consent-component","depth":3},{"value":"Customer management URLs","id":"customer-management-urls","depth":3},{"value":"Error handling and edge cases","id":"error-handling-and-edge-cases","depth":2},{"value":"Recurring payment failures","id":"recurring-payment-failures","depth":3},{"value":"Webhook handling","id":"webhook-handling","depth":3}],"frontmatter":{"seo":{"title":"Recurring payments"}},"lastModified":"2026-04-08T09:43:44.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/guides/checkout/components/web/apple-pay/recurring-payments","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}