WordPress часто участвует в бизнес-процессе вместе с CRM, платёжной системой, складом, Telegram, email-сервисом или внутренним кабинетом. Если каждую систему постоянно опрашивать по cron, данные приходят с задержкой, а сайт делает лишние запросы. Webhooks в WordPress позволяют поменять модель: внешняя система сама сообщает о событии сразу после того, как оно произошло.
Например, форма отправлена, платёж подтверждён, заказ получил новый статус или клиент изменился в CRM. WordPress принимает webhook, проверяет его, сохраняет событие и запускает нужное действие. Но надёжная реализация — это не один публичный endpoint и wp_remote_post(). Без проверки подписи, idempotency, очереди и повторных попыток webhook легко превращается в источник дублей и потерянных данных.
Что такое webhook и чем он отличается от обычного API-запроса
При обычной интеграции WordPress сам обращается к API и спрашивает: «Есть ли новые данные?». При webhook всё наоборот. Внешний сервис вызывает заранее заданный URL WordPress и передаёт событие сразу после изменения.
Это особенно полезно там, где важна скорость реакции:
- новая заявка должна сразу попасть в CRM;
- после оплаты заказ должен сменить статус;
- после изменения сделки нужно уведомить менеджера;
- после появления нового заказа нужно запустить внутренний процесс;
- внешняя система должна передать обновлённые данные на сайт.
Webhook не заменяет REST API полностью. Чаще всего они работают вместе: webhook сообщает, что что-то изменилось, а затем WordPress через API получает полное актуальное состояние.
Типовая схема webhook-интеграции WordPress
Рабочий поток события
- Внешний сервис отправляет событиеCRM, платёжная система, форма или другой сервис вызывает endpoint WordPress.
- WordPress проверяет запросПроверяются подпись, секретный заголовок, timestamp и формат payload.
- Событие получает стабильный IDОдин и тот же webhook не должен выполнить бизнес-действие дважды.
- Задача сохраняетсяКритичную обработку лучше отделить от HTTP-ответа и передать в очередь.
- Выполняется бизнес-логикаСоздаётся лид, меняется заказ, вызывается API или отправляется уведомление.
- Результат фиксируетсяСохраняются статус, внешний ID, ошибка и возможность безопасного retry.
Почему webhook нельзя принимать без проверки источника
Если endpoint публичный и выполняет действие по любому POST-запросу, злоумышленник или бот может отправить поддельное событие. В зависимости от логики это может привести к созданию мусорных заказов, изменению статусов или массовой отправке уведомлений.
Способ проверки зависит от сервиса. Обычно используется один или несколько механизмов:
- HMAC-подпись тела запроса;
- секретный HTTP-заголовок;
- timestamp с ограниченным сроком действия;
- идентификатор события, который можно сверить через API;
- allowlist IP как дополнительный, но не единственный защитный слой.
Секреты нельзя хранить в JavaScript или выводить в HTML. Они должны оставаться на серверной стороне.
Idempotency защищает от повторной обработки
Webhook может прийти несколько раз. Это нормальная ситуация: сервис не получил быстрый HTTP-ответ, сеть оборвалась, доставка была повторена или поставщик намеренно использует модель at least once delivery.
Если каждый повтор создавать как новую заявку или повторно менять заказ, быстро появляются дубли. Поэтому обработчик должен определять уникальность события. Лучший вариант — использовать event ID поставщика. Если его нет, можно сформировать стабильный ключ из типа события и идентификатора объекта.
$event_key = 'payment:' . $payment_id;
if (asg_webhook_already_processed($event_key)) {
return;
}
asg_process_payment($payload);
asg_mark_webhook_processed($event_key);
В реальном проекте важно учитывать и промежуточное состояние. Если операция началась, но внешнее API ответило таймаутом, повторный запуск должен понимать, можно ли безопасно выполнить её снова.
Почему тяжёлую обработку лучше не делать внутри HTTP-запроса
Внешний сервис обычно ожидает быстрый ответ. Если webhook внутри одного запроса начинает создавать документы, обращаться в несколько API, отправлять письма и пересчитывать данные WooCommerce, риск таймаута растёт.
Для критичных интеграций я разделяю приём и выполнение. Endpoint валидирует событие, сохраняет его и быстро подтверждает получение. Дальше отдельный worker, очередь или планировщик выполняет бизнес-логику. Такой подход даёт несколько преимуществ:
- webhook не теряется из-за медленного внешнего API;
- можно делать контролируемые retries;
- ошибки видны отдельно по каждому событию;
- повторная доставка не создаёт дубль;
- нагрузка на WordPress становится предсказуемее.
Webhooks для заявок и CRM
Один из частых сценариев — передача лидов. После отправки формы WordPress может сразу создать контакт или сделку в CRM, передать UTM-метки, страницу входа, выбранную услугу и комментарий клиента.
Обратный webhook из CRM может вернуть статус сделки или назначенного менеджера. При этом важно хранить связь между внутренним ID WordPress и внешним ID CRM. Без неё обновление существующей сделки легко превращается в создание новой.
Если нужна более широкая интеграция с CRM, можно посмотреть услугу интеграции CRM с сайтом.
Webhooks для оплат
Платёжные сервисы почти всегда используют callback или webhook, чтобы сообщить финальный статус операции. Нельзя считать оплату успешной только потому, что пользователь вернулся на страницу «Спасибо».
Корректный обработчик должен проверить подпись, ID платежа, сумму, валюту и соответствие заказа. Повторный webhook с тем же payment ID не должен второй раз выдавать товар, создавать документ или отправлять клиенту одинаковое письмо.
Webhooks в WooCommerce
WooCommerce умеет сам отправлять webhooks на события заказов, товаров и клиентов. Кроме штатного механизма, кастомный плагин может реагировать на конкретные hooks WooCommerce и формировать payload под нужную внешнюю систему.
Здесь особенно важно не делать тяжёлые сетевые запросы прямо внутри критического checkout-процесса. Покупатель не должен ждать CRM или склад, если заказ уже можно безопасно сохранить локально и синхронизировать отдельно.
Retries: повторять нужно не всё подряд
Повтор имеет смысл для временных ошибок: timeout, HTTP 429, часть 5xx или кратковременная недоступность DNS. Ошибка валидации payload или HTTP 401 сама по себе обычно не исправится через минуту.
Поэтому retry-механизм должен учитывать тип ошибки, количество попыток и задержку между ними. Для внешних API полезен exponential backoff. Например, повтор через минуту, затем через несколько минут, а не десятки запросов подряд.
Какие логи действительно нужны
Лог «webhook failed» почти ничего не даёт. Для диагностики полезно сохранять:
- время получения;
- поставщика и тип события;
- event ID;
- внутренний ID объекта WordPress или WooCommerce;
- HTTP-статус внешнего API;
- количество попыток;
- безопасную часть ответа;
- финальный статус обработки.
При этом access tokens, пароли, полные платёжные данные и лишние персональные сведения в лог попадать не должны.
WordPress REST API для входящего webhook
Для собственного обработчика удобно зарегистрировать отдельный REST endpoint в плагине. Логику интеграции лучше не помещать в тему: тема отвечает за представление, а webhook — за бизнес-процесс.
add_action('rest_api_init', function () {
register_rest_route('asg/v1', '/webhook', [
'methods' => 'POST',
'callback' => 'asg_handle_webhook',
'permission_callback' => '__return_true',
]);
});
В этом коротком примере permission_callback не является защитой. Проверка подписи и секрета должна выполняться внутри обработчика или через отдельный слой до запуска бизнес-логики. Публичный endpoint нужен поставщику для доставки, но публичность URL не означает доверие к любому запросу.
Когда webhook лучше cron
Webhook лучше подходит, когда событие нужно получить быстро и внешний сервис умеет надёжно его доставлять. Cron полезен как резервная сверка или для систем, которые вообще не поддерживают callbacks.
На сложных проектах я часто использую оба механизма. Webhook даёт мгновенную реакцию, а периодическая reconciliation-проверка раз в определённый интервал находит редкие пропущенные события и восстанавливает состояние.
Чек-лист надёжного webhook WordPress
- источник запроса проверяется;
- есть уникальный event ID или idempotency key;
- повторное событие не создаёт дубль;
- HTTP endpoint отвечает быстро;
- долгая обработка вынесена из запроса;
- настроены retries только для временных ошибок;
- в логах нет секретов;
- есть способ вручную повторить неудачную задачу;
- внешние и внутренние ID объектов связаны;
- есть периодическая сверка для критичных данных.
Когда нужна кастомная webhook-интеграция
Готового плагина достаточно, если он полностью соответствует API и бизнес-логике. Но когда нужно передавать нестандартный набор полей, объединять несколько сервисов, поддерживать очереди и особые правила повторов, отдельный модуль WordPress обычно надёжнее цепочки случайных сниппетов.
Я реализую такие интеграции как отдельный плагин или изолированный модуль, чтобы обновление темы не затронуло обмен данными. При необходимости webhook связывается с REST API, CRM, WooCommerce, Telegram, внутренним кабинетом или автоматизацией на стороне сервера.
Описание направления есть на странице интеграции WordPress с API. Если задача включает несколько систем и бизнес-правил, полезно также посмотреть автоматизацию бизнес-процессов.
Как проходит внедрение
Сначала фиксируется список событий и владелец каждого типа данных. Затем проверяется документация поставщика, формат подписи, лимиты API и поведение при повторной доставке. После этого проектируется схема idempotency, очередей и ошибок.
На тестовом окружении обязательно проверяются минимум пять сценариев: нормальный webhook, повтор того же события, неверная подпись, timeout внешнего API и восстановление после ошибки. Только после этого поток подключается к production.
Если нужно настроить webhooks WordPress для заявок, оплат, CRM или другого сервиса, отправьте описание систем и ссылки на API через контакты A.S Groups. По документации можно определить, где достаточно штатного механизма, а где нужен отдельный надёжный модуль.
Частые вопросы
Webhook и REST API — это одно и то же?
Нет. REST API обычно вызывается клиентом по необходимости, а webhook отправляется поставщиком автоматически при наступлении события. На практике они часто дополняют друг друга.
Можно ли сделать webhook в WordPress без отдельного плагина?
Технически можно, но для бизнес-критичной интеграции лучше отдельный плагин или модуль. Так логика не зависит от темы и её проще тестировать и сопровождать.
Как защитить webhook от поддельных запросов?
Использовать механизм, предусмотренный поставщиком: HMAC-подпись, секретный заголовок, timestamp и при необходимости дополнительную проверку события через API.
Что делать, если один webhook приходит дважды?
Обработчик должен быть idempotent. Повтор с тем же event ID должен возвращать корректный ответ, но не выполнять бизнес-действие повторно.
Нужен ли cron, если есть webhooks?
Не всегда, но для критичных интеграций периодическая сверка полезна как страховка на случай редких пропущенных событий.
Можно ли через webhook связать WordPress с CRM и Telegram одновременно?
Да. Лучше сначала сохранить событие и затем отдельно выполнить нужные действия через очередь, чтобы недоступность одного сервиса не блокировала остальные.
Обсуждение
Вопросы и комментарии
Можно уточнить детали статьи или поделиться своим опытом. Первый комментарий проходит проверку.