Skip to main content

Integration

This guide walks you through embedding the Apple Pay Express Checkout button on your page. The flow is:

  1. Load the component script.
  2. Add a container element.
  3. Define event handlers (including the Express-Checkout-specific shipping events).
  4. Build the in-sheet shipping payload and the paymentData object.
  5. Call init(options).

For a copy-paste-ready end-to-end snippet, jump to the Full Example.

Step 1: Add the Apple Pay Component script

Include the component bundle in the <head> of your HTML page.

Sandbox / Test:

<script src='https://test-pay.dnapayments.com/components/apple-pay/apple-pay-component.js'></script>

Production:

<script src='https://pay.dnapayments.com/components/apple-pay/apple-pay-component.js'></script>

The script exposes window.DNAPayments.ApplePayComponent.

Step 2: Create the container element

<div id='apple-pay-btn-container' style='width: 100%; height: 46px;'></div>

Apply the desired width and height to the container: the button takes the container's dimensions.

Step 3: Gate the render with isAvailable()

DNAPayments.ApplePayComponent.isAvailable() returns a Promise<boolean> that resolves to true only when the device supports Apple Pay and can make payments. Always gate init() behind it so non-supported devices (Android, unsupported browsers) never see a broken button:

async function renderApplePay() {
if (!await window.DNAPayments.ApplePayComponent.isAvailable()) {
return; // device cannot make Apple Pay payments
}
// ...continue with init() below
}

Step 4: Build the in-sheet shipping payload

Express Checkout collects the shipping address and delivery method inside the Apple Pay sheet. Tell the sheet which contact fields to ask for and which shipping methods to offer up-front via the payload option:

const payload = {
requiredShippingContactFields: ['postalAddress', 'name', 'email', 'phone'],
requiredBillingContactFields: ['postalAddress'],
shippingMethods: [
{ label: 'Free Shipping', detail: 'Arrives in 5–7 days', identifier: 'FreeShip', amount: '0.00' },
{ label: 'Fast Shipping', detail: 'Arrives in 2 days', identifier: 'FastShip', amount: '5.00' },
{ label: 'Collect yourself', detail: 'Collect today', identifier: 'Collect', amount: '0.00' }
]
};

See payload reference for the full field list.

Step 5: Define event handlers

Express Checkout adds two shipping events on top of the standard set. The full list is in the Events section.

async function onShippingContactSelected(resolve, reject, event) {
const { countryCode } = event.shippingContact;

if (countryCode !== 'GB') {
// Reject delivery to unsupported countries
resolve({
newTotal: { label: 'My Store', amount: paymentData.amount, type: 'final' },
errors: [new ApplePayError('shippingContactInvalid', 'countryCode',
'Cannot ship to the selected country')]
});
return;
}

// Recompute available shipping methods for this address
resolve({
newTotal: { label: 'My Store', amount: paymentData.amount, type: 'final' },
newShippingMethods: [
{ label: 'Fast Shipping', detail: 'Arrives in 2 days', identifier: 'FastShip', amount: '5.00' },
{ label: 'Collect yourself', detail: 'Collect today', identifier: 'Collect', amount: '0.00' }
]
});
}

async function onShippingMethodSelected(resolve, reject, event) {
const cost = parseFloat(event.shippingMethod.amount);
resolve({
newTotal: {
label: 'My Store',
amount: String(parseFloat(paymentData.amount) + cost),
type: 'final'
}
});
}

const events = {
onClick: () => { /* ... */ },
onShippingContactSelected,
onShippingMethodSelected,
onBeforeProcessPayment: (payment) => { /* ... */ },
onPaymentSuccess: (result) => { /* ... */ },
onCancel: () => { /* ... */ },
onError: (error) => { /* ... */ }
};

Step 6: Build paymentData

paymentData carries the order details. Top-level fields and nested structures are described in paymentData reference.

const paymentData = {
amount: 24,
currency: 'GBP',
invoiceId: 'YOUR_INVOICE_ID',
description: 'Shoes',
paymentSettings: {
terminalId: 'YOUR_TERMINAL_ID',
callbackUrl: 'https://example.com/callback',
failureCallbackUrl: 'https://example.com/failure-callback'
},
customerDetails: {
accountDetails: { accountId: 'uuid000001' },
billingAddress: { country: 'GB' }
},
orderLines: [{
name: 'Running shoe',
quantity: 1,
unitPrice: 24,
taxRate: 20,
totalAmount: 24,
totalTaxAmount: 4,
imageUrl: 'https://www.example.com/logo.png',
productUrl: 'https://www.example.com/AD6654412.html'
}]
};

Step 7: Initialize the button

Pass the container, paymentData, payload, events and your access token to init():

async function renderApplePay() {
if (!await window.DNAPayments.ApplePayComponent.isAvailable()) return;

window.DNAPayments.ApplePayComponent.init({
containerElement: document.getElementById('apple-pay-btn-container'),
paymentData,
payload,
events,
token: 'YOUR_ACCESS_TOKEN',
});
}

window.addEventListener('load', renderApplePay);
Access token

The OAuth token endpoint returns an object (access_token, expires_in, token_type, ...). Pass only the access_token string to the component. See Authentication for the token flow and the scopes required for the seamless component.

API reference

The component exposes the following functions on window.DNAPayments.ApplePayComponent:

MethodDescription
init(options)Render the button and return the component instance.
isAvailable()Promise<boolean>: true if the device can make Apple Pay payments.
create(...)⚠️ Deprecated: use init() instead.

isAvailable()

const ok = await window.DNAPayments.ApplePayComponent.isAvailable();

Resolves to true if Apple Pay is supported and the device can make payments.

init(options)

const component = window.DNAPayments.ApplePayComponent.init(options);

Renders the Apple Pay Express Checkout button into containerElement and returns the initialized component instance.

options fields

PropertyTypeRequiredDescription
containerElementHTMLElementDOM node where the button is rendered.
eventsobjectEvent handler map: see Events.
paymentDataobjectPayment request: see paymentData reference. Must include at least amount and currency so the Apple Pay sheet can display the total.
tokenstringOAuth2 access token (the access_token string returned by Authentication).
payloadobjectIn-sheet shipping configuration: see payload reference. Required for Express Checkout flow.
environmentstring-Either 'sandbox' or 'production'. Optional, defaults to the environment baked into the bundle.
cardBrandsstring[]-Restrict accepted card networks. Defaults to ['VISA', 'MASTERCARD']. Allowed values: 'VISA', 'MASTERCARD', 'AMEX', 'DISCOVER', 'INTERAC', 'JCB'.
localestring-Locale applied to the Apple Pay button (e.g. 'en-GB', 'de-DE'). Defaults to 'en-GB'. Does not affect the Apple Pay sheet: the sheet always follows the user's device language.
domainNamestring-Override for the domain used for merchant validation. Pass this only if the SDK's auto-detected host does not match the domain registered in the portal. The provided host must be registered in the relevant portal (see Prerequisites).

create(...) (deprecated)

Deprecated

create() is kept for backwards compatibility and will be removed in a future version. Use init(options) instead.

Migration:

// Before: positional arguments (5 parameters for Express Checkout)
window.DNAPayments.ApplePayComponent.create(
container, paymentData, events, token, payload
);

// After: single options object
window.DNAPayments.ApplePayComponent.init({
containerElement: container,
paymentData, events, token, payload
});

Events

The component emits the following events. All handlers are attached via the events map passed to init().

EventSignatureFires when
onClick() => voidThe user taps the Apple Pay button, before the sheet is shown.
onLoad() => voidFires after the button has been rendered and mounted into containerElement. Does not fire on devices where Apple Pay is unavailable: in that case init() simply renders nothing. Use isAvailable() to check support before relying on this event.
onShippingContactSelectedasync (resolve, reject, event) => voidThe user selected or changed a shipping address inside the sheet. Call resolve(update) with new totals / line items / shipping methods, or resolve(update) with errors for unsupported addresses. Call reject(error) only on unexpected failures of your own infrastructure (e.g. tax/shipping API is down). See the note below.
onShippingMethodSelectedasync (resolve, reject, event) => voidThe user selected a shipping method inside the sheet. Call resolve(update) with the new total. Call reject(error) only on unexpected failures of your own infrastructure. See the note below.
onBeforeProcessPaymentasync functionFires after the user authorizes the payment but before the component executes it on the backend. The payment argument contains the full Apple Pay token plus the billing/shipping contacts the customer entered in the sheet.
onPaymentSuccess(result) => voidThe payment has been processed successfully. See onPaymentSuccess payload.
onError(error) => voidAny error during initialization or processing. See onError payload and Handling Error Codes.
onCancel() => voidThe user dismisses the Apple Pay sheet.

onShippingContactSelected and onShippingMethodSelected: update object

resolve(update) accepts an object with the following fields:

FieldTypeDescription
newTotalLineItemThe new total to show in the sheet.
newLineItemsLineItem[]Optional, replaces the line items shown in the sheet.
newShippingMethodsShippingMethod[]Optional, replaces the shipping methods offered in the sheet (only applicable in onShippingContactSelected).
errorsApplePayError[]Optional, surface validation errors against specific fields (e.g. unsupported country).

LineItem

FieldTypeRequiredDescription
labelstringText shown to the customer (e.g. 'Total', 'Shoes').
amountstringDecimal amount as a string (e.g. '24.00'). Apple Pay rejects numeric values here.
type'final', 'pending'-'final' for known amounts, 'pending' if the value is still being calculated. Defaults to 'final'.

ShippingMethod

FieldTypeRequiredDescription
labelstringShort name shown in the sheet (e.g. 'Fast Shipping').
detailstringLonger description (e.g. 'Arrives in 2 days').
amountstringCost as a decimal string ('5.00'). Use '0.00' for free shipping.
identifierstringStable ID you receive back in event.shippingMethod.identifier inside onShippingMethodSelected.

ApplePayError

ApplePayError is Apple's global class, available on every Apple Pay-capable device: no import needed.

new ApplePayError(errorCode, contactField?, message?)

Common usage in the shipping flow:

new ApplePayError('shippingContactInvalid', 'countryCode', 'Cannot ship to the selected country');
new ApplePayError('addressUnserviceable', undefined, 'No couriers cover this postcode');

For the full list of allowed values see Apple's reference: ApplePayErrorCode, ApplePayErrorContactField.

resolve with errors, not reject

Validation errors (unsupported country, invalid postal code, no shipping methods for the address) must be returned via resolve({ errors: [...] }) so Apple Pay can surface a field-level message inside the open sheet and let the customer correct it.

reject(...) is reserved for unexpected failures of your own infrastructure (e.g. tax/shipping API is down). It does not display your error message to the customer, so always prefer resolve({ errors: [...] }) for anything you want the customer to see and act on.

onPaymentSuccess payload

{
id: string,
reference: string,
success: boolean
}

The object may include additional fields when applicable.

onError payload

{
code: number,
message: string,
additionalInfo?: any
}

additionalInfo carries the underlying cause when available (the original exception, or the response body from the DNA Payments backend), useful for logging and debugging. See Handling Error Codes for the full list of code values.

paymentData reference

The most commonly used fields of paymentData:

FieldRequiredDescription
amountTotal transaction amount as a decimal number. The customer can adjust this via the shipping flow inside the sheet.
currency-ISO 4217 currency code (e.g. 'GBP'). Defaults to 'GBP'.
invoiceId-Your internal order / invoice identifier.
description-Human-readable description shown on receipts.
paymentSettings.terminalIdYour DNA Payments terminal ID.
paymentSettings.callbackUrl-Server-to-server success callback.
paymentSettings.failureCallbackUrl-Server-to-server failure callback.
customerDetails.accountDetails.accountId-Stable customer ID on your side.
customerDetails.email-Customer email (the SDK populates this from the Apple Pay sheet contacts at authorization).
customerDetails.mobilePhone-Customer phone (same, populated from the sheet).
customerDetails.billingAddress.country-ISO 3166-1 alpha-2 country code shown in the Apple Pay sheet (e.g. 'GB'). Defaults to 'GB'.
orderLines-Array of line items (name, quantity, unitPrice, taxRate, totalAmount, totalTaxAmount, imageUrl, productUrl).

payload reference

payload is required in Express Checkout: it tells the Apple Pay sheet which contact fields to collect and which shipping methods to offer.

FieldTypeDescription
requiredBillingContactFieldsstring[]Contact fields to collect for billing, e.g. ['postalAddress'].
requiredShippingContactFieldsstring[]Contact fields to collect for shipping, e.g. ['postalAddress', 'name', 'email', 'phone'].
shippingMethodsobject[]Initial list of shipping methods shown in the sheet. Each item: { label, detail, identifier, amount }.
const payload = {
requiredShippingContactFields: ['postalAddress', 'name', 'email', 'phone'],
requiredBillingContactFields: ['postalAddress'],
shippingMethods: [
{ label: 'Standard', detail: '5–7 business days', identifier: 'standard', amount: '5.00' },
{ label: 'Express', detail: '1–2 business days', identifier: 'express', amount: '12.00' }
]
};

Once everything is wired up, continue to Full Example, Testing, and Handling Error Codes.