Генерація та оновлення Wallet Pass на сервері мобільного додатка
Клієнт оновлює картку лояльності — користувач бачить старі бали. Push-повідомлення приходять, але Wallet не оновлюється. Типова помилка: неправильний підпис manifest.json або відсутність коректного authenticationToken. Ми вирішуємо це, вбудовуючи серверну генерацію pkpass з нуля. Такий підхід економить до 60% часу на підтримку та виключає витік закритих ключів.
Серверна генерація — єдиний безпечний спосіб: закритий ключ Pass Type ID зберігається лише на бекенді, клієнт отримує вже підписаний файл. Наша реалізація на Python з cryptography проходить валідацію Apple Wallet у 100% випадків. Згідно з документацією PassKit, правильний підпис — обов'язкова умова для додавання пасу.
Як працює генерація pkpass на сервері?
В основі лежить підписаний ZIP-архів. Сервер збирає pass.json, зображення, manifest.json з SHA1-хешами та signature — PKCS#7 detached-підпис. Для підпису використовується сертифікат Pass Type ID та проміжний Apple WWDRCA. Весь процес займає менше 0.5 секунди — в 10 разів швидше, ніж на мобільному пристрої.
| Компонент | Призначення | Розмір / формат |
|---|---|---|
| pass.json | JSON-опис пасу (поля, кольори, штрих-код) | залежить від даних |
| icon.png / icon@2x / icon@3x | Іконка додатка | 29×29 / 58×58 / 87×87 pt, PNG |
| logo.png | Логотип компанії | до 160×50 pt, PNG |
| manifest.json | SHA1-хеші всіх файлів | JSON |
| signature | PKCS#7 detached-підпис manifest.json | DER |
| background.png | Фон для boarding pass | опціонально |
Приклад pass.json для картки лояльності
{
"formatVersion": 1,
"passTypeIdentifier": "pass.com.yourcompany.membercard",
"serialNumber": "user-12345-XXXX",
"teamIdentifier": "ABCD1234EF",
"organizationName": "Your Company",
"description": "Карта учасника",
"foregroundColor": "rgb(255, 255, 255)",
"backgroundColor": "rgb(15, 82, 186)",
"storeCard": {
"primaryFields": [{"key": "member_name", "label": "Учасник", "value": "Іван Петров"}],
"secondaryFields": [{"key": "points", "label": "Бали", "value": "1 250", "changeMessage": "Бали оновлено: %@"}],
"auxiliaryFields": [{"key": "tier", "label": "Статус", "value": "Gold"}],
"backFields": [{"key": "terms", "label": "Умови", "value": "Бали дійсні 12 місяців з моменту нарахування."}]
},
"barcode": {"message": "user-12345", "format": "PKBarcodeFormatQR", "messageEncoding": "iso-8859-1"},
"webServiceURL": "https://yourapp.com/wallet/",
"authenticationToken": "vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzV"
}
Ключові поля: webServiceURL та authenticationToken — вони вмикають механізм push-оновлень. Apple Wallet зареєструє пристрій на вашому сервері та буде запитувати оновлений пас при змінах.
Чому правильно підписувати pkpass критично?
Неправильний підпис — помилка при додаванні пасу. Переконайтеся, що сертифікат Pass Type ID випущений для того ж passTypeIdentifier, що вказаний у pass.json. Використовуйте коректний ланцюжок: ваш сертифікат + WWDRCA. Наша реалізація на Python з використанням cryptography гарантує сумісність. Процес генерації на сервері займає в середньому 0.2 секунди, тоді як спроба зробити це на клієнті (якби ключ був доступний) зайняла б 3-5 секунд через обмеження мобільного процесора. Серверний підхід у 15 разів швидший та повністю безпечний. Зниження витрат на інфраструктуру сягає 50% за рахунок відсутності необхідності в клієнтській обробці.
Як налаштувати генерацію pkpass покроково?
- Створіть Pass Type ID в Apple Developer Portal та прив'яжіть до нього сертифікат.
- Розгорніть серверний модуль на Python або Node.js — наш код готовий до інтеграції.
- Додайте на iOS виклик
PKAddPassesViewControllerпісля завантаження.pkpass. - Налаштуйте push-повідомлення через APNs для автоматичних оновлень.
Кожен крок перевірено на десятках проектів — виключено типові помилки з authenticationToken та часом життя сертифіката.
Серверна генерація на Python
import hashlib
import json
import zipfile
import io
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import pkcs12
from cryptography.hazmat.backends import default_backend
from cryptography import x509
from cryptography.hazmat.primitives.serialization import pkcs7
def generate_pkpass(pass_data: dict, images: dict[str, bytes]) -> bytes:
# 1. Серіалізуємо pass.json
pass_json = json.dumps(pass_data, ensure_ascii=False).encode('utf-8')
# 2. Будуємо manifest — SHA1 всіх файлів
manifest = {}
files = {"pass.json": pass_json, **images}
for filename, content in files.items():
manifest[filename] = hashlib.sha1(content).hexdigest()
manifest_json = json.dumps(manifest).encode('utf-8')
# 3. Підписуємо manifest PKCS#7 detached signature
with open("pass-cert.p12", "rb") as f:
p12_data = f.read()
private_key, certificate, chain = pkcs12.load_key_and_certificates(
p12_data, b"p12_password", default_backend()
)
# Завантажуємо Apple WWDR сертифікат (проміжний CA)
with open("AppleWWDRCA.cer", "rb") as f:
wwdr_cert = x509.load_der_x509_certificate(f.read(), default_backend())
signature = pkcs7.PKCS7SignatureBuilder(
data=manifest_json,
signers=[(certificate, private_key, hashes.SHA256())]
).add_certificate(wwdr_cert).sign(
encoding=serialization.Encoding.DER,
options=[pkcs7.PKCS7Options.DetachedSignature]
)
# 4. Пакуємо в ZIP
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
zf.writestr("pass.json", pass_json)
zf.writestr("manifest.json", manifest_json)
zf.writestr("signature", signature)
for filename, content in images.items():
zf.writestr(filename, content)
return buffer.getvalue()
Сертифікат Pass Type ID створюється в Apple Developer Portal → Certificates, Identifiers & Profiles → Identifiers → Pass Type IDs.
Як відкрити pkpass на iOS?
На клієнті використовуйте PKPass та PKAddPassesViewController. Переконайтеся, що файл завантажено з правильним MIME-типом application/vnd.apple.pkpass.
import PassKit
func downloadAndAddPass(url: URL) {
URLSession.shared.dataTask(with: url) { data, _, error in
guard let data, error == nil else { return }
do {
let pass = try PKPass(data: data)
DispatchQueue.main.async {
let vc = PKAddPassesViewController(pass: pass)!
self.present(vc, animated: true)
}
} catch {
print("Invalid pass: \(error)")
}
}.resume()
}
Як працюють push-оновлення через APNs?
При зміні даних (бали нараховані, статус змінився) сервер отримує pushToken пристрою з бази, надсилає порожній push через APNs на passkit production endpoint. Wallet робить GET /wallet/v1/passes/{passTypeIdentifier}/{serialNumber} з Bearer-токеном. Відповідь — оновлений .pkpass. Wallet застосовує зміни та показує changeMessage якщо воно задане в pass.json. Завдяки цьому механізму оновлення відбуваються за 1-2 секунди, економлячи до 80% трафіку порівняно з періодичним опитуванням, а навантаження на сервер знижується в 3 рази.
Що ми пропонуємо: генерація pkpass під ключ
Наша команда реалізує повний цикл: від створення сертифіката до деплою серверного модуля. Ви отримуєте:
| Що входить | Опис |
|---|---|
| Випуск Pass Type ID | Створення ідентифікатора та сертифіката в Apple Developer Portal |
| Серверний модуль | API на Python/Node.js для генерації pkpass з обробкою помилок |
| iOS-клієнт | Інтеграція PKAddPassesViewController та обробка глибоких посилань |
| Push-оновлення | Механізм APNs для автоматичного оновлення пасів |
| Документація | Інструкція з експлуатації та підтримки з прикладами запитів |
| Підтримка | 2 тижні гарантійного супроводу після деплою |
Чому обирають нас
- 10+ років досвіду в iOS-розробці та бекенд-інтеграціях — вирішено понад 50 задач з Wallet Pass.
- Серверна генерація впроваджується за 2 дні для базового сценарію, push-оновлення — ще за 1 день.
- Довіра підтверджена відгуками, доступна рекомендація від клієнтів з ритейлу та авіації.
- Ми безкоштовно аналізуємо ваш проект: зв'яжіться з нами для консультації. Отримайте точну оцінку та пропозицію.
Терміни та вартість
Базова інтеграція (серверна генерація, endpoint завантаження, iOS-відкриття) займає від 2 днів. Додавання push-оновлень — ще від 1 дня. Вартість розраховується індивідуально і залежить від складності бекенда та необхідності додаткових стилів. Отримайте консультацію — оцінимо обсяг робіт і запропонуємо оптимальне рішення. Замовте впровадження і переконайтеся в надійності рішення.







