Вебхуки без магии: подпись, повторы и дедупликация
Чеклист для webhook-интеграций: как договориться о подписи события, повторах, дедупликации, статусах и диагностике до разработки.
Что такое вебхук в рабочем смысле
Вебхук - это не просто “внешняя система дергает наш URL”. Это договоренность о событии: какая сторона сообщает о факте, как она подтверждает подлинность сообщения, как повторяет доставку и как получатель отличает новое событие от дубля.
Без этих договоренностей вебхук быстро становится неуправляемым: событие пришло дважды, подпись не проверяется, таймаут приводит к повтору, а система не понимает, обработала она факт или только получила похожее сообщение.
sequenceDiagram
participant External as Внешняя система
participant Hook as Webhook endpoint
participant Store as Состояние операции
External->>Hook: Отправляет событие
Hook->>Hook: Проверяет подпись и replay
alt Подпись не прошла
Hook-->>External: Reject и диагностика
else Дубль или неизвестная операция
Hook->>Store: Проверяет event id и operation id
Hook-->>External: ACK или ручной разбор
else Новый допустимый статус
Hook->>Store: Обновляет статус и сохраняет event id
Hook-->>External: ACK
end
1. Событие и его смысл
Сначала нужно описать не endpoint, а событие:
- что именно произошло во внешнем контуре;
- является ли событие финальным результатом или промежуточным статусом;
- может ли событие прийти повторно;
- может ли событие прийти не по порядку;
- какие поля обязательны для обработки;
- где находится источник истины по статусу;
- что делать, если событие не совпадает с текущим состоянием операции.
Если событий несколько, их полезно описывать как словарь: имя события, причина появления, обязательные данные, допустимые переходы статуса.
2. Подпись и доверие
Получатель должен понимать, что событие пришло от ожидаемой стороны и не было изменено по дороге.
До разработки нужно договориться:
- чем подписывается сообщение;
- какие поля входят в подпись;
- как передается timestamp или nonce;
- как защищаться от повторного воспроизведения старого сообщения;
- как ротируются ключи или сертификаты;
- что логируется при ошибке подписи;
- чем отличается ошибка подписи от ошибки формата.
Подпись не заменяет бизнес-проверку. Даже корректно подписанное событие нужно сопоставить с известной операцией, текущим статусом и правилами перехода.
3. Повторы доставки
Вебхуки часто повторяются не потому, что внешняя сторона “сломалась”, а потому что она не получила подтверждение доставки.
Нужно заранее зафиксировать:
- какой ответ считается успешным приемом события;
- через какие интервалы возможны повторы;
- сколько попыток допустимо;
- что происходит после исчерпания попыток;
- можно ли запросить повтор вручную;
- кто видит событие, которое не удалось доставить или обработать;
- нужен ли отдельный dead-letter или очередь ручного разбора.
Если получатель вернул успех до реальной обработки, нужно понимать, где теперь находится ответственность за дальнейший сбой.
4. Дедупликация
Дедупликация отвечает на вопрос: “мы уже видели это событие или это новая операция?”
Минимально нужны:
- event id;
- operation id или внешний идентификатор процесса;
- тип события;
- время события;
- правило хранения обработанных идентификаторов;
- правило поведения при повторе уже обработанного события;
- отдельная диагностика для события с тем же id, но другим содержимым.
Дубль не должен повторно запускать побочный эффект: списание, отправку уведомления, смену финального статуса или ручную задачу.
5. Документация контракта
Webhook-контракт можно описывать в AsyncAPI, OpenAPI с отдельным разделом callbacks или в короткой внутренней схеме. В любом варианте должны быть видны:
- список событий;
- формат payload;
- правила подписи;
- правила ответов получателя;
- повторы и дедупликация;
- статусы обработки;
- тестовые примеры без чувствительных данных.
Для команды важнее не нотация, а возможность проверить сценарий: валидное событие, неверная подпись, дубль, событие не по порядку, таймаут обработки.
Приемочный чеклист
Перед запуском webhook-интеграции проверьте:
- валидное событие меняет ожидаемый статус;
- повтор события не создает второй побочный эффект;
- событие с неверной подписью отклоняется и диагностируется;
- старое событие не проходит replay-проверку;
- событие без известной операции не ломает процесс;
- события не по порядку обрабатываются по правилу, а не случайно;
- поддержка может найти событие по event id и operation id;
- чувствительные данные не попадают в публичные примеры и лишние логи.
Если webhook влияет на деньги, доступ, договор, заявку или другой значимый процесс, эти проверки нужно считать частью MVP, а не улучшением “когда будет время”.