Сценарий типичный: в магазине включены предзаказы, отложенная оплата или резервирование товара, но для части ассортимента это нельзя оставлять включённым. Например, для цифровых товаров, товаров с жёстким складским учётом, акционных позиций или товаров, которые должны уходить только после полной оплаты. Если отключать всё целиком через настройки WooCommerce, вы ломаете рабочие сценарии в других категориях. Здесь нужен точечный запрет — по товарам, категориям или типу товара.
Когда проблема проявляется
Обычно это видно не в админке, а на стороне покупателя: товар можно добавить в корзину, оформить заказ, но система позволяет оплатить позже или создаёт заказ в статусе, который для этого товара не подходит. Иногда проблема всплывает уже после интеграции с платёжным шлюзом: заказ уходит в on-hold, а менеджер ожидает только processing или completed.
Что проверить до правок
- Включён ли у вас плагин для предзаказов, частичной оплаты или депозита.
- Используются ли вариации, у которых логика отличается от родительского товара.
- Есть ли отдельные категории, где предзаказ допустим, а где нет.
- Не переопределяет ли тема шаблоны корзины и оформления заказа.
- Какой статус получает заказ после оплаты у проблемного товара.
Если у вас уже есть сложная логика скидок, доставки или оплаты, сначала проверьте поведение на тестовом товаре. Иначе легко перепутать проблему предзаказа с проблемой шлюза или статуса заказа.
Какие есть варианты решения
На практике есть три подхода: отключить функцию в настройках плагина, ограничить её условиями или добавить проверку кодом. Первый вариант подходит, если предзаказ не нужен нигде. Второй — если плагин умеет правила по категориям или ролям. Третий — когда нужна точная логика, а в интерфейсе её нет.
| Подход | Когда подходит | Минус |
|---|---|---|
| Настройки плагина | Предзаказ отключается глобально или по категориям | Не всегда хватает гибкости |
| Код в теме или мини-плагине | Нужно исключить отдельные товары, категории или типы | Требует проверки после обновлений |
| Комбинация правил | Часть товаров с предзаказом, часть — только с полной оплатой | Нужно аккуратно тестировать статусы заказов |
Решение через код: запретить предзаказ для выбранных товаров
Если у вас есть плагин предзаказов, он обычно хранит логику на уровне фильтров или метаполей. Универсального хука для всех решений нет, поэтому безопаснее идти от WooCommerce-логики товара: определять, можно ли разрешать покупку без полной оплаты, и отключать это для нужных товаров.
Ниже пример, который запрещает предзаказ для товаров из конкретной категории. Его удобно использовать как основу, а затем расширить под свои условия.
<?php
add_filter( 'woocommerce_is_purchasable', 'wpexpert_disable_backorder_for_category', 10, 2 );
function wpexpert_disable_backorder_for_category( $purchasable, $product ) {
if ( ! $product instanceof WC_Product ) {
return $purchasable;
}
// Категория, для которой предзаказ и отложенная оплата запрещены.
$blocked_categories = array( 'no-backorder' );
if ( has_term( $blocked_categories, 'product_cat', $product->get_id() ) ) {
// Если товар в этой категории, оставляем обычную покупку только при наличии в наличии.
if ( ! $product->is_in_stock() ) {
return false;
}
}
return $purchasable;
}
Этот вариант не отключает предзаказ во всём магазине, а только убирает возможность купить товар, если он отсутствует на складе и попадает в нужную категорию. Для части магазинов этого достаточно: покупатель не сможет оформить заказ на то, что должно продаваться только при наличии.
Если нужно запретить именно отложенную оплату
Когда проблема не в остатках, а в том, что заказ должен оплачиваться сразу, лучше ограничивать доступные способы оплаты на этапе оформления. Для конкретных товаров можно убрать cod, банковский перевод или любой другой метод, который создаёт отложенный платёж.
<?php
add_filter( 'woocommerce_available_payment_gateways', 'wpexpert_disable_payment_for_specific_products' );
function wpexpert_disable_payment_for_specific_products( $gateways ) {
if ( is_admin() || ! is_checkout() ) {
return $gateways;
}
$blocked_product_ids = array( 123, 456 );
$cart = WC()->cart;
if ( ! $cart ) {
return $gateways;
}
foreach ( $cart->get_cart() as $item ) {
if ( in_array( (int) $item['product_id'], $blocked_product_ids, true ) ) {
// Убираем способы оплаты с отложенным списанием.
unset( $gateways['cod'] );
unset( $gateways['bacs'] );
break;
}
}
return $gateways;
}
Здесь логика уже практичнее: если в корзине есть товар из списка, покупателю не показываются неподходящие способы оплаты. Это полезно, когда товар можно купить только картой или только через мгновенный платёжный шлюз.
Пошаговая настройка без лишнего риска
- Определите, что именно нужно отключить: предзаказ, частичную оплату, оплату после подтверждения или конкретный способ оплаты.
- Соберите список товаров, категорий или вариаций, для которых правило должно работать.
- Добавьте код в мини-плагин или в
functions.phpдочерней темы. Для магазина лучше мини-плагин, чтобы не зависеть от темы. - Проверьте поведение на тестовом заказе с гостя и с авторизованного пользователя.
- Убедитесь, что статусы заказа и письма покупателю не изменились неожиданно.
Как проверить, что решение сработало
Проверка должна быть не только визуальной. Откройте товар, который попадает под правило, и пройдите весь сценарий до оформления заказа.
- Товар с запретом не должен предлагаться как доступный для предзаказа.
- Если товар отсутствует на складе, кнопка покупки должна вести себя так, как вы задумали: либо скрываться, либо блокироваться.
- На checkout не должны показываться неподходящие способы оплаты.
- После оформления заказ должен получать ожидаемый статус.
- В письмах и в админке не должно быть признаков, что товар ушёл в отложенную оплату.
Если используете кэш на уровне страницы, обязательно проверьте страницу товара и checkout в режиме без кэша или в приватном окне. Иначе можно принять старую версию страницы за рабочую.
Частые ошибки и как их исправить
Код проверяет только родительский товар
У вариативных товаров логика часто ломается, если вы смотрите только на product_id. Для вариаций нужно отдельно проверять variation_id и при необходимости родительскую категорию. Иначе часть вариантов останется доступной, хотя вы ожидали полный запрет.
Отключили не тот способ оплаты
Иногда разработчик убирает cod, а проблема была в банковском переводе или в платёжном шлюзе с отложенным capture. Проверьте, какой именно метод создаёт нежелательный сценарий, и отключайте только его.
Правило срабатывает в админке
Если не добавить проверку is_admin(), можно случайно сломать интерфейс редактирования заказа или предпросмотр товара. Для фильтров, связанных с checkout, это особенно важно.
Логика конфликтует с плагином предзаказов
Если у вас уже установлен плагин, который сам меняет доступность товара, не дублируйте его правила в двух местах. Сначала найдите, можно ли решить задачу настройкой плагина. Если нет — оставьте в коде только точечное исключение, а не вторую параллельную систему.
Безопасность и производительность
Такие правки лучше хранить не в теме, а в отдельном мини-плагине. Тогда при смене темы вы не потеряете бизнес-логику. Если правило завязано на категории или список ID товаров, не делайте тяжёлые запросы к базе на каждом рендере страницы: используйте встроенные методы WooCommerce и проверку текущей корзины.
Если вы часто меняете ассортимент, удобнее вынести список исключений в опции или в поле настроек плагина. Жёстко зашитые ID в коде работают, но плохо поддерживаются, когда каталог растёт.
Для магазинов, где нужно одновременно чистить лишнюю логику WooCommerce, отключать дубли и наводить порядок в шаблонах, иногда проще собрать базовую оптимизацию через Clearfy Pro: https://wpshop.ru/plugins/clearfy. Но саму бизнес-логику предзаказа всё равно лучше держать в коде или в специализированном плагине, а не в наборе разрозненных настроек.
Когда лучше не писать код
Если у вас уже есть плагин предзаказов с правилами по категориям, ролям и складу, сначала используйте его. Код нужен там, где интерфейс не даёт нужной точности. Если же магазин работает на нескольких платёжных сценариях и есть юридические ограничения по оплате, лучше отдельно согласовать логику с менеджером и бухгалтерией, а потом уже вносить изменения в WooCommerce.
Самая надёжная схема здесь простая: сначала определить, что именно запрещаем, потом ограничить это на уровне товара или оплаты, и только после этого проверять заказ от начала до конца. В WooCommerce такие точечные ограничения обычно работают лучше, чем попытка отключить функцию целиком по всему магазину.