В чём проблема: автоматическое создание заказов при незавершённом оформлении в WooCommerce
По умолчанию WooCommerce создаёт заказ в базе данных сразу после начала оформления, даже если пользователь не завершил покупку. Это приводит к накоплению большого числа «зависших» заказов со статусом pending или failed. Нагрузка на базу растёт, отчёты и аналитика искажаются, а очистка требует дополнительных усилий.
Для магазинов с высокой конверсией это не проблема, но если у вас много брошенных корзин, лучше отключить такое поведение и создавать заказ только после успешной оплаты.
Диагностика проблемы
- Проверьте количество заказов со статусом
pendingилиfailedв WooCommerce — в админке > Заказы. - Посмотрите в базе данных таблицу
wp_postsс фильтром поpost_type = 'shop_order'и статусамpost_status = 'wc-pending'илиwc-failed. - Если таких заказов тысячи и они не закрываются автоматически, это подтверждает проблему.
Почему WooCommerce создаёт заказ до оплаты
WooCommerce создаёт заказ при переходе к оплате, чтобы сохранить состояние корзины и данные пользователя. Это помогает отслеживать сеансы, кэшировать и управлять процессом оплаты, но приводит к накоплению лишних записей, если не настроена автоматическая очистка.
Пошаговое решение: отключаем автоматическое создание заказов до оплаты
Реализуем логику, при которой заказ создаётся только после успешного подтверждения оплаты, а не при начале оформления.
1. Отключаем стандартное поведение создания заказа на этапе оформления
Для этого перехватим процесс создания заказа через фильтр woocommerce_checkout_create_order или изменим логику в хуках.
Лучший способ — заменить стандартный обработчик формы оформления, чтобы заказ создавался только после подтверждения оплаты. Для платежных шлюзов, которые поддерживают асинхронные платежи, это критично.
2. Используем хук woocommerce_payment_complete для создания заказа после оплаты
Создадим заказ программно только после успешной оплаты. Вот пример кода для этого:
add_action('woocommerce_payment_complete', 'custom_create_order_after_payment', 10, 1);
function custom_create_order_after_payment($order_id) {
// Заказ уже создан WooCommerce, но скомментируем автоматическое создание ниже
// Если используете кастомную систему, создайте заказ здесь
// Пример:
// $order = wc_create_order();
// добавить товары и детали
// $order->calculate_totals();
// $order->save();
}
// Отключаем автоматическое создание заказа при начале оформления
remove_action('woocommerce_checkout_order_processed', 'wc_create_order', 10);Однако wc_create_order — внутренняя функция, не привязанная напрямую к хуку woocommerce_checkout_order_processed. Чтобы корректно отключить создание заказа на этапе оформления, нужно переопределить процесс checkout. Для этого можно использовать фильтр 'woocommerce_checkout_create_order', но проще — отложить создание заказа для конкретных платежных систем.
3. Пример отключения создания заказа при использовании платежного шлюза, например, для платежа через API
add_filter('woocommerce_checkout_create_order', 'disable_order_creation_before_payment', 10, 2);
function disable_order_creation_before_payment($order, $data) {
// Можно проверить способ оплаты и отменить создание заказа
if (isset($data['payment_method']) && $data['payment_method'] === 'your_gateway_id') {
// Возвращаем null или прерываем создание заказа
return null; // или throw исключение
}
return $order;
}Этот код предотвращает создание заказа до оплаты для конкретного шлюза. После успешной оплаты создайте заказ вручную через API WooCommerce.
Проверка результата
- Создайте тестовый заказ, не завершая оплату — в базе не должно появляться новых заказов со статусом
pending. - Завершите оплату — заказ должен создаться и иметь статус
processingилиcompleted. - Проверьте отчёты WooCommerce — количество «пустых» заказов уменьшилось.
Частые ошибки и их исправление
- Заказ не создаётся вовсе. Проверьте, что ваш код не прерывает процесс оформления полностью. Используйте логи и отладку.
- Платёжный шлюз требует заказ для API. Некоторые шлюзы не работают без существующего заказа. В этом случае создайте заказ с минимальными данными и статусом
on-hold. - Ошибки в хуках или фильтрах. Используйте
error_log()и WP_DEBUG для отладки. - Отсутствие статуса заказа после оплаты. Убедитесь, что хук
woocommerce_payment_completeкорректно срабатывает и обновляет статус.
Практические советы по безопасности и производительности
- Регулярно очищайте базу от старых заказов с помощью WP CLI или плагинов, например Clearfy Pro (https://wpshop.ru/plugins/clearfy?source=wpexpert.ru&medium=article&campaign=woocommerce-otkljuchenie-avtomaticheskogo-sozdaniya-zakazov-pri-nezakonchennom-oformlenii).
- Используйте транзакции и проверки на стороне платежного шлюза, чтобы исключить создание дубликатов заказов.
- Оптимизируйте запросы к базе данных, если вам нужно массово удалять «зависшие» заказы.
Сравнение вариантов решения
| Подход | Плюсы | Минусы |
|---|---|---|
| Отключение создания заказа до оплаты | Меньше мусора в базе, точные отчёты | Потребуется доработка платежных шлюзов, совместимость |
| Автоматическая очистка старых заказов | Простая реализация, совместима с любыми шлюзами | Зависшие заказы остаются некоторое время, нагрузка на базу |
Создание минимального заказа с on-hold статусом | Гарантированная совместимость с большинством шлюзов | База всё равно загружается заказами |