Перейти к основному содержимому

Возвраты

Вернуть покупателю деньги за оплаченный платёж можно через API или в личном кабинете. Можно вернуть всю сумму или часть. Деньги вернутся тем же способом, которым покупатель платил.

Все поля и ошибки — в справочнике: Создать возврат, Объект возврата.

Перед первым возвратом​

  1. Попросите поддержку включить ключу право «Возвраты»: напишите на [email protected]. По умолчанию право выключено, и запрос на возврат получит ответ 403 forbidden. Если возвраты нужно разрешить только с IP-адресов ваших серверов, укажите их в письме.
  2. Если хотите получать уведомления о возвратах, включите событие «Возврат выполнен» (refund.succeeded) в Ещё → Разработчикам → HTTP-уведомления.

Как сделать возврат​

  1. Запросите платёж: GET /v3/payments/{payment_id}. Вернуть его можно, если refundable равен true.

  2. Создайте ключ идемпотентности для этого возврата и сохраните его у себя до запроса. Например, номер заказа и номер возврата по нему: refund-123-1.

  3. Отправьте запрос POST /v3/refunds с id платежа и суммой. Свой номер возврата передайте в metadata.refund_number: по нему вы найдёте возврат в списке и в уведомлении, если ответ на создание не дошёл.

    curl https://api.avantpay.io/v3/refunds \
    -X POST \
    -u "$AVANTPAY_SHOP_ID:$AVANTPAY_SECRET_KEY" \
    -H "Idempotence-Key: refund-123-1" \
    -H "Content-Type: application/json" \
    -d '{
    "payment_id": "2f9b6c1e-4d7a-4c3b-9e8f-1a2b3c4d5e6f",
    "amount": {
    "value": "300.00",
    "currency": "RUB"
    },
    "description": "Возврат по заказу №123",
    "metadata": {
    "order_id": "123",
    "refund_number": "123-1"
    }
    }'
  4. В ответе — объект возврата со статусом pending. Сохраните его id. Возврат принят, но ещё не выполнен. Если это был повтор с тем же ключом, статус может быть уже succeeded или canceled: обрабатывайте любой статус из ответа.

  5. Дождитесь уведомления refund.succeeded или запрашивайте возврат GET /v3/refunds/{refund_id} раз в несколько минут, пока статус pending. Обычно итог — через несколько секунд или минут.

Статус возврата​

statusЧто значитЧто делать
pendingВозврат выполняется. Покупатель ещё не получил деньги.Ждать. Новый возврат по этому платежу не создавать. Дольше часа — написать в поддержку.
succeededДеньги вернули покупателю.Отметить в заказе, что деньги вернули.
canceledВозврат не выполнен, сумма осталась на счёте магазина или вернулась на него.Посмотреть причину — в разделе Если возврат отменён.

Ответ на запрос, который создал возврат, — всегда pending. Повтор с тем же ключом вернёт тот же возврат в текущем статусе. Статусы succeeded и canceled у возврата больше не меняются. Статус платежа после возврата остаётся succeeded, а сколько уже вернули — в поле refunded_amount платежа.

Если возврат в pending дольше часа, напишите в поддержку: [email protected], укажите id возврата. Не считайте его отменённым и не создавайте новый: API не примет новый возврат по этому платежу, пока этот не завершится.

Частичный возврат​

  • Передайте в amount.value сумму меньше суммы платежа.
  • По платежу одновременно выполняется только один возврат. Следующий создавайте, когда прежний стал succeeded или canceled, — с новым ключом идемпотентности. Пока прежний в статусе pending, API ответит 400.
  • Всего можно вернуть не больше суммы платежа и не больше чем 10 возвратами. Отменённые возвраты не считаются.
  • Минимальная сумма возврата — 1 ₽. Меньше можно вернуть, только если это весь остаток платежа.

Если сумма больше остатка, API ответит 400 и назовёт остаток:

{
"type": "error",
"id": "6b2d9e4f-1c3a-4e5b-8d7f-0a9b8c7d6e5f",
"code": "invalid_request",
"description": "Refund amount exceeds the amount available for refund: 700.00 RUB",
"parameter": "amount.value"
}

Если возврат отменён​

Уведомления об отмене возврата нет: отмену видно только в ответе на GET /v3/refunds/{refund_id}. Покупатель денег не получил. Причина — в cancellation_details:

  • "party": "avantpay" и "reason": "insufficient_funds" — на счёте магазина не хватило денег, сумма осталась на счёте. Дождитесь, когда на счёте будет нужная сумма, и создайте новый возврат с новым ключом идемпотентности. Остаток счёта виден в личном кабинете на странице «Обзор», через API его не узнать.
  • "party": "refund_network" — возврат отклонил банк или платёжная система. Сумма вернётся на счёт магазина, но до 3 дней может быть в резерве. Напишите в поддержку: [email protected], укажите id возврата.
  • Другие значения — напишите в поддержку: [email protected], укажите id возврата.

Все значения — в разделе Кто отменил возврат.

Деньги​

  • Со счёта магазина списывается вся сумма возврата. Комиссия AvantPay за платёж не возвращается.
  • Если на счёте не хватает денег, API всё равно примет возврат, а потом возврат перейдёт в canceled с причиной insufficient_funds.

Ключ идемпотентности​

  • Один возврат — один ключ. Создайте ключ, когда решили вернуть деньги, и сохраните его до запроса.
  • Нет ответа, таймаут, ответ 500 или 429 — повторите запрос с тем же ключом и тем же телом. Придёт тот же возврат, второго не будет.
  • Если это повтор после таймаута или ответа 500 и пришла ошибка 400, 401 или 403, возврат мог создаться первым запросом. Ключ не меняйте: исправьте причину и повторите запрос с тем же ключом. Ошибка ключ не занимает: повтор вернёт уже созданный возврат или создаст его сейчас. Или найдите возврат в списке возвратов по платежу по вашему metadata.refund_number. Новый ключ — только если там этого возврата нет.
  • Новый ключ — только для нового возврата. Если повторить запрос с новым ключом, покупатель может получить деньги дважды.
  • Тот же ключ с другим телом или позже чем через 24 часа — ошибка 400 с "parameter": "Idempotence-Key". Это значит, что возврат с этим ключом уже создан: найдите его в списке возвратов по платежу и не создавайте новый.

Подробнее — в разделе Идемпотентность.

Частые ошибки​

ОтветЧто не так
400, "parameter": "payment_id"Платёж нельзя вернуть сейчас: он не оплачен, уже возвращён полностью, по нему выполняется другой возврат или по нему уже 10 возвратов. В коде не разбирайте description: покажите его сотруднику или запишите в лог. Причину определяйте по платежу — как.
400, "parameter": "amount.value"Сумма больше остатка, меньше 1 ₽ или в неверном формате.
400, "parameter": "Idempotence-Key"Нет ключа или он длиннее 64 символов. Или возврат с этим ключом уже создан, а тело запроса другое или прошло больше 24 часов: найдите возврат в списке возвратов по платежу и не создавайте новый.
403 forbiddenУ ключа нет права «Возвраты» или запрос пришёл с IP-адреса, которого нет в списке ключа. Напишите в поддержку.
404, "parameter": "payment_id"Платежа с таким id нет у вашего магазина.

Все ошибки — в справочнике: Создать возврат.