Webhook должен быть идемпотентным

Провайдер может повторить событие из-за timeout или неуспешного HTTP-кода. Храните уникальный event_id с UNIQUE-ограничением и возвращайте 2xx повтору без повторной бизнес-операции.

Правильный порядок обработки

ШагДействие
1прочитать raw body
2проверить подпись по документации сервиса
3разобрать JSON
4получить event_id
5проверить, не обработан ли он ранее
6
ранить событие/поставить в очередь
7быстро вернуть 2xx
8
ронно

Каркас webhook с HMAC

PHP
$raw = file_get_contents('php://input');
$secret = getenv('WEBHOOK_SECRET');

$received = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$expected = hash_hmac('sha256', $raw, $secret);

if (!$received || !hash_equals($expected, $received)) {
    http_response_code(401);
    exit('invalid signature');
}

$event = json_decode($raw, true);
$eventId = (string)($event['id'] ?? '');

if ($eventId === '') {
    http_response_code(400);
    exit('missing event id');
}

// Проверить eventId в БД.
// Если уже обработан — вернуть 200.
// Иначе сохранить событие и поставить в очередь.

http_response_code(200);
echo 'ok';

Не придумывайте формат подписи сами

Заголовок, алгоритм, кодировка и строка для подписи отличаются у сервисов. Используйте HMAC-пример только как каркас и сверяйте его с документацией конкретного API.

Почему надо отвечать быстро

Если внутри webhook ждать CRM, отправку почты и десяток SQL-запросов, провайдер может посчитать доставку неуспешной и отправить событие повторно. Быстрый приём + очередь надёжнее.

Что логировать

ПолеМожно
event_idда
event_typeда
received_atда
status/attemptsда
HTTP status providerда
секрет/токеннет
полные платёжные реквизитынет
лишние персональные данныенет

Скачать примеры для веб-разработки

RuJul Web Development Examples — один ZIP

Связанные материалы

Безопасная обработка webhook

Сервер должен проверять подлинность входящего события по механизму провайдера, ограничивать размер тела запроса и не выполнять произвольные команды из полученных данных. Сохраняйте идентификатор события и не обрабатывайте один и тот же webhook дважды; доставка «как минимум один раз» — распространённое поведение внешних сервисов.

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