Диагностика проблемы: заказ остается в статусе "ожидает платежа" слишком долго
Иногда в WooCommerce заказы остаются в статусе pending (ожидает платежа) после того, как пользователь покинул сайт или не завершил оплату. Это приводит к захламлению базы и сбивает статистику продаж. Нужно автоматически переводить такие заказы в статус cancelled или failed спустя определенное время.
Как проверить текущие заказы с долгим статусом "pending"
SELECT ID, post_date, post_status FROM wp_posts WHERE post_type = 'shop_order' AND post_status = 'wc-pending' AND post_date < NOW() - INTERVAL 1 DAY;Этот запрос покажет заказы, которые в статусе ожидания платежа более суток. Если их много, стоит автоматизировать сброс статуса.
Пошаговое решение: автоматическое изменение статуса через WP-Cron
1. Создаем функцию для смены статуса заказов
function wpdemo_cancel_unpaid_orders() {
$args = [
'limit' => -1,
'status' => 'pending',
'date_created' => '<' . ( time() - 24 * 60 * 60 ) // заказы старше 24 часов
];
$orders = wc_get_orders( $args );
foreach ( $orders as $order ) {
$order->update_status( 'cancelled', 'Автоматически отменен из-за отсутствия платежа.' );
}
}2. Регистрируем WP-Cron задачу для ежедневного запуска
function wpdemo_schedule_cancel_unpaid_orders() {
if ( ! wp_next_scheduled( 'wpdemo_cancel_unpaid_orders_hook' ) ) {
wp_schedule_event( time(), 'daily', 'wpdemo_cancel_unpaid_orders_hook' );
}
}
add_action( 'wp', 'wpdemo_schedule_cancel_unpaid_orders' );
add_action( 'wpdemo_cancel_unpaid_orders_hook', 'wpdemo_cancel_unpaid_orders' );3. Очистка при деактивации плагина или темы
function wpdemo_clear_scheduled_event() {
$timestamp = wp_next_scheduled( 'wpdemo_cancel_unpaid_orders_hook' );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, 'wpdemo_cancel_unpaid_orders_hook' );
}
}
register_deactivation_hook( __FILE__, 'wpdemo_clear_scheduled_event' );Проверка результата после внедрения
Через сутки после активации функции проверьте наличие отмененных заказов через панель WooCommerce или по SQL-запросу:
SELECT ID, post_status, post_date FROM wp_posts WHERE post_type = 'shop_order' AND post_status = 'wc-cancelled' AND post_date > NOW() - INTERVAL 2 DAY;Если новые заказы автоматически меняют статус, значит задача работает корректно.
Частые ошибки и как их исправить
- Задача WP-Cron не запускается: проверьте системный CRON или настройте реальный cron на сервере, поскольку WP-Cron зависит от посещений сайта.
- Функция не находит заказы: убедитесь, что параметр
date_createdпередается корректно (time()в формате UNIX timestamp, аwc_get_ordersожидает объект даты или строку). - Статус не меняется: проверьте права пользователя, под которым работает PHP, а также логи ошибок.
Советы по безопасности и производительности
- Не запускать задачу слишком часто — это нагрузит базу.
- Используйте
limitи пагинацию, если заказов слишком много. - Записывайте логи в отдельный файл для отладки.
- Проверяйте, что статус меняется только у заказов со статусом
pendingи с нужным возрастом.
Альтернативы: плагин vs собственный код
| Метод | Преимущества | Недостатки |
|---|---|---|
| Плагин (например, WooCommerce Order Status Control) | Готовое решение, интерфейс настройки, поддержка | Может нагружать сайт, ограниченная кастомизация |
| Собственный WP-Cron скрипт | Полный контроль, легковесность, можно адаптировать | Требует навыков, нужно следить за работой |