Руководства → Вебхук не приходит: что проверить

Вебхук не приходит: что проверить

Разбор по шагам, от самого частого к редкому. Почти все случаи закрываются первыми тремя пунктами.

1. Посмотрите, что мы думаем о доставке

Первым делом спросите нас, а не свои логи:

curl -s https://kazpayment.kz/api/v1/webhook \
  -H "Authorization: Bearer $KAZPAYMENT_KEY"

В ответе — адрес приёмника и судьба последней доставки: статус, число попыток и текст последней ошибки. Дальше два разных мира:

2. Адрес вообще настроен?

Если GET /api/v1/webhook возвращает пусто — приёмник не настроен. Это самая частая причина «вебхук не приходит»: настраивали на тестовом ключе, а работаете боевым, или адрес удалили при отладке.

Требования к адресу жёсткие, и несоответствующий мы не примем при настройке:

Для локальной разработки используйте туннель (ngrok и аналоги) — он даёт публичное https-имя.

3. Проверьте приёмник тестовым событием

Не ждите настоящей оплаты:

curl -s -X POST https://kazpayment.kz/api/v1/webhook/test \
  -H "Authorization: Bearer $KAZPAYMENT_KEY"

В течение минуты придёт событие webhook.test — тем же путём и с той же подписью, что настоящие. Не пришло — проблема в доставке (пункт 4), пришло — значит канал жив, и дело в самой оплате (пункт 6).

4. Что считается недоставкой

Мы ждём 2xx в течение 10 секунд. Всё остальное — недоставка:

Что у вас Как выглядит у нас
500, 502, 404, 403 не-2xx, будем повторять
обработчик думает 30 секунд таймаут
редирект (301/302) на другой адрес недоставка: мы не ходим по редиректам
просроченный TLS-сертификат ошибка соединения
firewall режет чужие адреса ошибка соединения

Два самых частых самострела: долгий обработчик (ответьте 2xx сразу, работу делайте после) и редирект — например, с example.kz на www.example.kz. Указывайте в настройке конечный адрес.

5. Повторы и «мёртвая» доставка

Если не получилось, мы повторяем: через 1 минуту, 5 минут, 30 минут, 2 часа, 8 часов, 24 часа. Семь попыток примерно за полтора суток.

После этого доставка помечается мёртвой, а владелец бизнеса получает уведомление в Telegram (если он подключён). Текст последней ошибки виден в GET /api/v1/webhook.

Важно: у мёртвого события нет кнопки «отправить заново». Если ваш приёмник лежал дольше полутора суток, восстановите состояние опросом статусов: GET /api/v1/orders/<ваш_номер>.

6. Событие приходит, но обработчик его отвергает

Тогда виновата обычно проверка подписи. Три классические ошибки:

Подпись считается не от сырых байт. Многие фреймворки разбирают JSON до вашего кода, и JSON.stringify(req.body) даёт уже другую строку — порядок ключей и пробелы не совпадут. Нужен именно сырой буфер тела (в Express — express.raw() или сохранение rawBody до парсера).

Не тот секрет. Повторный PUT /api/v1/webhook — даже с тем же адресом — выпускает новый секрет, старый перестаёт работать сразу. Если вы перенастраивали адрес и не обновили секрет в окружении, все события пойдут мимо.

Сравнение строк «на глаз». Сравнивайте с защитой от утечки по времени (crypto.timingSafeEqual и аналоги), предварительно проверив длину.

Совет для отладки: логируйте отдельно «пришло событие с неверной подписью» — эта строка сразу отделяет проблему секрета от проблемы сети.

7. Оплаты действительно не было

Бывает и так. Проверьте статус заказа:

curl -s https://kazpayment.kz/api/v1/orders/SHOP-1042 \
  -H "Authorization: Bearer $KAZPAYMENT_KEY"

Если статус не paid — события и не должно было быть. Смотрите в кабинете раздел «Расхождения»: туда попадают поступления, которым не нашлось нашего счёта — например, клиент заплатил по старой ссылке или другой суммой.

Помните и про режим: в тестовом режиме настоящих оплат не бывает, статус меняется, только когда вы сами отмечаете оплату в кабинете (событие при этом уходит по-настоящему — это удобно для отладки).

Короткий чек-лист

  1. GET /api/v1/webhook — адрес есть? попытки есть? какая ошибка?
  2. Адрес https, публичный, без редиректа?
  3. POST /api/v1/webhook/test — тестовое событие доходит?
  4. Обработчик отвечает 2xx за 10 секунд?
  5. Секрет актуальный, подпись считается от сырых байт?
  6. Заказ вообще оплачен (GET /api/v1/orders/<ref>)?

Не сошлось — напишите на support@kazpayment.kz, приложив номер заказа и время: по ним видно всю историю доставок с нашей стороны.


Не помогло? Напишите на support@kazpayment.kz — отвечает разработчик сервиса.