Consumer Flow (B2C)
Полный сценарий для website / mobile-приложения пассажира — от поиска до посадочного.
Этот гайд описывает полный путь пассажира в B2C-приложении (website или mobile). Гость может бронировать без регистрации (magic-link на email), но регистрация открывает кабинет с историей поездок, профилем и push-уведомлениями.
Архитектура
┌─────────────────────────────┐
│ Mobile / Website (UI) │
└────────────┬────────────────┘
│
▼ (pk_live_* + X-Client-Type: consumer_app)
┌─────────────────────────────┐
│ Your BFF │ ← рекомендуется, см. Authentication
│ (Backend-for-Frontend) │ ← хранит sk_live_*, дополнительная логика
└────────────┬────────────────┘
│
▼ (sk_live_* + Internal calls)
┌─────────────────────────────┐
│ NurCore API Gateway │
└─────────────────────────────┘Best practice: mobile / website звонят ваш BFF, не NurCore напрямую. Это позволяет хранить
sk_live_*server-side и добавлять свою бизнес-логику (markup, promo-коды партнёров, branding).
Сценарий 1: Гостевая броня (без регистрации)
Шаг 1. Поиск рейсов
POST /api/v1/schedules/flights/search
{
"origin": "FRU",
"destination": "OSS",
"departure_date": "2026-05-15",
"return_date": "2026-05-20", # для round-trip
"adults": 1,
"children": 0,
"infants": 0,
"include_prices": true
}Возвращает массив legs[] с flight_id, временами, наличием мест и
ценами по fare-families.
Для multi-city используйте
POST /flights/search-multicityс массивомsegments[].
Шаг 2. Расчёт цены (Quote)
Для финализации цены с ancillaries / promo используйте Quote API:
POST /api/v1/fares/quote
{
"flight_id": "...",
"fare_price_id": "...",
"pax_count": {"adult": 1, "child": 0, "infant": 0},
"offers": [
{"offer_id": "BG23", "amount": 1500}
],
"promo_code": "SUMMER10"
}Quote живёт 300 секунд в Redis. Сохраните quote_id для следующего
шага.
Шаг 3. SSR availability (опционально)
Если показываете опции багажа / питания на странице до Quote:
GET /api/v1/fares/ssr-availability/by-flight?\
route_id=...&aircraft_model_id=...&fare_family_code=CLASSICСм. Ancillary Services для деталей.
Шаг 4. Создание брони
POST /api/v1/bookings/
{
"flight_id": "...",
"quote_id": "quote_abc123", # M2.E — берём цену из quote
"passengers": [{
"first_name": "JOHN",
"last_name": "DOE",
"passenger_type": "adult",
"date_of_birth": "1990-01-15",
"gender": "male",
"nationality": "KGZ",
"document_type": "passport",
"document_number": "AN1234567",
"document_expiry": "2030-05-01"
}],
"contact_email": "user@example.com",
"contact_phone": "+996555000000",
"contact_name": "John Doe"
}Response: booking_reference (PNR) + expiry_date (через 15 минут).
Шаг 5. Оплата
POST /api/v1/bookings/{id}/initiate-payment
{
"amount": 6500,
"currency": "KGS",
"return_url": "https://your-site.com/payment-result"
}Редирект на payment_url. После webhook от провайдера → бронь в
CONFIRMED, на email уходит magic-link.
См. Payment Integration.
Шаг 6. Magic-link на email
Email содержит ссылку с access_token (TTL 24 часа). По этой ссылке
гость может:
| Действие | Endpoint |
|---|---|
| Посмотреть детали брони | GET /bookings/{id}/public?access_token= |
| Скачать e-ticket (PDF) | GET /bookings/{id}/eticket?access_token= |
| Online check-in | POST /checkin/consumer?access_token= |
| Отмена с возвратом | POST /bookings/{id}/cancel-consumer?access_token= |
Шаг 7. Find my trip (если email потерян)
GET /api/v1/bookings/lookup-consumer?pnr=ABC123&email=user@example.comNurCore не подтверждает существование брони — если PNR + email совпали, отправит ссылку на email. Защита от brute-force: 3 req/min на IP.
Сценарий 2: Регистрация пассажира
Регистрация — опциональна, но даёт UX-преимущества:
- История поездок без email-маги
- Сохранённые документы (auto-fill при бронировании)
- Сохранённые
preferences(seat, meal, language) - Push-уведомления (статус рейса, посадка, задержка)
Регистрация
POST /api/v1/auth/passenger/register
{
"email": "user@example.com",
"password": "StrongPass123!",
"first_name": "John",
"last_name": "Doe",
"phone": "+996555000000"
}→ access_token + refresh_token + профиль. См.
Passenger Auth.
Сохранение документов в профиль
PATCH /api/v1/auth/passenger/me
{
"documents": [{
"type": "passport",
"number": "AN1234567",
"expiry": "2030-05-01",
"country": "KGZ"
}],
"preferences": {
"seat": "window",
"meal": "vegetarian",
"language": "ky",
"notifications": {"email": true, "push": true}
}
}Регистрация FCM token (push)
POST /api/v1/auth/passenger/devices/register
{
"platform": "ios", # ios / android / web
"fcm_token": "...",
"device_id": "...",
"app_version": "1.0.0",
"locale": "ru"
}См. Mobile Push для содержимого уведомлений (статус рейса, посадка, задержка).
Сценарий 3: Online Check-in
OCI открывается за 24 часа до вылета и закрывается за 45 минут до вылета.
POST /api/v1/checkin/consumer
{
"access_token": "...", # из magic-link
"passenger_id": "...",
"seat_number": "12A",
"document_number": "AN1234567"
}→ Boarding pass (PDF + JSON с QR-кодом).
См. Online Check-in.
Сценарий 4: Изменение брони
| Действие | Endpoint |
|---|---|
| Добавить infant к существующей брони | POST /bookings/{id}/add-infant |
| Обновить контактные данные | PATCH /bookings/{id}/contact |
| Обмен на другой рейс | См. Exchange |
| Отмена с возвратом | POST /bookings/{id}/cancel-consumer |
| SSR после создания брони | (planned — пока требует exchange) |
Сценарий 5: Обмен билета
См. Exchange API для 4-шагового flow:
1. dates → доступные даты
2. flights → варианты на дату
3. preview → расчёт цены (Price Lock 15 мин)
4. execute → выполнить → может потребовать доплатуСостояния брони
PENDING (15м на оплату)
│
├─ оплата успешна → CONFIRMED
├─ expiry истёк → EXPIRED (места освобождены)
└─ ручная отмена → CANCELLED
│
▼
ARCHIVED (после вылета)CONFIRMED → checked-in → boarded → flown → COMPLETED.
Обработка ошибок
См. Error Handling для:
- Retry policy при 429 / 5xx
- Идемпотентность для POST refund
x-request-idдля bug-репортов
Webhooks для CRM (опционально)
Если у вашей авиакомпании есть свой CRM/loyalty backend — настройте
webhooks через partners@nurcore.kg:
| Event | Когда |
|---|---|
booking.confirmed | После оплаты |
booking.cancelled | При отмене |
booking.refunded | При возврате |
flight.delayed | Задержка ≥ 30 мин |
flight.cancelled | Отмена рейса |
passenger.checked_in | Регистрация пассажира |
Все webhooks подписаны HMAC-SHA256 (X-NurCore-Signature).
Полный flow в одном sequence-diagram
Пассажир ── search-flights ──────► NurCore
◄── legs[] ─────────────────
── fares/quote ──────────►
◄── quote_id, total ────────
── /bookings/ (quote_id) ──►
◄── PNR + 15м expiry ───────
── initiate-payment ──────►
◄── payment_url ────────────
─→ Payment provider
◄── webhook ◄──────────────
(email с magic-link)
── /bookings/.../eticket ──►
◄── PDF e-ticket ──────────
(T-24h: open OCI)
── /checkin/consumer ─────►
◄── boarding-pass ──────────
(T-30m: gate open)
Сканирование BCBP на gate → boarded
(T-0: рейс улетает)
─→ flight.departed event ──►
─→ COMPLETED status ───────►Чек-лист для команды интеграции
- Получены
pk_test_*+sk_test_*(sandbox) - Настроен BFF c
sk_test_*в env - Mobile bundle / SPA использует только
pk_test_* - Реализован retry с backoff на 429 / 5xx
-
x-request-idлогируется на каждый ответ - Magic-link tested end-to-end
- Webhooks подписи проверяются (если используете)
- Перед production switch — sandbox → live ключи + smoke-tests