Диагностика проблемы: почему WooCommerce не отслеживает статус отсроченного платежа
В стандартной установке WooCommerce статус заказа меняется в момент успешного платежа. Однако при использовании отсроченных платежей, например, банковским переводом или через платежные шлюзы с задержкой подтверждения, система не всегда корректно обновляет статус заказа. Это приводит к проблемам с учётом, обработкой заказов и уведомлениями.
Основные симптомы:
- Заказы остаются в статусе «Ожидает оплаты» или «В обработке» длительное время;
- Покупатель не получает уведомления об изменении статуса;
- Администратор не может отследить, что оплата всё-таки прошла;
- Отсутствует автоматическое изменение статуса при получении оплаты от платежного шлюза.
Пошаговое решение: настройка отслеживания отсроченных платежей в WooCommerce
Шаг 1. Убедитесь, что ваш платежный шлюз поддерживает вебхуки или IPN
Практически все современные шлюзы (например, Яндекс.Касса, PayPal, Stripe) предоставляют механизм уведомлений о статусе платежа (вебхуки, IPN). Проверьте в настройках плагина платежного шлюза, что вебхуки активированы и правильно настроены на ваш сайт.
Шаг 2. Добавьте обработчик вебхуков для обновления статуса заказа
Если у вас кастомный способ обработки или шлюз не полностью интегрирован, добавьте свой обработчик, который будет менять статус заказа при получении подтверждения о платеже.
add_action('woocommerce_api_custom_payment_gateway', 'handle_custom_gateway_webhook');
function handle_custom_gateway_webhook() {
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['order_id']) || empty($data['payment_status'])) {
status_header(400);
exit('Invalid data');
}
$order_id = intval($data['order_id']);
$order = wc_get_order($order_id);
if (!$order) {
status_header(404);
exit('Order not found');
}
if ($data['payment_status'] === 'paid') {
$order->payment_complete(); // меняет статус на обработан
$order->add_order_note('Оплата подтверждена через вебхук.');
}
status_header(200);
exit('OK');
}
В этом примере создаётся новый REST API endpoint woocommerce_api_custom_payment_gateway для приёма уведомлений. В реальном сценарии используйте хук, соответствующий вашему платежному плагину.
Шаг 3. Обновите статус заказа вручную или через WP-Cron при задержках
Если вебхуки недоступны, можно настроить задачу WP-Cron, которая будет периодически проверять статус заказа у платежного провайдера через API и обновлять состояние.
add_action('my_check_delayed_payments', 'check_delayed_orders_status');
function check_delayed_orders_status() {
$args = [
'status' => 'on-hold',
'limit' => -1,
];
$orders = wc_get_orders($args);
foreach ($orders as $order) {
$payment_status = my_check_payment_provider_status($order->get_id());
if ($payment_status === 'paid') {
$order->payment_complete();
$order->add_order_note('Статус изменён автоматически через WP-Cron.');
}
}
}
if (!wp_next_scheduled('my_check_delayed_payments')) {
wp_schedule_event(time(), 'hourly', 'my_check_delayed_payments');
}
Функцию my_check_payment_provider_status() нужно реализовать под конкретный API платежного провайдера.
Как проверить, что решение сработало
- Сделайте тестовый заказ с оплатой отсроченным способом;
- Отправьте уведомление от платежного провайдера (вебхук) вручную или дождитесь автоматического обновления;
- Проверьте, что статус заказа в админке изменился на «Обработан» или нужный статус;
- Проверьте, что покупатель получил уведомление об оплате (если настроены письма);
- Посмотрите в историю заказов, что добавилась заметка о подтверждении оплаты.
Частые ошибки и как их исправить
- Неправильный URL вебхука в настройках платежного шлюза. Решение: проверьте URL, он должен указывать на
https://вашсайт.com/wc-api/имя_обработчикаили другой endpoint, предусмотренный плагином. - Отсутствие прав на изменение заказа в обработчике. Решение: используйте функции WooCommerce API
wc_get_order()и методыpayment_complete(), не меняйте статус напрямую в базе. - WP-Cron отключён на сервере. Решение: настройте системный cron для запуска
wp-cron.phpили используйте сторонние сервисы для вызова cron. - Обработчик не возвращает правильный HTTP статус. Решение: всегда отправляйте
status_header(200)и выходите сexit('OK'), иначе шлюз может считать, что уведомление не доставлено.
Практические советы по безопасности и производительности
- Проверяйте подписи webhook-уведомлений, если провайдер их предоставляет, чтобы исключить подделку данных.
- Используйте nonce или другие методы аутентификации для REST API, если создаёте кастомные обработчики.
- Делайте логирование вебхуков в отдельный файл для отладки и аудита.
- Ограничьте частоту запросов WP-Cron, чтобы не нагружать сервер.
- Используйте кеширование ответов при проверке статуса платежа во внешнем API.
Сравнение вариантов решения
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Вебхуки от платежного провайдера | Моментальное обновление, минимальная нагрузка на сервер | Зависит от корректной настройки провайдера и соединения | Рекомендуется для всех современных шлюзов |
| WP-Cron с периодической проверкой | Работает при отсутствии вебхуков, можно кастомизировать | Задержка обновления, нагрузка на сервер и API | Если вебхуки недоступны или ненадёжны |
| Ручное обновление статусов | Простота реализации | Требует вмешательства администратора | Для малых магазинов с редкими заказами |