Skip to content

Implementation

Complete guide to integrating the Apple Pay component into your application.

Overview

The Apple Pay component provides a secure, streamlined payment experience for Apple device users. The component follows a simple three-step lifecycle:

  1. Initialise: Configure the SDK with your session and transaction data.
  2. Create & mount: Build the Apple Pay button with your configuration and render it to your page.
  3. Handle callbacks: Respond to payment success, errors, and other events.

The component automatically handles Apple Pay authorization, tokenisation, and transaction processing.

Backend verification is mandatory. Always verify payments on your backend before fulfilling orders. Frontend callbacks can be manipulated by malicious users.

Before you start

To use the Apple Pay component, you first need to:

  • Complete the Apple Pay onboarding process in the Unity Portal.
  • Ensure your website is served over HTTPS (required for Apple Pay).
  • Verify your domain with Apple Pay (configured in the Unity Portal).

Browser and device compatibility

Apple Pay for Web has specific requirements for optimal functionality.

Supported browsers

  • Safari 11.1+ on macOS 10.13.4+
  • Safari on iOS 11.2+
  • Other WebKit-based browsers with Apple Pay support

Device requirements

  • iOS devices: iPhone 6 or later, iPad Pro, iPad (5th generation) or later, iPad Air 2, iPad mini 3 or later
  • macOS devices: MacBook Pro with Touch Bar, MacBook Air (2018 or later), iMac Pro, Mac Pro (2019 or later), or any Mac with Touch ID

Configuration requirements

  • The customer must have a supported payment method in their Wallet
  • The device must have Touch ID, Face ID, or passcode enabled

Step 1: Install the Web SDK library

Install the latest version of the Web SDK from the npm public registry. You'll need to have Node.js 22.x or higher.

npm i @pxpio/web-components-sdk

The Apple Pay component is part of the main SDK package. Import PxpCheckout directly from @pxpio/web-components-sdk.

Step 2: Get your API credentials

In order to initialise Components for Web, you'll need to send authenticated requests to the PXP API.

To get your credentials:

  1. In the Unity Portal, go to Merchant setup > Merchant groups.
  2. Select a merchant group.
  3. Click the Inbound calls tab.
  4. Copy the Client ID in the top-right corner.
  5. Click New token.
  6. Choose a number of days before token expiry. For example, 30.
  7. Click Save to confirm. Your token is now created.
  8. Copy the token ID and token value. Make sure to keep these confidential to protect the integrity of your authentication process.

As best practice, we recommend regularly generating and implementing new tokens.

Step 3: Create a session on your backend

The Apple Pay component requires a session from the PXP Sessions API. This must be done on your backend using HMAC authentication to keep your credentials secure.

For detailed HMAC authentication instructions, see the card implementation guide.

Session request example

{
  "merchant": "MERCHANT-1",
  "site": "SITE-1",
  "sessionTimeout": 120,
  "merchantTransactionId": "txn-123",
  "transactionMethod": {
    "intent": {
      "card": "Purchase"
    }
  },
  "amounts": {
    "currencyCode": "USD",
    "transactionValue": 25.00
  },
  "allowTransaction": true
}

Session response

The session response will include Apple Pay configuration if it's enabled for your site:

{
  "sessionId": "c5f0799b-0839-43ce-abc5-5b462a98f250",
  "hmacKey": "904bc42395d4af634e2fd48ee8c2c7f52955a1da97a3aa3d82957ff12980a7bb",
  "encryptionKey": "20d175a669ad3f8c195c9c283fc86155",
  "sessionExpiry": "2025-05-19T13:39:20.3843454Z",
  "allowedFundingTypes": {
    "cardSchemes": ["Visa", "Mastercard", "AmericanExpress"],
    "cards": [],
    "wallets": {
      "applePay": {
        "merchantId": "merchant.com.yourcompany.yourapp"
      }
    }
  }
}

The Apple Pay merchantId is automatically included in the session response when Apple Pay is configured for your site in the Unity Portal.

Step 4: Initialise the SDK on your frontend

Import PxpCheckout from the SDK and initialise with your configuration.

import { PxpCheckout, IntentType } from '@pxpio/web-components-sdk';

// Get session data from your backend
const sessionData = await fetch('/api/sessions', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' }
}).then(response => response.json());

// Initialise the SDK
const pxpSdk = PxpCheckout.initialize({
  environment: 'test',
  session: sessionData,
  ownerId: 'MERCHANT-1',
  ownerType: 'MerchantGroup',
  transactionData: {
    currency: 'USD',
    amount: 25,
    entryType: 'Ecom',
    intent: {
      card: IntentType.Authorisation
    },
    merchantTransactionId: crypto.randomUUID(),
    merchantTransactionDate: () => new Date().toISOString()
  },
  kountDisabled: false, // OPTIONAL: Set to true to disable Kount fraud detection
  onGetShopper: () => Promise.resolve({ 
    id: 'shopper-123',
    email: 'customer@example.com',
    firstName: 'John',
    lastName: 'Doe'
  })
});

Step 5: Create and configure the Apple Pay button

Use the SDK's create() method to build the Apple Pay button with your desired configuration:

const applePayButton = pxpSdk.create('apple-pay-button', {
  merchantDisplayName: 'Merchant Store',
  paymentDescription: 'Apple Pay payment',
  style: {
    type: 'buy',
    buttonstyle: 'black',
    locale: 'en-US',
  },
  paymentRequest: {
    merchantCapabilities: ['supports3DS'],
    supportedNetworks: ['visa', 'masterCard', 'amex'],
    countryCode: 'US',
    currencyCode: 'USD',
    total: {
      label: 'Pay',
      amount: '25.00',
    },
  },
  onPreAuthorisation: () => {
    return {};
  },
  onPostAuthorisation: (data: any) => {
     // CRITICAL: Verify on backend before fulfilling order
     await verifyPaymentOnBackend(data)
  },
  onError: (error: any) => {
    console.error('Apple Pay failed:', error);
  },
});

Configuration options

ParameterDescription
merchantDisplayName
string
required
The name of your store displayed in the Apple Pay sheet.
paymentDescription
string
required
Description of the payment shown to the customer.
style
object
Button styling options.
style.type
string
Button label type. Possible values: 'buy', 'donate', 'plain', 'check-out', 'book', 'subscribe'.
style.buttonstyle
string
Button colour. Possible values: 'black', 'white', 'white-outline'.
style.locale
string
Button locale (e.g., 'en-US').
paymentRequest
object
required
Apple Pay payment request configuration.
paymentRequest.merchantCapabilities
array
required
Merchant capabilities. Example: ['supports3DS'].
paymentRequest.supportedNetworks
array
required
Supported card networks. Example: ['visa', 'masterCard', 'amex'].
paymentRequest.countryCode
string
required
Merchant country code (e.g., 'US').
paymentRequest.currencyCode
string
required
Payment currency code (e.g., 'USD').
paymentRequest.total
object
required
Total payment information.
paymentRequest.total.label
string
required
Label for the total amount.
paymentRequest.total.amount
string
required
Total amount as a string.
onPreAuthorisation
function
Callback fired before authorisation. Return an empty object {} to proceed.
onPostAuthorisation
function
required
Callback fired when payment succeeds.
onError
function
Callback fired when an error occurs.

Step 6: Mount the button to your page

Add a container element to your page where the Apple Pay button will be rendered:

<div id="apple-pay-container"></div>

Then call the mount() method to render the button:

applePayButton.mount('apple-pay-container');

Step 7: Unmount the component

When your component unmounts (e.g., when navigating away or cleaning up), call the unmount() method:

return () => {
  applePayButton.unmount();
};

Step 8: Handle callbacks

onGetShopper callback

Returns shopper information for transaction processing.

onGetShopper: () => Promise.resolve({ 
  id: 'shopper-123',
  email: 'customer@example.com',
  firstName: 'John',
  lastName: 'Doe',
  phoneNumber: '+1-555-0123'
})

onPostAuthorisation callback

Fires when payment succeeds. CRITICAL: Always verify on your backend before fulfilling orders.

onPostAuthorisation: async (data) => {
  // Verify payment on backend
  const verified = await fetch('/api/verify-payment', {
    method: 'POST',
    body: JSON.stringify({
      systemTransactionId: data.systemTransactionId,
      merchantTransactionId: data.merchantTransactionId
    })
  }).then(r => r.json());
  
  if (verified.success) {
    globalThis.location.href = `/success?orderId=${verified.orderId}`;
  }
}

Never trust frontend callbacks for order fulfillment. Always verify payments on your backend using webhooks or the Query Transaction API before fulfilling orders.

Step 9: Backend verification (CRITICAL)

Frontend callbacks can be manipulated by malicious users. You must verify all payments on your backend before fulfilling orders.

Use the same webhook and API verification patterns described in the card implementation guide.

Complete example

Here's a complete example showing Apple Pay integration in a React component:

import { PxpCheckout, IntentType } from '@pxpio/web-components-sdk';
import { useEffect, useState } from 'react';

export default function ApplePayPage() {
  const [sessionData, setSessionData] = useState<any>(null);

  const createSession = async () => {
    const createdSession = await fetch('/api/sessions', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: 
        JSON.stringify({
          merchant: "MERCHANT-1",
          site: "SITE-1",
          sessionTimeout: 120,
          merchantTransactionId: crypto.randomUUID(),
          transactionMethod: {
            intent: {
              card: "Authorisation"
            }
          },
          amounts: {
            currencyCode: "USD",
            transactionValue: 25.00
          },
          allowTransaction: true
        })
,
    }).then((response) => response.json());
    setSessionData(createdSession);
  };

  useEffect(() => {
    createSession();
  }, []);

  useEffect(() => {
    if (!sessionData) {
      return;
    }

    const pxpSdk = PxpCheckout.initialize({
      environment: 'test',
      session: sessionData,
      ownerId: 'MERCHANT_GROUP_1', // Replace with your merchant group id
      ownerType: 'MerchantGroup',
      transactionData: {
        currency: 'USD',
        amount: 25,
        entryType: 'Ecom',
        intent: {
          card: IntentType.Authorisation,
        },
        merchantTransactionId: sessionData.merchantTransactionId,
        merchantTransactionDate: () => new Date().toISOString(),
      },
      kountDisabled: false, // OPTIONAL: Set to true to disable Kount fraud detection
      onGetShopper: async () => {
        return {
          id: 'shopper-123',
          email: 'customer@example.com',
          firstName: 'John',
          lastName: 'Doe',
        };
      },
    });

    const applePayButton = pxpSdk.create('apple-pay-button', {
      merchantDisplayName: 'Merchant store',
      paymentDescription: 'Apple Pay payment',
      style: {
        type: 'buy',
        buttonstyle: 'black',
        locale: 'en-US',
      },
      paymentRequest: {
        merchantCapabilities: ['supports3DS'],
        supportedNetworks: ['visa', 'masterCard', 'amex'],
        countryCode: 'US',
        currencyCode: 'USD',
        total: {
          label: 'Pay',
          amount: '25.00',
        },
      },
      onPreAuthorisation: () => {
        return {};
      },
      onPostAuthorisation: async (data: any) => {
        console.log('Payment successful:', data.systemTransactionId, data.merchantTransactionId);
        // CRITICAL: Verify on backend before fulfilling order
        await verifyPaymentOnBackend(data)
      },
      onError: (error: any) => {
        console.error('Apple Pay failed:', error);
      },
    });

    applePayButton.mount('apple-pay-container');

    return () => {
      applePayButton.unmount();
    };
  }, [sessionData]);

  return (
    <div>
      <h1>Apple Pay</h1>
      <div id="apple-pay-container"></div>
    </div>
  );
}

What's next?

Now that you've integrated Apple Pay, here are some recommended next steps:

  • Customisation: Learn how to customise the Apple Pay button appearance.
  • Events: Explore all available callbacks and event handling.
  • Testing: Use test cards and sandbox environment to test your integration.
  • Configure webhooks: Set up server-side webhook handling for reliable payment verification.