Payment Docs
Возвраты

Webhook-уведомления по возвратам

Подписанные уведомления об изменении статуса возвратов

При каждом изменении статуса возврата после его создания мы отправляем подписанный POST-запрос. Опрос GET /v1/refunds/{refundId} — резервный способ, а не замена.

Адрес отправки уведомлений

Адрес определяется в следующем порядке:

  1. callbackUrl, переданный в теле запроса POST /v1/refunds: применяется только к этому возврату;
  2. callbackUrl заказа, по которому сделан возврат;
  3. callbackUrl из настроек мерчанта;
  4. если не задано ни одно из значений, уведомления по возврату не отправляются.

Требования к callbackUrl

ТребованиеЗначение
Схемаhttp или https
Длинадо 2048 символов
Валидациянекорректный URL → 400 Validation failed

Условия отправки уведомлений

Уведомление формируется при каждом изменении статуса после создания возврата. Начальный статус (MANUAL, PENDING или FAILED) не отправляется: он возвращается в ответе на POST /v1/refunds.

Когда возврат переходит в COMPLETED, заказ переходит в статус REFUND, поэтому приходит и уведомление по заказу с X-Type: ORDER_UPDATE. Если платформа позже переведёт завершённый возврат в другой статус, заказ вернётся в COMPLETED, и вы получите уведомления об обоих изменениях.

Ваш менеджер также может повторно отправить уведомление вручную. Дублирующиеся записи исключаются по совокупности адреса, ID возврата и статуса среди неотправленных уведомлений.

Формат уведомления

POST {callbackUrl}
Content-Type: application/json
X-Type: REFUND_UPDATE
X-Signature: HMAC-SHA512(тело запроса, API-токен) в формате hex

Тело

{
  "id": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
  "orderId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5c",
  "orderExternalId": "order_1234",
  "externalId": "refund-123",
  "status": "COMPLETED",
  "amount": "1000.5",
  "currency": "RUB",
  "debitAmount": "1000.5",
  "debitCurrency": "RUB",
  "reason": "Запрос покупателя",
  "merchantId": "0199a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5e",
  "createdAt": "2026-09-23T12:34:56.000Z",
  "updatedAt": "2026-09-23T12:41:03.512Z",
  "completedAt": "2026-09-23T12:41:03.512Z"
}
ПолеТипОписание
idstring (UUID)ID возврата
orderIdstring (UUID)ID заказа, по которому сделан возврат
orderExternalIdstring / nullexternalId заказа
externalIdstring / nullID возврата в вашей системе
statusstringТекущий статус, см. Статусы возвратов
amountstringСумма, возвращаемая плательщику, в валюте заказа
currencystringВалюта заказа
debitAmountstringСумма списания с вашего баланса
debitCurrencystringВалюта баланса, с которого списывается возврат
reasonstring / nullПричина возврата
merchantIdstring (UUID)ID вашего мерчанта
createdAtstringВремя создания
updatedAtstringВремя последнего обновления
completedAtstring / nullВремя завершения

Проверка подписи

Каждое уведомление содержит заголовок X-Signature: HMAC-SHA512-хеш исходного тела запроса в формате hex, вычисленный с вашим API-токеном в качестве секрета. Та же схема используется для webhook-уведомлений по платежам и выплатам.

import crypto from "crypto";

// Ваш API-токен используется как секрет для HMAC
const apiToken = process.env.API_TOKEN;

app.post("/webhooks/payments", (req, res) => {
  const signature = req.headers["x-signature"];
  const body = JSON.stringify(req.body);

  // Считаем HMAC-SHA512 от тела запроса и сравниваем в HEX
  const expected = crypto.createHmac("sha512", apiToken).update(body).digest("hex");

  if (expected !== signature) {
    return res.status(403).send("Invalid signature");
  }

  // Подпись верна — обрабатываем уведомление идемпотентно
  const data = req.body;
  if (data.status === "COMPLETED") {
    console.log(`Заказ ${data.externalId} оплачен`);
  }

  res.status(200).send("OK");
});

Если один endpoint получает уведомления разных видов, различайте их по заголовку X-Type: ORDER_UPDATE, PAYOUT_UPDATE или REFUND_UPDATE.

Политика повторных отправок

ПараметрЗначение
Количество попытокдо 30
Интервал30s × 2^n, но не более 30 минут
Критерий успехаHTTP-статус 200–399

Дополнительно применяется circuit breaker: адрес, стабильно возвращающий ошибки, временно исключается из доставки.

Рекомендации по работе с webhook-уведомлениями

  • Всегда отвечайте кодом HTTP 200, чтобы подтвердить получение. Если ваш сервер не отвечает, мы повторяем отправку уведомления.
  • Проверяйте заголовок X-Signature перед обработкой тела запроса.
  • Обрабатывайте уведомления идемпотентно: одно и то же уведомление может быть доставлено несколько раз.
  • Сопоставляйте уведомление с вашими записями по externalId, а не по сумме.
  • Обрабатывайте все возможные значения статусов, включая неуспешные.

Смотрите также

На этой странице