S
docs.syncra.money
API ReferenceMerchant API

Обратный вызов (Callbacks / Webhooks)

Получение и проверка подлинности серверных уведомлений о статусах платежей и выплат в Syncra V2

Серверные уведомления (Callbacks / Webhooks)

Для информирования вашей системы о смене статусов транзакций (например, об успешном завершении оплаты клиентом или о завершении перевода выплаты трейдером) шлюз Syncra V2 отправляет асинхронные HTTP POST-запросы на указанный вами адрес обратного вызова (Callback URL).


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

Тело уведомления передается в формате JSON и содержит подробную информацию о событии и сделке:

{
  "event": "deal.completed",
  "deal_id": "7ac148fe-19a3-45bb-b992-019fac55b721",
  "merchant_id": "8f870a31-b88d-4cb0-a882-628d08cbda88",
  "tenant_id": "550e8400-e29b-41d4-a716-446655440000",
  "amount": 250050,
  "currency": "RUB",
  "status": "COMPLETED",
  "timestamp": "2026-07-12T17:24:12Z"
}

Типы событий (event)

Имя событияОписание события
deal.completedУспешное завершение входящего платежа (PayIn) или выплаты (PayOut).
deal.failedОшибка проведения платежа или выплаты (переход в финальный неуспешный статус).
dispute.createdПо транзакции мерчанта был открыт спор (диспут).
dispute.resolvedСпор по транзакции был успешно урегулирован.
withdrawal.completedЗаявка на криптографический вывод средств (USDT) выполнена в блокчейне.

Типы уведомлений в адаптере (V1 Compatibility)

Если вы используете legacy-интеграцию V1 через Compatibility Adapter, формат уведомлений будет соответствовать спецификации V1:

{
  "failures": [],
  "value": {
    "type": 1,
    "paymentId": "7ac148fe-19a3-45bb-b992-019fac55b721",
    "status": 11,
    "amount": "2500.50",
    "currency": 643,
    "salt": 4729103
  },
  "isSuccess": true,
  "isFailure": false
}

Маппинг типов уведомлений V1 (type)

  • 1 — Входящий платеж (PayIn Callback)
  • 2 — Исходящий платеж (PayOut Callback)
  • 10 — Криптографический вывод средств (Withdrawal Callback)

Верификация подписи Webhook

Чтобы злоумышленники не могли отправить фальшивые уведомления на ваш сервер, шлюз подписывает каждый запрос. Сигнатура передается в HTTP-заголовке:

  • В V2 API: X-Syncra-Signature: t={timestamp},v1={hmac_sha256_hex}
  • В legacy V1 API: SIGNATURE (содержит HMAC-SHA512 от строки {startOfDayUTC};{salt})

КРИТИЧЕСКАЯ ОСОБЕННОСТЬ V1 CALLBACK: В legacy-вебхуках V1 временная метка подписи формируется строго как начало текущих суток в UTC (полночь, 00:00:00). Формула подписи: timestamp = DateTime.UtcNow.Date.ToUnixTimestamp() signature = HMACSHA512(timestamp + ";" + salt, merchantSecret) Если вы обрабатываете вебхуки через V1 адаптер, проверяйте подпись строго по этой формуле с округлением времени до начала дня.

Пример верификации подписи V2 (Node.js)

const crypto = require('crypto');

function verifyV2Webhook(rawBody, signatureHeader, webhookSecret) {
  // 1. Парсинг заголовка
  const parts = signatureHeader.split(',');
  const timestampPart = parts.find(p => p.startsWith('t='));
  const signaturePart = parts.find(p => p.startsWith('v1='));
  
  if (!timestampPart || !signaturePart) return false;
  
  const timestamp = timestampPart.substring(2);
  const providedSignature = signaturePart.substring(3);
  
  // 2. Проверка возраста метки времени (защита от replay-атак)
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
    return false; // Запрос старше 5 минут
  }
  
  // 3. Вычисление ожидаемой сигнатуры
  const payload = `${timestamp}.${rawBody}`;
  const expectedSignature = crypto
    .createHmac('sha256', webhookSecret)
    .update(payload)
    .digest('hex');
    
  // 4. Безопасное сравнение строк во избежание timing attacks
  return crypto.timingSafeEqual(
    Buffer.from(providedSignature, 'utf-8'),
    Buffer.from(expectedSignature, 'utf-8')
  );
}

Правила обработки вебхуков (Best Practices)

  1. Возвращайте HTTP 200 быстро: Ваш обработчик должен сразу возвращать статус 200 OK с телом {"status":"success"}. Не выполняйте тяжелую бизнес-логику внутри HTTP-потока вебхука. Сначала сохраните событие в очередь задач (очередь сообщений или базу данных), верните ответ 200, а затем обрабатывайте задачу асинхронно.
  2. Используйте идемпотентность: Всегда проверяйте, не обрабатывали ли вы транзакцию с данным deal_id (или paymentId в V1) ранее. Одно и то же уведомление может прийти повторно из-за сбоев сети.
  3. Политика повторных попыток (Retry Policy): Если ваш сервер возвращает ошибку (статус отличный от 2xx) или не отвечает в течение 10 секунд, Syncra запускает повторную отправку уведомления.
    • Попытки повторяются с экспоненциальной задержкой (Exponential Backoff): через 10 секунд, 1 минуту, 5 минут, 15 минут, 1 час.
    • Максимальное число попыток по умолчанию — 5.
  4. IP Whitelisting: Для дополнительного уровня защиты вы можете ограничить прием вебхуков только со списков IP-адресов шлюза Syncra. Актуальный список адресов можно получить в панели управления.

On this page