Integrating 1C-Bitrix with Apple Pay
Apple Pay on a website is not a standalone payment system — it is a method of confirming a card payment through an Apple device. Technically, this means the buyer does not enter a card number; instead, they authorize the payment via Face ID or Touch ID, and the tokenized card data is transmitted to your acquiring bank. A common misconception is that you need to "connect Apple Pay separately." This is not the case: Apple Pay works on top of an already connected acquiring service that supports this method (YooKassa, Tinkoff, Sber, Stripe, and others).
Prerequisites
For Apple Pay to work on a website, you need:
- An acquiring service with Apple Pay support — check your contract with the bank or payment aggregator
- HTTPS — mandatory; Apple Pay does not work over HTTP
-
Domain verification — Apple requires placing a file at
/.well-known/apple-developer-merchantid-domain-association - Merchant ID — created in Apple Developer Console, linked to the domain and certificate
Domain Verification
# nginx: serving a file without an extension
location /.well-known/apple-developer-merchantid-domain-association {
default_type text/plain;
alias /var/www/myshop/.well-known/apple-developer-merchantid-domain-association;
}
The verification file is downloaded from Apple Developer Console. In most cases, the acquiring service (YooKassa, Tinkoff) handles verification through their own services — you simply need to specify the domain in the aggregator's merchant portal.
Apple Pay Button in 1C-Bitrix
Apple Pay is displayed only in Safari on Apple devices. For all other browsers, the standard payment form is shown. In the sale.order.checkout component template or on the payment page:
// Check support before displaying the button
if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
document.querySelector('.apple-pay-button').style.display = 'block';
}
function startApplePay(orderTotal, orderId) {
const request = {
countryCode: 'RU',
currencyCode: 'RUB',
supportedNetworks: ['visa', 'masterCard', 'mir'],
merchantCapabilities: ['supports3DS'],
total: { label: 'My Store', amount: String(orderTotal) },
};
const session = new ApplePaySession(6, request);
// Merchant validation — request to Apple via your server
session.onvalidatemerchant = async (event) => {
const res = await fetch('/bitrix/tools/apple_pay_validate.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ validationURL: event.validationURL }),
});
session.completeMerchantValidation(await res.json());
};
// Received payment token
session.onpaymentauthorized = async (event) => {
const res = await fetch('/bitrix/tools/apple_pay_charge.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ token: event.payment.token, orderId }),
});
const data = await res.json();
session.completePayment(
data.success ? ApplePaySession.STATUS_SUCCESS : ApplePaySession.STATUS_FAILURE
);
if (data.success) window.location.href = data.redirect;
};
session.begin();
}
Server-Side Merchant Validation
// /bitrix/tools/apple_pay_validate.php
$body = json_decode(file_get_contents('php://input'), true);
$validationUrl = filter_var($body['validationURL'] ?? '', FILTER_VALIDATE_URL);
$ch = curl_init($validationUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'merchantIdentifier' => APPLE_MERCHANT_ID,
'displayName' => 'My Store',
'initiative' => 'web',
'initiativeContext' => $_SERVER['HTTP_HOST'],
]),
CURLOPT_SSLCERT => APPLE_CERT_PATH, // .pem merchant certificate file
CURLOPT_SSLKEY => APPLE_CERT_KEY_PATH, // private key
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
]);
$merchantSession = curl_exec($ch);
curl_close($ch);
header('Content-Type: application/json');
echo $merchantSession; // pass directly to session.completeMerchantValidation
Token Processing via Acquiring Service
Apple Pay transmits an encrypted PKPaymentToken. It must be passed to your acquiring service:
// Example for YooKassa: /bitrix/tools/apple_pay_charge.php
$input = json_decode(file_get_contents('php://input'), true);
$token = $input['token'];
$orderId = (int)$input['orderId'];
$payment = $yookassaClient->createPayment([
'amount' => ['value' => getOrderAmount($orderId), 'currency' => 'RUB'],
'payment_method_data' => [
'type' => 'apple_pay',
'payment_data' => base64_encode(json_encode($token['paymentData'])),
],
'capture' => true,
'description' => 'Order #' . $orderId,
], uniqid('', true));
// Update status in 1C-Bitrix on success
if ($payment->getStatus() === 'succeeded') {
$bitrixPayment->setPaid('Y');
$bitrixPayment->save();
}
Timeline
| Task | Duration |
|---|---|
| Domain verification, Merchant ID | 0.5 day |
| JS button + server-side merchant validation | 1 day |
| Token integration with acquiring service and testing | 1 day |







