Native Apple Pay Integration Guide

Native Apple Pay integration. Enable seamless Apple Pay checkout directly on your website or application. Your frontend manages the user interface and Apple Pay interaction, while Mercuryo handles payment processing on the backend.

What You Can Build

Native Apple Pay checkout – Process payments directly on your site without redirecting users to the Mercuryo widget

Seamless user experience – Users complete the entire payment flow without leaving your application

Headless integration – Full control over the UI while Mercuryo handles payment processing

Built-in compliance – KYC/AML handled, with automatic fallback to full widget when needed

Secure processing – Two-certificate model ensures maximum security and clear separation of responsibilities

Contact your integration manager for more details, or email us at sales@mercuryo.io.

Country Restrictions

  • For users from the United States (US) or United Kingdom (GB): Native Apple Pay is currently not working.

  • For payments with bank cards issued in the United States (US) or United Kingdom (GB): Payments will not be processed at this time, regardless of the user's location.

Mercuryo will enforce this on our backend, but we recommend you also apply this logic on your frontend to improve the user experience.

Transaction Limits for Non-KYC Users

For users who have not completed the KYC (Know Your Customer) procedure, there is a cumulative transaction limit. The total turnover for a user, calculated across all their transactions and converted to EUR, cannot exceed €700. If a new transaction causes the user to exceed this limit, it will be rejected. This is one of the primary scenarios that may trigger an error requiring the user to be redirected to the full Mercuryo widget to complete KYC.

Integration Flow Overview

The integration is based on a "headless" model where your application manages the user interface and initial interaction with Apple, and Mercuryo's backend manages the payment execution.

The process consists of three main stages:

  1. Client-Side (Partner's Frontend): The user initiates the payment, and your frontend application communicates with the Apple Pay SDK.
  2. Server-Side (Partner's Backend): Your backend validates the merchant session with Apple using your own Merchant Identity Certificate.
  3. Processing (Mercuryo's Backend): Your application sends the encrypted payment data to Mercuryo, where we decrypt it using your Payment Processing Certificate and process the transaction.

Sequence Diagram

This diagram provides a detailed, step-by-step visualization of the entire flow.

Native Apple Pay Flow (Merchant Integration View) Native Apple Pay Flow (Merchant Integration View) User User Partner Frontend Partner Frontend Partner Backend Partner Backend Browser & OS (PaymentRequest API) Browser & OS (PaymentRequest API) Apple Servers Apple Servers Mercuryo Backend Mercuryo Backend "Partner-Side: Request Quote" GET /widget/buy/rate Purpose : Get a quote and check if native payment is available for this transaction. Query Params : `widget_id` `from`, `to`, `amount` `is_total` `payment_method=apple` `network` `address` `country` `ip_address` Mercuryo checks if native payment is available for this transaction. Response Response : `buy_token` `currency` `amount` `fiat_amount` `fiat_currency` `is_native_available` ... other relevant fields "Partner-Side: Payment Initialization & Session Validation" Clicks "Pay with Apple Pay" new PaymentRequest(config) Partner initializes the browser's native payment API. The config includes `payment_request_options` to request the necessary user data: - `requestPayerName: true` - `requestPayerEmail: true` - `requestBillingAddress: true` request.show() Triggers the native Apple Pay UI. [Internal SDK Call] Initiate Session Returns `validationURL` Triggers 'onmerchantvalidation' event (provides `validationURL`) POST /validate-apple-pay-session Request sends : `validationURL` POST {validation_url} Authentication : Partner uses their private Merchant Identity Certificate for mTLS authentication. Returns `merchantSession` object Returns `merchantSession` object event.complete(merchantSession) Confirms to the browser that the merchant is valid. Shows final native Apple Pay UI for confirmation Confirms payment (e.g., with Face ID) [Internal SDK Call] Generate Payment Token Returns encrypted `paymentToken` `request.show()` promise resolves with `PaymentResponse` `PaymentResponse` contains : - `details`: The encrypted `paymentToken` - `payerEmail`, `payerName` - `billingContact` object "Mercuryo-Side: Payment Processing" POST /process-apple-payment Purpose : Send encrypted token and user data to Partner's backend for secure processing. Request sends : `paymentToken` from Apple User & Order Data (`email`, `name`, `billing_address`, etc.) 1. Base64 encode `paymentToken`. 2. Sign the request. 3. Add SDK token for authentication. POST /sdk-partner/native-mobile-pay/mobile-pay Purpose : Send prepared and signed data to Mercuryo to process the payment. Request sends : `pay_token` (Base64 encoded `paymentToken`) `buy_token` (Mercuryo's quote/rate identifier) `address` (destination cryptocurrency wallet address) User & Order Data Headers : `sdk-partner-token`: The partner's SDK token. `x-signature`: The request signature. Mercuryo processes the transaction. Returns initial `{transactionId, status}` Returns initial `{transactionId, status}` response.complete('success') Inform browser to close the Apple Pay UI with a success indicator. "Backend Callback with Final Status" POST /callback Purpose : Return the final transaction status. Request Body: `transaction_id` `status` 200 OK

Onboarding: Certificate Setup

Before you can begin the integration, you must configure two types of Apple Pay certificates. This integration relies on a two-certificate model to ensure maximum security and clear separation of responsibilities.

1. Merchant Identity Certificate

  • Purpose: To authenticate your server with Apple's servers when validating a merchant session. This certificate is used to establish a secure TLS connection for the session validation request.
  • Responsibility: Yours.
  • Action: You must generate this certificate in your Apple Developer account and securely store it along with its private key on your backend infrastructure. You will use it to handle the onmerchantvalidation step. Mercuryo never sees this certificate or its key.
  • Official Documentation: For details, see Apple's documentation on Creating a Merchant Identity Certificate.

2. Payment Processing Certificate

  • Purpose: To allow Mercuryo to decrypt the final payment token. Apple uses the public key of this certificate to encrypt the payment data.
  • Responsibility: Ours to initiate, Yours to generate, Ours to use.
  • Action: During the onboarding process, we (Mercuryo) will provide you with a Certificate Signing Request (CSR). You must upload this CSR to your Apple Developer account to generate the final Payment Processing Certificate (.cer file). You then need to securely provide the downloaded .cer file back to us. We will use this certificate, paired with our private key, to process payments on your behalf.
  • Official Documentation: This certificate is associated with your Merchant ID and is used for encrypting payment data. See Apple's guide on configuring Apple Pay.

Step 1: Getting a Quote

Before initiating the Apple Pay payment sheet, your application must first get a transaction quote from Mercuryo. This step provides your user with the exact exchange rate and provides your application with a buy_token required to execute the payment.

You must call the standard /widget/buy/rate endpoint. To specify that this is a Native Apple Pay transaction, you must include the payment_method=apple parameter.

API Endpoint: GET /widget/buy/rate

Parameter Required For Native Flow Determination Description
widget_id Yes Your unique identifier provided by Mercuryo.
from Yes Source currency code (e.g., USD).
to Yes Target currency code (e.g., BTC).
amount Yes The amount in the from currency.
payment_method Yes Must be apple for this flow.
is_total Yes A boolean that determines how to interpret the amount. While optional in the generic API, it is required for this flow to ensure correct calculations. Defaults to true.
network Yes While optional in the generic API, the blockchain network is required for this flow to determine availability and correct fees.
address Yes While optional in the generic API, the destination wallet address is required for this flow for risk assessment.
country / ip_address Yes At least one of these fields is required to perform geo-restriction checks. ip_address is the preferred method.

Success Response

The response will contain the current rate, fee breakdown, and the buy_token. Crucially, it will also include a new boolean flag, is_native_available.

{
    "status": 200,
    "data": {
        "buy_token": "abc123def456...",
        "currency": "BTC",
        "amount": "0.00234398",
        "fiat_amount": "300.00",
        "fiat_currency": "USD",
        ...
        "is_native_available": true
    }
}

Note: Your frontend should check for is_native_available: true. If this flag is present and true, you can proceed with showing the native Apple Pay button. If it is false or absent, you should fall back to a different flow (e.g., redirecting the user to the full Mercuryo widget).

You must store the buy_token as it is a required field for the final POST /sdk-partner/native-mobile-pay/mobile-pay call.

Step 2: Partner-Side Implementation

Terms of Service

Since the payment is processed entirely on your side without redirecting users to the Mercuryo widget, you MUST obtain user consent to Mercuryo's Terms of Service before processing the payment. This is a mandatory compliance requirement.

You must display a link to Mercuryo's Terms of Service either before initiating Apple Pay or on the Apple Pay screen.

Payment Processing Disclosure

According to Apple's requirements, you MUST clearly indicate that the payment is processed through Mercuryo. This must be visible to the user on the Apple Pay payment sheet.

Example: "Pay Mercuryo (via [Your Company Name])"

PaymentRequest Initialization

Your frontend is responsible for creating and displaying the Apple Pay payment request. The modern and recommended way to integrate Apple Pay on the Web is by using the W3C standard Payment Request API.

When the user clicks the "Pay with Apple Pay" button, your frontend must create an ApplePayPaymentRequest or PaymentRequest. It is crucial that this request asks for all the necessary user information that Mercuryo requires for processing.

Official Documentation:

You must verify that your PaymentRequest includes the following parameters with the specified values:

1. merchantCapabilities

Reference: ApplePayMerchantCapability

You MUST include:

  • "supports3DS"
  • "supportsCredit"
  • "supportsDebit"

2. supportedNetworks

References:

You MUST include:

  • "masterCard"
  • "visa"

3. countryCode

Reference: countryCode

You MUST set:

  • "LT"

4. label (in total object)

Reference: ApplePayLineItem.label

This is the code, but essentially it refers to the label field of the total object.

According to Apple's requirements, you MUST clearly indicate that the payment is processed through Mercuryo. This must be visible to the user on the Apple Pay payment sheet.

Example: "Pay Mercuryo (via [Your Company Name])"

5. Contact Information & Billing Address

Reference: requiredBillingContactFields

You MUST request the following information from the payer via requiredBillingContactFields:

  • Payer Name
  • Payer Email
  • Billing Address

Important: The values retrieved from these fields (Email, Name, Billing Address) MUST be passed to Mercuryo in the subsequent payment processing request.

Example PaymentRequest Configuration:

const paymentRequest = {
    // ... your countryCode, currencyCode, total, etc.
    "requiredBillingContactFields": [
        "postalAddress",
        "name",
        "email"
    ],
    // Note: If using W3C Payment Request API, use options:
    // requestPayerName: true,
    // requestPayerEmail: true,
    // requestBillingAddress: true
    // requestShipping: false
    // ... other Apple Pay configuration
};

Your frontend will then handle the onmerchantvalidation event by calling your backend to get a valid merchantSession. After the user authorizes the payment, your frontend will receive the encrypted paymentToken.

Backend: Validating the Merchant Session

Your backend must expose an endpoint that your frontend can call during the onmerchantvalidation event. This endpoint is responsible for:

  1. Receiving the validationURL from your frontend.
  2. Making a POST request to that URL using your Merchant Identity Certificate to authenticate with Apple's servers.
  3. Returning the resulting merchantSession object to your frontend.

Step 3: Calling the Mercuryo API

Once your frontend has the encrypted paymentToken, it sends this token along with other transaction details to Mercuryo's dedicated native processing endpoint. The paymentToken must be encoded in base64 format before sending.

Request Authentication

All API requests sent from your backend to Mercuryo's API must be authenticated. This is done using two HTTP headers: sdk-partner-token for identification and x-signature for verifying the request integrity.

HTTP Headers

Header Description
sdk-partner-token Your unique partner authentication token, provided by your account manager.
x-signature The HMAC-SHA256 signature of the raw request body. See the next section for how to generate this value.

How to Generate the Signature (x-signature)

The signature ensures that the request body has not been tampered with.

  1. Get Your Sign Key: This is your unique Sign Key, which you can find in your partner dashboard. Keep this key confidential.
  2. Prepare the Request Body: Your request body must be a valid JSON object.
  3. Construct the Message to Sign: The signature is generated from the raw JSON request body string. Important: The JSON string must not contain any extra whitespace or formatting. It should be a compact, one-line string.
  4. Compute the Signature: Use the HMAC-SHA256 algorithm to compute the signature. The message is the raw JSON request body, and the key is your Sign Key. The output should be a hex-encoded string.
  5. Add the Signature to the Header: Include the generated signature in the x-signature HTTP header with every request.

API Endpoint: POST /sdk-partner/native-mobile-pay/mobile-pay

  • Authentication: The request must be authenticated using your partner sdk-partner-token, sent as an HTTP header.
  • Content-Type: application/json

Request Body

Field Type Description
pay_token string Required. The base64 encrypted paymentToken received from the Apple Pay SDK.
buy_token string Required. The unique quote identifier received from Mercuryo's GET /widget/buy/rate endpoint.
email string Required. The user's email address, obtained from the Apple Pay payment sheet.
first_name string Required. The user's first name.
last_name string Required. The user's last name.
billing_address object Required. The user's billing address object, as provided by Apple Pay. The object must match the structure of Apple's ApplePayPaymentContact object. See example below.
address string Required. The destination cryptocurrency wallet address for the user.
ip string Required. The user's IP address.
merchant_transaction_id string Optional. Your internal identifier for the transaction.

Example billing_address object:

"billing_address": {
    "country_code": "US",
    "street_line_1": "Asden Ct",
    "street_line_2": "123",
    "state_code": "OH",
    "city": "Reynoldsburg",
    "zip_code": "43068"
}

Success Response

Mercuryo's endpoint will synchronously return the initial status of the transaction in a nested data object.

{
    "status": 200,
    "data": {
        "id": "28a3c125a28075453",
        "status": "pending"
    }
}

The status field inside the data object (e.g., "pending") indicates that the transaction has been accepted and is being processed. The final status will be sent via the server-to-server callback.

Handling Errors and Fallback to Widget

While the API can return standard HTTP error codes for general issues (e.g., 400 Bad Request for invalid parameters), the most critical response to handle is the one that triggers a fallback flow.

A key feature of this integration is the ability to seamlessly transition the user from a native Apple Pay flow to the full Mercuryo widget if additional user action is required. This ensures that transactions are not lost in cases where simple native payment is insufficient (e.g., the user needs to complete KYC).

Triggering the Fallback

The fallback mechanism is triggered when the /sdk-partner/native-mobile-pay/mobile-pay endpoint responds with a specific error code indicating that the transaction cannot be completed natively. This response indicates that while the request is valid, it cannot be processed without further user interaction. A detailed list of error codes will be provided later.

Example Error Responses:

Error response (transaction blocked):

{
    "status": 403,
    "code": 403006,
    "message": "Transaction blocked."
}

Error response (transaction failed):

{
    "status": 200,
    "data": {
        "id": "28a3c125a28075453",
        "status": "order_failed"
    }
}

Partner Frontend Implementation

Your frontend application should be designed to handle this fallback response:

  1. Check the response for the specific error code that signals a fallback is needed.
  2. Redirect the user's browser to the widget URL.

The user will land on the Mercuryo widget with all their transaction data pre-filled, where they can complete the required steps (e.g., upload documents for KYC) and finalize their purchase.

Step 4: Receiving the Final Status (Callback)

Because the final processing of the transaction is asynchronous, Mercuryo will notify your backend of the final transaction status using our standard server-to-server webhook. You must provide a secure callback URL to your Mercuryo integration manager during onboarding.

Callback Verification

To ensure the security and authenticity of the callback, each request will contain an x-signature HTTP header. You must verify this signature by calculating an HMAC-SHA256 hash of the raw JSON payload using your widget's Sign key (available in your Mercuryo dashboard) and comparing it to the value of the header.

Callback Payload

The callback payload is a standard CallbackNotification object, as described in our main API reference. For a Native Apple Pay transaction, the data object within the payload will have the following key identifiers:

  • "type": "buy"
  • "payment_method": "mobile_pay"
  • "method_code": "apple"

The status field within the data object will reflect the final state of the transaction, such as paid, order_failed, or cancelled.

Please refer to the /callback section in our main swagger-widget-integration.yaml documentation for the complete schema of the callback body and all possible transaction statuses.

FAQ

Visit Help Center for Merchants