Генерація та оновлення 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 дня. Вартість розраховується індивідуально і залежить від складності бекенда та необхідності додаткових стилів. Отримайте консультацію — оцінимо обсяг робіт і запропонуємо оптимальне рішення. Замовте впровадження і переконайтеся в надійності рішення.







