Qut Pay Сайт Кабинет База знаний Инструкции Документация API ҚАЗРУС
Главная → База знаний → Справочник

Как автоматически узнать, что Kaspi QR оплачен

Обновлено: 2026-10-25 · Версия в Markdown

Коротко

Когда покупатель оплатил QR, Qut Pay замечает это сам и делает две вещи: присылает на ваш сервер webhook invoice.paid и меняет статус счёта на paid, который можно запросить. Правильная схема: заказ отмечается оплаченным по webhook с проверенной подписью или по ответу GET /invoices/{id} с сервера, но никогда — по тому, что покупатель вернулся на страницу «спасибо».

Способ 1 — webhook (основной)

  1. В кабинете → Интеграции укажите адрес на вашем сервере и получите секрет — настройка вебхуков.
  2. При оплате придёт POST с JSON { "event": "invoice.paid", "invoice": { "id", "status": "paid", "amount", "externalOrderId", "paidAt", "receiptUrl", … } }.
  3. Проверьте подпись: заголовок X-Webhook-Signature: sha256=… — это HMAC-SHA256 от строки timestamp + "." + сырое тело, где timestamp из X-Webhook-Timestamp. Считайте по сырым байтам тела, до разбора JSON — почему не сходится подпись.
  4. Найдите заказ по externalOrderId, сверьте amount, отметьте оплаченным и ответьте 200 в течение 8 секунд.
  5. Сделайте обработчик идемпотентным: один и тот же (invoice.id, status) может прийти дважды, повторный должен ничего не менять.

Если сервер не ответил 2xx, Qut Pay повторяет доставку до 11 раз в течение примерно двух часов — вебхук не приходит.

Способ 2 — запрос статуса (дополнительный)

curl https://api.qut.kz/api/v1/invoices/inv_… -H "X-API-Key: qp_live_…"

Ответ содержит status: pending — ждём, paid — оплачен, expired / cancelled / failed — не оплачен. Добавьте ?live=1, чтобы сервис спросил Kaspi прямо сейчас, а не отдал последнее известное состояние. Опрашивать раз в 5–10 секунд, пока покупатель на странице оплаты, нормально; опрос каждую секунду упирается в лимиты запросов. Когда что выбирать: вебхук или опрос.

Страница «спасибо»

После оплаты покупатель возвращается на ваш successUrl. Этот переход — не доказательство оплаты: ссылку можно открыть вручную. На этой странице запросите статус счёта с сервера и показывайте «оплачено» только при paid.

Чего ещё ждать

Проверить без реальных денег

В песочнице (qp_test_…) оплату имитирует запрос POST /invoices/{id}/simulate с телом {"status":"paid"} — webhook приходит настоящий, со всеми заголовками — песочница.

Связанные статьи

Настройка вебхуковКак добавить адрес вебхука в кабинете, выбрать события и сохранить секрет, какие приходят заголовки и тело, как устроены 11 повторов, как читать журнал, протестировать адрес и что с редиректами.Вебхук или опрос статуса: что когдаВебхук — основной способ узнать об оплате, но гарантия доставки не абсолютна. В сценариях, чувствительных к задержке, нужны оба механизма сразу: как их совместить, с какой частотой опрашивать и почему это не лишняя работа.Подпись вебхука не сходитсяПодпись считается как HMAC-SHA256(secret, timestamp + "." + rawBody). Самая частая ошибка — разобрать тело в JSON и собрать обратно в строку. Примеры получения raw body для Express, Laravel, Django.Жизненный цикл счётаВсе статусы счёта и переходы между ними, какое событие вебхука приходит в какой момент, какие статусы считаются открытыми и оплаченными, и как обработать поздно пришедшую оплату.Поздняя оплата — счёт закрыт, а деньги пришлиНа отменённый или просроченный счёт деньги могут прийти с опозданием. В этом случае событие invoice.paid приходит с меткой late: true. Что делать и как заранее подготовить к этому код.

Остались вопросы? WhatsApp +77788813333 · kazprose@gmail.com
Написать можно и из кабинета: Поддержка.

Qut Pay — независимый сервис, не аффилирован с АО «Kaspi Bank». Kaspi и Kaspi Pay — товарные знаки их правообладателя.