Диагностика проблемы повторных заказов в WooCommerce
В интернет-магазинах на WooCommerce нередко возникает ситуация, когда пользователь случайно или намеренно создает несколько заказов на один и тот же товар или услугу, несмотря на наличие активного (не оплаченого или в процессе обработки) заказа. Это может привести к путанице в учете, дублированию оплаты и дополнительной нагрузке на службу поддержки.
Проблема особенно актуальна для товаров с ограниченным запасом, предзаказов, или услуг с длительным временем обработки.
Как понять, что проблема существует?
- Пользователь жалуется, что случайно сделал несколько заказов.
- В админке WooCommerce видны несколько заказов от одного пользователя с одинаковыми товарами, статус которых —
processing,pendingилиon-hold. - Статистика заказов показывает повторные неоплаченные заказы от одних и тех же пользователей.
Пошаговое решение: запрет повторных заказов при наличии активного
Идея решения — при попытке добавить товар в корзину проверить, есть ли у пользователя активный заказ с этим товаром, и если есть — блокировать добавление и выводить сообщение.
Для этого используем хук woocommerce_add_to_cart_validation, который позволяет предотвратить добавление товара в корзину.
function wpbono_prevent_duplicate_active_order( $passed, $product_id, $quantity, $variation_id = null, $variations= null ) {
if ( ! is_user_logged_in() ) {
// Ограничение работает только для авторизованных пользователей
return $passed;
}
$user_id = get_current_user_id();
$active_statuses = array( 'pending', 'processing', 'on-hold' );
// Получаем заказы пользователя с активными статусами
$orders = wc_get_orders( array(
'customer' => $user_id,
'status' => $active_statuses,
'limit' => -1
) );
foreach ( $orders as $order ) {
foreach ( $order->get_items() as $item ) {
if ( $item->get_product_id() == $product_id ) {
wc_add_notice( __('У вас уже есть активный заказ с этим товаром. Пожалуйста, дождитесь его обработки перед повторным заказом.'), 'error' );
return false;
}
}
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'wpbono_prevent_duplicate_active_order', 10, 5 );Этот код проверяет, есть ли у текущего пользователя заказы с активным статусом (pending, processing, on-hold), содержащие товар, который он хочет добавить в корзину. Если есть — блокирует добавление и выводит сообщение об ошибке.
Расширение: запретить повторное оформление заказа на уровне оформления
Иногда пользователь уже добавил товар в корзину, но пытается оформить заказ заново через прямой URL. Для дополнительной защиты можно запретить оформление, если в корзине есть товар, который уже есть в активном заказе пользователя.
function wpbono_prevent_checkout_with_duplicate_order() {
if ( ! is_user_logged_in() ) {
return;
}
$user_id = get_current_user_id();
$active_statuses = array( 'pending', 'processing', 'on-hold' );
$orders = wc_get_orders( array(
'customer' => $user_id,
'status' => $active_statuses,
'limit' => -1
) );
$cart = WC()->cart->get_cart();
foreach ( $orders as $order ) {
foreach ( $order->get_items() as $item ) {
$ordered_product_id = $item->get_product_id();
foreach ( $cart as $cart_item_key => $cart_item ) {
if ( $cart_item['product_id'] == $ordered_product_id ) {
wc_add_notice( __('Ваша корзина содержит товар, по которому уже есть активный заказ. Пожалуйста, дождитесь обработки существующего заказа.'), 'error' );
wp_safe_redirect( wc_get_cart_url() );
exit;
}
}
}
}
}
add_action( 'woocommerce_check_cart_items', 'wpbono_prevent_checkout_with_duplicate_order' );Проверка результата после внедрения
- Авторизуйтесь как пользователь, создайте заказ с товаром, оставьте его в статусе
pendingилиprocessing. - Попытайтесь добавить в корзину тот же товар — должна появиться ошибка, а товар не добавится.
- Попытайтесь оформить заказ с корзиной, содержащей товар из активного заказа — оформление должно быть заблокировано с выводом уведомления.
- Проверьте работу на разных статусах заказов (выполнен, отменен) — ограничения не должно быть для выполненных или отмененных заказов.
Частые ошибки и как их исправить
- Проверка только по
product_id, игнорируя вариации. Если у вас вариативные товары, то в проверке нужно сравнивать не толькоproduct_id, но иvariation_id. Иначе могут возникать ложные срабатывания или пропуски. - Работа с неавторизованными пользователями. В коде выше ограничение действует только для авторизованных, так как по гостям сложно отслеживать заказы. Если нужно — можно добавить логику по email из заказа.
- Отсутствие уведомления пользователю. Если не вызвать
wc_add_notice, пользователь не поймет, почему товар не добавляется. - Переадресация на странице оформления заказа без выхода. При переадресации нужно вызывать
exit;для остановки дальнейшего выполнения.
Практические советы по безопасности и производительности
- Используйте кэширование заказов для уменьшения нагрузки, если у вас много пользователей и заказов.
- Проверяйте, что хук
woocommerce_add_to_cart_validationне конфликтует с другими плагинами, которые тоже модифицируют добавление в корзину. - Для масштабируемых решений можно хранить информацию о «активных» товарах пользователя в пользовательском мета или transient в базе, обновляя при изменении статуса заказов.
Сравнение решений
| Способ | Плюсы | Минусы | Применимость |
|---|---|---|---|
Хук woocommerce_add_to_cart_validation | Простая реализация, блокирует добавление на уровне корзины | Работает только для авторизованных, не учитывает вариации без доработок | Малые и средние магазины |
Проверка на woocommerce_check_cart_items | Блокирует оформление заказа, предотвращая дублирование | Не предотвращает добавление в корзину, только оформление | Дополнительный уровень защиты |
| Использование сторонних плагинов | Может содержать дополнительные настройки и логику | Может быть избыточно, влияет на производительность | Крупные проекты с кастомными требованиями |