Apple Pay Module
Enable Apple Pay on the web for customers using Safari on compatible Apple devices.
Apple Pay Module
Accept Apple Pay payments on the web via the Comcarde JavaScript SDK. This module wraps the Apple Pay JS API, handling button rendering and session management so your checkout can go live with minimal boilerplate.
Supported environmentsApple Pay on the web is available in Safari on macOS and iOS only. It requires a device with a Secure Enclave and a card enrolled in Apple Pay. The module will not load on unsupported browsers — see Checking for availability below.
How it works
When a customer taps the Apple Pay button, the BR-DGE SDK initiates a session with Apple's servers. Apple authenticates the payment using Face ID, Touch ID, or a passcode and returns an encrypted payment token. The BR-DGE SDK converts that token into a single-use BR-DGE token, which you send to your server to authorise the payment via the BR-DGE API. Once your server confirms the outcome, you call completePayment() to dismiss the Apple Pay sheet.
Prerequisites
Before adding this module:
- Complete the Comcarde JavaScript Client setup.
- Your domain must be registered with Apple and verified through the BR-DGE merchant configuration. Contact the BR-DGE support team if you haven't done this yet.
- Serve your checkout page over HTTPS. Apple Pay will not initialise on an insecure origin.
If you're loading the Apple Pay button inside an iFrame you must adhere to the following requirements:
- Loading the Apple Pay button on devices running iOS version 18, or greater.
- The registered domain must belong to the parent, not the iFrame domain.
- The iFrame must have an
allow=paymentattribute.
Checking for availability
Always check before loading the moduleAttempting to start an Apple Pay session on a non-supported browser throws an unhandled error. Guard against this with a
window.ApplePaySessioncheck before your integration code runs.
The window.ApplePaySession global is only present in Safari on Apple devices that support Apple Pay. Use it as your availability gate:
if (window.ApplePaySession) {
// Safe to initialise the Comcarde Apple Pay module
}If your checkout serves a mix of browsers, you may want to conditionally show or hide the Apple Pay button based on this check. Apple's own guidelines recommend always showing the button when the device supports it, even if the customer hasn't yet added a card, as Safari will prompt them to do so.
Integration guide
Step 1 — Add the script
Include the apple-pay module after the Comcarde JavaScript Client script on your checkout page.
<script src="https://sandbox-assets.comcarde.com/web/v2/js/apple-pay.min.js"></script><script src="https://assets.comcarde.com/web/v2/js/apple-pay.min.js"></script>Step 2 — Add a button placeholder
Add a container element to your page. The SDK will inject an Apple Pay button into this element when the module initialises.
<div id="apple-pay-button" onclick="processApplePayPayment()" hidden></div>
Why onclick?Apple Pay sessions must be initiated from a direct user gesture (a click or tap). Attempting to call
startSession()outside of a user interaction event will cause the session to fail. Attaching your handler toonclicksatisfies Apple's requirement.
Give the element a unique id — you'll pass this to button.container in the next step.
The
hiddenattribute prevents interaction before initialisation is complete.applePay.create()renders the button into the container before the.then()callback runs, so without it a tap in that window would call an undefined function.You can remove the
hiddenattribute once the handler is assigned in Step 3.
Step 3 — Initialise the module
Wire up the BR-DGE Apple Pay module inside your existing comcarde.client.create() callback. The example below includes all lifecycle handlers with clear signposting for what to implement in each.
comcarde.client.create(
{
authorization: clientApiKey, // Your client API key
},
function (clientErr, clientInstance) {
if (clientErr) {
console.error('Comcarde client error:', clientErr);
return;
}
// Guard: only proceed in browsers that support Apple Pay
if (!window.ApplePaySession) {
return;
}
comcarde.applePay
.create({
client: clientInstance,
sdkVersion: 14, // The Apple SDK version to use for the payment session
button: {
container: 'apple-pay-button', // Must match the id of your placeholder element
style: 'black',
type: 'buy',
},
})
.then(function (applePayClientModule) {
// This function is called when the customer taps the Apple Pay button.
// It must be assigned here so the onclick handler on the placeholder can reach it.
window.processApplePayPayment = function () {
applePayClientModule
.startSession(
{
label: 'Example Industries Ltd', // Your merchant or trading name
type: 'final', // Always "final"
amount: '10.00', // Total charge as a decimal string
currencyCode: 'GBP', // ISO 4217 code — defaults to retail channel config if omitted
},
function (comcardeSingleUseToken, applePaySession) {
// ─── onpaymentauthorized ─────────────────────────────────────
// The customer has authenticated with Face ID / Touch ID.
// You now have a single-use token to authorise the payment server-side.
//
// IMPORTANT: You must call applePaySession.completePayment() within
// 30 seconds or Apple will dismiss the sheet with a failure message.
// See "Completing the payment" below for full guidance.
sendTokenToServer(comcardeSingleUseToken)
.then(function (serverSuccess) {
applePaySession.completePayment(
serverSuccess
? ApplePaySession.STATUS_SUCCESS
: ApplePaySession.STATUS_FAILURE
);
})
.catch(function () {
// Always call completePayment — even on error — to close the sheet
applePaySession.completePayment(ApplePaySession.STATUS_FAILURE);
});
}
)
.then(function (applePayPaymentRequest) {
applePayClientModule
.session(applePayPaymentRequest)
.then(function (applePaySession) {
applePaySession.onerror = function (error) {
// Called when the Apple Pay session encounters an unrecoverable error.
// Log the error and surface a fallback payment option to the customer.
console.error('Apple Pay session error:', error);
};
applePaySession.oncancel = function (event) {
// Called when the customer dismisses the Apple Pay sheet without paying.
// No completePayment() call is needed — the session is already closed.
// Use this to reset your UI or log the abandonment.
console.warn('Apple Pay session cancelled:', event);
};
})
.catch(function (sessionError) {
console.error('Failed to create Apple Pay session:', sessionError);
});
})
.catch(function (startSessionError) {
console.error('startSession error:', startSessionError);
});
};
document.getElementById('apple-pay-button').removeAttribute('hidden');
})
.catch(function (createError) {
console.error('applePay.create error:', createError);
});
}
);Completing the payment
After the customer authenticates with Face ID, Touch ID, or a passcode, the onpaymentauthorized callback fires. At this point, the Apple Pay sheet shows a processing spinner — your code has 30 seconds to call applePaySession.completePayment() before Apple automatically dismisses the sheet with an error.
Passing the result
Call completePayment() with one of two status constants:
| Constant | When to use |
|---|---|
ApplePaySession.STATUS_SUCCESS | Your server confirmed the payment was authorised successfully. |
ApplePaySession.STATUS_FAILURE | The payment was declined, an error occurred, or you cannot confirm the outcome in time. |
// On success
applePaySession.completePayment(ApplePaySession.STATUS_SUCCESS);
// On failure or error
applePaySession.completePayment(ApplePaySession.STATUS_FAILURE);Handling slow server responses
Payment authorisation via your backend can take time — network latency, downstream processor delays, and retries can all eat into the 30-second window. Structure your server call to be non-blocking and apply a client-side timeout so you always call completePayment() in time.
function sendTokenToServer(token) {
// Race the server call against a 25-second client-side timeout.
// The 5-second buffer gives you headroom before Apple's 30-second hard cutoff.
var timeoutPromise = new Promise(function (_, reject) {
setTimeout(function () {
reject(new Error('Payment authorisation timed out'));
}, 25000);
});
//Send the token to your own server
var serverCall = fetch('/token/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: token }),
}).then(function (response) {
return response.ok;
});
return Promise.race([serverCall, timeoutPromise]);
}Then use it in your onpaymentauthorized callback:
function (comcardeSingleUseToken, applePaySession) {
sendTokenToServer(comcardeSingleUseToken)
.then(function (serverSuccess) {
applePaySession.completePayment(
serverSuccess
? ApplePaySession.STATUS_SUCCESS
: ApplePaySession.STATUS_FAILURE
);
})
.catch(function (err) {
// Timeout or network failure — always close the sheet with a failure status.
// You may still want to verify the payment outcome server-side after this point.
console.error('Payment authorisation error:', err);
applePaySession.completePayment(applePaySession.STATUS_FAILURE);
});
}
Always call completePayment()
completePayment()must be called in every code path — including error handlers and timeouts. If you do not call it, the Apple Pay sheet will hang until Apple times it out after 30 seconds, leaving the customer with no feedback and no way to retry.
Payment outcome after a timeoutIf your server successfully processed the payment but your client timed out before receiving the response, the Apple Pay sheet will close with a failure status — but the charge may still have gone through. Implement a server-side order status check (e.g. polling or a webhook) so you can reconcile the outcome and inform the customer correctly after the sheet closes.
Session lifecycle events
The applePaySession object exposes two events for you to handle after the session is created.
onerror
onerrorFires when the Apple Pay session encounters an unrecoverable error — for example, if Apple's servers are unreachable or a session configuration issue is detected. Use this to log the event and present a fallback payment method to the customer.
applePaySession.onerror = function (error) {
console.error('Apple Pay session error:', error);
// Show a fallback payment option
};oncancel
oncancelFires when the customer explicitly dismisses the Apple Pay sheet without completing a payment (e.g. tapping Cancel). The session is already closed at this point — do not call completePayment(). Use this to reset your UI state or log payment abandonment.
applePaySession.oncancel = function (event) {
console.warn('Apple Pay cancelled by customer:', event);
// Reset UI, re-enable the checkout button, etc.
};API reference
comcarde.applePay.create(options)
comcarde.applePay.create(options)Creates an Apple Pay button and renders it into the specified container element.
comcarde.applePay.create({
client: clientInstance,
sdkVersion: 14,
button: {
container: 'apple-pay-button',
style: 'black',
type: 'buy',
},
});Returns a Promise that resolves with applePayClientModule.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
client | object | ✅ | A Comcarde client instance, obtained from comcarde.client.create(). |
sdkVersion | int | The Apple Pay SDK version for the session. Use the lowest version that supports your required payment methods and features. Defaults to BR-DGE's highest version. Details in Apple's version docs. | |
button | object | ✅ | Configuration for the Apple Pay button. |
button.container | string | ✅ | The id of the HTML element to render the button into. |
button.style | string | Visual style of the button. Accepted values: black (default), white, white-with-line. | |
button.type | string | The button label type. Default: buy. See accepted values below. |
button.style values
button.style values| Value | Appearance |
|---|---|
black (default) | Black background, white Apple Pay mark |
white | White background, black Apple Pay mark |
white-with-line | White background with a black border |
button.type values
button.type valuesplain | add-money | book | buy (default) |
check-out | contribute | donate | order |
reload | rent | set-up | subscribe |
support | tip | top-up |
applePayClientModule.startSession(options, onPaymentAuthorized)
applePayClientModule.startSession(options, onPaymentAuthorized)Initiates an Apple Pay payment session when called from a user interaction handler.
applePayClientModule.startSession(
{
label: 'Example Industries Ltd',
type: 'final',
amount: '10.00',
currencyCode: 'GBP',
},
function (comcardeSingleUseToken, applePaySession) {
// Handle the authorised payment
}
);Returns a Promise that resolves with applePayPaymentRequest.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
label | string | ✅ | Your business or trading name. Displayed on the Apple Pay sheet. |
type | string | ✅ | Must always be "final". |
amount | string | ✅ | The total charge as a decimal string — e.g. "10.00". |
currencyCode | string | Transaction currency in ISO 4217 alphabetic format — e.g. GBP, EUR, USD. If omitted, defaults to the currency configured in your BR-DGE retail channel. |
Callback: onPaymentAuthorized(comcardeSingleUseToken, applePaySession)
onPaymentAuthorized(comcardeSingleUseToken, applePaySession)| Argument | Type | Description |
|---|---|---|
comcardeSingleUseToken | string | An encrypted, single-use token representing the customer's Apple Pay payment instrument. Send this to your server to authorise the payment via the BR-DGE API. |
applePaySession | object | The native ApplePaySession instance. Use this to call completePayment() once your server confirms the payment outcome. |
Decrypting the payment token
Get full payment details from the tokenUse the GET Apple Pay Token Metadata endpoint to decrypt the
comcardeSingleUseTokenserver-side. You'll receive payment details and BIN lookup metadata derived from the customer's Device Primary Account Number (DPAN).
Updated 12 days ago