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

Как не вернуть деньги дважды

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

Коротко

Если запрос на возврат вернул refund_unknown (502) или refund_pending_unknown (409), это не значит «возврат не прошёл» — это значит результат пока неизвестен. Если в этот момент повторить запрос, а первый возврат на самом деле прошёл, покупатель получит деньги дважды. Правильное действие одно: не повторяйте, прочитайте статус счёта через GET /api/v1/invoices/{id} и узнайте результат оттуда.

Почему вообще бывает ответ «неизвестно»

Возврат проходит через несколько систем. Запрос может дойти до Kaspi, тот может его выполнить, а ответ до нас не дойти. В такой момент мы отвечаем вам честно: результат неизвестен.

КодHTTPЧто это значит
refund_unknown502Kaspi не ответил, прошёл возврат или нет — неизвестно
refund_pending_unknown409Судьба предыдущего возврата ещё не ясна, новый не принимаем
refund_failed502Kaspi возврат не выполнил. Это как раз «не прошёл»
refund_state_conflict409Состояние возврата отличается от ожидаемого, перечитайте статус

Разница между refund_failed и refund_unknown — суть всей этой статьи. Первое — определённая неудача, её можно повторить. Второе — неопределённость, и повторять её нельзя.

refund_pending_unknown — это наша защита: пока судьба предыдущего возврата не выяснена, новый мы не пропускаем. Увидев его, считайте, что система прямо сейчас уберегла вас от ошибки.

Правильный порядок действий

  1. Не повторяйте запрос. Если у вас есть автоматический ретрай, уберите из него возвраты.
  2. Подождите несколько секунд.
  3. Отправьте GET /api/v1/invoices/{id}. В ответе будет статус счёта и список возвратов по нему.
  4. Решайте по статусу:
Статус счётаЧто это значитЧто делать
refundedВозвращён полностьюВсё, готово. Не повторяйте
partially_refundedЧасть возвращенаПосчитайте возвращённую сумму и досылайте только разницу, если её не хватает
paidВозврат не прошёлТолько теперь можно повторить
  1. Запишите результат в свой журнал, чтобы в следующий раз не выяснять заново.

Если даже после нескольких проверок статус не проясняется, подождите и напишите в поддержку. Мысль «попробую повторить всего один разок» именно здесь самая опасная.

Узнать результат можно и через вебхук

Результат операции приходит и событиями: refund.done, refund.failed, refund.unknown, а при смене статуса счёта — invoice.refunded или invoice.partially_refunded.

То есть после refund_unknown у вас два пути: спросить статус самому или дождаться события. Надёжнее вести оба канала, но результат обоих обрабатывать в одном месте и идемпотентно.

Идемпотентность

Главная защита от двойного возврата — гарантия неповторяемости на вашей стороне.

Учёт частичных возвратов

В частичных возвратах сбиться со счёта легче всего. Правило простое: сумма всех возвратов не может превышать оплаченную сумму. Если отправите больше, получите invalid_refund_amount (422) — это хорошо, но полагаться на это не стоит, считайте сами.

Пример: счёт на 10 000 ₸ оплачен. Вы вернули 3 000 ₸ — счёт становится partially_refunded, остаток 7 000 ₸. Если отправить ещё 3 000 ₸, это будет не повтор первого возврата, а новый возврат: всего вернётся 6 000 ₸. Поэтому мысль «просто отправлю ещё раз» в частичных возвратах опаснее всего.

Считайте всегда по списку возвратов из ответа GET /api/v1/invoices/{id}, а не по своим предположениям.

Что должен содержать журнал

Именно он спасает в спорной ситуации.

Сам ключ в журнал не пишите. При логировании заголовков вырезайте значение X-API-Key.

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

Пришёл refund_unknown, а статус счёта paid. Можно повторять? Да. Если статус paid, возврат не прошёл, повторять можно.

Сколько держится refund_pending_unknown? Пока не прояснится судьба предыдущего возврата. Подождите несколько секунд и перечитайте статус счёта.

Если я всё-таки вернул дважды, можно отменить? Нет, операции «отменить возврат» не существует. Придётся связаться с покупателем и выставить новый счёт на излишек.

Есть ли ключ идемпотентности для возвратов? При создании счёта есть заголовок Idempotency-Key. В возвратах защита устроена иначе: пока результат предыдущего возврата неизвестен, новый не принимается (refund_pending_unknown). Собственный журнал и блокировка на вашей стороне всё равно обязательны.

Откуда берутся деньги на возврат? С вашего счёта Kaspi. У нас деньги не хранятся: Когда и куда приходят деньги.

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

Оплата подтверждается медленно — почему и что делатьПокупатель заплатил, а счёт не сразу становится paid. Как частота проверки зависит от возраста счёта, сколько это занимает на практике и что делать в сценариях, чувствительных к задержке.Вебхук не приходит — как найти причинуСчёт оплачен, а на ваш сервер уведомление не пришло. С чего начать диагностику, какая причина встречается чаще всего и как проверить её одним запросом.Когда и куда приходят деньгиДеньги приходят напрямую на ваш счёт Kaspi Pay в момент оплаты — у нас они не задерживаются. Плата за сервис не зависит от суммы платежа, это месячная подписка. Как вести сверку.API-ключ утёк — что делать срочноКлюч попал в репозиторий, чат или чужие руки. Что сделать в первую минуту: удалить, создать новый, проверить последние счета. Что вообще можно сделать ключом и как не допустить повторения.

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

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