# Apple Pay (/apple-pay/integrate)

Accept one-tap Apple Pay payments.



With PayPal's JavaScript SDK v6, you can accept Apple Pay for secure, one-tap payments. You'll set up a test environment, add the needed frontend and backend, and then launch Apple Pay in both sandbox and production.

## Prerequisites [#prerequisites]

Before beginning your integration, meet these requirements:

* Create a [PayPal Developer account](https://developer.paypal.com) with Apple Pay enabled.
* Obtain an Apple Developer Program membership for live payments.
* Set up an HTTPS environment or ngrok for local development.

## Development setup [#development-setup]

Configure your local development environment to work with Apple Pay's HTTPS requirement and PayPal's domain validation.

1. Install and configure ngrok:
   ```bash
   npm install -g ngrok
   ngrok config add-authtoken YOUR_AUTHTOKEN
   ngrok http 3000
   ```

2. Update the Vite configuration:
   ```javascript
   // vite.config.js
   export default defineConfig({
     server: {
       allowedHosts: ["your-ngrok-domain.ngrok-free.app"],
       proxy: {
         "/paypal-api": {
           target: "http://localhost:8080",
           changeOrigin: true,
           secure: false,
         },
       },
     },
   });
   ```

3. Register your domain with PayPal:
   * Add your ngrok domain to PayPal's Apple Pay settings
   * Download and save the domain association file

## Implementation steps [#implementation-steps]

Implement Apple Pay by following the detailed steps.

### 1. Set up HTML structure [#1-set-up-html-structure]

Create your basic HTML page and include the Apple Pay and PayPal SDK scripts.

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Apple Pay Integration</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <h1>Apple Pay Payment</h1>
    <div id="apple-pay-button-container"></div>
    
    <!-- Apple Pay SDK -->
    <script src="https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js"></script>
    
    <!-- PayPal JavaScript SDK -->
    <script
      async
      src="https://www.sandbox.paypal.com/web-sdk/v6/core"
      onload="onPayPalWebSdkLoaded()"
    ></script>
    
    <script src="app.js"></script>
  </body>
</html>
```

### 2. Initialize PayPal SDK [#2-initialize-paypal-sdk]

Set up the v6 SDK with Apple Pay components once it loads.

```javascript
async function onPayPalWebSdkLoaded() {
  try {
    const clientToken = await getBrowserSafeClientToken();
    const sdkInstance = await window.paypal.createInstance({
      clientToken,
      components: ["applepay-payments"],
      pageType: "checkout",
    });

    setupApplePayButton(sdkInstance);
  } catch (error) {
    console.error("SDK initialization failed:", error);
  }
}
```

### 3. Configure Apple Pay button [#3-configure-apple-pay-button]

Generate the Apple Pay button element and configure it for your payment flow.

```javascript
async function setupApplePayButton(sdkInstance) {
  const paypalSdkApplePayPaymentSession = 
    await sdkInstance.createApplePayOneTimePaymentSession();

  const { merchantCapabilities, supportedNetworks } = 
    await paypalSdkApplePayPaymentSession.config();

  // Create Apple Pay button
  document.getElementById("apple-pay-button-container").innerHTML =
    '<apple-pay-button id="apple-pay-button" buttonstyle="black" type="buy" locale="en">';
  
  document.getElementById("apple-pay-button")
    .addEventListener("click", handleApplePayClick);
}
```

### 4. Configure payment request [#4-configure-payment-request]

Set up your payment details and start the Apple Pay session when users tap the button.

```javascript
async function handleApplePayClick() {
  const paymentRequest = {
    countryCode: "US",
    currencyCode: "USD",
    merchantCapabilities,
    supportedNetworks,
    requiredBillingContactFields: ["name", "phone", "email", "postalAddress"],
    requiredShippingContactFields: [],
    total: {
      label: "Your Store Name",
      amount: "100.00",
      type: "final",
    },
  };

  const applePaySession = new ApplePaySession(4, paymentRequest);
  
  // Configure event handlers
  setupApplePayEventHandlers(applePaySession, paypalSdkApplePayPaymentSession);
  
  applePaySession.begin();
}
```

### 5. Handle Apple Pay events [#5-handle-apple-pay-events]

Implement event handlers to process the payment through Apple Pay's workflow.

```javascript
function setupApplePayEventHandlers(applePaySession, paypalSession) {
  // Merchant validation
  applePaySession.onvalidatemerchant = (event) => {
    paypalSession.validateMerchant({
      validationUrl: event.validationURL,
    }).then((payload) => {
      applePaySession.completeMerchantValidation(payload.merchantSession);
    }).catch((err) => {
      console.error("Merchant validation failed:", err);
      applePaySession.abort();
    });
  };

  // Payment method selection
  applePaySession.onpaymentmethodselected = () => {
    applePaySession.completePaymentMethodSelection({
      newTotal: paymentRequest.total,
    });
  };

  // Payment authorization
  applePaySession.onpaymentauthorized = async (event) => {
    try {
      // Create PayPal order
      const order = await createOrder();
      
      // Confirm order with Apple Pay token
      await paypalSession.confirmOrder({
        orderId: order.orderId,
        token: event.payment.token,
        billingContact: event.payment.billingContact,
        shippingContact: event.payment.shippingContact,
      });

      // Capture payment
      const result = await captureOrder({ orderId: order.orderId });
      
      applePaySession.completePayment({
        status: window.ApplePaySession.STATUS_SUCCESS,
      });
      
      console.log("Payment successful:", result);
    } catch (error) {
      console.error("Payment failed:", error);
      applePaySession.completePayment({
        status: window.ApplePaySession.STATUS_FAILURE,
      });
    }
  };

  // Payment cancellation
  applePaySession.oncancel = () => {
    console.log("Apple Pay cancelled");
  };
}
```

### 6. Add server integration [#6-add-server-integration]

Implement server endpoints for token generation and order management.

```javascript
// Get browser-safe client token
async function getBrowserSafeClientToken() {
  const response = await fetch("/paypal-api/auth/browser-safe-client-token", {
    method: "GET",
    headers: { "Content-Type": "application/json" },
  });
  const { accessToken } = await response.json();
  return accessToken;
}

// Create PayPal order
async function createOrder() {
  const response = await fetch("/paypal-api/checkout/orders/create-with-sample-data", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
  });
  const { id } = await response.json();
  return { orderId: id };
}

// Capture order
async function captureOrder({ orderId }) {
  const response = await fetch(`/paypal-api/checkout/orders/${orderId}/capture`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
  });
  return await response.json();
}
```

## Server-side requirements [#server-side-requirements]

Your backend needs these endpoints to support the Apple Pay integration:

* **Client token generation endpoint**: Returns browser-safe client token for SDK initialization
* **Order creation endpoint**: Creates PayPal order and returns order ID for payment processing
* **Order capture endpoint**: Captures authorized payment and returns transaction details
* **Proper CORS and security headers**: Ensures secure communication between client and server

## Testing [#testing]

Use the following steps to test your Apple Pay integration.

1. Open Safari browser on macOS or iOS device.
2. Sign into your sandbox iCloud account.
3. Add test credit cards to your Apple Pay wallet.
4. Test the complete payment flow.

## Production deployment [#production-deployment]

Deploy your Apple Pay integration to production.

1. Replace all sandbox URLs with production endpoints.
2. Update your application to use production PayPal credentials.
3. Register your production domain with Apple Pay.
4. Test the integration with a real Apple Pay setup
5. Add proper error monitoring to track payment issues

## Security considerations [#security-considerations]

* Use HTTPS in production.
* Ensure your merchant domain is valid.
* Keep domain association files current.
* Use secure client tokens for frontend.
* Implement proper error handling.

## Troubleshooting [#troubleshooting]

Issue

Solution

Button not appearing

Check Safari Apple Pay settings

Verify domain registration

Ensure HTTPS connection

Merchant validation fails

Check domain association file

Verify PayPal domain registration

Confirm ngrok domain in vite config

Payment authorization fails

Use sandbox iCloud account

Check test credit card setup

Verify server endpoints

## Resources [#resources]

* For more information, see the [Apple Pay HTML sample integration](https://github.com/paypal-examples/v6-web-sdk-sample-integration/tree/main/client/components/applepayPayments/html).
