Интеграция платежной системы Apple Pay в мобильное приложение
Apple Pay — не «добавить кнопку». Это цепочка из Merchant ID, сертификатов, PKPaymentAuthorizationController, серверной верификации платёжного токена и обработки финального статуса транзакции. Ошибка в любом звене — и либо приложение не покажет кнопку вовсе, либо получит отказ от Apple Pay на этапе авторизации.
Настройка Merchant ID и сертификатов
Всё начинается в Apple Developer Portal:
- Создаём Merchant ID:
merchant.com.yourcompany.appname - Генерируем Payment Processing Certificate — используется Apple для шифрования токена перед отправкой вашему серверу
- Добавляем домен для Apple Pay on the Web (если нужен) — требует верификационного файла на сервере
В Xcode: Signing & Capabilities → Добавить Apple Pay → выбрать Merchant ID. Xcode автоматически обновит .entitlements файл:
<key>com.apple.developer.in-app-payments</key>
<array>
<string>merchant.com.yourcompany.appname</string>
</array>
Без этого entitlement Apple Pay не активируется на устройстве, даже если код написан правильно.
PKPaymentRequest и PKPaymentAuthorizationController
import PassKit
class CheckoutViewController: UIViewController {
func startApplePay() {
guard PKPaymentAuthorizationController.canMakePayments(
usingNetworks: [.visa, .masterCard, .mir]
) else {
// Показываем альтернативный способ оплаты
return
}
let request = PKPaymentRequest()
request.merchantIdentifier = "merchant.com.yourcompany.appname"
request.supportedNetworks = [.visa, .masterCard, .mir]
request.merchantCapabilities = [.capability3DS]
request.countryCode = "RU"
request.currencyCode = "RUB"
let item = PKPaymentSummaryItem(
label: "Заказ №1234",
amount: NSDecimalNumber(string: "1500.00")
)
let shipping = PKPaymentSummaryItem(
label: "Доставка",
amount: NSDecimalNumber(string: "250.00")
)
let total = PKPaymentSummaryItem(
label: "YourCompany", // имя вашей компании, показывается на Face ID/Touch ID экране
amount: NSDecimalNumber(string: "1750.00")
)
request.paymentSummaryItems = [item, shipping, total]
let controller = PKPaymentAuthorizationController(paymentRequest: request)
controller.delegate = self
controller.present(completion: nil)
}
}
extension CheckoutViewController: PKPaymentAuthorizationControllerDelegate {
func paymentAuthorizationController(
_ controller: PKPaymentAuthorizationController,
didAuthorizePayment payment: PKPayment,
handler completion: @escaping (PKPaymentAuthorizationResult) -> Void
) {
// payment.token.paymentData — зашифрованный JSON токен
// Отправляем на бэкенд для верификации
sendTokenToBackend(payment.token.paymentData) { success in
completion(PKPaymentAuthorizationResult(
status: success ? .success : .failure,
errors: nil
))
}
}
func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
controller.dismiss(completion: nil)
}
}
Важный нюанс с .mir: Mir Pay требует отдельной настройки и работает только на картах, выпущенных в НСПК. Не все эквайеры поддерживают Mir через Apple Pay — нужно уточнять у платёжного провайдера.
Серверная верификация токена
payment.token.paymentData — это зашифрованный JSON, который Apple зашифровала вашим Payment Processing Certificate. Расшифровывается на сервере.
Структура токена:
{
"version": "EC_v1",
"data": "base64-encrypted-payment-data",
"signature": "base64-pkcs7-signature",
"header": {
"ephemeralPublicKey": "base64-ec-public-key",
"publicKeyHash": "base64-sha256-hash",
"transactionId": "hex-transaction-id"
}
}
Процесс расшифровки:
- Верифицировать подпись через Apple Root CA
- Восстановить shared secret через ECDH (ваш приватный ключ + ephemeralPublicKey из токена)
- Получить симметричный ключ через HKDF
- Расшифровать
dataчерез AES-256-GCM
На практике большинство платёжных провайдеров (Stripe, CloudPayments, ЮKassa) берут на себя расшифровку — вы просто передаёте им сырой paymentData. Самостоятельная реализация нужна только при прямом эквайринге.
Типичные проблемы
Кнопка Apple Pay не отображается. Причины: Merchant ID не добавлен в entitlements (проверьте .entitlements файл), сертификат истёк (срок 2 года), canMakePayments(usingNetworks:) возвращает false на симуляторе без настроенных карт.
PKPaymentAuthorizationStatus.failure без ошибки. Бэкенд вернул ошибку, но errors в PKPaymentAuthorizationResult не передан. Пользователь видит просто «Ошибка» без объяснений. Правильно — передавать PKPaymentError с описанием причины.
Тестирование. Apple Pay не работает на симуляторе для реальных транзакций. Для тестирования нужно устройство с тестовой картой Visa из Apple Sandbox. Тестовые карты доступны только аккаунтам в Apple Sandbox environment.
Что входит в работу
- Регистрация Merchant ID, генерация и загрузка сертификатов
- Реализация
PKPaymentRequestс корректнымиpaymentSummaryItems - Интеграция с платёжным провайдером (передача token.paymentData)
- Обработка ошибок с
PKPaymentError - Тестирование на физическом устройстве в Sandbox
Сроки
2–3 дня включая настройку в Developer Portal и интеграцию с провайдером. Стоимость рассчитывается индивидуально после анализа требований.







