Реалізація push-оновлень Wallet Pass у мобільному додатку
Apple Wallet Pass — це не статична карточка. Програма лояльності, авіабілет, купон — дані змінюються в реальному часі, і користувач повинен бачити актуальну інформацію без переустановки додатка. Саме для цього Apple реалізувала механізм серверних push-оновлень для PassKit.
Як працює механізм оновлень
Архітектурно схема виглядає так: ваш сервер реєструє пристрій через PassKit Web Service API, зберігає пару deviceLibraryIdentifier + pushToken, і при зміні даних відправляє push через APNs. iOS «просипається», робить GET-запит до сервера за оновленим .pkpass файлом, і карточка оновлюється без участі користувача.
Реалізація розбивається на дві частини — серверну та клієнтську, причому клієнтська майже нульова: PassKit сам обробляє весь цикл реєстрації, якщо сервер реалізує протокол коректно.
Серверний протокол PassKit Web Service
Сервер обов'язан поднести чотири ендпоінти:
-
POST /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber}— реєстрація пристрою -
DELETE /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber}— дереєстрація -
GET /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}?passesUpdatedSince={tag}— список оновлених passes -
GET /v1/passes/{passTypeIdentifier}/{serialNumber}— скачування актуального.pkpass
Найрозповсюджена помилка — неверний HTTP-статус. Apple PassKit крайне чутливий: 200 з пустим тілом на DELETE → iOS ломить дереєстрацію. Потрібно 204 No Content. На GET без змін — строго 204, не 200 [].
// Приклад структури відповіді на GET /registrations
{
"serialNumbers": ["ABC123", "DEF456"],
"lastUpdated": "1711234567"
}
Поле lastUpdated — це UNIX timestamp строкою. iOS передає його обратно в passesUpdatedSince при наступному запиті. Якщо вернути timestamp в неправильному форматі, пристрій буде постійно запитувати всі passes, ігноруючи інкрементальну логіку.
APNs push для оновлення
Push для Wallet — нестандартний. Payload мінімален:
{
"aps": {}
}
Саме так — пустий aps. Ніякого alert, badge, sound. iOS при отриманні такого push-a молча йде до сервера за оновленнями. Відправляти потрібно через APNs з apns-topic рівним passTypeIdentifier додатка (формат: pass.com.yourcompany.appname), не bundleIdentifier.
Сертифікат для PassKit окремий — це Pass Type ID Certificate з Apple Developer Portal, не звичайний APN-сертифікат додатка. Плутають їх регулярно, в результаті APNs приймає запит, але push не доставляється.
# Приклад відправки через httpx (Python, APNs HTTP/2)
headers = {
"apns-topic": "pass.com.example.loyalty",
"apns-push-type": "background",
"apns-priority": "5",
"authorization": f"bearer {jwt_token}"
}
payload = json.dumps({"aps": {}})
response = await client.post(
f"https://api.push.apple.com/3/device/{push_token}",
content=payload,
headers=headers
)
apns-priority: 5 — обов'язковий для фонових push. Пріоритет 10 для Wallet не працює як очікується.
Підпис .pkpass
Кожен .pkpass — ZIP-архів з файлом manifest.json (SHA-1 хеши всіх файлів) та signature (PKCS#7 detached signature). При оновленні Pass потрібно пересчітати манніфест та пересоздати підпис. Використання старої підписи з новими даними → iOS мовчки ігнорує файл.
Генерація підписи через openssl:
openssl smime -binary -sign \
-certfile AppleWWDRCA.pem \
-signer passcertificate.pem \
-inkey passkey.pem \
-in manifest.json \
-out signature \
-outform DER
Бібліотека signpass від Apple зручна для тестування, але в продакшені краще реалізувати підпис нативно на сервері — без зовнішніх бінарників.
Тестування циклу оновлень
Інструмент PassKit Companion App (macOS) дозволяє симулювати реєстрацію та перевіряти ендпоінти напрямку. Для дебага серверних запитів — включити WKWebsiteDataStore логування на iOS-симуляторі не отримується, зато Charles Proxy на реальному пристрої перехоплює всі запити PassKit повністю.
Типовий цикл відладки: додати pass через додаток → в Charles перевірити POST-реєстрацію → дёрнути push вручну через curl → впевниться, що iOS зробив GET за оновленим pass → перевірити UI карточки.
Процес
Аудит поточної серверної інфраструктури або реалізація з нуля: Pass Type ID, серверні ендпоінти, зберігання pushToken.
Настройка APNs з Pass Type ID Certificate, реалізація відправки push при зміні даних.
Генерація та підпис .pkpass на сервері, настройка інкрементальних оновлень.
Тестування повного циклу: реєстрація → зміна даних → push → оновлення карточки.
Орієнтири за терміни
Якщо серверна інфраструктура вже есть та потрібно тільки додати підтримку PassKit Web Service — 3–5 днів. Реалізація з нуля, включаючи генерацію pass-файлів та серверний бекенд — від 1 до 2 тижнів залежно від складності логіки оновлень.







