WooCommerce webhooks удобны для передачи заказов, клиентов и изменений статусов во внешнюю CRM, ERP или собственный API. Но сама настройка webhook в админке ещё не делает интеграцию надёжной: внешний сервис может быть недоступен, один и тот же запрос может прийти повторно, а обработчик может вернуть ошибку уже после того, как частично записал данные.
Поэтому production-интеграция строится не как «WooCommerce отправил JSON — CRM сохранила», а как цепочка с проверкой подписи, идемпотентностью, быстрым подтверждением приёма, очередью повторов и журналом доставки.
Как WooCommerce доставляет webhook
WooCommerce позволяет подписаться на события, связанные с заказами, товарами, купонами и другими сущностями. Для каждого webhook задаются topic, delivery URL и secret. Secret используется для подписи payload: получатель может проверить заголовок X-WC-Webhook-Signature и убедиться, что запрос сформирован доверенным источником.
Официальная документация WooCommerce также описывает журнал доставок и автоматическое отключение webhook после серии последовательных неуспешных доставок. Поэтому отсутствие новых запросов в CRM нужно диагностировать не только на стороне CRM, но и в WooCommerce: webhook мог стать неактивным после ошибок внешней системы.
Главная архитектурная ошибка — делать всю синхронизацию до ответа WooCommerce
Если endpoint получает webhook, затем ждёт медленный API CRM, создаёт сделку, добавляет позиции, пересчитывает скидки и только после этого отвечает WooCommerce, любой таймаут превращается в неопределённое состояние. CRM могла уже создать заказ, но WooCommerce увидел ошибку и позже повторил доставку.
Надёжнее разделить приём и бизнес-обработку:
- получить raw body и заголовки;
- проверить HMAC-подпись;
- проверить идентификатор доставки и бизнес-ключ;
- записать событие в локальный inbox/queue;
- быстро вернуть успешный HTTP-ответ;
- обработать CRM асинхронно;
- зафиксировать результат и при необходимости повторить попытку.
Для небольшого сайта очередь может быть таблицей в базе и Action Scheduler. Для более нагруженной схемы — Redis, RabbitMQ, SQS или отдельный worker. Ключевой принцип один: временная недоступность CRM не должна заставлять WooCommerce ждать весь внешний процесс.
Проверяйте HMAC по исходному body
Подпись нужно вычислять по исходным байтам тела запроса, а не по JSON после декодирования и повторной сериализации. Даже логически одинаковый JSON может дать другой HMAC, если изменился порядок ключей, пробелы или экранирование.
$raw = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'] ?? '';
$expected = base64_encode(
hash_hmac('sha256', $raw, $secret, true)
);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
Secret нельзя хранить в публичном JavaScript, Git-репозитории или логах. Если webhook проходит через прокси, CDN или API gateway, важно убедиться, что body не модифицируется до проверки подписи.
Идемпотентность защищает от дублей
Повторная доставка — нормальная ситуация для распределённых систем. Поэтому обработчик должен спокойно принять один и тот же event несколько раз и получить тот же бизнес-результат.
Полезно хранить технический ключ доставки, например сочетание webhook ID и delivery ID, а на уровне бизнеса — WooCommerce order ID и тип операции. Перед созданием сущности в CRM обработчик проверяет, не был ли этот event уже подтверждён.
Нельзя строить дедупликацию только по email или номеру телефона: один клиент может сделать несколько заказов. Базовый стабильный ключ для заказа — его ID в WooCommerce, а CRM ID лучше сохранять в отдельном mapping.
Webhook сообщает событие, но источником истины остаётся WooCommerce
Во время обработки полезно различать «полученное событие» и «актуальное состояние заказа». Если несколько изменений статуса пришли почти одновременно или обработка очереди задержалась, старый payload может попасть в worker позже нового.
Для критичных интеграций worker может использовать order ID из webhook и дополнительно запросить актуальное состояние заказа через WooCommerce REST API. Это особенно полезно для оплаты, отмены, возврата и обновления состава заказа.
Какие данные логировать
Лог интеграции должен помогать ответить на четыре вопроса: что пришло, было ли принято, что отправили в CRM и какой результат вернула CRM. Достаточно хранить event/delivery ID, WooCommerce order ID, дату, статус обработки, количество попыток, HTTP-код внешнего API и короткое безопасное описание ошибки.
Не стоит без необходимости писать в лог полный payload с персональными данными, токенами и реквизитами. Для диагностики обычно достаточно технических идентификаторов и ограниченного контекста.
Retry должен быть управляемым
Повторять запрос к CRM каждую секунду бессмысленно. При временных ошибках 429 или 5xx обычно применяют backoff: например, следующая попытка через 1, 5, 15 и 60 минут. После заданного лимита событие переводится в состояние, требующее внимания, но не удаляется.
Отдельно нужно различать временные и постоянные ошибки. HTTP 401 из-за неверного токена не исправится от десяти повторов; 429 или 503 часто исправятся. Поэтому retry policy должна учитывать класс ошибки.
Контролируйте состояние webhook в WooCommerce
В WooCommerce есть delivery logs, по которым видно URL, request/response и результат доставки. Если endpoint подряд возвращает ошибки, webhook может быть автоматически отключён. Мониторинг должен проверять не только вашу очередь, но и то, что сам webhook остаётся активным.
Практический минимум — уведомление, если несколько минут не было ожидаемых событий, если растёт очередь необработанных сообщений или если процент ошибок CRM превысил нормальный уровень.
Не привязывайте интеграцию к DOM checkout
CRM должна получать данные из серверного состояния заказа, а не из JavaScript-события кнопки «Оформить заказ». Пользователь может закрыть вкладку, платёж может подтвердиться webhook-ом платёжной системы позже, а Checkout Block может изменить front-end поведение после обновления.
Для сложных сценариев полезна отдельная интеграция WordPress с CRM, REST API и webhooks, где источники событий и правила синхронизации описаны явно.
Что делать, если событие всё-таки потерялось
Даже хорошая webhook-схема должна иметь reconciliation-процесс. Например, раз в час можно запрашивать заказы, изменённые после последней успешной точки синхронизации, и сравнивать их с CRM. Такой процесс не заменяет webhook, но закрывает редкие сетевые и операционные сбои.
Reconciliation особенно важен, если внешний API периодически недоступен или если интеграцию обновляют. После восстановления можно безопасно догнать пропущенные заказы без ручного копирования.
Чек-лист надёжной интеграции WooCommerce → CRM
- webhook подписан secret и HMAC проверяется по raw body;
- endpoint быстро подтверждает приём и не ждёт медленную CRM;
- есть inbox/queue для асинхронной обработки;
- каждое событие имеет idempotency key;
- WooCommerce order ID связан с CRM ID;
- retry использует backoff и ограничение попыток;
- ошибки 4xx и 5xx обрабатываются по-разному;
- delivery logs WooCommerce регулярно проверяются;
- есть мониторинг отключённых webhooks;
- есть reconciliation через REST API;
- логи не раскрывают токены и лишние персональные данные.
Когда нужна кастомная разработка
Готовый коннектор подходит, если нужно просто создать сделку из заказа. Но когда есть несколько статусов, частичные оплаты, возвраты, разные склады, промокоды, B2B-реквизиты, доставка и двусторонняя синхронизация, надёжнее проектировать интеграцию как отдельный сервисный слой.
В A.S Groups можно заказать разработку WooCommerce или доработку существующего магазина: аудит текущих webhooks, устранение дублей, очередь повторов, логирование и восстановление пропущенных заказов. Для оценки достаточно описать CRM, какие события должны передаваться и что сейчас происходит при ошибке.
Обсуждение
Вопросы и комментарии
Можно уточнить детали статьи или поделиться своим опытом. Первый комментарий проходит проверку.