WooCommerce: как автоматически удалять зависшие платежи

Что такое зависшие платежи в WooCommerce и почему они опасны?

Зависшие платежи — это заказы с неопределённым или незавершённым статусом, например, pending или on-hold, которые по каким-то причинам не были оплачены или подтверждены. Они накапливаются в базе данных, создавая нагрузку и мешая корректной работе магазина: заказчики могут запутаться, отчёты и аналитика искажаются, а интеграции с платёжными системами работают нестабильно.

Типичные причины возникновения зависших платежей

  • Проблемы с платёжным шлюзом (ошибки API, тайм-ауты).
  • Покупатель прервал процесс оплаты.
  • Сбой валидации оплаты на стороне сайта.
  • Необработанные возвраты или отмены.

Диагностика: как выявить зависшие платежи

Первый шаг — найти все заказы с неподтверждённой оплатой. В WooCommerce для этого служат статусы заказов:

  • pending (ожидает оплаты)
  • failed (неудачная оплата)
  • on-hold (ожидает подтверждения)

Чтобы получить список таких заказов через SQL, используйте:

SELECT ID, post_status, post_date FROM wp_posts WHERE post_type = 'shop_order' AND post_status IN ('wc-pending', 'wc-on-hold') ORDER BY post_date ASC;

Рекомендуется проверять эти заказы старше определённого срока (например, 7 дней), чтобы не удалять текущие транзакции.

Пошаговое решение: автоматическое удаление зависших платежей

1. Создаём функцию для удаления старых зависших заказов

Добавим в functions.php дочерней темы или в собственный плагин следующий код:

function wppay_remove_stale_orders() {
    $days = 7; // количество дней, после которых заказ считается «зависшим»
    $date = date('Y-m-d H:i:s', strtotime("-{$days} days"));

    $args = [
        'post_type' => 'shop_order',
        'post_status' => ['wc-pending', 'wc-on-hold'],
        'date_query' => [
            [
                'before' => $date,
            ],
        ],
        'posts_per_page' => -1,
        'fields' => 'ids',
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        foreach ($query->posts as $order_id) {
            wp_trash_post($order_id); // помещаем заказ в корзину
            // или использовать wp_delete_post($order_id, true); для полного удаления
        }
    }
}

2. Настраиваем автоматический запуск по CRON

Чтобы функция запускалась регулярно, зарегистрируем задачу в WP-Cron:

if (!wp_next_scheduled('wppay_cron_remove_stale_orders')) {
    wp_schedule_event(time(), 'daily', 'wppay_cron_remove_stale_orders');
}

add_action('wppay_cron_remove_stale_orders', 'wppay_remove_stale_orders');

Этот код запускает очистку раз в сутки. При необходимости можно изменить период на twicedaily или создать свой интервал.

Проверка результата после внедрения

  • Через 24 часа проверьте заказы со статусом pending и on-hold, старше 7 дней — их должно быть значительно меньше или они должны отсутствовать.
  • В админке WooCommerce в разделе заказы фильтруйте по статусам — убедитесь, что старые «зависшие» заказы удалены.
  • Проверьте логи платежных систем и убедитесь, что платежи не обрабатываются повторно.

Частые ошибки и как их исправить

Неправильный выбор статусов для удаления

Удаление заказов в статусах, которые означают успешные или обрабатываемые платежи (например, processing или completed), приведёт к потере данных и конфликтам. Используйте только wc-pending и wc-on-hold.

Удаление заказов с актуальными платежами

Если период удаления слишком короткий (например, 1 день), есть риск удалить заказы, по которым платеж ещё не прошёл. Рекомендуется минимум 7 дней.

Отсутствие запуска CRON

WP-Cron запускается только при посещении сайта. Для гарантированного выполнения рекомендуется настроить системный CRON на сервере, вызывающий wp-cron.php.

Практические советы по безопасности и производительности

  • Резервное копирование: перед внедрением автоматического удаления обязательно настройте регулярное резервное копирование базы данных.
  • Логирование удаления: добавьте запись в лог при удалении заказов для аудита и отладки:
function wppay_remove_stale_orders() {
    $days = 7;
    $date = date('Y-m-d H:i:s', strtotime("-{$days} days"));

    $args = [
        'post_type' => 'shop_order',
        'post_status' => ['wc-pending', 'wc-on-hold'],
        'date_query' => [
            [
                'before' => $date,
            ],
        ],
        'posts_per_page' => -1,
        'fields' => 'ids',
    ];

    $query = new WP_Query($args);

    if ($query->have_posts()) {
        foreach ($query->posts as $order_id) {
            wp_trash_post($order_id);
            error_log("[wppay] Удалён зависший заказ ID: {$order_id}");
        }
    }
}
  • Минимизация нагрузки: при большом количестве заказов разбивайте удаление на партии (например, по 50 заказов за один запуск).
  • Тестирование на staging: внедряйте и тестируйте на тестовом сайте, чтобы избежать случайной потери данных.

Сравнение вариантов удаления зависших платежей

МетодПлюсыМинусы
Ручное удаление через админкуПростота, контрольТрудозатратно, риск забыть
Автоматизация через WP-Cron и кодАвтоматично, снижает ошибки, экономит времяТребуется настройка, возможны ошибки без теста
Плагины очистки базыУдобный интерфейс, дополнительные функцииЗависимость от стороннего ПО, нагрузка
WooCommerce: как настроить обязательную 3D Secure авторизацию платежей
04.05.2026
WooCommerce: автоматическое отключение подписок при неуплаченных платежах
01.07.2026
Как создать собственный платежный шорткод в WordPress
09.11.2025
Как отладить проблемы с платежными API в WordPress
04.03.2026
Как создать подписку на платные услуги в WordPress
16.11.2025