Диагностика проблемы повторного использования купонов
В стандартной комплектации WooCommerce купоны могут быть использованы несколько раз, если не заданы ограничения. Это вызывает проблемы с контролем скидок, особенно если вы хотите, чтобы каждый купон был активен только для одной покупки или одного пользователя.
Проверьте, как работает ваш купон:
- Перейдите в WooCommerce > Купоны;
- Откройте интересующий купон;
- В разделе "Ограничения использования" проверьте поле "Использование купона" — если там нет ограничений по количеству или пользователям, купон будет многократно применяться;
- Проверьте, могут ли зарегистрированные пользователи применить купон несколько раз;
Если купон можно использовать неограниченное количество раз, это проблема для бизнеса.
Пошаговое решение: запрет повторного использования купонов одним пользователем
WooCommerce не предлагает опцию «один купон — один пользователь» из коробки, но это можно исправить с помощью кастомного кода.
1. Добавляем проверку использования купона для текущего пользователя
В functions.php вашей дочерней темы или в кастомном плагине добавьте следующий код:
add_filter('woocommerce_coupon_is_valid', 'wpprotect_prevent_coupon_reuse', 10, 3);
function wpprotect_prevent_coupon_reuse($valid, $coupon, $discount) {
if (!$valid) return false;
$user_id = get_current_user_id();
if (!$user_id) return $valid; // Ограничение для гостей можно настроить отдельно
$coupon_code = $coupon->get_code();
// Получаем заказы пользователя
$args = array(
'customer_id' => $user_id,
'status' => array('wc-processing', 'wc-completed', 'wc-on-hold'),
'limit' => -1
);
$orders = wc_get_orders($args);
foreach ($orders as $order) {
$used_coupons = $order->get_used_coupons();
if (in_array($coupon_code, $used_coupons)) {
// Купон уже использован этим пользователем
return false;
}
}
return $valid;
}
2. Сообщение об ошибке для пользователя
Данный фильтр автоматически отклонит купон, но чтобы пользователь видел пояснение, добавим кастомное сообщение:
add_filter('woocommerce_coupon_error', 'wpprotect_coupon_used_message', 10, 3);
function wpprotect_coupon_used_message($err, $err_code, $coupon) {
if ($err_code === 'coupon_already_used') {
return 'Вы уже использовали этот купон ранее. Повторное использование запрещено.';
}
return $err;
}
Чтобы система выдавала ошибку coupon_already_used, нужно немного доработать логику в функции проверки:
add_filter('woocommerce_coupon_is_valid', 'wpprotect_prevent_coupon_reuse', 10, 3);
function wpprotect_prevent_coupon_reuse($valid, $coupon, $discount) {
if (!$valid) return false;
$user_id = get_current_user_id();
if (!$user_id) return $valid;
$coupon_code = $coupon->get_code();
$args = array(
'customer_id' => $user_id,
'status' => array('wc-processing', 'wc-completed', 'wc-on-hold'),
'limit' => -1
);
$orders = wc_get_orders($args);
foreach ($orders as $order) {
$used_coupons = $order->get_used_coupons();
if (in_array($coupon_code, $used_coupons)) {
wc_add_notice(__('Вы уже использовали этот купон ранее. Повторное использование запрещено.', 'woocommerce'), 'error');
return false;
}
}
return $valid;
}
Проверка результата после внедрения
Для тестирования:
- Зарегистрируйте тестового пользователя и авторизуйтесь;
- Примените купон при оформлении заказа, завершите заказ;
- Попробуйте применить тот же купон в новой корзине под тем же пользователем;
- Должно появиться сообщение об ошибке, и купон отклонится;
- Проверьте, что другой пользователь может применить купон (если это допустимо);
- Для гостей купон будет работать без ограничений, если не добавить отдельную проверку.
Частые ошибки и способы их исправления
- Купон не отклоняется при повторном использовании: Возможно, ваш фильтр подключен некорректно или конфликтует с другими плагинами. Проверьте приоритеты фильтров и отключите сторонние плагины для теста.
- Сообщение об ошибке не появляется: Важно, чтобы функция
wc_add_noticeбыла вызвана при проверке купона. Убедитесь, что код вставлен именно так, как в примерах. - Купон запрещён даже при первом использовании: Проверьте, что $user_id корректно определяется, и что заказы действительно содержат купон. Для теста добавьте логирование внутри функции.
- Проверка не работает для гостей: Гости не имеют ID пользователя, для них нужно реализовать отдельную логику, например, по IP или через сессии, что менее надёжно.
Практические советы по безопасности и производительности
- Используйте кэширование заказов для оптимизации запроса
wc_get_orders, особенно на сайтах с большим количеством заказов. - Если у вас много заказов, ограничьте статусами и датами запрос, чтобы ускорить проверку.
- Для повышения безопасности не позволяйте гостям использовать купоны без ограничений — рассмотрите регистрацию или двухфакторную авторизацию.
- Рассмотрите интеграцию с Clearfy Pro для оптимизации WooCommerce и очистки лишних запросов — это ускорит проверку купонов и работу магазина (подробнее).
Альтернативные варианты реализации
| Метод | Преимущества | Недостатки |
|---|---|---|
| Код в functions.php (описанный выше) | Бесплатно, гибко, кастомизация под задачи | Требует поддержки, может конфликтовать с другими плагинами |
| Плагины ограничения использования купонов (например, Advanced Coupons) | Простота установки, готовый функционал, поддержка | Платные решения, ограниченная гибкость |
| Использование кастомных ролей и условий | Можно тонко настроить под бизнес-процессы | Сложно в реализации, требует глубоких знаний |