Генерация и обновление Wallet Pass (pkpass) на сервере мобильного приложения

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Генерация и обновление Wallet Pass (pkpass) на сервере мобильного приложения
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    874
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Генерация и обновление Wallet Pass (pkpass) на сервере мобильного приложения

Файл .pkpass — это ZIP-архив с JSON-описанием, изображениями и подписью. Apple Wallet принимает только пассы, подписанные сертификатом из Apple Developer Program. Это серверная операция: сертификат хранится на бекенде, клиент получает готовый .pkpass файл и открывает его.

Структура pkpass

pass.pkpass/
├── pass.json          # описание паса
├── manifest.json      # SHA1-хеши всех файлов
├── signature          # PKCS#7 подпись manifest.json
├── icon.png           # 29x29 pt
├── [email protected]        # 58x58 pt
├── [email protected]        # 87x87 pt
├── logo.png           # до 160x50 pt
└── background.png     # опционально, только для boardingPass

pass.json: ключевые поля

{
  "formatVersion": 1,
  "passTypeIdentifier": "pass.com.yourcompany.membercard",
  "serialNumber": "user-12345-2024",
  "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 зарегистрирует устройство на вашем сервере и будет запрашивать обновлённый пасс при изменениях.

Серверная генерация на 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.

Endpoint для скачивания pass

@app.get("/wallet/pass/{user_id}")
async def download_pass(user_id: str, token: str = Query(...)):
    user = db.get_user(user_id)
    if not verify_token(user, token):
        raise HTTPException(403)

    pass_data = build_pass_json(user)
    images = load_pass_images()
    pkpass_bytes = generate_pkpass(pass_data, images)

    return Response(
        content=pkpass_bytes,
        media_type="application/vnd.apple.pkpass",
        headers={"Content-Disposition": f"attachment; filename={user_id}.pkpass"}
    )

iOS: открытие 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

При изменении данных (баллы начислены, статус изменился) сервер:

  1. Получает pushToken устройства из базы (Apple Wallet зарегистрировал его при добавлении пасса)
  2. Отправляет пустой push через APNs на passkit production endpoint
  3. Wallet делает GET /wallet/v1/passes/{passTypeIdentifier}/{serialNumber} с Bearer-токеном

Ответ — обновлённый .pkpass. Wallet применяет изменения и показывает changeMessage если оно задано в pass.json.

Сроки

2–3 дня. Серверная генерация с подписью, endpoint скачивания, iOS-интеграция — 2 дня. Push-обновления через APNs — дополнительно 0,5–1 день. Стоимость рассчитывается индивидуально.