Accept Apple Pay with a server-side-only integration

Build your own payment form to add Apple Pay payment to the checkout page


Using Apple Pay on your page, you need to use the Apple Pay JS API in order to get the payment authorized by Apple Pay. The payment data provided by Apple Pay are required by the Unzer Payment API to create the applepay payment type and perform transactions with it.

Before you begin

  • Follow the steps in the Get started guide to set up your environment.
  • See the full list of prerequisites for Accepting Apple Pay payments using the Unzer payment system here: Apple Pay Prerequisites

Check https://applepaydemo.apple.com/ for a detailed description on how to use Apple Pay on the web.

Using Apple Pay

Apple Pay guidelines

Before you can use Apple Pay you must make sure that your website or app comply with all of the guidelines mentioned by Apple: https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/

Apple Pay version compatibility

You can accept payments via Apple Pay with the Unzer Payment API. In our code examples, we have chosen version 6 to provide a good mix between compatibility with most Apple devices available and the data which you can request from a customer to process orders.

Apple Pay - Good to know

Here are some things which you should keep in mind while implementing Apple Pay in your application:

  • The domainName-parameter from the merchant validation-step must be equal to the one which has been validated in the Apple developer account.
  • Apple Pay is only available on supported Apple devices. See the full list of supported devices here: https://support.apple.com/en-us/HT208531
On the web Apple Pay is only available on Safari.

Step 1: Add Apple Pay to your project
client side

Create an Apple Pay button

When using Apple Pay as a payment method, you can use a pre-defined Apple Pay button or style it on your own.

For the setup of the pre-defined button, see the following Apple Pay Reference: https://developer.apple.com/documentation/apple_pay_on_the_web/displaying_apple_pay_buttons_using_css

<div class="apple-pay-button apple-pay-button-black" lang="us" onclick="setupApplePaySession()" title="Start Apple Pay" role="link" tabindex="0"></div>
<div onclick="setupApplePaySession()" title="Start Apple Pay" role="link" tabindex="0"></div>

Create an Apple Pay session

In your OnClick Handler Function setupApplePaySession() you first need to to create a paymentRequest object containing the transaction details needed to set up the Apple Pay session.

var paymentRequest = {
    currencyCode: 'yourCurrencyCode',
    countryCode: 'yourCountryCode',
    requiredShippingContactFields: ['postalAddress'],
    requiredBillingContactFields: ['postalAddress','email', 'name', 'phone'],
    lineItems: [
   {label: 'someSubTotalDescr', amount: someSubTotalAmount }, 
   {label: 'someOtherLabelDescr', amount: someOtherAmount }
    total: {
    label: 'someLabel',
    amount: someTotalAmount
    supportedNetworks: ['masterCard', 'visa' ],
    merchantCapabilities: [ 'supports3DS' ]
For more information about the ApplePayPaymentRequest, see the Apple Pay Documentation.

Now, you need to create your Apple Pay session and call the begin() method on the created session object to start the merchant validation process.

var session = new ApplePaySession(6, paymentRequest);

You then need to provide custom implementations for the following Apple Pay event handlers:

Event Handler Description
onvalidatemerchant This is a callback function to handle the Apple Pay merchant validation event.

Here you will need to call the backend validation endpoint, passing the validationURL from the event object.

To complete the validation process, you need to call the session.completeMerchantValidation(merchantSession), where merchantSession is the object fetched from the backend.

Also see Apple documentation: Event handler
onpaymentauthorized This event is called when the customer authorized the payment via Touch ID, Face ID or the passcode.

Here you need to create the Unzer payment type resource. You can do this by calling unzerApplePayInstance.createResource(paymentData), where paymentData is read from the encrypted Apple Pay token in the event parameter.

Then you will need to call the backend authorized endpoint in your server-side integration, passing the ID of created, payment type resource.

To complete the authorization process, you need to call session.completePayment passing either STATUS_SUCCESS or STATUS_FAILURE.
For more information about the ApplePaySession and other available event handlers, see the Apple Pay documentation.

Step 2: Create a Payment Type resource
server side

To create the actual payment, you need to pass the user data to your server backend and request a payment at our Payment API with the following code:

POST https://api.unzer.com/v1/types/applepay

  "version": "EC_v1",
  "data": "7jY1W5M61c5Br23lTmP06sZ....",
  "signature": "MIAGCSqGSIb3DQEHAqCAMIAC....",
  "header": {
    "ephemeralPublicKey": "MFkwEwYHKoZIzj0CAQYIKo....",
    "publicKeyHash": "zqO5Y3ldWWm4NnIk....",
    "transactionId": "f9ca8450a285b7fb3d9f9af5...."
$unzer = new Unzer('s-priv-xxxxxxxxxx');
$applePay = new Applepay('EC_v1', 'yourApplepayData', 'yourApplepaySignature', 'yourApplepayHeader');
Unzer unzer = new Unzer(new HttpClientBasedRestCommunication(), "s-priv-xxxxxxxxxx");
Applepay applePay = new Applepay('EC_v1', 'yourApplepayData', 'yourApplepaySignature', 'yourApplepayHeader');
applePay = unzer.createPaymentType(applePay);

The response looks similar to the following example:

  "id" : "s-apl-jxpxorn9poen",
  "method" : "applepay",
  "recurring" : false,
  "geoLocation" : {
    "clientIp" : "clientIp",
    "countryIsoA2" : ""
  "applicationPrimaryAccountNumber" : "applicationPrimaryAccountNumber",
  "applicationExpirationDate" : "09/2022",
  "currencyCode" : "currencyCode",
  "transactionAmount" : "transactionAmount"

Provide merchant validation
server side

In order to accept payments via Apple Pay, you need to be able to process the Apple Pay merchant validation. With this, Apple adds a security layer so that the customer can be sure that the merchant and the shop where they’re shopping at match.
This is a synchronous call from the ApplePaySession inside the Safari-Browser to the backend. The actual call to the Apple Pay server for the validation can only be done from the backend. You need to add functionality to validate your merchant to the onvalidatemerchant-event inside the Apple Pay session.
Find more information about this here: Apple documentation: Merchant validation

The Unzer SDKs also provides an adapter function to process the merchant validation on the server side for you.

To construct an ApplepaySession object, the following parameters are needed:

Parameter Description
merchantIdentifier This can be found in the Apple Developer account.
displayName The merchant name (can be anything).
domainName The domain name which has been validated in the Apple Developer account.
$applepaySession = new ApplepaySession('your.merchantIdentifier', 'ExampleTitle', 'your-domain.com');
$appleAdapter = new ApplepayAdapter();
$appleAdapter->init('/path/to/merchant_id.pem', '/path/to/rsakey.key')

// Get the merchant validation url from the frontend.
$merchantValidationURL = urldecode($_POST['merchantValidationUrl']);

try {
  $validationResponse = $appleAdapter->validateApplePayMerchant(
} catch (\Exception $e) {
String merchantValidationUrl = getMerchantValidationUrlFromFrontend();
ApplePaySession applePaySession = new ApplePaySession(applePayMerchantIdentifier, applePayDisplayName, domainName);
KeyManagerFactory kmf = getKeyManagerFactory();
TrustManagerFactory tmf = getTrustManagerFactory();
String response = ApplePayAdapterUtil.validateApplePayMerchant(merchantValidationUrl, applePaySession, kmf, tmf);

return response;

//Create TruststoreManagerFactory

private TrustManagerFactory getTrustManagerFactory() {
    KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    InputStream is = new ClassPathResource("path/to/file").getInputStream();
    trustStore.load(is, "password".toCharArray());

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");

    return trustManagerFactory;

//Create KeyManagerFactory
private KeyManagerFactory getKeyManagerFactory() {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    InputStream is = new ClassPathResource("path/to/file").getInputStream();
    keyStore.load(is, "password".toCharArray());
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
    keyManagerFactory.init(keyStore, "password".toCharArray());

    return keyManagerFactory;

All the SDKs require the Apple Pay Merchant ID Certificate to be present and provided to the adapter function. See the Apple Pay documentation to learn how to request an Apple Pay Merchant ID Certificate.

In the Java SDK, you also need to provide the Apple Pay certificate keychain in a trust store.

Provide a payment authorized endpoint
server side

After the customer has authorized the payment via the Apple Pay overlay, Safari will return an object with the data you need to transfer to our API in order to authorize or charge a payment via our Payment API. For this, you should provide a backend controller to accept the data from your frontend. This controller should then return the result of the API authorization because Apple Pay uses this to display the result to the customer.

The following example displays how Apple Pay data is handled on the server side:

$jsonData      = json_decode(file_get_contents('php://input'), false);
$applePayAuthorisation= $jsonData->applePayAuthorisation;

// Catch API errors, write the message to your log and show the ClientMessage to the client.
$response = ['transactionStatus' => 'error'];
try {
    // Create an Unzer object using your private key and register a debug handler if you want to.
    $unzer = new Unzer('s-priv-xxxxxxxxxxxxxx');
    $applepay = new Applepay(null, null, null, null);
    // -> Here you can place the Charge or Authorize call as shown in Step 3 <-
    // E.g $transaction = $unzer->charge(...);
    // Or  $transaction = $unzer->authorize(...);
    $response['transactionStatus'] = 'pending';
    if ($transaction->isSuccess()) {
        $response['transactionStatus'] = 'success';
} catch (UnzerApiException $e) {
    $merchantMessage = $e->getMerchantMessage();
    $clientMessage = $e->getClientMessage();
} catch (RuntimeException $e) {
    $merchantMessage = $e->getMessage();
echo json_encode($response);
String applePayAuthorisation = getApplePayAuthorisationFromFrontend();
Unzer unzer = new Unzer(new HttpClientBasedRestCommunication(), privateKey);
ObjectMapper mapper = new ObjectMapper();
boolean authStatus = false;

Applepay applepay = mapper.readValue(applePayAuthorisation, Applepay.class);

try {
    applepay = unzer.createPaymentType(applepay);
    // -> Here you can place the Charge or Authorize call as shown in Step 3 <-
    // E.g Charge charge = unzer.charge(...);
    // Or Authorize authorize = unzer.authorize(...);
    // Set the authStatus based on the resulting Status of the Payment-Transaction
    // The Functions charge.getStatus() or authorize.getStatus() will return the Status-Enum (SUCCESS, PENDING, ERROR)
        authStatus = true;
} catch (Exception ex) {

return authStatus;

Next steps

The next steps are the same as for the UI components integration, see Accept Apple Pay with UI Components from Step 3 onwards.