Full Integration Example
Two ready-to-run snippets: pick the one that matches your backend.
- Basic: the order ID (
invoiceId) is known at page-load time. Pass it toinit()and you are done. - CMS pattern: the order does not exist yet at page-load (typical for WooCommerce, Magento, OpenCart, custom platforms). When the customer authorizes the payment, your backend creates the order and returns the resulting
invoiceIdthroughonBeforeProcessPayment.
Both snippets gate init() behind isAvailable() so the button never renders on devices that cannot pay (e.g. Android), and both pass the required paymentData (with amount + currency) and token to init(): these cannot be deferred because the Apple Pay sheet needs the total to display, and the component validates the merchant session against our backend before the sheet opens.
If the cart amount can change after the button is rendered (quantity edits, coupons, shipping recalculation), re-initialize the component with fresh paymentData and a token issued for the new amount each time the cart changes. Do not try to mutate amount inside onBeforeProcessPayment: the component rejects it with 1010 PAYMENT_DATA_MISMATCH. See Authentication for how the token is bound to amount and invoiceId.
For an Apple Pay button that collects the shipping address and delivery method inside the Apple Pay sheet (typical for product-page checkout), use the dedicated Apple Pay Express Checkout component instead.
- Basic
- CMS pattern
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='https://test-pay.dnapayments.com/components/apple-pay/apple-pay-component.js'></script>
<script>
async function renderApplePay() {
if (!await window.DNAPayments.ApplePayComponent.isAvailable()) {
// Device cannot make Apple Pay payments; leave the button hidden.
return;
}
const token = 'YOUR_ACCESS_TOKEN';
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'
}]
};
const events = {
onClick: () => {
console.log('Apple Pay button clicked');
},
onError: (error) => {
console.error('Apple Pay error:', error);
},
onCancel: () => {
console.log('Payment cancelled');
},
onPaymentSuccess: (result) => {
console.log('Payment processed', result);
}
};
window.DNAPayments.ApplePayComponent.init({
containerElement: document.getElementById('apple-pay-btn-container'),
paymentData,
events,
token
});
}
window.addEventListener('load', renderApplePay);
</script>
</head>
<body>
<div id='apple-pay-btn-container' style='width: 100%; height: 46px;'></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src='https://test-pay.dnapayments.com/components/apple-pay/apple-pay-component.js'></script>
<script>
// Cart total and currency are known at page-load. The order itself is created
// on the merchant backend only after the customer authorizes payment, so
// invoiceId is omitted here and supplied later via onBeforeProcessPayment.
const initialPaymentData = {
amount: 24,
currency: 'GBP',
description: 'Shoes',
paymentSettings: {
terminalId: 'YOUR_TERMINAL_ID',
returnUrl: 'https://example.com/success.html',
failureReturnUrl: 'https://example.com/failure.html',
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'
}]
};
async function renderApplePay() {
if (!await window.DNAPayments.ApplePayComponent.isAvailable()) {
return;
}
window.DNAPayments.ApplePayComponent.init({
containerElement: document.getElementById('apple-pay-btn-container'),
paymentData: initialPaymentData,
token: 'YOUR_ACCESS_TOKEN',
events: {
onClick: () => {
console.log('Apple Pay button clicked');
},
// Fires after the user authorizes the payment, before charge execution.
// Create the order on your backend now and return paymentData enriched
// with the freshly created invoiceId.
onBeforeProcessPayment: async (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: {
...initialPaymentData,
invoiceId: orderId
}
};
},
onPaymentSuccess: (result) => {
console.log('Payment processed', result);
window.location.href = '/success';
},
onCancel: () => {
console.log('Payment cancelled');
},
onError: (error) => {
console.error('Apple Pay error:', error);
}
}
});
}
window.addEventListener('load', renderApplePay);
</script>
</head>
<body>
<div id='apple-pay-btn-container' style='width: 100%; height: 46px;'></div>
</body>
</html>
Replace the script source with the production CDN before going live:
<script src='https://pay.dnapayments.com/components/apple-pay/apple-pay-component.js'></script>
See Deployment for the full go-live checklist.