Проблема повторного создания заказов в WooCommerce
В интернет-магазинах на WooCommerce часто возникает ситуация, когда пользователь пытается оформить несколько заказов подряд, не завершив предыдущий или имея активный заказ в обработке. Это может привести к дублированию заказов, увеличению нагрузки на службу поддержки и путанице в учёте.
Диагностика проблемы
Для начала необходимо проверить, есть ли у пользователя активные заказы, которые не завершены (статусы processing, on-hold и т.п.). Для этого можно использовать SQL-запрос или WP_Query с фильтром по статусу и ID пользователя.
$args = [
'customer_id' => get_current_user_id(),
'status' => ['processing', 'on-hold']
];
$orders = wc_get_orders($args);
if (count($orders) > 0) {
// Пользователь имеет активные заказы
}
Если пользователь пытается оформить новый заказ, не завершив предыдущий, нужно блокировать оформление.
Пошаговое решение: запретить новый заказ при наличии активного
1. Добавляем проверку перед добавлением товара в корзину
Используем хук woocommerce_add_to_cart_validation, чтобы проверить наличие активных заказов и запретить добавление товара в корзину, если такие есть.
add_filter('woocommerce_add_to_cart_validation', 'block_add_to_cart_if_active_order', 10, 3);
function block_add_to_cart_if_active_order($passed, $product_id, $quantity) {
$user_id = get_current_user_id();
if (!$user_id) {
return $passed; // Неавторизованные пользователи пропускаются
}
$active_statuses = ['processing', 'on-hold', 'pending'];
$orders = wc_get_orders([
'customer_id' => $user_id,
'status' => $active_statuses,
'limit' => 1
]);
if (!empty($orders)) {
wc_add_notice('У вас уже есть активный заказ. Пожалуйста, завершите его перед созданием нового.', 'error');
return false; // Блокируем добавление
}
return $passed;
}
2. Блокируем оформление заказа, если пользователь обошёл проверку корзины
Проверяем наличие активных заказов прямо перед оформлением заказа, используя хук woocommerce_checkout_process.
add_action('woocommerce_checkout_process', 'block_checkout_if_active_order');
function block_checkout_if_active_order() {
$user_id = get_current_user_id();
if (!$user_id) {
return; // Неавторизованные пользователи
}
$active_statuses = ['processing', 'on-hold', 'pending'];
$orders = wc_get_orders([
'customer_id' => $user_id,
'status' => $active_statuses,
'limit' => 1
]);
if (!empty($orders)) {
wc_add_notice('У вас уже есть активный заказ. Пожалуйста, завершите его перед оформлением нового.', 'error');
}
}
Проверка результата после внедрения
- Авторизуйтесь под пользователем с активным заказом и попробуйте добавить товар в корзину — должно появиться сообщение об ошибке.
- Попытка оформить заказ с активным заказом должна прерываться с ошибкой на странице оформления.
- Для пользователей без активных заказов добавление и оформление работают как обычно.
Частые ошибки и как их исправить
- Ошибка: Проверка не срабатывает для новых пользователей без заказов.
Причина: Функция не учитывает статус гостевого пользователя или неправильно проверяет ID пользователя.
Решение: Добавьте проверкуget_current_user_id()и пропускайте неавторизованных пользователей. - Ошибка: Пользователь может добавить товар в корзину, но оформление заказа блокируется.
Причина: Проверка на добавление в корзину отсутствует или реализована неправильно.
Решение: Используйте оба хука — и для добавления в корзину, и для оформления заказа. - Ошибка: Сообщения об ошибках не отображаются.
Причина: Темы или плагины могут переопределять вывод уведомлений WooCommerce.
Решение: Проверьте поддержкуwc_print_notices()в шаблоне и отключите конфликтующие плагины.
Практические советы по производительности и безопасности
- Кэширование запросов
wc_get_ordersможет повысить производительность, если на сайте много заказов. Используйте transient API для кеширования результата на 5 минут. - Не раскрывайте в сообщениях детали о заказах или статусах, чтобы не допустить утечки информации.
- Для гостевых пользователей можно дополнительно блокировать оформление заказа по IP или email, если это актуально.
Сравнение способов реализации
| Метод | Плюсы | Минусы |
|---|---|---|
Хуки woocommerce_add_to_cart_validation и woocommerce_checkout_process | Полный контроль, гибкость, не требует сторонних плагинов | Требует базовых навыков PHP, может конфликтовать с кастомными модификациями |
| Использование плагина для ограничения заказов | Простота установки, готовые настройки | Зависимость от плагина, возможное снижение производительности, ограниченная кастомизация |
| Кастомная JavaScript-валидация на фронтенде | Быстрая обратная связь пользователю | Можно обойти, не защищает серверную логику |