Вебхук доходит до сайта, но обработчик отклоняет его с ошибкой подписи? Сначала проверьте три вещи: секрет именно этого endpoint, заголовок подписи и исходное тело запроса до разбора JSON. Успешное открытие сайта не подтверждает исправность этого обработчика.
HMAC связывает сообщение с общим секретом. Если провайдер подписывает исходные байты, одинаковые по смыслу JSON-документы могут иметь разные подписи: пробелы, порядок полей и перенос строки меняют входные данные. Отключать проверку ради восстановления доставки нельзя.
1. Отделите отказ подписи от ошибки доставки
Найдите одну неуспешную попытку в кабинете отправителя и соответствующий запрос в журнале приложения. Сопоставьте время с часовым поясом, маршрут, HTTP-код и внутренний идентификатор трассировки.
Если запрос не дошёл до обработчика, сначала разбирайте DNS, TLS, маршрутизацию или ограничения доступа. Если приложение зафиксировало именно отказ проверки подписи, переходите к входным данным проверки; один код 400 или 403 ещё не доказывает причину.
Не сохраняйте полный payload, секрет или заголовок подписи в общий журнал. Для первичной диагностики достаточно этапа отказа, длины тела и версии конфигурации без её значений.
2. Сверьте контракт конкретного провайдера
Запишите для разработчика короткую карточку проверки:
- какое имя заголовка используется;
- какой алгоритм и формат результата нужны: hex или Base64;
- подписывается только тело или составная строка с дополнительными полями;
- какой секрет назначен этому адресу и окружению;
- предусмотрены ли версия подписи и проверка времени.
Например, GitHub передаёт HMAC-SHA256 в заголовке X-Hub-Signature-256 с префиксом sha256=. Сравнение выполняют функцией с постоянным временем, а не обычным оператором равенства. Это описано в документации проверки доставок GitHub.
Не переносите этот формат на другого отправителя. Секрет вебхука также не следует автоматически считать API-ключом: сверяйте назначение через штатное хранилище секретов, не выводя значение в консоль или переписку.
3. Найдите место, где изменилось тело
Проследите путь запроса: входной прокси → middleware приложения → обработчик подписи → JSON-парсер. Для схемы с подписью raw body проверяющий код должен получить неизменённое тело, а бизнес-обработчик — уже проверенные данные.
Показательный тест: {"ok":true} и { "ok": true } дают одинаковый объект после разбора JSON, но это разные последовательности байтов. Повторная сериализация объекта не восстанавливает исходный запрос.
Проверьте, не происходит ли до верификации:
- разбор JSON с последующей сборкой строки;
- удаление пробелов или завершающего переноса;
- изменение кодировки или экранирования Unicode;
- чтение потока другим компонентом без сохранения исходного тела.
Stripe отдельно описывает изменение тела фреймворками и различие секретов endpoint, созданного в кабинете, и доставки через CLI. Для Express порядок подключения JSON-middleware имеет значение. См. разбор ошибок подписи Stripe.
Для сравнения этапов используйте искусственный payload в тестовом окружении: сопоставьте длину и байты до и после middleware. Не копируйте боевые сообщения с персональными данными в публичные сервисы вычисления HMAC.
4. Разделите ошибки по воспроизводимости
Если не проходит даже официальный тестовый пример провайдера, проверьте реализацию алгоритма, состав подписываемой строки и кодирование результата. Предпочтителен поддерживаемый SDK: самописный разбор заголовка легко расходится с контрактом.
Если пример проходит, а доставка в приложение нет, исследуйте маршрут и обработку тела. Если сбой появляется только после релиза или на части экземпляров приложения, сравните версии кода и конфигурации этих экземпляров, включая завершение ротации секрета.
Если контракт проверяет timestamp, отдельно сверяйте часы сервера и допустимый возраст сообщения. Старый сохранённый запрос может не пройти такую проверку даже с правильной подписью; расширять окно наугад нельзя.
5. Подтвердите исправление без побочных действий
Проведите проверку на изолированном стенде, где обработчик не создаёт реальные заказы и не отправляет письма:
- корректная тестовая доставка проходит;
- изменение одного байта тела приводит к отказу;
- отсутствие подписи и неверный секрет приводят к отказу;
- отклонённое сообщение не меняет бизнес-данные;
- повтор принятого события не выполняет действие второй раз.
Подлинность сообщения и безопасность повторов — разные задачи. После успешной проверки подписи остаётся защитить состояние от дублей и запоздалых событий: этому посвящён материал о порядке обработки вебхуков.
Когда нужна помощь
Web-Puls помогает контролировать доступность сайта, но обычная внешняя HTTP-проверка не воспроизводит подписанную доставку провайдера. Для этого нужны тест обработчика и наблюдение за результатами приёма событий.
Если место изменения тела найти не удалось, отправьте заявку на диагностику: укажите провайдера, публичный адрес без секретных параметров, время ошибки, HTTP-код и недавние изменения. Команда поддержки оценит задачу и предложит формат работ; секреты, подписи и персональные payload в заявку не включайте.