On this page
No Headings
Last updated: May 28, 2026
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.
Before beginning your integration, meet these requirements:
Configure your local development environment to work with Apple Pay's HTTPS requirement and PayPal's domain validation.
Install and configure ngrok:
npm install -g ngrok
ngrok config add-authtoken YOUR_AUTHTOKEN
ngrok http 3000Update the Vite configuration:
// 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,
},
},
},
});Register your domain with PayPal:
Implement Apple Pay by following the detailed steps.
Create your basic HTML page and include the Apple Pay and PayPal SDK scripts.
<!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>Set up the v6 SDK with Apple Pay components once it loads.
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);
}
}Generate the Apple Pay button element and configure it for your payment flow.
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);
}Set up your payment details and start the Apple Pay session when users tap the button.
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();
}Implement event handlers to process the payment through Apple Pay's workflow.
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");
};
}Implement server endpoints for token generation and order management.
// 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();
}Your backend needs these endpoints to support the Apple Pay integration:
Use the following steps to test your Apple Pay integration.
Deploy your Apple Pay integration to production.
| Issue | Solution |
|---|---|
| Button not appearing |
|
| Merchant validation fails |
|
| Payment authorization fails |
|