Тестирование вебхуков: интеграция, которая переживает повтор, задержку и подделку
Вебхук — это чужой сервис, который в непредсказуемый момент присылает вам событие, иногда дважды, иногда не в том порядке, иногда поддельное. Большинство интеграций проверяют на «пришло — обработали». Дефекты живут в остальных случаях, и именно они создают двойные заказы и зависшие статусы.
Что такое вебхук и почему он ненадёжен по природе
Вебхук — HTTP-запрос, который внешний сервис отправляет на ваш адрес при событии: оплата прошла, доставка изменила статус, подписка продлилась. Отправитель не знает, получили ли вы запрос, поэтому повторяет его при любом сомнении: таймаут, ошибка сети, ваш ответ с кодом ошибки. Отсюда три свойства, с которыми приходится жить: одно событие может прийти несколько раз, события могут приходить не в порядке возникновения, и любой может прислать запрос на ваш адрес, если не проверять подпись.
Чек-лист проверок
- Идемпотентность: одно и то же событие, доставленное дважды и трижды, обрабатывается один раз — по идентификатору события, а не по времени получения.
- Порядок: событие «оплата отменена» пришло раньше «оплата создана» — статус в итоге верный, а не затёртый более старым событием.
- Подпись: запрос с неверной или отсутствующей подписью отклоняется и логируется; запрос с правильной подписью, но истёкшей меткой времени — тоже.
- Таймаут ответа: ваш обработчик отвечает быстро и подтверждает приём, а тяжёлую работу выполняет позже; иначе отправитель считает доставку неудачной и повторяет.
- Ошибки обработки: временная ошибка базы на вашей стороне не теряет событие — оно уходит в очередь на повтор, а не в никуда.
- Недоставка: событие не пришло вовсе — есть ли сверка по расписанию, которая это обнаружит.
- Изменение формата: отправитель добавил поле или изменил версию — обработчик не падает на неизвестных полях.
- Нагрузка: сотни событий за минуту при акции — очередь и база выдерживают, порядок обработки не ломается.
Как это проверять на практике
- Собрать коллекцию запросов в Postman или аналоге: по одному примеру каждого события от реального отправителя, с подписью.
- Отправлять их вручную и скриптом в тестовый стенд: по одному, дважды подряд, в обратном порядке, с испорченной подписью, с устаревшей меткой времени.
- Проверять не ответ обработчика, а состояние системы после: статус заказа, записи в базе, отправленные уведомления, записи в логе.
- Эмулировать отказ своей стороны: остановить базу или очередь в момент приёма и убедиться, что событие не потеряно.
- Сверка: сравнить список событий на стороне отправителя со списком обработанных за период.
Типичные дефекты
Двойной заказ после повторной доставки вебхука об оплате. Заказ в статусе «оплачен» после отмены, потому что события обработали в порядке получения. Пуш «оплата прошла», отправленный дважды. Обработчик, который делает запрос к внешнему API внутри приёма вебхука и не укладывается в таймаут отправителя. Подпись, которая проверяется только в продакшене, потому что на тестовом стенде её «временно отключили». Все они проявляются не на тестовом прогоне, а в пик нагрузки — когда повторов и задержек больше всего.
Интеграции в обратную сторону
Те же принципы работают, когда вы сами вызываете внешний API: таймауты и ретраи с увеличивающимся интервалом, идемпотентные ключи при создании платежей и заказов, обработка лимитов запросов, поведение при изменении контракта. Регрессионный набор по исходящим интеграциям собирается тем же способом и прогоняется по тому же расписанию.
Частые вопросы
Нужен ли реальный отправитель для тестов?
Как проверить идемпотентность, если идентификатора события нет?
Как часто повторять набор?
Можно ли это автоматизировать?
Расскажите о задаче
Ответим в течение одного рабочего дня, оценку пришлём за 1–2 дня. Бесплатно.