Payment Docs
Выплаты

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

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

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

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

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

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

Адрес фиксируется в момент создания выплаты. Последующее изменение настроек мерчанта не переносит уведомления по уже созданной выплате на новый адрес.

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

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

Поле возвращается в объекте выплаты. Значение null означает, что используются настройки мерчанта.

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

Уведомление формируется при каждом изменении статуса, за тремя исключениями:

  • CREATED: уведомление не отправляется;
  • COMPLETED: уведомление ставится в очередь в рамках транзакции завершения выплаты, когда известна итоговая комиссия;
  • ручная смена статуса выплаты COMPLETED из-за ошибки на стороне банка: уведомление отправляется по запросу, обратитесь к вашему менеджеру.

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

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

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

Тело

{
  "id": "0198c3f1-2a4b-7c3d-9e0f-1a2b3c4d5e6f",
  "status": "COMPLETED",
  "amount": "1000.5",
  "fee": "60",
  "currency": "RUB",
  "type": "C2C",
  "note": null,
  "externalId": "payout-123",
  "merchantId": "0198c3f1-1111-7222-8333-444455556666",
  "settlementCurrency": "USD",
  "settlementAmount": "11.28",
  "createdAt": "2026-07-29T10:00:00.000Z",
  "completedAt": "2026-07-29T10:04:12.317Z"
}
ПолеТипОписание
idstring (UUID)ID выплаты
statusstringТекущий статус, см. Статусы выплат
amountstringСумма выплаты
feestringКомиссия за выплату
currencystringВалюта выплаты
typestringТип платежа
notestring / nullЗаметка к выплате
externalIdstring / nullID выплаты в вашей системе
merchantIdstring (UUID)ID вашего мерчанта
settlementCurrencystring / nullВалюта расчётов
settlementAmountstring / nullСумма в валюте расчётов
createdAtstringВремя создания
completedAtstring / nullВремя завершения

callbackUrl не включается в тело: он определяет адрес доставки и не является частью состояния выплаты.

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

Каждое уведомление содержит заголовок 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: PAYOUT_UPDATE.

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

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

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

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

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

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

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