В чём суть задачи и когда это нужно
В интернет-магазинах на WooCommerce часто возникает необходимость ограничить возможность оформления заказа, если в корзине присутствуют товары с определёнными атрибутами. Например, товары с пометкой "предзаказ", "товар под заказ" или с особым статусом, для которых нужна дополнительная проверка или согласование. Это помогает избежать ошибок в заказах и снизить нагрузку на службу поддержки.
Диагностика проблемы: как понять, что оплата не должна быть доступна
Основная задача — определить, есть ли в корзине товары с нужными атрибутами. Атрибуты в WooCommerce — это свойства товаров, которые можно задать в админке. Для проверки нужно пройтись по всем товарам в корзине и проверить наличие целевых атрибутов.
Для диагностики используйте следующий код в functions.php или в собственном плагине для отладки:
function debug_check_cart_for_attribute( $attribute_name, $attribute_value ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
$attributes = $product->get_attributes();
if ( isset( $attributes[ $attribute_name ] ) ) {
$terms = wc_get_product_terms( $product->get_id(), $attribute_name, array( 'fields' => 'names' ) );
if ( in_array( $attribute_value, $terms, true ) ) {
error_log( "Товар с атрибутом $attribute_name: $attribute_value найден в корзине" );
return true;
}
}
}
error_log( "Товар с атрибутом $attribute_name: $attribute_value НЕ найден в корзине" );
return false;
}После добавления товаров с нужным атрибутом в корзину и перехода на страницу оформления заказа, смотрите журнал ошибок PHP (error_log), чтобы убедиться, что функция находит нужные товары.
Пошаговое решение: блокируем оплату при наличии товара с атрибутом
1. Определяем атрибут (например, pa_status) и значение (например, preorder).
2. Создаём функцию проверки корзины на наличие таких товаров.
3. Используем хук woocommerce_checkout_process для блокировки оформления.
4. Добавляем уведомление пользователю о причине блокировки.
add_action( 'woocommerce_checkout_process', 'block_checkout_if_cart_has_attribute' );
function block_checkout_if_cart_has_attribute() {
$attribute_name = 'pa_status'; // техническое имя атрибута
$attribute_value = 'preorder'; // значение, при котором блокируем
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
$terms = wc_get_product_terms( $product->get_id(), $attribute_name, array( 'fields' => 'slugs' ) );
if ( in_array( $attribute_value, $terms, true ) ) {
wc_add_notice( 'Оплата недоступна: в вашей корзине есть товары с пометкой «Предзаказ». Пожалуйста, свяжитесь с нами для уточнения.', 'error' );
break;
}
}
}Дополнительно: блокируем кнопку «Оформить заказ» на фронте
Чтобы UX был лучше, можно скрыть кнопку «Оформить заказ» или отключить её на странице корзины и оформления заказа, если есть товары с блокирующим атрибутом.
add_filter( 'woocommerce_order_button_html', 'disable_place_order_button_if_attribute' );
function disable_place_order_button_if_attribute( $button_html ) {
$attribute_name = 'pa_status';
$attribute_value = 'preorder';
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
$terms = wc_get_product_terms( $product->get_id(), $attribute_name, array( 'fields' => 'slugs' ) );
if ( in_array( $attribute_value, $terms, true ) ) {
return '<button type="submit" class="button alt" disabled style="opacity: 0.5; cursor: not-allowed;">Оплата недоступна</button>';
}
}
return $button_html;
}Как проверить, что всё работает
- Создайте атрибут товара в WooCommerce, например
pa_status, и добавьте значениеpreorder. - Назначьте этот атрибут одному или нескольким товарам в магазине.
- Добавьте такие товары в корзину.
- Перейдите к оформлению заказа — должно появиться сообщение об ошибке, и оформление будет заблокировано.
- На странице корзины кнопка «Оформить заказ» будет отключена (серой и недоступной для клика).
- Если удалить товары с этим атрибутом из корзины, оформление снова станет доступным.
Частые ошибки и как их исправить
- Неправильное имя атрибута: В WooCommerce атрибуты товаров имеют префикс
pa_. Проверьте точное техническое имя атрибута в разделе «Атрибуты» — оно должно совпадать с используемым в коде. - Значение атрибута указано не slug, а название: В функции
wc_get_product_termsважно указывать, что берутся слаги (slug), если сравниваете с ними. - Кэширование страницы корзины или оформления заказа: Иногда кэш мешает обновлению состояния кнопки или сообщения. Очистите кэш или используйте режим разработчика для проверки.
- Проблемы с темой или плагинами: Если другие плагины или тема переопределяют обработку кнопки оформления заказа, нужно проверить совместимость и приоритеты хуков.
Практические советы по безопасности и производительности
- Не используйте тяжелые операции в цикле проверки корзины. В приведённом примере мы только получаем атрибуты и сравниваем — это быстро и не создаёт нагрузки.
- Используйте правильные хуки WooCommerce (
woocommerce_checkout_processдля проверки на этапе оформления иwoocommerce_order_button_htmlдля управления кнопкой). - Обязательно проверяйте, что в корзине есть товары, чтобы не вызывать лишних ошибок.
- Для улучшения UX показывайте поясняющие сообщения пользователю, чтобы он понимал причину блокировки.
Сравнение способов реализации блокировки оплаты
| Способ | Плюсы | Минусы |
|---|---|---|
| PHP-код на хуках WooCommerce | Лёгкость настройки, контроль, без сторонних плагинов | Требует навыков программирования, возможна несовместимость с кастомными темами |
| Плагин блокировки товаров | Простота использования, визуальные настройки | Дополнительная нагрузка, возможны конфликты с другими плагинами |
| JavaScript-скрипты для скрытия кнопки | Быстрое визуальное решение | Не блокирует серверную обработку, легко обходится пользователем |