Our company sells insurance and we'd like to offer annual renewals via Apple Pay on the Web. Most of the docs seem to point towards using recurringpaymentrequest but this method required an amount value which would only be calculated at renewal time.
It appears that Shopify is doing something akin to what we want where they do auto payments so my question is can we do annual payments with unknown renewal prices with Apple Pay for Web ?
What we cannot do is show the renewal price like this as it being insurance is almost certain to change.
This is our current code which works but won't get past the regulator.
const applePayPaymentRequestAnnual = {
countryCode: 'GB',
currencyCode: 'GBP',
supportedNetworks: ['visa', 'masterCard'],
merchantCapabilities: ['supports3DS'],
requiredBillingContactFields: ['postalAddress', 'email'],
requiredShippingContactFields: ['phone'],
recurringPaymentRequest: {
paymentDescription: 'Annual Insurance Renewal',
regularBilling: {
label: 'Annual Renewal Premium',
amount: price,
paymentTiming: "recurring",
recurringPaymentIntervalUnit: "year",
recurringPaymentStartDate: year + "-" + month + "-" + day + "T00:00:00.000Z",
type: 'final'
},
managementURL: window.location.protocol + '//' + window.location.host + '/manage-policy',
tokenNotificationURL: window.location.protocol + '//' + window.location.host + '/apple-pay-notifications'
},
lineItems: [{
label: alabel,
amount: price,
}],
total: { label: alabel, amount: price, type: "final" },
}
Hi @depicus-at-work,
You wrote:
[...] It appears that Shopify is doing something akin to what we want where they do auto payments so my question is can we do annual payments with unknown renewal prices with Apple Pay for Web ?
You are setting type: 'final' on your regularBilling object. This tells Apple Pay—and the customer—that the amount shown is fixed and final:
regularBilling: {
...
amount: price,
type: 'final' // ← This is the regulatory issue
}
The ApplePayLineItem object supports the 'pending' type explicitly for situations where the final amount is not yet known. This is the correct mechanism for variable recurring billing such as insurance:
const applePayPaymentRequestAnnual = {
countryCode: 'GB',
currencyCode: 'GBP',
supportedNetworks: ['visa', 'masterCard'],
merchantCapabilities: ['supports3DS'],
requiredBillingContactFields: ['postalAddress', 'email'],
requiredShippingContactFields: ['phone'],
recurringPaymentRequest: {
paymentDescription: 'Annual Insurance Renewal – premium subject to change at renewal',
regularBilling: {
label: 'Annual Renewal Premium (variable)',
amount: price,
paymentTiming: "recurring",
recurringPaymentIntervalUnit: "year",
recurringPaymentStartDate: year + "-" + month + "-" + day + "T00:00:00.000Z",
type: 'pending' // ← Key change: signals amount is not fixed
},
billingAgreement: 'Your renewal premium will be calculated at renewal time and may differ from the amount shown. You will be notified before any charge is made.',
managementURL: window.location.protocol + '//' + window.location.host + '/manage-policy',
tokenNotificationURL: window.location.protocol + '//' + window.location.host + '/apple-pay-notifications'
},
lineItems: [{
label: 'Current Premium (indicative)',
amount: price,
type: 'pending' // ← Also mark line items as pending
}],
total: {
label: alabel,
amount: price,
type: 'pending' // ← And the total
},
}
Also, what recurringPaymentRequest actually returns is not just a one-time payment token—it returns a merchant token (MPAN). The MPAN is stable across renewals and allows you to charge any amount at renewal time without requiring the customer to re-authorize through Apple Pay.
Then, use the billingAgreement field, as it's specifically designed for regulator and compliance use cases and is displayed to the customer during authorization:
recurringPaymentRequest: {
billingAgreement: `Your insurance premium will be recalculated at each annual
renewal based on your risk profile and market conditions. The amount shown is
your current premium for reference only. You will receive advance notice of
your renewal premium before any charge is applied. You can manage or cancel
this payment authority at any time via your policy portal.`,
...
}
This surfaces directly in the Apple Pay payment sheet and creates a clear, auditable disclosure.
Lastly, you already have tokenNotificatinURL in your code, which is great! Make sure you endpoint handles:
{
"merchantTokenIdentifier": "DNITHE302308187",
"tokenExpirationDate": "2025-12-31",
"tokenStatus": "active"
}
Apple Pay will call this URL when the MPAN is updated, replaced, or expires—critical for maintaining uninterrupted renewals. For more information, review the documentation below:
Apple Pay Merchant Token Management API
https://developer.apple.com/documentation/merchanttokennotificationservices
Cheers,
Paris X Pinkney | WWDR | DTS Engineer