Skip to content

Apple Pay Web Integration

Overview

This guide describes how to integrate Apple Pay with the Bpayd API for web using Apple Pay JS. It covers the front-end implementation, domain verification, and the backend payment flow.

The integration involves two main components:

  1. Front-end (Web): Collecting the Apple Pay payment token using Apple's JavaScript API
  2. Back-end: Sending the Apple Pay token to the Bpayd API for payment processing

Choose Who Manages Apple Pay

There are two supported setup paths. Both use SaleWithApplePay to process the payment; they differ in who manages the Apple identity, certificates, domain registration, and merchant session.

Responsibility Blackstone-managed Merchant-managed
Apple Developer account and Merchant ID Blackstone's configuration Your own account and Merchant ID
Domain registration and verification Blackstone registers the domain; you host the verification file it provides You register and verify the domain in your Apple account
Payment Processing Certificate, used to encrypt the payment token Managed by Blackstone You create it using the Portal-generated CSR and upload the certificate to the Portal for the relevant Bpayd MID
Merchant Identity Certificate, used to authenticate session requests to Apple Managed by Blackstone You create and keep it, together with its private key, on your back-end
Merchant session request Your back-end calls Bpayd's ValidateApplePayMerchant Your back-end calls Apple directly using your Merchant Identity Certificate
Payment processing Your back-end calls Bpayd's SaleWithApplePay Your back-end calls Bpayd's SaleWithApplePay

The Payment Processing Certificate and Merchant Identity Certificate have different roles. Uploading a processing certificate to the Merchants Portal does not configure merchant-session validation for your Apple identity. See Apple's web configuration guide.

Prerequisites

Before you begin, make sure you have:

  • Bpayd API Credentials: Provided by Bpayd/Blackstone for your integration:
  • AppKey: Application Key that uniquely identifies your application
  • AppType: Application Type identifier
  • UserName: API username
  • Password: API password
  • mid: Merchant ID
  • cid: Cashier ID
  • Apple Pay enablement from Bpayd:
  • Apple Pay is enabled for your merchant in Bpayd.
  • Choose the Blackstone-managed or merchant-managed setup above and complete its configuration before requesting payments.
  • Blackstone-managed web integrations do not need their own Apple Developer account or certificates in the Merchants Portal.
  • Merchant-managed web integrations need their own Apple Merchant ID, a processing certificate configured in the Portal, and a separate identity certificate configured on their back-end.
  • Apple Pay domains:
  • A list of all domains where you will show the Apple Pay button (see Domain Configuration for Bpayd below).
  • Each domain must be available over HTTPS in production.
  • Supported devices and browsers:
  • iPhone (iOS 16+): Apple Pay works natively in all browsers (Safari, Chrome, Edge, Firefox, etc.).
  • Mac (macOS): Native Apple Pay is available only in Safari.
  • Other environments: On macOS with other browsers (Chrome, Firefox) or on Windows/Linux, the user will see a QR Code which they must scan with their iPhone to complete the payment.
  • Official web documentation:
  • Apple Pay on the Web overview: https://developer.apple.com/documentation/apple_pay_on_the_web/
  • Apple Pay JS API reference: https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession

Integration Flow

The complete Apple Pay on the web flow consists of these steps:

  1. The customer clicks the Apple Pay button on your site (on a compatible Apple device and browser).
  2. Your front-end creates an ApplePaySession with a payment request (amount, currency, supported networks, capabilities).
  3. During the session, Apple calls your front-end's onvalidatemerchant handler with a validationURL.
  4. Your front-end sends this validationURL to your back-end.
  5. Your back-end obtains a merchant session: through Bpayd's ValidateApplePayMerchant for Blackstone-managed setup, or directly from Apple with your identity certificate for merchant-managed setup.
  6. Your front-end completes merchant validation using that merchant session.
  7. When the customer authorizes the payment, Apple Pay returns a payment token to your front-end.
  8. Your front-end sends the Apple Pay token to your back-end.
  9. Your back-end Base64-encodes the token and calls the Bpayd API SaleWithApplePay endpoint.
  10. Bpayd processes the payment and returns the result.
  11. Your application displays the payment result to the customer.

Responsibilities

Bpayd provides

  • Bpayd API credentials (AppKey, AppType, UserName, Password, mid, cid).
  • Apple Pay merchant configuration (merchant identifier, certificates, and processing keys) for Blackstone-managed setup.
  • Portal key-pair/CSR generation and processing-certificate upload for merchant-managed setup, scoped to the selected Bpayd MID.
  • API endpoints for:
  • SaleWithApplePay (Apple Pay sale processing).
  • ValidateApplePayMerchant (merchant session validation using Blackstone's identity, for Blackstone-managed setup only).
  • Domain registration and verification files for Blackstone-managed setup.

Your application is responsible for

  • Completing domain configuration for the selected setup and hosting the verification files from Blackstone or your own Apple account, as applicable.
  • For merchant-managed setup, configuring the processing certificate in the Portal and implementing direct merchant-session validation on your back-end.
  • Building the Apple Pay front-end integration (ApplePaySession, merchant validation, payment authorization).
  • Forwarding the Apple Pay token to your back-end exactly as received from Apple (without modification).
  • Base64-encoding the token on the back-end before sending it to Bpayd.
  • Generating a unique UserTransactionNumber for each transaction.

Front-End Implementation

[!NOTE] Disclaimer: The following web front-end implementation is provided as a reference guide. Your actual implementation may vary depending on your technology stack (e.g., React, Vue, Angular) and specific application architecture. You should adapt these examples to fit your needs rather than copying them verbatim.

On the web, you integrate Apple Pay using Apple's JavaScript API (ApplePaySession).

1. Import the Apple Pay SDK

You must include the Apple Pay JS SDK in your page. Add the following script tag to your HTML:

<script src="https://applepay.cdn-apple.com/jsapi/1.latest/apple-pay-sdk.js"></script>

2. Implementation Steps

At a high level:

  1. Check for Secure Context: Apple Pay requires HTTPS (or localhost).
  2. Wait for API Availability: The ApplePaySession object might load asynchronously.
  3. Check Payment Capability: Use canMakePayments() to check if the device and browser support Apple Pay.
  4. Show the Button: If supported, display the Apple Pay button.
  5. Handle Session: Create the session, handle merchant validation, and process the payment.

For full implementation details, follow Apple's official documentation:

Configuration for Bpayd

When integrating Apple Pay with Bpayd, your front-end code should:

  • Use a payment request that matches the selected merchant's payment configuration.
  • Implement merchant validation by sending Apple's validationURL to your back-end. That back-end uses Bpayd's ValidateApplePayMerchant for Blackstone-managed setup, or Apple directly for merchant-managed setup.
  • Implement payment authorization by forwarding the Apple Pay token to your back-end, unchanged.

Robust JavaScript Example

Below is a robust JavaScript example that handles cross-browser support, async loading, and secure context checks.

The /your-backend/... URLs belong to your application, not to Bpayd. In this example, your validation route returns { "result": <merchant session object> } in either setup; implement the appropriate server-side branch described below. This wrapper is your application's response shape, not an additional Bpayd API field. Keep all private keys and Bpayd credentials on the server. The availability check below does not register a domain or guarantee that an unregistered localhost checkout can complete a payment.

// 1. Helper: Check if the context is secure (HTTPS or localhost)
function isSecureApplePayContext() {
    return location.protocol === 'https:' || location.hostname === 'localhost';
}

// 2. Helper: Wait for ApplePaySession to be available (it may load asynchronously)
function waitForApplePaySession(maxAttempts = 10, delayMs = 300) {
    return new Promise(resolve => {
        const attempt = (count) => {
            if (window.ApplePaySession) {
                return resolve(true);
            }
            if (count >= maxAttempts) {
                return resolve(false);
            }
            setTimeout(() => attempt(count + 1), delayMs);
        };
        attempt(0);
    });
}

// 3. Helper: Resolve the supported Apple Pay version
function resolveApplePayVersion() {
    if (!window.ApplePaySession) {
        return null;
    }
    if (typeof ApplePaySession.supportsVersion !== 'function') {
        return 1; // Default to version 1 if supportsVersion is missing
    }
    // Check for versions in descending order
    const versions = [3, 2, 1];
    for (let i = 0; i < versions.length; i++) {
        if (ApplePaySession.supportsVersion(versions[i])) {
            return versions[i];
        }
    }
    return null;
}

// 4. Main Initialization Function
async function initializeApplePay() {
    // Security check
    if (!isSecureApplePayContext()) {
        console.warn('Apple Pay requires a secure (HTTPS) connection.');
        return;
    }

    // Wait for the SDK to load
    const sessionReady = await waitForApplePaySession();
    if (!sessionReady) {
        console.warn('Apple Pay SDK not loaded or not supported in this browser.');
        return;
    }

    // Check availability
    try {
        const result = ApplePaySession.canMakePayments();

        // Handle both Promise (newer) and Boolean (older) returns
        if (result && typeof result.then === 'function') {
            result.then(function (canPay) {
                if (canPay) showApplePayButton();
            }).catch(function (err) {
                console.error('Apple Pay availability check failed:', err);
            });
        } else {
            if (result) showApplePayButton();
        }
    } catch (error) {
        console.error('Apple Pay availability check failed:', error);
    }
}

function showApplePayButton() {
    const button = document.getElementById('applePayButton');
    if (button) {
        button.style.display = 'inline-flex';
        button.addEventListener('click', beginApplePaySession);
    }
}

// 5. Begin Session
function beginApplePaySession() {
    if (!window.ApplePaySession) return;

    const version = resolveApplePayVersion();
    if (!version) {
        console.error('No supported Apple Pay version found.');
        return;
    }

    const totalAmount = '10.50'; // Your computed total

    // Configuration must match Bpayd agreement
    const paymentRequest = {
        countryCode: 'US',
        currencyCode: 'USD',
        supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
        merchantCapabilities: ['supports3DS'],
        total: {
            label: 'Your Business Name',
            amount: totalAmount,
        },
    };

    const session = new ApplePaySession(version, paymentRequest);

    // Your backend uses Bpayd (Blackstone-managed) or Apple (merchant-managed).
    session.onvalidatemerchant = function (event) {
        fetch('/your-backend/apple-pay/validate-merchant', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                validationUrl: event.validationURL
            }),
        })
        .then(response => {
            if (!response.ok) throw new Error('Merchant validation failed');
            return response.json();
        })
        .then(data => {
            // Your backend wraps the opaque Apple merchant session as { result }.
            session.completeMerchantValidation(data.result);
        })
        .catch(err => {
            console.error('Merchant validation failed:', err);
            session.abort();
        });
    };

    // Payment Authorization
    session.onpaymentauthorized = function (event) {
        const rawToken = event.payment.token;
        // Ensure token is a JSON string
        const tokenString = typeof rawToken === 'string'
            ? rawToken
            : JSON.stringify(rawToken);

        fetch('/your-backend/apple-pay/process-payment', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                applePayToken: tokenString,
                amount: totalAmount
            }),
        })
        .then(response => response.json())
        .then(result => {
            if (result && result.success) {
                session.completePayment(ApplePaySession.STATUS_SUCCESS);
            } else {
                session.completePayment(ApplePaySession.STATUS_FAILURE);
            }
        })
        .catch(err => {
            console.error('Payment processing failed:', err);
            session.completePayment(ApplePaySession.STATUS_FAILURE);
        });
    };

    session.oncancel = function () {
        console.info('Apple Pay session cancelled by user.');
    };

    session.begin();
}

// Start initialization
document.addEventListener('DOMContentLoaded', initializeApplePay);

All other Apple Pay UI and configuration options (button style, locale, additional line items, etc.) should follow Apple's guides. The Bpayd-specific requirements are:

  • The supported networks should include at least visa, masterCard, amex, and discover (subject to the configuration agreed with Bpayd).
  • merchantCapabilities must include supports3DS.
  • You must forward the full Apple Pay payment.token payload to your back-end, unchanged.

Domain Configuration for Bpayd

Domain verification applies to Apple Pay on the web, not to native iOS payment authorization. Use the registration path that matches the Apple identity you selected above.

Blackstone-managed domain registration

Contact Alexandra through your existing email or WhatsApp conversation to request setup. Provide the following information:

  • Every domain and subdomain where you intend to show the Apple Pay button.
  • Domains must be specified without protocol and without paths.
  • Examples of valid entries:
    • example.com
    • store.example.com
    • checkout.example.net
  • Invalid examples (do not include protocol or subpaths):
    • https://example.com
    • example.com/checkout
  • Identify the Bpayd merchant or platform associated with the request so the configuration can be linked to the correct integration. Do not send API passwords or private keys.

  • If you use multiple subdomains, you must list each one explicitly. Registering only example.com is not sufficient if you also use checkout.example.com or shop.example.com.

  • Bpayd will:

  • Register those domains under Blackstone's Apple configuration and configure Bpayd's domain authorization.
  • Provide you with one or more verification files and the exact URLs where they must be hosted for each domain (typically under the /.well-known/ path).

  • You must:

  • Deploy the provided verification file(s) to each specified domain at the exact path indicated by Bpayd.
  • Ensure the files are served over HTTPS and are publicly accessible.

For a SaaS checkout shared by several Bpayd merchants, registering the same domain under Blackstone's identity is not repeated for each MID. Use the credentials of the merchant that owns each payment. Adding a different domain or subdomain requires its own registration; domain verification must also be kept valid. Bpayd's internal domain authorization is separate from Apple's domain verification.

You do not need to generate certificates in the Merchants Portal for this Blackstone-managed web flow.

Merchant-managed domain and certificate setup

  1. In your Apple Developer account, create or select the Merchant ID for your web integration. This Apple identifier is different from your numeric Bpayd mid.
  2. In the Bpayd Merchants Portal > Business Settings > Developers > Apple Pay, select the relevant Bpayd merchant, generate a new key pair using that Apple Merchant ID, and download its CSR. The processing private key is generated and retained by Bpayd.
  3. In Apple Developer, create a Payment Processing Certificate for that Merchant ID using the CSR from the Portal. Download the .cer file and upload it to the matching pending key entry in the Portal. Do not substitute a CSR generated elsewhere: its private key would not match the key Bpayd holds.
  4. Register each domain/subdomain under your Apple Merchant ID. Download Apple's domain-verification file, host it at Apple's specified HTTPS path, and complete verification in your Apple account. You manage this registration instead of asking Blackstone to register it under Blackstone's identity.
  5. Separately create a Merchant Identity Certificate for your Apple Merchant ID using a CSR whose private key is held by your own back-end. Keep this certificate and its private key securely on that server for mutual TLS requests to Apple. Do not upload this identity certificate as the Portal's processing certificate.
  6. Implement merchant-managed session validation below, then send the authorized payment token to Bpayd's SaleWithApplePay with the MID whose processing key you configured.

An Active processing-certificate entry in the Portal does not by itself verify the domain, configure the identity certificate, or prove that a web payment can complete. Validate the whole flow. You remain responsible for the lifecycle and renewal of your Apple certificates and domain verification.

The Portal processing-certificate steps are also used by native iOS integrations, but web integrations additionally need domain verification and merchant-session validation. See Apple's domain and certificate setup instructions.

Back-End Implementation

Apple Pay sale endpoint

To process an Apple Pay payment in either setup, your back-end calls the same Bpayd API Apple Pay sale endpoint. For merchant-managed setup, the API resolves the processing key using the token's public-key identifier and the authenticated Bpayd MID; the matching processing certificate must be configured for that MID. You do not add an Apple Merchant ID or a certificate to the sale request body.

URL: https://services.bmspay.com/api/Transactions/SaleWithApplePay Method: POST Content-Type: application/json

Required fields

At a minimum, your request must include:

  • Authentication fields: AppKey, AppType, UserName, Password, mid, cid
  • Transaction fields: Amount, Token, UserTransactionNumber

UserTransactionNumber must be unique for the merchant (mid), across endpoints and test/live modes. Reusing a previously reserved reference returns ResponseCode: 5; it does not return the original payment response. This is duplicate rejection, not response replay. See Duplicate references and retries before retrying a payment, especially after a timeout.

For the full list of supported fields and detailed schema for SaleWithApplePay, refer to the Bpayd API Reference.

Important: Token encoding

The Apple Pay token you receive on the front end is a JSON payload (event.payment.token). Before sending it to the Bpayd API, you must Base64-encode it and place the result in the Token field of the request.

The typical sequence is:

  1. On the front end, obtain the full Apple Pay token payload and convert it to a JSON string (for example, JSON.stringify(event.payment.token)).
  2. Send that JSON string to your back-end (for example, in a field named applePayToken).
  3. On the back-end, Base64-encode the JSON string and assign the result to the Token field in the SaleWithApplePay request body.

Sample request body

{
    "AppKey": "YOUR_APP_KEY",
    "AppType": 1,
    "UserName": "YOUR_USERNAME",
    "Password": "YOUR_PASSWORD",
    "mid": 12345,
    "cid": 1,

    "Amount": 10.50,
    "Token": "<BASE64_ENCODED_APPLE_PAY_TOKEN>",
    "UserTransactionNumber": "UNIQUE_TXN_123456",

    "IsTest": true
}

For the full list of supported fields, refer to the Bpayd API Reference.

Merchant validation endpoint

Blackstone-managed setup only. Your back-end calls this endpoint to obtain an Apple merchant session using Blackstone's identity and certificate. The endpoint does not switch to your own Apple identity when you upload a processing certificate to the Portal. For merchant-managed setup, use the direct validation flow in the next section instead.

URL: https://services.bmspay.com/api/Transactions/ValidateApplePayMerchant Method: POST Content-Type: application/json

At a high level:

  • Your front-end receives a validationURL from Apple in onvalidatemerchant.
  • Your back-end calls ValidateApplePayMerchant with:
  • Your standard Bpayd authentication fields (AppKey, AppType, UserName, Password, mid, cid).
  • ValidationUrl: the validationURL received from Apple.
  • Initiative: "web".
  • InitiativeContext: the domain that Apple is validating (must exactly match one of the Apple Pay domains registered with Bpayd, without protocol or path).
  • Bpayd performs the domain checks and calls Apple's servers.
  • The response contains the merchant session object that your front-end must pass to session.completeMerchantValidation.

For the exact schema of the ValidateApplePayMerchant request and response, refer to the Bpayd API Reference.

Merchant-managed session validation

Your own server performs this step; do not call Bpayd's ValidateApplePayMerchant for a merchant session using your own Apple identity.

  1. Receive event.validationURL from your front-end's onvalidatemerchant handler.
  2. Authorize the checkout request and resolve the Apple Merchant ID and verified checkout domain from trusted server-side configuration. Allow only Apple's documented HTTPS validation destinations; do not expose an arbitrary-URL proxy or follow redirects to untrusted hosts.
  3. Request the merchant session from Apple over mutual TLS, presenting your Merchant Identity Certificate and its private key, not the processing certificate uploaded to Bpayd. Follow Apple's payment-session request documentation for the validation URL received from Apple.
  4. Send your configured merchantIdentifier, displayName, initiative: "web", and initiativeContext (your verified domain, without protocol or path). The identity and domain must correspond to your Apple setup.
  5. Return the opaque session object from Apple to the browser without modifying its contents. In the JavaScript example above, your back-end wraps it as { "result": <session object> }; the browser passes data.result to session.completeMerchantValidation.
  6. After the customer authorizes payment, send the token to your back-end, Base64-encode its JSON, and call Bpayd's SaleWithApplePay with the correct merchant's credentials. Bpayd decrypts and processes it using the configured processing key.

Session acquisition happens server-to-server, never directly from the browser with a private key. Obtain a fresh session for each payment session; do not reuse a session object. If validation fails, abort the browser session rather than continuing to payment authorization. See Apple's merchant-validation flow.

Testing

Use the Apple Pay sandbox when testing your integration, and set IsTest: true in your requests to Bpayd. Follow Apple's official guidance for configuring test cards and devices:

IsTest does not choose the certificate-management model or bypass Apple's domain and session requirements. Before production, check the selected session-validation path, domain verification, processing-certificate mapping to the Bpayd MID, and the complete sandbox payment result.

Summary

Integrating Apple Pay on the web with Bpayd API involves:

  1. Choose management: Use Blackstone's Apple configuration, or manage your own Apple account and certificates. With Blackstone, arrange domain setup through Alexandra and host the file provided. With your own account, configure the Portal processing certificate, register/verify your domain, and configure your own server's identity certificate.
  2. Front-end: Implement Apple Pay using ApplePaySession and obtain the Apple Pay token payload.
  3. Merchant session: Call Bpayd's ValidateApplePayMerchant only for Blackstone-managed setup; for merchant-managed setup, your server requests the session from Apple directly.
  4. Payment: In either setup, call SaleWithApplePay, Base64-encoding the Apple Pay token before sending it to Bpayd.
  5. Handle response: Process the result and update your application accordingly.

The key requirements are to correctly configure and verify your domains with Apple and to Base64-encode the Apple Pay token before calling SaleWithApplePay. All other parameters follow standard Bpayd API conventions.

If you also need to support Google Pay, see the Google Pay Integration Guide for Web, Android, or Flutter.