Интеграция Apple Wallet для посадочных талонов в мобильном приложении
Посадочный талон в Apple Wallet — это boardingPass-тип .pkpass-архива с жёсткими требованиями к полям: transitType обязателен, структура primaryFields/auxiliaryFields влияет на то, что видит пользователь на экране блокировки. Ошибка в transitType или отсутствие обязательных полей — Apple Wallet покажет сообщение «Неверный формат пропуска».
Структура boardingPass
{
"formatVersion": 1,
"passTypeIdentifier": "pass.com.yourairline.boarding",
"serialNumber": "FLIGHT-SU123-20240615-IVANOV",
"teamIdentifier": "ABCDE12345",
"organizationName": "YourAirline",
"description": "Посадочный талон SU 123",
"foregroundColor": "rgb(255,255,255)",
"backgroundColor": "rgb(0,60,130)",
"boardingPass": {
"transitType": "PKTransitTypeAir",
"primaryFields": [
{ "key": "origin", "value": "SVO", "label": "Откуда" },
{ "key": "destination", "value": "LED", "label": "Куда" }
],
"auxiliaryFields": [
{ "key": "flight", "value": "SU 123", "label": "Рейс" },
{ "key": "seat", "value": "14A", "label": "Место" },
{ "key": "date", "value": "2024-06-15T07:30+03:00", "label": "Вылет",
"dateStyle": "PKDateStyleShort", "timeStyle": "PKDateStyleShort" }
],
"backFields": [
{ "key": "terms", "label": "Условия", "value": "Багаж 23 кг включён" }
],
"barcode": {
"message": "M1IVANOV/IVAN ABCDEF SVO LED SU 0123 165Y014A0047 100",
"format": "PKBarcodeFormatAztec",
"messageEncoding": "iso-8859-1"
}
},
"relevantDate": "2024-06-15T07:00+03:00"
}
Значения transitType: PKTransitTypeAir, PKTransitTypeTrain, PKTransitTypeBus, PKTransitTypeBoat, PKTransitTypeGeneric. Тип влияет на иконку транспорта в шапке пасса.
Формат штрихкода для авиации — PKBarcodeFormatAztec (IATA 2D Barcode standard). QR тоже работает, но aztec-коды читаются быстрее при плохом освещении.
Поле relevantDate и геолокация
relevantDate выводит пасс на экран блокировки за 15–30 минут до события. Для аэропортов добно добавить locations:
"locations": [
{
"latitude": 55.9729,
"longitude": 37.4146,
"relevantText": "Регистрация на рейс SU 123"
}
]
Wallet покажет уведомление, когда пользователь появится в аэропорту Шереметьево.
Динамические поля: обновление статуса рейса
Главная потребность авиакомпаний — обновлять поля в реальном времени. Wallet поддерживает это через push APN:
- Устройство при добавлении пасса регистрирует себя через
POST /v1/devices/{deviceLibraryIdentifier}/registrations/{passTypeIdentifier}/{serialNumber} - Сервер при изменении данных (задержка рейса, смена ворот) отправляет push на
pushTokenиз регистрационного запроса - Устройство запрашивает обновлённый
.pkpassи заменяет старый
Payload APN push для Wallet минимальный:
{
"aps": {}
}
Пустой aps — Wallet сам знает, что делать. Добавлять текст уведомления не нужно.
Серверная генерация и подпись
Архив собирается на лету под каждого пассажира. Каждый пасс уникален: serialNumber должен идентифицировать конкретный рейс + пассажира. После изменения любого файла в архиве необходимо пересчитать manifest.json и перегенерировать signature.
На Node.js удобно использовать passkit-generator:
import { PKPass } from "passkit-generator";
const pass = await PKPass.from({
model: "./models/boarding-pass.pass",
certificates: {
wwdr: fs.readFileSync("./certs/wwdr.pem"),
signerCert: fs.readFileSync("./certs/pass.pem"),
signerKey: fs.readFileSync("./certs/pass.key"),
},
overrides: {
serialNumber: `FLIGHT-SU123-${passengerId}`,
description: `Посадочный талон ${flightNumber}`,
},
});
pass.setBarcodes({
message: bcbpData,
format: "PKBarcodeFormatAztec",
messageEncoding: "iso-8859-1",
});
const buffer = pass.getAsBuffer();
Сроки
2–3 дня — серверная генерация, подписание, регистрация устройств, push-обновления статуса рейса. Стоимость рассчитывается индивидуально.







