Integration of Apple Pay on Website
Apple Pay on a website is not a standalone system, but a payment method implemented on top of an existing payment gateway (Stripe, CloudPayments, Tinkoff, Sberbank, etc.). From a development perspective, there are two levels: domain setup on Apple's side and implementing Payment Request API in the browser.
Requirements for Operation
- HTTPS with valid SSL certificate (self-signed do not work)
- Safari or Chrome on iOS / macOS with card added to Wallet
- Domain verification in Apple Developer Account
- Apple Pay support in the payment gateway
Domain Verification
For each domain accepting Apple Pay, verification is required:
- Download verification file from Apple Pay Merchant Configuration (Stripe Dashboard / CloudPayments dashboard / Apple Developer)
- Place it at exact path:
https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association - File must be served with Content-Type
text/plainor without it, with no redirects
location /.well-known/apple-developer-merchantid-domain-association {
root /var/www/well-known;
default_type text/plain;
}
In Laravel:
// routes/web.php
Route::get('/.well-known/apple-developer-merchantid-domain-association', function () {
return response()->file(storage_path('apple-pay-domain-verification'));
});
Implementation via Stripe
Stripe handles all work with Apple Pay Merchant Certificate. After domain verification in Stripe Dashboard, button appears automatically in PaymentElement:
import { PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
// PaymentElement automatically shows Apple Pay / Google Pay
// if device supports and card is added to Wallet
function StripeCheckout() {
const stripe = useStripe();
const elements = useElements();
const handleSubmit = async () => {
await stripe?.confirmPayment({
elements: elements!,
confirmParams: { return_url: 'https://example.com/payment/complete' },
});
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<button type="submit">Pay</button>
</form>
);
}
Implementation via Payment Request Button (Stripe)
To display only Apple Pay / Google Pay button (without full form):
import { useStripe } from '@stripe/react-stripe-js';
import { useEffect, useState } from 'react';
function ExpressCheckout({ amount }: { amount: number }) {
const stripe = useStripe();
const [paymentRequest, setPaymentRequest] = useState<any>(null);
const [canPay, setCanPay] = useState(false);
useEffect(() => {
if (!stripe) return;
const pr = stripe.paymentRequest({
country: 'RU',
currency: 'rub',
total: {
label: 'Total Amount',
amount,
},
requestPayerName: true,
requestPayerEmail: true,
});
pr.canMakePayment().then(result => {
if (result) {
setPaymentRequest(pr);
setCanPay(true);
}
});
pr.on('paymentmethod', async (ev) => {
// Confirm PaymentIntent with received paymentMethod
const { error } = await stripe.confirmCardPayment(clientSecret, {
payment_method: ev.paymentMethod.id,
});
if (error) {
ev.complete('fail');
} else {
ev.complete('success');
}
});
}, [stripe, amount]);
if (!canPay) return null;
return <PaymentRequestButtonElement options={{ paymentRequest }} />;
}
Implementation via CloudPayments
const widget = new cp.CloudPayments();
widget.charge(
{
publicId: 'pk_xxxx',
description: 'Order #12345',
amount: 1500,
currency: 'RUB',
invoiceId: 'order-12345',
// Apple Pay is enabled automatically if supported by browser
},
(options) => console.log('success', options),
(reason) => console.error('fail', reason),
);
CloudPayments automatically displays Apple Pay button instead of standard card form if device supports it.
Checking Support on Client
function isApplePayAvailable(): boolean {
return (
typeof window !== 'undefined' &&
'ApplePaySession' in window &&
ApplePaySession.canMakePayments()
);
}
// To check with specific networks
function isApplePayReadyToMakePayments(): Promise<boolean> {
if (!('ApplePaySession' in window)) return Promise.resolve(false);
return ApplePaySession.canMakePaymentsWithActiveCard('merchant.com.example.shop');
}
Common Issues
Error "The domain yourdomain.com is not registered" — verification file not found or returns 404. Check via curl -I https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association.
Apple Pay doesn't appear on test device — ensure device uses Apple Pay Sandbox test card (added in Settings → Wallet & Apple Pay → Simulator Environment → Sandbox Cards).
Domain must be verified separately for each subdomain. Verification of example.com does not extend to shop.example.com.







