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 environments

Apple 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=payment attribute.

Checking for availability

🚧

Always check before loading the module

Attempting to start an Apple Pay session on a non-supported browser throws an unhandled error. Guard against this with a window.ApplePaySession check 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 to onclick satisfies Apple's requirement.

Give the element a unique id — you'll pass this to button.container in the next step.

🚧

The hidden attribute 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 hidden attribute 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:

ConstantWhen to use
ApplePaySession.STATUS_SUCCESSYour server confirmed the payment was authorised successfully.
ApplePaySession.STATUS_FAILUREThe 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 timeout

If 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

Fires 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

Fires 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)

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

ParameterTypeRequiredDescription
clientobjectA Comcarde client instance, obtained from comcarde.client.create().
sdkVersionintThe 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.
buttonobjectConfiguration for the Apple Pay button.
button.containerstringThe id of the HTML element to render the button into.
button.stylestringVisual style of the button. Accepted values: black (default), white, white-with-line.
button.typestringThe button label type. Default: buy. See accepted values below.

button.style values

ValueAppearance
black (default)Black background, white Apple Pay mark
whiteWhite background, black Apple Pay mark
white-with-lineWhite background with a black border

button.type values

plainadd-moneybookbuy (default)
check-outcontributedonateorder
reloadrentset-upsubscribe
supporttiptop-up

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

ParameterTypeRequiredDescription
labelstringYour business or trading name. Displayed on the Apple Pay sheet.
typestringMust always be "final".
amountstringThe total charge as a decimal string — e.g. "10.00".
currencyCodestringTransaction 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)

ArgumentTypeDescription
comcardeSingleUseTokenstringAn 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.
applePaySessionobjectThe 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 token

Use the GET Apple Pay Token Metadata endpoint to decrypt the comcardeSingleUseToken server-side. You'll receive payment details and BIN lookup metadata derived from the customer's Device Primary Account Number (DPAN).