Диагностика проблемы: почему нужно блокировать оплату по атрибутам товара
В WooCommerce иногда возникает задача запретить оформление заказа, если в корзине находятся товары с определёнными атрибутами. Например, запрещать оплату при наличии товаров с атрибутом "Распродажа" или "Не для продажи онлайн". Без такого ограничения покупатель сможет оформить заказ, хотя продажа таких товаров запрещена, что ведёт к проблемам с логистикой и учётом.
Проверка проблемы:
- Добавьте в корзину товар с нужным атрибутом.
- Попробуйте перейти к оплате.
- Если оплата доступна, значит ограничения нет.
Пошаговое решение: блокировка оплаты на основании атрибутов товаров
1. Определяем атрибуты, по которым будет блокировка
Для примера возьмём атрибут с именем special_sale и значением yes. Это может быть любой атрибут, настроенный в WooCommerce.
2. Добавляем код в functions.php или в свой плагин
add_action('woocommerce_check_cart_items', 'block_checkout_if_attribute_in_cart');
function block_checkout_if_attribute_in_cart() {
$block_attribute = 'special_sale'; // слаг атрибута товара
$block_value = 'yes'; // значение атрибута для блокировки
foreach (WC()->cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
if (isset($attributes[$block_attribute])) {
$attribute = $attributes[$block_attribute];
// Для глобальных атрибутов получаем термы
if ($attribute->is_taxonomy()) {
$terms = wp_get_post_terms($product->get_id(), $attribute->get_name(), array('fields' => 'slugs'));
if (in_array($block_value, $terms)) {
wc_add_notice('Оплата недоступна: в корзине есть товар с запрещённым атрибутом.', 'error');
break;
}
} else {
// Для пользовательских атрибутов
if ($attribute->get_options() && in_array($block_value, $attribute->get_options())) {
wc_add_notice('Оплата недоступна: в корзине есть товар с запрещённым атрибутом.', 'error');
break;
}
}
}
}
}3. Объяснение кода
Хук woocommerce_check_cart_items вызывается перед оформлением заказа. Мы перебираем все товары в корзине, проверяем их атрибуты, и если находим запрещённый атрибут с нужным значением — добавляем уведомление об ошибке, которое блокирует переход к оплате.
Проверка результата после внедрения
- Добавьте в корзину товар с атрибутом
special_saleи значениемyes. - Перейдите к оформлению заказа.
- Вы должны увидеть ошибку и невозможность перейти к оплате.
- Для товаров без такого атрибута оформление заказа должно быть доступно.
Частые ошибки и способы их исправления
- Атрибут не определяется: убедитесь, что используете правильный слаг атрибута, а не его название. Атрибуты WooCommerce хранятся с префиксом
pa_для глобальных (например,pa_special_sale). - Значение не совпадает: проверьте, что значение атрибута соответствует slug терма, а не его имени.
- Ошибка в типе атрибута: для пользовательских (локальных) атрибутов get_options() возвращает массив строк, для глобальных используется таксономия — нужно проверить оба варианта.
- Кэширование корзины: иногда кэш плагинов или браузера мешает обновлению статуса оплаты — очистите кэш после изменений.
Практические советы по безопасности и производительности
- Не добавляйте тяжёлые запросы внутри
woocommerce_check_cart_items, чтобы не замедлять процесс оформления заказа. - Используйте правильные хуки и не меняйте глобальные переменные напрямую.
- Если атрибутов много — можно кешировать результаты проверки на время сессии.
- Чтобы избежать проблем с кэшированием страниц, используйте фрагменты кэша WooCommerce или AJAX-обновления корзины.
Сравнение вариантов реализации блокировки оплаты
| Метод | Плюсы | Минусы | Рекомендуется для |
|---|---|---|---|
| Код в functions.php | Полный контроль, нет лишних плагинов | Требуется знание PHP, возможны ошибки | Разработчики, кастомные сайты |
| Плагин блокировки оплаты | Простота настройки, поддержка | Может быть избыточным, нагрузка | Новички, быстрые решения |
| Изменение атрибутов товара | Управление на уровне товаров | Не всегда возможно без кода | Маленькие магазины |