Проблема: автоматическое обновление статуса заказа в WooCommerce по webhook
Часто платежные системы отправляют уведомления о смене статуса платежа через webhook. По умолчанию WooCommerce не всегда корректно обрабатывает эти уведомления, особенно если используется кастомный шлюз или сторонний сервис. В результате заказ остается в статусе «Ожидает оплаты» или «В обработке», что мешает бизнес-процессам.
Диагностика проблемы
- Проверьте, что webhook от платежной системы успешно поступает на ваш сайт.
- Убедитесь, что WooCommerce регистрирует изменение статуса заказа в админке.
- Проверьте логи сервера и WooCommerce (включите WP_DEBUG и WP_DEBUG_LOG) на наличие ошибок при получении webhook.
- Убедитесь, что ID заказа из webhook совпадает с ID заказа в WooCommerce.
Пошаговое решение: обработка webhook и смена статуса заказа
1. Создайте endpoint для обработки webhook
Добавьте в файл functions.php вашей темы или в собственный плагин следующий код:
add_action('rest_api_init', function () {
register_rest_route('custom/v1', '/payment-webhook', array(
'methods' => 'POST',
'callback' => 'handle_payment_webhook',
'permission_callback' => '__return_true',
));
});
function handle_payment_webhook(WP_REST_Request $request) {
$data = $request->get_json_params();
if (empty($data['order_id']) || empty($data['status'])) {
return new WP_REST_Response('Invalid data', 400);
}
$order_id = intval($data['order_id']);
$new_status = sanitize_text_field($data['status']);
$order = wc_get_order($order_id);
if (!$order) {
return new WP_REST_Response('Order not found', 404);
}
// Карта статусов платежной системы на статусы WooCommerce
$status_map = array(
'paid' => 'completed',
'pending' => 'pending',
'failed' => 'failed',
'refunded' => 'refunded'
);
if (!array_key_exists($new_status, $status_map)) {
return new WP_REST_Response('Unknown status', 400);
}
$wc_status = $status_map[$new_status];
// Меняем статус заказа, если он отличается
if ($order->get_status() !== $wc_status) {
$order->update_status($wc_status, 'Статус изменён по webhook платежной системы');
}
return new WP_REST_Response('Order status updated', 200);
}2. Настройте платежную систему на отправку webhook на URL:
https://ваш-сайт.ru/wp-json/custom/v1/payment-webhook
3. Тестирование webhook
Используйте ReqBin или curl для отправки тестового POST-запроса:
curl -X POST https://ваш-сайт.ru/wp-json/custom/v1/payment-webhook \
-H "Content-Type: application/json" \
-d '{"order_id":123,"status":"paid"}'Если всё настроено правильно, статус заказа №123 изменится на completed.
Проверка результата после внедрения
- В административной панели WooCommerce откройте заказ, ID которого вы указали в webhook.
- Проверьте в журнале активности заказа, что появился комментарий с текстом «Статус изменён по webhook платежной системы».
- Проверьте, что статус заказа изменился на соответствующий.
- Проверьте логи сервера на отсутствие ошибок при вызове webhook.
Частые ошибки и их исправление
- Webhook не доходит до сайта: Проверьте доступность
/wp-json/custom/v1/payment-webhook, настройки SSL и firewall. - Неверные данные в webhook: Убедитесь, что платежная система передаёт корректный ID заказа и статус.
- Статус не меняется: Проверьте, что в
$status_mapесть соответствие статусов платежной системы и WooCommerce. - Проблемы с правами доступа REST API: В коде указан
permission_callback => '__return_true', что открывает endpoint. Если нужна безопасность, добавьте проверку ключа или хеша.
Практические советы по безопасности и производительности
- Добавьте проверку подписи webhook, если платежная система её поддерживает, чтобы исключить посторонние запросы.
- Логируйте входящие webhook для отладки и аудита.
- Используйте transient или кэширование, если планируются частые обращения к заказам.
- Обрабатывайте webhook асинхронно через очередь, если требуется высокая нагрузка.
Сравнение вариантов реализации
| Метод | Преимущества | Недостатки | Пример |
|---|---|---|---|
| REST API endpoint | Стандартный, легко масштабируется, интеграция с WP REST API | Требует настройки безопасности, возможна нагрузка на сервер | Код выше |
| Обработка webhook через admin-post.php | Простая реализация, работает без REST | Менее гибкий, сложнее масштабировать | add_action('admin_post_nopriv_payment_webhook', 'callback'); |
| Плагины для webhook | Простая настройка без кода | Может быть избыточным, зависят от обновлений | WP Webhooks, AutomateWoo |