Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Вебхуки

Вебхук — REST API наоборот: не внешняя программа спрашивает магазин, а магазин сам отправляет HTTP-запрос на заданный адрес, когда что-то произошло. Заказ создан — склад узнаёт об этом через секунду, без постоянных опросов.

Создание в панели

Откройте «WooCommerce → Настройки → Дополнительно → Вебхуки» и нажмите «Добавить вебхук»:

ПолеЧто указать
НазваниеЛюбое, для себя: «Заказы на склад»
Статус«Активный»
ТемаСобытие: «Заказ создан»
URL доставкиАдрес получателя: https://erp.example.com/woo-webhook.php
Секретный ключСтрока для подписи запросов

После сохранения каждый новый заказ будет уходить на указанный адрес запросом POST.

Темы

ТемаКогда отправляется
order.createdЗаказ создан
order.updatedЗаказ изменён, в том числе состояние
product.updatedТовар изменён
customer.createdЗарегистрирован покупатель
coupon.createdСоздан купон

Для каждой сущности есть события created, updated и deleted.

Что приходит

Тело запроса — JSON той же структуры, что и ответ REST API: для темы order.created это заказ целиком. Сведения о событии лежат в заголовках:

ЗаголовокЧто в нём
X-WC-Webhook-TopicТема: order.created
X-WC-Webhook-SignatureПодпись тела запроса
X-WC-Webhook-Delivery-IDНомер доставки
X-WC-Webhook-SourceАдрес магазина

Получатель

Вебхук принимает другая программа. Вот минимальный получатель на PHP — файл лежит на сервере учётной системы, а не в плагине:

// erp.example.com/woo-webhook.php
$secret = 'your-webhook-secret';
$body = file_get_contents('php://input');
 
$expected = base64_encode(hash_hmac('sha256', $body, $secret, true));
$actual = $_SERVER['HTTP_X_WC_WEBHOOK_SIGNATURE'] ?? '';
 
if (!hash_equals($expected, $actual)) {
    http_response_code(401);
    exit;
}
 
$order = json_decode($body, true);
 
file_put_contents(__DIR__ . '/orders.log', $order['id'] . ' ' . $order['total'] . PHP_EOL, FILE_APPEND);
 
http_response_code(200);

Подпись — это HMAC-SHA256 от тела запроса с секретным ключом, закодированный в Base64. Получатель считает её сам и сравнивает с заголовком: совпадение доказывает, что запрос прислал ваш магазин. Оформите заказ — в файле orders.log появится строка с номером и суммой.

Создание в коде

Вебхук — объект WC_Webhook. Файл scripts/create-webhook.php:

// wp-content/plugins/acme-shop/scripts/create-webhook.php
$webhook = new WC_Webhook();
 
$webhook->set_name('Заказы на склад');
$webhook->set_user_id(1);
$webhook->set_topic('order.created');
$webhook->set_delivery_url('https://erp.example.com/woo-webhook.php');
$webhook->set_secret('your-webhook-secret');
$webhook->set_status('active');
 
$webhook->save();

Запустите файл через wp eval-file — вебхук появится в списке в панели. Пользователь из set_user_id() определяет, с какими правами собираются данные для отправки.

Как идёт доставка

Запрос отправляется не в момент оформления заказа, а чуть позже, фоновой задачей — покупатель не ждёт ответа чужого сервера. Получатель должен ответить кодом из диапазона 200–299. После пяти неудачных доставок подряд WooCommerce отключает вебхук, и его включают заново в панели.

Журнал доставок находится в «WooCommerce → Статус → Журналы», источник webhooks-delivery.

Вебхук или REST API

ЗадачаЧто выбрать
Узнать о событии сразуВебхук
Получить данные по запросуREST API
Изменить данные в магазинеREST API
Сверить всё раз в суткиREST API с modified_after

Обычно их сочетают: вебхук сообщает о событии, а раз в сутки интеграция сверяется через REST API на случай потерянных доставок.

Частая ошибка

Получатель не проверяет подпись и обрабатывает всё, что пришло на адрес. Адрес вебхука рано или поздно становится известен, и любой может прислать поддельный «оплаченный заказ». Проверка hash_equals() с секретным ключом обязательна — и считать подпись нужно от исходного тела запроса, а не от разобранного и собранного заново JSON.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.