Integration
This guide walks you through embedding the Apple Pay button on your page. The flow is:
- Load the component script.
- Add a container element.
- Define event handlers.
- Build the
paymentDataobject. - 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: Define event handlers
The component is event-driven. Provide callbacks via the events object passed to init(). The full list is in the Events section; the most common four are shown here.
function onClick() {
console.log('Apple Pay button has been clicked');
}
function onError(error) {
// error is { code, message }; see the Handling Error Codes page
console.error('Apple Pay error:', error);
}
function onCancel() {
console.log('Payment was cancelled by the user');
}
function onPaymentSuccess(result) {
console.log('Payment processed successfully', result);
// redirect to a success page, persist invoiceId, etc.
}
const events = {
onClick,
onError,
onCancel,
onPaymentSuccess,
};
Step 5: 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: {
firstName: 'John', lastName: 'Doe',
addressLine1: 'Fulham Rd',
postalCode: 'SW6 1HS', city: 'London', country: 'GB'
},
email: 'example@email.com',
mobilePhone: '+441234567890'
},
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 6: Initialize the button
Pass the container, paymentData, 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,
events,
token: 'YOUR_ACCESS_TOKEN',
});
}
window.addEventListener('load', renderApplePay);
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:
| Method | Description |
|---|---|
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 button into containerElement and returns the initialized component instance.
options fields
| Property | Type | Required | Description |
|---|---|---|---|
containerElement | HTMLElement | ✅ | DOM node where the button is rendered. |
events | object | ✅ | Event handler map: see Events. |
paymentData | object | ✅ | Payment request: see paymentData reference. Must include at least amount and currency so the Apple Pay sheet can display the total. |
token | string | ✅ | OAuth2 access token (the access_token string returned by Authentication). |
environment | string | - | Either 'sandbox' or 'production'. Optional, defaults to the environment baked into the bundle (test bundle → sandbox, production bundle → production). |
cardBrands | string[] | - | Restrict accepted card networks. Defaults to ['VISA', 'MASTERCARD']. Allowed values: 'VISA', 'MASTERCARD', 'AMEX', 'DISCOVER', 'INTERAC', 'JCB'. |
locale | string | - | 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. |
domainName | string | - | 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)
create() is kept for backwards compatibility and will be removed in a future version. Use init(options) instead.
Migration:
// Before: positional arguments
window.DNAPayments.ApplePayComponent.create(
container, paymentData, events, token, payload, cardBrands
);
// After: single options object
window.DNAPayments.ApplePayComponent.init({
containerElement: container,
paymentData, events, token, payload, cardBrands
});
Events
The component emits the following events. All handlers are attached via the events map passed to init().
| Event | Signature | Fires when |
|---|---|---|
onClick | () => void | The user taps the Apple Pay button, before the sheet is shown. |
onLoad | () => void | Fires 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. |
onPaymentSuccess | (result) => void | The payment has been processed successfully. See onPaymentSuccess payload. |
onError | (error) => void | Any error during initialization or processing. See onError payload and Handling Error Codes. |
onCancel | () => void | The user dismisses the Apple Pay sheet. |
onBeforeProcessPayment | async function | Fires after the user authorizes the payment but before the component executes it on the backend. Optionally return a paymentData object enriched with server-side fields that did not exist at button-render time, most commonly an invoiceId (order ID) created by your CMS at the moment of payment. See onBeforeProcessPayment example. |
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.
onPaymentSuccess payload
{
id: string,
reference: string,
success: boolean
}
The object may include additional fields when applicable.
onBeforeProcessPayment example
The hook fires after the user authorizes the payment in the Apple Pay sheet but before the component executes the charge on our backend. By that point the sheet has already displayed the total and the user has approved it via Touch ID / Face ID, so amount and currency are locked in.
The typical use case is CMS-style integrations (WooCommerce, Magento, OpenCart, custom platforms) where the order does not exist as a database record at button-render time: it is only created on the merchant's backend at the moment of payment. The hook gives you exactly that point in the flow to create the order and return its ID:
const events = {
onBeforeProcessPayment: async (payment) => {
// Create the order on your backend now that the customer has authorized payment.
const { orderId } = await fetch('/api/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ applePayPayment: payment })
}).then(r => r.json());
// Return paymentData enriched with the freshly created order ID.
// The amount, currency and delivery address must match init() values.
return {
paymentData: {
...initialPaymentData,
invoiceId: orderId
}
};
},
onPaymentSuccess: (result) => { /* ... */ },
onError: (error) => { /* ... */ }
};
If you do not need to enrich paymentData, simply omit the hook or return undefined: the component proceeds with the values from init().
The component compares the returned paymentData against the values used at init() and raises 1010 PAYMENT_DATA_MISMATCH if any of these differ:
amountcurrencycustomerDetails.deliveryDetails.deliveryAddress(postalCode+addressLine1+addressLine2)
This guard prevents silent tampering with the value the user just approved on screen. Use the hook to add server-side fields (invoiceId, dynamic paymentSettings.callbackUrl, etc.), not to change the displayed total.
paymentData reference
The most commonly used fields of paymentData:
| Field | Required | Description |
|---|---|---|
amount | ✅ | Total transaction amount as a decimal number. |
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.terminalId | ✅ | Your 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. |
customerDetails.mobilePhone | - | Customer phone. |
customerDetails.billingAddress | - | Billing address object (firstName, lastName, addressLine1, postalCode, city, country, ...). The country defaults to 'GB' when omitted. |
customerDetails.deliveryDetails.deliveryAddress | - | Shipping address object (same shape as billingAddress). |
orderLines | - | Array of line items (name, quantity, unitPrice, taxRate, totalAmount, totalTaxAmount, imageUrl, productUrl). |
Once everything is wired up, continue to Full Example, Testing, and Handling Error Codes.