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

Как протестировать интеграцию

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

Коротко

Песочница (ключ qp_test_…) — полноценный режим, в котором не двигаются реальные деньги и не вызывается Kaspi. Оплату вы «проводите» сами через POST /api/v1/invoices/{id}/simulate. Кассир Kaspi для песочницы не нужен, а счета песочницы не расходуют лимит тарифа.

Перед выходом в прод прогоните минимум шесть сценариев: успешная оплата, отмена, истечение срока, полный возврат, частичный возврат и поздняя оплата. Последний обычно забывают — и именно он потом ломает боевую работу.

Подготовка

  1. Переключите режим организации в песочницу
  2. Создайте ключ qp_test_… и выдайте нужные scope
  3. Добавьте адрес вебхука и сохраните секрет (показывается один раз)

Чем режимы отличаются: Чем песочница отличается от боевого режима.

Шесть основных сценариев

Эндпоинт simulate принимает три статуса: paid, failed, expired. Отмена делается отдельным эндпоинтом, возврат — тоже.

СценарийКак воспроизвестиЧто проверяете
1Успешная оплатаСоздать счёт → simulate {"status":"paid"}Пришёл invoice.paid, заказ помечен оплаченным, товар/услуга выданы
2ОтменаСоздать счёт → POST /invoices/{id}/cancelСтатус cancelled, пришёл invoice.cancelled, заказ закрыт
3Истечение срокаСоздать счёт → simulate {"status":"expired"}Статус expired, пришёл invoice.expired, резерв товара снят
4Полный возвратОплаченный счёт → POST /invoices/{id}/refund без суммыСтатус refunded, пришли refund.done и invoice.refunded
5Частичный возвратОплаченный счёт → refund {"amount": половина}Статус partially_refunded, остаток посчитан верно
6Поздняя оплатаЗакрыть счёт через cancel или simulate expired, затем simulate {"status":"paid"}Событие invoice.paid пришло с признаком late: true — видно, как система обрабатывает оплату уже закрытого заказа

Шестой сценарий — самый важный. В жизни клиент сканирует QR, думает и подтверждает оплату уже после того, как счёт закрылся. Что делает ваша система: выдаёт услугу или автоматически возвращает деньги? Решите заранее, иначе первый такой случай придётся разбирать руками. Подробно: Поздняя оплата.

Полное описание симуляции: Симуляция оплаты в песочнице.

Как тестировать вебхуки

Вебхук — самая хрупкая часть интеграции, потому что это входящий запрос на ваш сервер. Есть три подхода.

1. Локальный сервер плюс туннель. Удобно во время разработки: туннель (вроде ngrok) выставляет ваш локальный порт наружу. В песочнице это работает.

Но в боевом режиме туннельный адрес не принимается — вы получите webhook_url_tunnel_forbidden. В проде допустим только постоянный домен на https. Используйте туннель на этапе разработки и не оставляйте его как боевой адрес.

2. Внешний приёмник (вроде webhook.site). Хорош, чтобы своими глазами увидеть заголовки, тело и подпись. Но не кладите туда свой секрет — пользуйтесь только секретом песочницы и только для просмотра.

3. Офлайн-проверка подписи. Самый надёжный вариант. Сохраните пришедшее тело в файл и напишите юнит-тест: посчитайте HMAC-SHA256 от строки timestamp + "." + rawBody и сравните с X-Webhook-Signature.

Что обязано делать ваше обработчик вебхука:

Если вы не отвечаете 2xx, доставка повторяется 11 раз (с нарастающей паузой от 10 секунд до 1 часа). При длительной череде ошибок адрес временно ставится на паузу. Поэтому порядок «ответить 200, обработать потом» имеет значение.

Детали: Безопасность вебхуков, Настройка вебхуков.

Граничные случаи

Когда основные сценарии пройдены, проверьте вот это — именно оно валит интеграции в проде.

Что проверяемКакОжидаемый результат
Дубль запросаСоздайте счёт дважды с одним Idempotency-KeyНовый счёт не создаётся, HTTP 200 и idempotentReplay: true
Один заказ дваждыПопробуйте два счёта с одним externalOrderIdРешите заранее, как обрабатываете это на своей стороне
Неверная сумма0, отрицательное число, строка, тиыны в счёте phoneinvalid_amount, amount_too_small, amount_must_be_whole_tenge
Отсутствующий телефонkind: "phone" без customer.phone или с неверным форматомinvalid_phone
Несуществующий счётGET по выдуманному idinvoice_not_found, 404
Закрытый счётПопробуйте отменить оплаченный счётinvoice_not_open, 409
Возврат больше суммыВернуть больше, чем оплаченоinvalid_refund_amount
ЛимитыСоздайте много счетов в песочницеСчета песочницы не идут в месячный лимит, но частота запросов может дать 429
Битый ключЗапрос заведомо испорченным ключомunauthorized, 401
Нехватка правВозврат ключом без refunds:writeinsufficient_scope, 403

Все коды: Каталог ошибок.

Автотесты

Ручная проверка хороша один раз, но повторять её после каждой правки никто не будет. Песочница подходит для автотестов: реальных денег нет, Kaspi не вызывается, лимит не расходуется.

Типовой цикл одного теста:

  1. POST /api/v1/invoices — создать счёт, получить id
  2. POST /api/v1/invoices/{id}/simulate{"status":"paid"}
  3. Дождаться вебхука (или прочитать GET /api/v1/invoices/{id} напрямую)
  4. Убедиться, что статус заказа в вашей базе изменился
  5. Прибраться за собой

Практические советы:

Примеры автотестового цикла есть в документации SDK: Node.js SDK, PHP SDK, Python SDK.

При переходе в боевой режим

Пройденные тесты песочницы не гарантируют, что в проде всё хорошо. Дополнительно проверьте:

Полный список: Чек-лист выхода в прод.

Вопросы и ответы

QR в песочнице настоящий? Нет. Картинка генерируется, но приложение Kaspi её не отсканирует. Оплата проводится через simulate.

Счета песочницы расходуют лимит тарифа? Нет. И в месячный лимит не попадают, и семидневный пробный период не запускают — он начинается с первого боевого счёта.

Можно ли выставить через simulate статус cancelled? Нет, принимаются только paid, failed, expired. Для отмены есть POST /invoices/{id}/cancel.

Что будет, если вызвать simulate боевым ключом? Ошибка not_sandbox, 403. Симуляция доступна только в песочнице.

Нужен ли кассир для тестов? Для песочницы — нет. Кассир Kaspi требуется только для боевых счетов.

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

Симуляция оплаты в песочницеЭндпоинт simulate меняет статус счёта в песочнице: paid, failed, expired. Kaspi не вызывается, вебхук приходит как при настоящей оплате. Цикл проверки и написание автотестов.Чем песочница отличается от боевого режимаВ песочнице Kaspi не вызывается вообще, реальных денег нет и кассир не нужен — оплату вы симулируете сами. Полное сравнение двух режимов и что проверить при переходе в боевой.Чек-лист выхода в продДвенадцать пунктов, которые нужно закрыть перед переходом в боевой режим: кассир, боевой ключ, вебхук, подпись, идемпотентность, поздняя оплата, обработка ошибок, логи, тариф и лимиты, уведомления, возвраты, первый реальный платёж.Идемпотентность: защита от дублейКак работает заголовок Idempotency-Key, как правильно составить ключ, какова роль externalOrderId, и как защититься от повторов при обработке вебхуков и при возвратах.Каталог ошибок — что возвращает API и что делатьВсе основные коды ошибок Qut Pay API по группам: авторизация, привязка Kaspi, счета, возвраты, лимиты тарифа, вебхуки, подписки. Причина и решение для каждой.

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

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