Бронь и оплата по шагам
Главный сценарий от начала до конца: родитель выбрал смену → ваша CRM оформляет бронь → лагерь отправляет родителю счёт Kaspi → родитель платит → место закреплено → остаток оплачивается к сроку.
Все данные в примерах вымышленные. Ключ — в переменной ZB_KEY (см.
Первый запрос).
Что нужно знать до начала
Пять правил, на которых держится весь сценарий
- Бронь сразу занимает место в квоте вашего отдела, но держит его только 24 часа. За сутки плательщик должен внести минимальный платёж. Не внёс — бронь отменяется сама.
- Деньги принимает только лагерь — счётом Kaspi. Счёт уходит с Kaspi лагеря на телефон плательщика. Ваш отдел денег не принимает и отметить бронь оплаченной не может.
- Дата рождения ребёнка обязательна. Без неё бронь не оформится.
- У брони одновременно только один неоплаченный счёт.
- Каждый
POST— с заголовкомIdempotency-Key, кроме расчёта стоимости и проверки «можно ли оформить». Это защищает от двойной брони при обрыве связи (см. Повтор запроса).
Что пригодится для оформления:
| Что | Откуда взять |
|---|---|
Номер смены (shift_id) | GET /shifts?on_sale=true |
| ФИО ребёнка | От родителя. Полностью: фамилия, имя, отчество (если есть) |
| Дата рождения ребёнка | От родителя, формат ГГГГ-ММ-ДД |
Город ребёнка (city_id) | Номер из справочника городов лагеря. Список номеров городов лагерь передаёт вместе с ключом; в ответах API город приходит как {"id": "1", "name": "Астана"} |
| ФИО и телефон родителя | От родителя. Телефон — любой записью: 8 701 000 00 01, +7 (701) 000-00-01 |
| Телефон плательщика | Только если платит не родитель — на него уйдёт счёт Kaspi |
| Точка посадки | Если нужен трансфер: transfer_point_id из transfer_prices смены |
Как проходит бронь — схема
Code
-
Найдите смену и проверьте места
CodeПодходит смена с
on_sale: trueиseats.freeбольше нуля. Пример ответа и что значит каждое поле — в Первом запросе. Одну смену можно перечитать по номеру:GET /shifts/12.Места меняются каждую минуту — их занимают и другие менеджеры вашего отдела. Не храните
seats.freeу себя надолго: перечитывайте смену перед оформлением или следите за событиемshift.seats_changed. -
Посчитайте стоимость (по желанию)
POST /quote— сколько будет стоить бронь. Считает тем же расчётом, что и оформление, поэтому цифры совпадут. Ничего не создаёт, место не занимает,Idempotency-Keyне нужен. Нужно правоread.CodeОтвет
200:Codetotal— к оплате всего: 250 000 + 15 000 − 10 000 = 255 000 ₸;min_payment_now— минимальный платёж: на эту сумму уйдёт счёт при оформлении.0.00— предоплата не нужна, бронь сразу закреплена;hold_hours— сколько часов держится место без минимального платежа.null— предоплата не нужна.
Скидка больше
max_discountсмены — отказdiscount_over_max(большую скидку даёт только администратор лагеря). -
Проверьте, пройдёт ли оформление (по желанию)
POST /bookings/check— те же проверки, что при оформлении, но без брони: продажи открыты, у отдела есть место, ребёнок ещё не записан на эту смену, нет запрета. Удобно, чтобы показать менеджеру все препятствия сразу, ещё до ввода остальных данных. Нужно правоbookings;Idempotency-Keyне нужен; не больше 300 проверок в час на отдел.CodeОтвет
200, если оформить можно:CodeЕсли нельзя — все причины сразу:
CodeВозможные
code:sales_closed,shift_not_open,quota_exhausted,no_quota,duplicate_child,blacklisted,birth_date_implausible(что каждый значит — в Ошибках).can_book: trueне гарантирует места: между проверкой и оформлением его может занять другой менеджер. -
Оформите бронь
POST /bookingsс заголовкомIdempotency-Key. Нужно правоbookings.Поля запроса:
Поле Обязательно Что это shift_idда Номер смены child.full_nameда ФИО ребёнка child.birth_dateда Дата рождения ГГГГ-ММ-ДД. Без неё — отказbirth_date_required(почему — ниже)child.city_idда Город из справочника городов лагеря parent.full_nameда ФИО родителя parent.phoneда Телефон родителя, любой записью payer_phoneнет Телефон плательщика, если платит не родитель: счета Kaspi уйдут на него needs_transferнет true— нужен трансфер. По умолчаниюfalsetransfer_point_idесли трансфер Точка посадки из transfer_pricesсменыdiscountнет Скидка: amount— тенге строкой ("10000"),note— за что. Не большеmax_discountсменыinvoiceнет Какой счёт Kaspi отправить сразу: min,fullилиnone(таблица ниже)commentнет Комментарий для лагеря together_withнет Номера ваших броней той же смены, с кем поселить вместе (до 50) external_idнет Номер сделки или заявки в вашей CRM (до 255 знаков, уникален в вашем отделе) metadataнет Ваши метки: до 20 пар «ключ — значение» partner_managerнет Кто продал в вашей CRM (до 200 знаков) — для ваших отчётов Поле, которого нет в этой таблице, — отказ
422 invalid_input(имя поля — вmessage). Так опечатка в имени поля не превращается в молча потерянные данные.Какой счёт отправить сразу (
invoice):Значение Что произойдёт minСчёт на минимальный платёж смены. Так и будет, если поле не передать, когда у смены минимальный платёж больше нуля fullСчёт сразу на всю сумму к оплате noneСчёт не отправляется. Место всё равно держится только 24 часа — выставьте счёт сами до hold_untilЕсли у смены минимальный платёж
0.00иinvoiceне передан, счёт не отправляется: бронь сразу закреплена, оплатить её можно позже (счётомfullили автоматическим счётом на остаток).Почему дата рождения обязательна
В базе лагеря ребёнок узнаётся по ФИО и дате рождения вместе. По ним лагерь понимает, что «Тестов Тимур, 12.04.2016» — тот же ребёнок, что ездил прошлым летом, а не новый; находит дубль, если ребёнка уже записали на эту смену; назначает отряд по возрасту.
Без даты рождения двух детей с одним именем в одной семье не различить, а ребёнок другого отдела мог бы «перейти» к вам по одному совпадению имени и телефона. Поэтому без даты API не оформляет бронь вовсе (
400 birth_date_required). Дата должна быть правдоподобной: в лагерь едут дети от 3 до 19 лет на дату заезда, иначе —birth_date_implausible. Дата в будущем —bad_birth_date.Ответ
201— бронь целиком:CodeСохраните у себя
idброни — по нему все дальнейшие запросы. Телефон в ответе всегда в виде+7XXXXXXXXXX, даже если вы прислали8 701 ….Самые частые отказы при оформлении:
Ответ Что значит и что делать 400 birth_date_requiredНет даты рождения. Спросите у родителя 409 quota_exhaustedМеста вашего отдела на смене закончились. Предложите другую смену или попросите лагерь добавить мест 409 no_quotaВашему отделу не выделены места на эту смену 409 sales_closedПродажи на смену закрыты 409 duplicate_childРебёнок уже записан на эту смену (возможно, другим отделом). Если это ошибка — в лагерь 403 blacklistedОформить этого ребёнка нельзя. Причину API не сообщает — обратитесь в лагерь 400 discount_over_maxСкидка больше разрешённой 409 external_id_takenЭтот external_idуже у другой вашей брони (вmessage— её номер). Скорее всего, бронь уже оформлена — прочитайте её:GET /bookings/by-external-id/deal-10452Все коды — в Ошибках.
-
Лагерь отправляет счёт Kaspi
При
invoice: minилиfullсчёт создаётся вместе с бронью и уходит плательщику очередью — обычно за несколько секунд. Вы узнаете об этом событиями:invoice.queued— счёт создан и ждёт отправки в Kaspi;invoice.issued— счёт у плательщика в приложении Kaspi.
Счета брони —
GET /bookings/15230/invoices:Codepurpose— текст, который плательщик видит в Kaspi рядом с суммой. Подскажите родителю искать счёт с этим текстом;payment_type: prepayment— счёт меньше полной суммы,payment— на весь остаток.
Если счёт не выставился (
invoice.error, у счёта заполненоerror) — чаще всего телефон плательщика не зарегистрирован в Kaspi. Что делать — в Счета Kaspi и оплата. -
Плательщик оплачивает
Плательщик открывает Kaspi, видит счёт и оплачивает. Через несколько секунд лагерь узнаёт об оплате, и приходят события (обычно в таком порядке, но полагайтесь на номера событий, а не на порядок типов):
invoice.paid— счёт оплачен;payment.received— платёж записан;booking.secured— минимальный платёж набран, место закреплено.
Платёж —
GET /bookings/15230/paymentsили по номеру из события:CodeБронь после этого (
GET /bookings/15230, только изменившиеся поля):Codeverified: false— бухгалтерия лагеря ещё не сверила платёж с банком. Это не мешает: остаток уменьшился и место закреплено сразу. Когда сверят — придёт событиеpayment.verified. -
Если плательщик не оплатил за сутки
Не пришёл минимальный платёж до
hold_until— лагерь сам отменяет бронь (обычно в течение нескольких минут после срока):- событие
booking.hold_expired; - у брони
status: cancelled,payment_state: unpaid; - место вернулось в квоту (
shift.seats_changed); - неоплаченный счёт гасится в Kaspi.
Ребёнок при этом остаётся в вашей базе — чтобы менеджер мог перезвонить. Список таких броней на обзвон —
GET /reports/unpaid. Если семья всё-таки хочет ехать — восстановите бронь, если места ещё есть. - событие
-
Остаток — к сроку полной оплаты
В день
full_payment_dueлагерь сам выставляет плательщику один счёт на весь остаток. Ничего делать не нужно. Родитель хочет заплатить раньше или частями — выставьте счёт сами (см. Счета Kaspi и оплата).Когда остаток оплачен —
debtстановится0.00. Бронь оплачена полностью.
Как узнавать о переменах
Не опрашивайте каждую бронь по кругу — для этого есть события: лента изменений вашего отдела. Самый удобный способ — вебхуки: лагерь сам присылает вам каждое событие. Если своего публичного сервера нет — опрос ленты раз в 10–30 секунд.
Какие события важны в этом сценарии:
| Событие | Что сделать у себя |
|---|---|
booking.created | Бронь появилась (в том числе оформленная менеджером вашего отдела в CRM лагеря) |
invoice.issued | Сказать менеджеру: «счёт у родителя в Kaspi» |
invoice.error | Предупредить менеджера: счёт не ушёл, проверить телефон |
payment.received | Обновить «оплачено» и «остаток» — перечитайте бронь |
booking.secured | Место закреплено — сделка выиграна |
booking.hold_expired | Бронь снята по неоплате — задача менеджеру на звонок |
booking.cancelled | Бронь отменена (вами или лагерем) |
Несколько детей одной семьи
POST /bookings/batch оформляет от 1 до 10 детей одной семьи за один раз: или все,
или никого. Если не прошёл хотя бы один ребёнок (нет мест, дубль, запрет), не оформляется никто, а
в message сказано, какой ребёнок и почему: «Ребёнок 2: …».
Code
Ответ 201 — {"items": [бронь, бронь]} в порядке детей запроса. У каждого ребёнка — своя бронь и
свой счёт Kaspi. together: true — поселить вместе детей семьи, попавших на одну смену. У
каждого ребёнка можно указать свой invoice; если не указан — берётся общий.
Дальше
- Счета Kaspi и оплата — частичная оплата, замена и отмена счёта, юрлица лагеря.
- Изменения брони — правка, отмена, восстановление, перенос.