Вебхуки в интеграции калькулятора с сайтом: зачем нужны и как не терять события
Вебхук — это автоматическое уведомление, которое одна система отправляет другой в момент события: изменилась цена, опубликован новый прайс, пришла заявка. В связке калькулятора с сайтом вебхук заменяет постоянные опросы и сокращает задержку, но работает надёжно только вместе с подтверждением доставки, повтором и журналом событий.
Что такое вебхук и чем он отличается от обычного запроса к API?
Обычный запрос к API инициирует тот, кому нужны данные: калькулятор спрашивает каталог «какая цена у этой позиции» и получает ответ. Вебхук устроен наоборот — инициатива у того, у кого произошло событие. Каталог сам сообщает калькулятору: «у этой позиции изменилась цена».
Разница не в технологии, а в направлении инициативы. Технически вебхук — это тот же HTTP-запрос, только его отправляет не интерфейс по действию пользователя, а система по факту события. Получателю не нужно ничего спрашивать: он принимает уведомление и решает, что с ним делать.
Из этого сразу следует главное ограничение. При обычном запросе клиент сам выбирает момент, когда ему удобно, и может повторить попытку. При вебхуке момент выбирает отправитель — и если получатель в этот момент недоступен, уведомление может потеряться. Поэтому вебхук без механизма повторной доставки — это не интеграция, а надежда.
Зачем вебхуки связке «калькулятор — сайт», если API уже есть?
API чтения отвечает на вопрос «дай данные», вебхук — на вопрос «сообщи, когда данные изменятся». Это две разные задачи, и одна не заменяет другую.
Без вебхуков остаётся опрос: калькулятор или сайт периодически спрашивает каталог, не изменилось ли что-нибудь. Схема работает, но у неё врождённый компромисс. Опрашивать редко — значит показывать устаревшие цены. Опрашивать часто — значит гонять запросы ради того, чтобы почти всегда получить ответ «ничего нового».
Вебхук убирает этот компромисс: запрос происходит тогда, когда действительно есть изменение. Для производителя это важно в трёх местах. Публикация новой версии прайса — сайт и калькулятор узнают о ней сразу, а не через сутки. Новая заявка — она попадает в работу без задержки на опрос. Смена статуса заявки — клиент видит «принята» или «отклонена» тогда, когда это произошло на самом деле.
При этом вебхук не отменяет API чтения. Хорошее уведомление говорит только «есть изменение» и содержит идентификатор, по которому получатель доберёт актуальные данные обычным запросом. Попытка уместить в уведомление весь прайс — распространённая ошибка: такое событие становится тяжёлым, хрупким и быстро устаревает само по себе.
Есть случаи, когда вебхуки не нужны. Если каталог небольшой, цены меняются раз в месяц, а задержка в несколько часов никого не беспокоит, достаточно опроса по расписанию.
Какие события стоит отправлять, а какие — нет?
Событие должно быть фактом, у которого есть адресат и последствия. «Что-то изменилось» — не событие, потому что получатель не знает, что с этим делать.
Для связки калькулятора с сайтом обычно осмысленны четыре группы. Первая — версия прайса: не «изменилась цена у четырёхсот позиций», а «опубликована новая версия прайс-листа» с её идентификатором. Одно событие вместо четырёхсот, и получатель сам решает, что перечитывать.
Вторая группа — заявка: создана, принята, отклонена, требует уточнения. Здесь событие обязано нести идентификатор заявки и новый статус, иначе получателю придётся угадывать, о чём речь.
Третья — изменения каталога, влияющие на подбор: появилась новая позиция, позиция снята с продажи, изменились правила совместимости. Это события, после которых калькулятор обязан перечитать данные, иначе будет предлагать то, чего нет.
Четвёртая — служебные сигналы: завершился импорт прайса, импорт упал с ошибкой. Такие события нужны не калькулятору, а людям, которые отвечают за данные.
Чего отправлять не стоит: каждый пересчёт цены, каждое открытие карточки, любой технический шум. Чем больше событий, тем больше нагрузка на приёмник и тем выше шанс, что важное уведомление утонет в неважных. Отдельно не стоит класть в тело уведомления персональные данные клиента — для этого есть идентификатор и защищённый запрос за деталями.
Общее правило простое: событие — это минимальный факт плюс идентификатор, по которому получатель доберёт остальное.
Из чего состоит надёжное уведомление?
Надёжность вебхука складывается из нескольких элементов, и пропуск любого из них проявляется не сразу, а через месяц эксплуатации.
Идентификатор события
У каждого уведомления должен быть собственный неизменный идентификатор. Он нужен не для красоты, а чтобы получатель мог отличить новое событие от повторно доставленного. Без него любая повторная попытка превращается в риск задвоить заявку.
Тип события и версия схемы
Получатель должен понимать, что именно пришло, не разбирая текст. Тип события — отдельное поле. Версия схемы нужна, чтобы можно было добавить новые поля, не ломая тех, кто уже принимает уведомления.
Полезная нагрузка
Минимум данных, достаточный для решения: идентификатор объекта, тип изменения, версия или время события. Всё остальное — отдельным запросом.
Подпись отправителя
Адрес вебхука рано или поздно станет известен не только вам. Подпись позволяет отличить настоящее уведомление от чужого запроса.
Ссылка на исходные данные
Получателю нужен способ сказать: «покажи мне это в актуальном виде». Идентификатор объекта и есть такая ссылка — не обязательно в виде полного URL, достаточно ключа, по которому данные запрашиваются через API.
Важно принять как данность: вебхуки почти всегда работают по модели «доставлено хотя бы один раз». Это значит, что дубли — не авария, а штатный режим. Проектировать приёмник нужно соответственно.
Что делать, если получатель не ответил?
Успехом считается только подтверждение от получателя. Если ответа нет, ответ пришёл с ошибкой или соединение оборвалось, событие остаётся не доставленным — и это нужно где-то хранить.
Первое решение — повтор с увеличивающейся паузой. Общий принцип известен: несколько попыток, интервал растёт, общее число попыток ограничено. Пауза обязательно должна расти, иначе при падении получателя повторные отправки превращаются в атаку на него же, и восстановиться он не сможет.
Второе решение — различать ошибки. Сетевая недоступность и ответы вида «сервер не смог обработать» — временные, их имеет смысл повторять. Ошибки вида «неверный адрес», «неверный формат», «нет прав» — постоянные: повторять их бессмысленно, очередь только забьётся мусором. Постоянная ошибка должна сразу попадать в журнал и к ответственному человеку.
Третье решение — очередь недосланного. События, которые не удалось доставить после всех попыток, не должны исчезать. Их место — отдельный список, который кто-то просматривает: «вот три события, которые не дошли, вот почему». Список без владельца бесполезен: если его никто не открывает, это просто способ аккуратно потерять данные.
Четвёртое — и самое частое упущение: отправитель должен знать, что получатель жив. Если приёмник отключён на неделю, а очередь растёт молча, обнаружение проблемы откладывается до момента, когда клиент пожалуется на старую цену.
Почему события приходят дважды и как не задвоить заявку?
Дубли возникают по естественной причине: отправитель не получил подтверждение, повторил отправку, а первый запрос на самом деле дошёл. Получатель видит два одинаковых уведомления и не может отличить «повтор» от «двух реальных событий».
Решается это идемпотентностью приёмника, а не настройками отправителя. Приёмник хранит идентификаторы уже обработанных событий и на повтор отвечает «принято», ничего не создавая заново. Ответ при этом должен быть успешным — иначе отправитель будет повторять бесконечно.
Для заявки ключ идемпотентности берётся из бизнес-смысла: идентификатор расчёта или заявки на стороне сайта. Время создания ключом быть не может — при повторе оно будет новым, и дубль пройдёт проверку.
Отдельно стоит проверять заявку по бизнес-ключу, а не по сумме. Две разные заявки с одинаковой суммой — нормальная ситуация, а одна заявка, отправленная дважды, отличается именно идентификатором.
Правило, которое стоит проговорить с владельцем процесса: дубль в журнале доставки — это нормально и разбирается за пять минут. Дубль заказа в учётной системе — это уже работа для бухгалтерии, звонок клиенту и объяснения. Выбирать нужно первое.
Как убедиться, что вебхук пришёл от вашей системы?
Адрес вебхука — публичная точка входа. Его может вызвать кто угодно: сканер, чужой сервис, человек с любопытством. Если приёмник этого не проверяет, он выполняет действия по чужому запросу.
Защита строится на подписи. Отправитель и получатель договариваются об общем секрете, отправитель подписывает тело уведомления, получатель проверяет подпись до того, как разбирать содержимое. Неверная подпись — отказ, запись в журнал, никаких бизнес-действий.
Второй элемент — ограничение по времени. Подпись, перехваченная и отправленная повторно через сутки, не должна приниматься. Для этого в уведомление кладут метку времени и отклоняют всё, что старше разумного окна.
Третий — сам секрет. Он живёт в переменных окружения, а не в коде, не в репозитории и не в переписке. И у него должна быть процедура замены: если секрет утёк, его меняют на обеих сторонах, и лучше иметь эту процедуру до инцидента, а не во время.
Надеяться на «секретный адрес» не стоит. Длинный URL с случайным набором символов немного снижает шум от сканеров, но не заменяет проверку подлинности: адрес утекает через логи, историю браузера и настройки прокси.
Как не получить бесконечный цикл событий?
Цикл возникает, когда обе системы умеют и принимать, и отправлять изменения. Каталог сообщает сайту об изменении цены, сайт обновляет у себя и отправляет событие обратно, каталог применяет его и снова сообщает — и так по кругу.
Первый предохранитель — сравнение «было/стало». Если полученное значение совпадает с текущим, событие не порождается: изменение не состоялось, сообщать не о чем. Это самая простая и самая эффективная защита, но она требует, чтобы сравнение было по существу, а не по факту получения запроса.
Второй — метка источника. В событии указывается, кто его породил, и система игнорирует события, которые вернулись оттуда, куда она сама их отправила.
Третий — ограничение глубины цепочки. Даже с первыми двумя предохранителями стоит считать, сколько переходов событие прошло, и останавливать цепочку после разумного предела. Это дешёвая страховка от логических ошибок, которые не видны на тестах.
Что делать с порядком событий и устаревшими данными?
Сеть не гарантирует порядок доставки. Событие «цена стала 120» вполне может прийти раньше, чем событие «цена стала 100», хотя второе произошло первым. Если приёмник просто применяет всё подряд, он закончит устаревшим значением.
Решение — версия события. У каждого изменения есть номер версии или монотонная метка, и приёмник хранит последнюю применённую. Пришло событие со старшей версией — применяем; со младшей — фиксируем в журнале и игнорируем.
Полагаться на время отправки, выставленное сервером, рискованно: часовые пояса, рассинхронизация и повторные отправки делают такую метку ненадёжной. Номер версии, который растёт при каждом изменении сущности, ведёт себя предсказуемо.
Для заявок порядок менее критичен, если есть статусная модель. «Принята» после «отклонена» — не проблема порядка, а проблема бизнес-правила: нужно решить, можно ли отменить отклонённую заявку, и закрепить это правило в одном месте.
Как понять, что вебхуки работают, если они молчат?
Молчание — двусмысленный сигнал. Оно одинаково означает «изменений не было» и «обмен сломан». Различить эти два состояния — отдельная задача, и решать её нужно заранее.
Первый инструмент — журнал доставок: что отправлено, когда, с каким результатом, что ждёт повтора. Без него разбор инцидента превращается в переписку «а вы точно отправляли?».
Второй — регулярная сверка. Раз в сутки имеет смысл сравнивать: сколько изменений зафиксировано в источнике и сколько событий доставлено. Расхождение — повод разбираться, даже если жалоб пока нет.
Третий — сигнал о простое. Если события не доходят дольше ожидаемого, об этом должен узнать человек, отвечающий за процесс, а не только разработчик. Практика показывает: алерты, которые приходят «в никуда», живут ровно до первого отпуска ответственного.
Четвёртый — видимость для бизнеса. Менеджеру не нужен технический журнал, ему нужен ответ на вопрос «заявка точно ушла?». Этот ответ строится на статусе, который меняется по факту подтверждённой доставки, а не по факту нажатия кнопки.
Как тестировать вебхуки до запуска?
Тестировать нужно не «работает ли вообще», а поведение в неудобных условиях. Обычная доставка — самая простая часть и почти никогда не ломается в продакшене.
Начните с приёмника, который просто записывает входящие запросы. Он покажет, что уведомления действительно уходят, в каком виде и с какой подписью.
Дальше — сценарии, которые в жизни случаются регулярно. Повторная доставка того же события: создаётся ли дубль заявки. Недоступный получатель: что происходит с очередью и не теряется ли событие. Неверная подпись: отклоняется ли запрос. Устаревшее событие: не откатывается ли цена назад. Всплеск событий: выдерживает ли приёмник публикацию большого прайса.
Отдельно стоит прогнать сценарий «получатель лежал час». Именно он показывает, растёт ли пауза между попытками, не забилась ли очередь и увидит ли кто-нибудь недосланные события.
И последняя проверка — сверка на реальных данных. После теста число обработанных событий должно совпадать с числом фактических изменений. Если не совпадает, дальше искать нечего: сначала нужно понять, где расходятся счётчики.
Нужны ли вебхуки на первом этапе?
Часто — нет. Первый шаг связки калькулятора с сайтом — единый источник данных о продукции, из которого интерфейсы читают цены и характеристики, а не держат собственные копии. Об этом подробно написано в обзоре параметрического каталога и data layer.
Второй шаг — API чтения: калькулятор получает данные по запросу, сайт показывает актуальные цены. Этого достаточно, чтобы отказаться от ручных правок и Excel-прайса в качестве основного источника.
Вебхуки становятся нужны позже — когда появляются события, на которые должны реагировать несколько потребителей, и когда задержка начинает стоить денег: клиент видит старую цену, заявка ждёт очереди, менеджер узнаёт о заказе последним.
Событийная схема поверх разрозненных прайсов только ускоряет распространение ошибок: уведомления приходят быстро, а данные в них противоречивые.
Если задача — не просто связать калькулятор с сайтом, а сделать конфигуратор с правилами совместимости, набор событий меняется: добавятся публикация новой версии правил и изменение состава компонентов. Об этом — в обзоре конфигуратора оборудования и разделе решений для конфигураторов.
Частые вопросы
Вебхук — это то же самое, что API?
Нет. API — это способ запросить данные, когда они понадобились. Вебхук — это уведомление о том, что что-то произошло. В типовой связке они работают вместе: вебхук сообщает о событии, API отдаёт актуальные данные по идентификатору из уведомления.
Обязательно ли делать повторные отправки?
Да, если вы не хотите терять события. Любая сеть и любой сервер время от времени недоступны, и без повторов часть уведомлений пропадёт незаметно. Повторы обязательно должны сочетаться с идемпотентностью приёмника, иначе начнутся дубли заявок.
Сколько попыток делать и с какой паузой?
Универсального числа нет: оно зависит от того, насколько критична задержка. Общий принцип — несколько попыток с растущим интервалом и обязательный «последний приют» для тех событий, которые так и не дошли. Настраивать это нужно под процесс, а не по привычке.
Можно ли обойтись без подписи, если адрес вебхука никому не известен?
Можно до первого инцидента. Адреса утекают через логи, прокси и настройки, а последствия ложного события — испорченные цены или фиктивная заявка. Проверка подписи стоит недорого и снимает целый класс проблем.
Что делать, если события приходят не по порядку?
Хранить у каждого объекта последнюю применённую версию и игнорировать всё, что старше. Опираться на время отправки ненадёжно, а на порядок доставки — тем более.
Кто должен отвечать за недосланные события?
Тот, кто отвечает за процесс обмена, а не «разработка в целом». Нужен человек, который видит список недосланного и понимает, что с этим делать: переотправить, разобрать вручную или сообщить клиенту.
Как это связано с заявками, которые не доходят до учётной системы?
Напрямую: вебхук — один из каналов, по которому приходит подтверждение приёмки. Если подтверждения нет, заявка остаётся в неопределённом состоянии: сайт считает её отправленной, учётная система о ней не знает. Приёмку и статусы стоит разбирать отдельно от событийной схемы — это разные слои одной задачи.
С чего начать, если хочется проверить схему на своём каталоге?
С описания текущего процесса: откуда берутся цены, кто их правит, какие события важны и кто должен на них реагировать. Это можно сделать на странице старта. Формат и стоимость работ указаны на странице тарифов, общее описание студии — на главной, а как калькулятор встраивается в сайт — в обзоре калькулятора и разделе решений для калькуляторов.