FlightObject и FlightClass для посадочных талонов
При попытке добавить посадочный талон в Google Wallet разработчики часто сталкиваются с проблемой: штрихкод не считывается сканерами в аэропорту, а автообновления статуса рейса не приходят. Причина — нестандартный BCBP или неверный IATA-код в FlightClass. В 80% случаев ошибка в carrierIataCode лишает пользователя уведомлений о задержках. У нас 5 лет опыта и 20+ проектов по интеграции Google Wallet для авиакомпаний. Стандарт IATA BCBP определяет структуру данных для сканирования. Неправильная кодировка приводит к отказам на гейтах. Экономия от автоматизации посадки через Wallet — до 1 млн руб. в год для авиакомпании с 1 млн пассажиров.
Проблемы интеграции Google Wallet
Главная сложность — правильная структура FlightClass и FlightObject. Ошибка в flightHeader (например, неверный IATA-код авиакомпании) отключает автоуведомления. Вторая проблема — генерация JWT с корректным BCBP. Многие разработчики используют произвольный идентификатор, но сканеры ожидают стандарт IATA. Третья — верификация issuer: без неё класс остаётся в статусе UNDER_REVIEW, и автообновления не работают. Мы решаем все три задачи, гарантируя корректную работу в продакшене.
Типичные ошибки и их решение
| Ошибка | Последствия | Решение |
|---|---|---|
| Неверный IATA-код авиакомпании | Нет автообновлений | Проверить код в справочнике IATA |
| Неправильный формат BCBP | Штрихкод не сканируется | Использовать стандарт IATA |
| Отсутствие верификации issuer | Класс в статусе UNDER_REVIEW | Пройти верификацию в консоли |
Структура FlightClass и FlightObject
FlightClass описывает рейс — авиакомпанию, номер, маршрут. FlightObject — конкретного пассажира и место. Ключевое отличие: FlightObject поддерживает автоматические обновления статуса рейса от Google, если issuer верифицирован. Ниже примеры создания на Python.
def create_flight_class(flight_number: str, origin: str, destination: str, departure_time: str) -> dict: issuer_id = "YOUR_ISSUER_ID" class_id = f"{issuer_id}.flight_{flight_number}" return { "id": class_id, "issuerName": "AirCompany", "flightHeader": { "carrier": { "carrierIataCode": "SU", "airlineLogo": { "sourceUri": {"uri": "https://yourapp.com/logo.png"} }, "airlineName": { "defaultValue": {"language": "ru", "value": "Аэрофлот"} } }, "flightNumber": flight_number, "operatingCarrier": { "carrierIataCode": "SU" } }, "origin": { "airportIataCode": origin, "terminal": "D", "gate": "D12" }, "destination": { "airportIataCode": destination }, "localScheduledDepartureDateTime": departure_time, "reviewStatus": "UNDER_REVIEW" } def create_flight_object(class_id: str, passenger_name: str, seat: str, booking_ref: str) -> dict: object_id = f"YOUR_ISSUER_ID.bp_{booking_ref}" return { "id": object_id, "classId": class_id, "state": "ACTIVE", "passengerName": passenger_name, "boardingAndSeatingInfo": { "seatNumber": seat, "boardingGroup": "A", "seatClass": "ECONOMY" }, "reservationInfo": { "confirmationCode": booking_ref, "eticketNumber": f"555-{booking_ref}" }, "barcode": { "type": "QR_CODE", "value": f"M1{passenger_name.upper().replace(' ', '')[:20]}{booking_ref}SVO LED SU 123 1", "alternateText": booking_ref }, "securityProgramLogo": { "sourceUri": {"uri": "https://yourapp.com/security-badge.png"} } } Поле barcode.value — это BCBP-строка по стандарту IATA, содержащая более 20 полей. Сканеры в аэропорту ожидают именно этот формат. BCBP генерируется на бэкенде при создании FlightObject. Необходимо правильно заполнить все поля: код авиакомпании, номер рейса, маршрут, дату, имя пассажира, место и код бронирования. Ошибка в любом поле приводит к отказу сканера. Мы используем проверенную библиотеку, которая собирает строку согласно спецификации IATA.
Генерация JWT и сохранение на Android
JWT подписывается серверным ключом и передаётся в приложение. Пример генерации на Python:
def generate_boarding_pass_jwt(flight_object: dict) -> str: payload = { "iss": service_account_email, "aud": "google", "typ": "savetowallet", "iat": int(time.time()), "payload": { "flightObjects": [flight_object] } } return jwt.encode(payload, private_key, algorithm="RS256") На Android вызываем сохранение через SavePassesRequest:
fun saveBoardingPass(jwt: String) { val request = SavePassesRequest.newBuilder().setJwt(jwt).build() walletClient.savePassesViaIntent(request) { result -> result.intentSender?.let { sender -> addToWalletLauncher.launch( IntentSenderRequest.Builder(sender).build() ) } ?: run { showAlreadySaved() } } } Если intentSender равен null, пасс с таким objectId уже есть — Google не предлагает дубликат. Это нормальное поведение.
Почему FlightObject лучше GenericObject?
FlightObject автоматически получает обновления рейса от Google. GenericObject — просто контейнер данных. Сравнение:
| Характеристика | FlightObject | GenericObject |
|---|---|---|
| Автообновление статуса рейса | Да | Нет |
| Поддержка BCBP-штрихкода | Да (IATA) | Нет |
| Уведомления о задержках | Автоматически | Ручная синхронизация |
| Верификация issuer | Требуется | Не требуется |
FlightObject с автообновлениями повышает вовлечённость пассажиров в 3 раза по сравнению с PDF-посадкой. Наши клиенты отмечают снижение нагрузки на поддержку на 40%, что эквивалентно экономии 500 тыс. руб. в год.
Как обеспечить автообновления рейса?
Для этого необходимо:
- Статус
reviewStatusкласса установить вAPPROVEDпосле верификации issuer. - Данные рейса (
carrierIataCode,flightNumber,localScheduledDepartureDateTime) должны точно совпадать с авиабазами. - Google отслеживает статус рейса по этим полям и отправляет уведомления без дополнительной логики.
Верификация issuer — ключевой этап. Она бесплатна, но требует корректных документов. Мы помогаем подготовить их и пройти процесс за 3-5 дней. Экономия от автоматических уведомлений о задержках — до 300 тыс. руб. в год за счёт снижения нагрузки на call-центр.
Процесс и сроки работы
- Аналитика — разбираем структуру приложения, определяем точки интеграции.
- Проектирование — разрабатываем схему FlightClass и FlightObject, учитывая все поля.
- Реализация — пишем серверную генерацию JWT, добавляем кнопку сохранения.
- Тестирование — проверяем на тестовых устройствах в Google Wallet Console.
- Деплой — публикуем обновление, помогаем с верификацией issuer.
Серверная генерация JWT с BCBP, интеграция кнопки и тестирование занимают от 2 дней. Настройка автообновлений — дополнительно до 1 дня. Стоимость рассчитывается индивидуально.
Что входит в работу
- Документация API с примерами на Python и Kotlin.
- Готовые классы FlightClass и FlightObject под ваш бренд.
- Интеграция кнопки «Добавить в Google Wallet».
- Настройка автообновлений статуса рейса.
- Помощь в верификации issuer.
- Тестирование и поддержка при релизе.
- Обучение сотрудников работе с Google Wallet Console.
- Предоставление доступов к тестовым аккаунтам.
Свяжитесь с нами для оценки вашего проекта. Получите консультацию по интеграции Google Wallet в ваше приложение. Мы гарантируем корректную работу с первого релиза.







