Диагностика проблемы с неподтверждёнными заказами в WooCommerce
В интернет-магазинах на WooCommerce часто возникает ситуация, когда заказ создан, но пользователь не завершил оплату. Это приводит к "зависшим" заказам в статусе "ожидает оплаты" (pending). Такие заказы занимают место в базе, могут мешать аналитике и создавать путаницу при управлении запасами.
Задача: автоматически блокировать возможность повторной оплаты для таких заказов через определённый промежуток времени — например, 24 часа — чтобы предотвратить проблемы с резервированием товаров и улучшить управление заказами.
Пошаговое решение: отключение оплаты для неподтверждённых заказов
1. Создание функции для проверки времени заказа
Нужно добавить в functions.php вашей темы (или в кастомный плагин) следующий код, который проверяет время создания заказа и переводит заказ в статус "отменён", если прошло более 24 часов без оплаты.
add_action('woocommerce_order_status_pending', 'auto_cancel_unpaid_orders_after_24h', 10, 1);
function auto_cancel_unpaid_orders_after_24h($order_id) {
$order = wc_get_order($order_id);
if (!$order) return;
$created = $order->get_date_created();
if (!$created) return;
$now = new DateTime('now', new DateTimeZone('UTC'));
$diff = $now->getTimestamp() - $created->getTimestamp();
// 86400 секунд = 24 часа
if ($diff > 86400) {
// Меняем статус заказа на отменён
$order->update_status('cancelled', 'Заказ автоматически отменён: не оплачен более 24 часов.');
}
}2. Отключение кнопки оплаты для отменённых и неподтверждённых заказов
Чтобы полностью отключить возможность оплаты для заказов, которые находятся в статусе "cancelled" или "pending" после 24 часов, нужно убрать кнопку повторной оплаты. Для этого добавьте фильтр:
add_filter('woocommerce_valid_order_statuses_for_payment', 'disable_payment_for_cancelled_orders', 10, 2);
function disable_payment_for_cancelled_orders($statuses, $order) {
if (!$order) return $statuses;
// Уберём статус cancelled из разрешённых для оплаты
$statuses = array_diff($statuses, array('cancelled'));
// Дополнительно можно убрать pending, если нужно полностью запретить оплату для неподтверждённых заказов
// $statuses = array_diff($statuses, array('pending'));
return $statuses;
}3. Настройка периодического запуска проверки
Хука woocommerce_order_status_pending может быть недостаточно, если заказ не меняет статус. Для периодической проверки можно настроить WP-Cron, который будет запускать функцию проверки всех заказов со статусом "pending", созданных более 24 часов назад.
if (!wp_next_scheduled('auto_cancel_unpaid_orders_cron')) {
wp_schedule_event(time(), 'hourly', 'auto_cancel_unpaid_orders_cron');
}
add_action('auto_cancel_unpaid_orders_cron', 'auto_cancel_all_pending_orders');
function auto_cancel_all_pending_orders() {
$args = array(
'status' => 'pending',
'date_created' => '<' . (new DateTime('-24 hours'))->format('Y-m-d H:i:s'),
'limit' => -1
);
$orders = wc_get_orders($args);
foreach ($orders as $order) {
$order->update_status('cancelled', 'Автоматическая отмена заказа, не оплачен более 24 часов.');
}
}Проверка результата после внедрения
- Создайте тестовый заказ и оставьте его в статусе "pending".
- Подождите 24 часа (или отредактируйте дату создания заказа в базе для ускорения теста).
- Запустите вручную CRON-задание через WP-CLI:
wp cron event run auto_cancel_unpaid_orders_cron. - Проверьте, что заказ сменил статус на "cancelled" и что на странице заказа отсутствует кнопка оплаты.
Частые ошибки и как их исправить
- Функция не срабатывает автоматически: проверьте, активен ли WP-Cron и нет ли конфликтов с другими плагинами, блокирующими его.
- Кнопка оплаты всё ещё доступна: убедитесь, что фильтр
woocommerce_valid_order_statuses_for_paymentкорректно подключён и не переопределяется другим кодом. - Отмена заказа происходит слишком рано или поздно: проверьте корректность вычисления времени в UTC, сравните с часовым поясом сервера и WordPress.
- Проблемы с производительностью при большом количестве заказов: ограничьте количество обрабатываемых заказов за один запуск CRON или используйте пагинацию.
Практические советы по безопасности и производительности
- Для безопасности не используйте прямые SQL-запросы в коде для выборки заказов — используйте WC_Query или wc_get_orders.
- При большом количестве заказов настройте WP-Cron на выполнение с промежутком не чаще часа, чтобы не перегружать сервер.
- Для надёжности автоматизации рассмотрите запуск WP-Cron через системный cron (например, через crontab на сервере).
- Храните сообщения изменения статуса заказа с пояснениями — это упрощает аудит и поддержку.
Сравнение вариантов реализации автоматической отмены заказов
| Вариант | Плюсы | Минусы | Пример кода |
|---|---|---|---|
Хук woocommerce_order_status_pending | Автоматический запуск при смене статуса | Не срабатывает, если статус не меняется | Функция auto_cancel_unpaid_orders_after_24h() |
| WP-Cron с периодической проверкой | Гарантированное срабатывание для всех заказов | Нагрузка на сервер при большом числе заказов | Функция auto_cancel_all_pending_orders() и расписание cron |
| Плагины автоматизации (например, Clearfy) | Готовые решения, простая настройка | Меньше контроля, возможны ограничения в функционале | Зависит от плагина, ссылка https://wpshop.ru/plugins/clearfy?utm_source=wptasks.ru&utm_medium=article&utm_campaign=woocommerce-avtomaticheskoe-otkljuchenie-oplaty-pri-nepodtverzhdennom-zakaze-s-pomoshhju-hoo |