Коротко
Вебхук — основной способ. Когда клиент оплатил, мы сами приходим на ваш адрес, вам ничего не нужно спрашивать.
Но вебхук идёт по сети, а сеть не идеальна: ваш сервер может перезагружаться, хостинг — не ответить. Поэтому в сценариях, чувствительных к задержке (шлагбаум, вендинг, касса, прямой эфир), ведите оба механизма параллельно: если вебхук не пришёл за отведённое время, спросите статус сами через GET /api/v1/invoices/{id}.
Там, где несколько секунд ничего не решают — интернет-магазин, CRM, отчётность — достаточно одного вебхука.
Чем они отличаются
| Вебхук | Опрос статуса (polling) | |
|---|---|---|
| Кто инициирует | Мы | Вы |
| Что нужно с вашей стороны | Доступный извне адрес на https | Только исходящий интернет |
| Задержка | Обычно в пределах 5 секунд | Равна вашей частоте опроса |
| Гарантия доставки | Высокая, но не абсолютная | Ответ приходит на каждый ваш запрос |
| Проверка подписи | Нужна | Не нужна |
| Работает без своего сервера | Нет | Да |
Почему вебхук всё-таки основной
После оплаты наш поллер забирает статус у Kaspi и в тот же момент уведомляет вас. На практике вебхук приходит в пределах 5 секунд.
Поллер работает с учётом возраста счёта — свежие проверяются чаще:
| Возраст счёта | Частота проверки |
|---|---|
| Младше 3 минут | Каждый проход, то есть примерно раз в 3 секунды |
| До 30 минут | Примерно раз в 20 секунд |
| Старше | Примерно раз в 90 секунд |
Очередь начинается с самых свежих счетов: счёт, рядом с которым прямо сейчас стоит покупатель, никогда не ждёт позади вчерашних.
Если вебхук не получил ответ 2xx, доставка повторяется 11 раз — с паузой, растущей от 10 секунд до 1 часа. А когда адрес отвечает ошибками подряд, он временно ставится на паузу (5 неудач — 5 минут, 10 — 30 минут, 20 — 2 часа, 50 — отключение). Это защита и вашего сервера, и очереди, но знать о ней нужно: пока адрес на паузе, вебхуки не приходят вовсе.
Подробно: Настройка вебхуков.
Когда нужны оба механизма
Не полагайтесь на один вебхук в таких сценариях:
- Шлагбаум, турникет, дверь. Клиент сидит в машине, ждать полминуты неприемлемо
- Вендинговый автомат. Человек стоит перед автоматом
- Офлайн-касса. За спиной очередь
- Прямой эфир, быстрые продажи. Десятки секунд — это потерянная продажа
- Курьер доставки. Стоит у двери
Общий признак: человек ждёт, и десятки секунд стоят дорого.
Одного вебхука достаточно там, где:
- Интернет-магазин (заказ собирается позже)
- Перевод сделки по этапам в CRM
- Отчётность и бухгалтерия
- Открытие доступа к подписочному сервису
Как совместить
Схема простая: ждёте вебхук, не дождались — спрашиваете сами.
- Создаёте счёт, получаете
id - Показываете клиенту QR или ссылку
- Запускаете таймер. Например, на 5 секунд
- Пришёл вебхук за это время — готово, опрашивать не нужно
- Не пришёл — отправляете
GET /api/v1/invoices/{id}и читаете статус - Статус
paid— продолжаете работу - Всё ещё
pending— ждёте дальше
Важно: вебхук и опрос приводят к одному и тому же результату, и прийти они могут одновременно. Обработчик должен быть идемпотентным — не обрабатывайте пару (invoice.id, status) дважды. Подробно: Идемпотентность.
Какую частоту опроса выбрать
«Чаще спрашиваю — быстрее узнаю» здесь не работает: наш поллер забирает статус у Kaspi по своему расписанию, а ваш запрос возвращает лишь то, что у нас уже есть. Десять запросов в секунду ничего не ускорят, зато приведут к 429 (rate_limited).
Разумное расписание:
| Возраст счёта | Частота опроса |
|---|---|
| Первые 3 минуты | Раз в 3-5 секунд |
| 3-30 минут | Раз в 20-30 секунд |
| Старше | Раз в 1-2 минуты или прекратить |
Оно совпадает с расписанием нашего поллера: свежие счета и так проверяются часто, а по старым частый опрос бессмыслен.
Дополнительные правила:
- Опрашивайте только открытые счета.
paid,cancelled,expired— конечные статусы, переспрашивать их не нужно - Ограничьте время ожидания. Прошёл
expiresAt— прекращайте опрос - Забирайте список одним запросом. Если открытых счетов сотни, вместо опроса каждого используйте
GET /api/v1/invoices - Получили 429 — смотрите заголовок
Retry-After: Ограничения частоты запросов
А можно только опрашивать
Да, можно — если у вас нет сервера, доступного снаружи (локальная кассовая программа, система в закрытой сети). Тогда вебхук просто не подключается, и вы работаете через GET /api/v1/invoices/{id}.
Минус: запросов больше, а задержка равна вашей частоте опроса. Плюс: не нужны ни входящий адрес, ни проверка подписи, ни сертификат HTTPS.
Вопросы и ответы
Если вебхук не пришёл сразу, значит он потерян? Нет. Он повторится 11 раз, то есть будет пытаться доставиться около часа. Но если ваш бизнес-сценарий не может столько ждать — нужен опрос.
Если придут оба, я обработаю заказ дважды? При наличии идемпотентности — нет. Проверяйте по паре (invoice.id, status).
Опрос расходует лимит тарифа? Нет. Месячный лимит считается по количеству счетов, а не запросов. Но у частоты запросов есть отдельное ограничение, оно отвечает 429.
Оплата подтверждается медленно — может, опрашивать чаще? Сначала разберитесь в причине: Оплата подтверждается медленно. Учащение не поможет, потому что узкое место — на стороне получения статуса из Kaspi.
Как проверить, что сам сервис жив? Для этого есть GET /api/v1/status: Проверка состояния сервиса.