Skip to main content

Webhooks

Webhooks позволяют получать уведомления об изменении статуса платежей в реальном времени.

Настройка

При создании платежа укажите:

  • notify_url — URL для получения уведомлений
  • notification_token — токен для валидации (опционально)

Заголовки webhook

ЗаголовокОписание
Content-Typeapplication/json
X-Webhook-EventТип события (payment.status_changed)
X-SignatureHMAC-SHA256 подпись тела запроса
X-Notification-TokenВаш токен из notification_token (если был передан)
Валидация через Notification Token

Если при создании платежа вы передали notification_token, он вернётся в заголовке X-Notification-Token. Сравните его с ожидаемым значением для быстрой валидации без вычисления подписи.

Формат webhook

{
"event": "payment.status_changed",
"paymentId": "550e8400-e29b-41d4-a716-446655440000",
"ext_id": "order_12345",
"status": "COMPLETED",
"amount": 5000,
"currency": "RUB",
"timestamp": "2026-01-30T12:22:00Z"
}

События

СобытиеСтатусОписание
payment.status_changedCOMPLETEDПлатёж успешно завершён
payment.status_changedCANCELLEDПлатёж отменён
payment.status_changedCOMPLETED_APPEALАпелляция одобрена
payment.status_changedCANCELLED_APPEALАпелляция отклонена
payment.status_changedDISPUTEОткрыт спор по платежу

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

Заголовок X-Signature содержит HMAC-SHA256 подпись тела запроса (hex).

JavaScript

const crypto = require('crypto');

function verifyWebhook(body, signature, secretKey) {
const expectedSignature = crypto
.createHmac('sha256', secretKey)
.update(JSON.stringify(body))
.digest('hex');

return signature === expectedSignature;
}

app.post('/webhook', (req, res) => {
// Способ 1: Проверка через notification_token (быстро)
const token = req.headers['x-notification-token'];
if (token && token === expectedToken) {
// Валидация пройдена
}

// Способ 2: Проверка через подпись (надёжно)
const signature = req.headers['x-signature'];
if (!verifyWebhook(req.body, signature, secretKey)) {
return res.status(401).send('Invalid signature');
}

const { event, paymentId, status } = req.body;
console.log(`${event}: Payment ${paymentId} is ${status}`);

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

Python

import hmac
import hashlib
import json

def verify_webhook(body, signature, secret_key):
expected_signature = hmac.new(
secret_key.encode(),
json.dumps(body).encode(),
hashlib.sha256
).hexdigest()

return signature == expected_signature

PHP

function verifyWebhook($body, $signature, $secretKey) {
$expectedSignature = hash_hmac(
'sha256',
json_encode($body),
$secretKey
);

return hash_equals($expectedSignature, $signature);
}

Требования к серверу

  1. HTTP 200 OK — webhook считается доставленным при получении HTTP 200
  2. Таймаут — ответ должен быть получен в течение 10 секунд
  3. Идемпотентность — корректно обрабатывайте повторные доставки

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

При неудачной доставке система повторит отправку:

ПопыткаЗадержка
1Сразу
260 секунд
360 секунд

После 3 неудачных попыток webhook помечается как недоставленный.