Что такое зависшие платежи в 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 и код | Автоматично, снижает ошибки, экономит время | Требуется настройка, возможны ошибки без теста |
| Плагины очистки базы | Удобный интерфейс, дополнительные функции | Зависимость от стороннего ПО, нагрузка |