Webhooks в интеграциях: доставка событий, повторы и восстановление
Webhooks для интеграций: контракт событий, подпись, повторы, порядок и восстановление. Как обработать ошибки и проверить доставку без дублей.
Webhook помогает одной системе сообщить другой о событии: заказ создан, документ изменён, платёж подтверждён. Но отправленный HTTP-запрос ещё не означает выполненную бизнес-операцию. Получатель должен проверить источник, сохранить событие, обработать повторы и объяснить ошибки. Для интеграции важно заранее согласовать контракт и восстановление, иначе редкий сетевой сбой превращается в потерянный заказ или дубль. Разберём устройство надёжного обмена через webhooks для CRM, учётной системы, сайта и внешнего сервиса. Материал адресован владельцу продукта и технической команде. Примеры контрактов условные и не являются схемой конкретного поставщика. Для каждого реального API необходимо проверять его документацию, версии и условия доставки. Что такое webhook Webhook — способ уведомления, при котором источник отправляет запрос на согласованный адрес получателя после определённого события. Контракт определяет формат, подтверждение, защиту и повторы. Надёжная интеграция различает приём сообщения и завершение бизнес-действия, сохраняет идентификатор события и имеет путь восстановления после сбоя. Не путайте событие и команду. Событие сообщает о произошедшем факте; команда просит выполнить действие. Если сообщение «заказ создан» используется как команда создать документ, нужно определить связь и защиту от повторов. Получатель должен понимать, что уже подтверждено источником и что ему ещё предстоит сделать. Webhook не гарантирует автоматически мгновенную доставку, единственный вызов или нужный порядок. Эти свойства зависят от поставщика и контракта. Продуктовая команда должна знать допустимую задержку и поведение при недоступности. Слово «реальное время» без условий не является достаточным техническим заданием. Webhook или периодический опрос Webhook подходит, когда источник умеет отправлять события и есть управляемый получатель. Опрос полезен, когда такого механизма нет либо нужна регулярная сверка. Часто оба подхода сочетаются: событие запускает обработку, а сверка помогает обнаружить пропущенное состояние. Выбор зависит от возможностей API и последствий потери. Учебный пример: сервис получает уведомления об изменении документа, затем запрашивает актуальную запись по API. Это позволяет отделить сигнал от получения состояния. Но запрос должен учитывать версию и доступность: позднее уведомление может относиться к уже изменённому объекту. Нужно знать, требуется ли обработать каждое событие или только привести проекцию к актуальному состоянию. Подход Что проверить Ограничение Webhook Формат, защита, повторы и наблюдаемость Зависимость от условий отправителя Опрос Фильтр изменений, лимиты и полнота ответа Задержка и нагрузка запросов Сверка состояния Сопоставление и исправление расхождений Не заменяет историю каждой операции Сочетание Единая модель и отсутствие дублей Дополнительная сложность сопровождения Не добавляйте второй механизм без причины. Он должен закрывать конкретную неопределённость, например пропущенное событие или восстановление после долгого простоя. Если оба пути независимо создают одну операцию без общего ключа, сочетание увеличит риск дублей. Контракт события Контракт должен иметь тип, идентификатор, связь с объектом, время и версию формата там, где они нужны. Для изменения полезно знать версию объекта или другое основание порядка. Состав данных должен быть достаточным для обработки, но не избыточным. Не передавайте весь клиентский профиль, если получателю нужен только статус заказа. Условный пример ниже показывает идею разделения полей. Идентификатор события относится к доставке одного факта, идентификатор объекта — к бизнес-сущности, версия — к состоянию. Эти понятия нельзя заменять одним случайным номером. Реальная схема определяется API и не обязана совпадать с образцом. { "eventId": "example-event", "type": "order.updated", "schemaVersion": "example-v1", "objectId": "example-order", "objectVersion": 3, "data": { "status": "confirmed" } } Опишите обязательность и тип каждого поля, неизвестные значения и дополнительные свойства. Если появляется новый статус, получатель должен иметь безопасное поведение. Молчаливое преобразование неизвестного значения в «завершено» опасно. Версионирование и обработка ошибок должны быть частью контракта до запуска. Приём сообщения и бизнес-подтверждение Получатель должен понимать, когда он может подтвердить приём. Если событие не сохранено и обработка ещё не завершена, положительный ответ может привести к потере после сбоя. Если вся тяжёлая работа выполняется до ответа, источник может получить тайм-аут и повторить запрос. Выберите управляемую границу по возможностям архитектуры. Один подход — проверить запрос и устойчиво сохранить событие, затем обработать его отдельно. Но сохранение должно действительно обеспечивать продолжение после перезапуска. Очередь в памяти не даёт такого подтверждения. Другой подход возможен для небольшого действия, если контракт и условия позволяют его безопасно завершить. В документации Stripe по webhooks описаны проверка подписи, быстрый ответ и особенности событий. Это пример конкретного поставщика, который полезно изучить перед его интеграцией. Правила другого API могут отличаться; нельзя переносить заголовки, формат и график повторов по аналогии. Продуктовый статус хранится отдельно от технического. «Событие принято» не означает «заказ исполнен». Оператор должен видеть этап и причину ожидания. Если действие завершилось ошибкой после приёма, нужен путь исправления без требования, чтобы отправитель обязательно прислал всё снова. Проверка источника Получатель должен проверять, что запрос соответствует согласованному источнику и формату. Конкретный механизм определяется поставщиком: подпись, ключ, сертификат или другой предусмотренный способ. Публичный адрес и необычное имя пути сами по себе не подтверждают происхождение сообщения. Проверяйте ограничения размера и допустимые типы до затратной обработки. Неизвестный формат не должен приводить к частичной бизнес-операции. Секреты хранятся в предназначенном для этого контуре, а не в исходном коде и журнале. Процедура замены должна учитывать оба конца интеграции. Учебный тест: запрос имеет правильную структуру, но недопустимое подтверждение источника. Система должна отказать без изменения заказа. Затем проверяют настоящий тестовый запрос поставщика и сценарий замены ключа. Это отделяет формальную проверку наличия заголовка от реальной валидации. Если контракт содержит защиту от повторного воспроизведения старого запроса, реализуйте её по документации и проверьте условия времени. Не выдумывайте универсальное окно без понимания доставки. Недопустимый запрос должен быть наблюдаемым в безопасном объёме, не сохраняя открытые секреты. Идемпотентность Повтор одного события не должен создавать вторую операцию, если контракт описывает один факт. Получатель сохраняет устойчивую связь с событием и результатом. Проверка только внутри интерфейса не помогает: повтор может возникнуть на стороне сети, поставщика или оператора восстановления. Выберите область уникальности. Номер события может быть уникальным глобально или только в пределах аккаунта поставщика. Идентификатор заказа может совпадать в разных организациях. Ключ должен учитывать реальные границы, иначе допустимое событие будет пропущено либо повтор обработан как новый. Учебная ситуация: документ создан, но ответ источнику потерян. Следующий вызов должен распознать уже выполненную операцию и вернуть согласованное подтверждение. Если система создаёт второй документ, интеграция не выдерживает обычный сетевой сценарий. Испытание проводится в тестовом контуре с безопасными объектами. Отдельно различайте повтор и новое изменение того же объекта. Один заказ может законно иметь несколько событий. Дедупликация только по идентификатору заказа способна потерять обновление. Контракт и состояние обработки должны сохранять смысл события, а не просто блокировать похожие запросы. Порядок событий и версия объекта События могут прийти в порядке, который отличается от бизнес-порядка. Получатель должен знать, что делать со старым состоянием и пропущенной версией. Для проекции часто важно не вернуть объект назад; для учётной операции может требоваться обработать каждый факт. Эти задачи требуют разных правил. Учебный пример: сначала приходит сообщение об отгрузке, затем более раннее подтверждение заказа. Без проверки перехода интерфейс может вернуть состояние к «принят». Нужно сравнить версию, получить актуальную запись либо применить согласованную модель событий. Решение зависит от доступного контракта. Время отправки не всегда достаточно для порядка. Разные системы имеют разные часы, а событие может задержаться. Если требуется строгая последовательность, используйте предусмотренный поставщиком механизм и проверьте его границы. Не делайте вывод по случайной сортировке времени получения. Неизвестное промежуточное состояние лучше выделить для разбора, чем молча применить удобный переход. Оператор должен видеть, чего не хватает и можно ли безопасно повторить. Регламент восстановления связывается с моделью, а не ограничивается кнопкой «отправить ещё раз». Повторы и управление нагрузкой Повтор должен иметь правила, ограничение и наблюдаемое состояние. Сетевая недоступность и ошибка бизнес-данных различаются. В первом случае следующая попытка может помочь, во втором обычно требуется исправление. Бесконечная частая отправка одинакового неверного сообщения только увеличивает нагрузку. Укажите максимальные условия ожидания по конкретному контракту и путь после исчерпания автоматических попыток. Получатель должен знать, где искать необработанное событие. Отправитель — что означает ответ. Если поставщик не даёт ручного повтора, нужен другой согласованный способ сверки. Нагрузка требует ограничений на вход и обработку. Большой поток одного клиента не должен без контроля блокировать остальных. Очередь и обработчики должны иметь понятные границы ресурсов. При росте проверяйте возраст ожидания и завершение операций, а не только число полученных запросов. Пиковая нагрузка испытывается в согласованной среде. Не отправляйте массовые тестовые события в рабочую систему с реальными платежами и рассылками. Если внешние сервисы имеют лимиты, тестовый план должен учитывать их и исключать нежелательные побочные действия. Ошибка данных и очередь разбора Необрабатываемое событие должно сохранять причину и связь с объектом. Например, неизвестный тип цены, отсутствующий клиент или недопустимый переход. Оператору нужно понять, кто исправляет данные и что произойдёт при повторе. Сообщение «ошибка интеграции» слишком широко для действия. Выделяйте событие после согласованных попыток либо сразу при очевидной ошибке правил. Остальные независимые события должны продолжать работу, если модель это допускает. Одна запись не должна бесконечно останавливать весь поток без объяснения. Для зависимых операций правило может быть другим. После исправления повторите конкретное событие по тому же устойчивому ключу. Сохраняйте историю попыток. Если оператор меняет содержимое, это уже отдельное действие, которое требует основания и следа. Нельзя незаметно подменять исходный факт ради успешного статуса. Иногда проблема требует сверки текущего состояния источника, а не повторной обработки старого снимка. Укажите такой путь в регламенте. Решение должно учитывать уже выполненные операции и внешние последствия. «Перезапустим всё» не является универсальным безопасным восстановлением. Версионирование и изменение контракта Изменения формата должны быть управляемыми. Новое поле может быть совместимым, а изменение смысла статуса — нет. Определите поддерживаемые версии, порядок выпуска сторон и поведение неизвестного сообщения. Контракт хранится рядом с реализацией и тестовыми образцами. Проверяйте старого отправителя с новым получателем и наоборот там, где такой переход возможен. Внешний поставщик может обновляться независимо от вашей команды. Если есть объявленный срок изменения, включите подготовку в план. Не откладывайте проверку до первого рабочего отказа. Условные образцы должны содержа
Автор: Дмитрий Ковалёв, Backend Developer, 404gen.
404gen — креативное digital-агентство полного цикла, работаем удалённо по всей России.
Телефон: +7 993 729-59-59 (пн–пт, 10:00–19:00 МСК). WhatsApp: +7 913 141-20-96. Telegram: @aporkulevich. Почта: ap@404gen.ru.