Інтеграція платежної системи 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 та інтеграцію з провайдером. Вартість розраховується індивідуально.







