Как отключить способы оплаты для определённых категорий товаров в WooCommerce

Сценарий типичный: в магазине есть категории товаров, для которых нельзя принимать часть оплат. Например, для цифровых товаров не нужен наложенный платёж, а для хрупких или дорогих позиций вы хотите убрать оплату при получении. В WooCommerce это лучше решать на уровне логики корзины и checkout, а не вручную в каждом заказе.

Ниже — рабочий способ через фильтр woocommerce_available_payment_gateways. Он не требует отдельного плагина и позволяет точно задать правило: если в корзине есть товар из нужной категории, скрыть конкретные способы оплаты.

Когда это действительно нужно

Ограничение платёжных методов по категориям полезно, когда правила зависят не от всей корзины, а от состава товаров. Это встречается чаще, чем кажется:

  • для цифровых товаров нужно убрать оплату при получении;
  • для предзаказов — оставить только предоплату;
  • для крупногабаритных товаров — отключить методы, которые не поддерживает логистика;
  • для B2B-категорий — показать только безналичный расчёт;
  • для акционных наборов — запретить методы, которые конфликтуют с условиями продажи.

Диагностика проблемы перед изменениями

Сначала проверьте, где именно ломается логика. Частая ошибка — пытаться скрыть оплату на странице товара, хотя WooCommerce принимает решение уже на этапе корзины и оформления заказа.

Что проверить в админке и в теме

  • какие категории назначены товарам в корзине;
  • какие способы оплаты включены в WooCommerce → Настройки → Платежи;
  • не переопределяет ли тема шаблон checkout;
  • нет ли плагина, который уже фильтрует платёжные методы;
  • не кэшируется ли checkout сторонним плагином или CDN.

Если правило не срабатывает, сначала проверьте, видит ли код нужную категорию у товара в корзине. Для этого удобно временно записать состав корзины в лог.

add_action('woocommerce_before_checkout_form', function () {
    if ( ! function_exists('WC') || ! WC()->cart ) {
        return;
    }

    foreach ( WC()->cart->get_cart() as $item ) {
        $product = $item['data'];
        if ( $product ) {
            error_log('Cart product ID: ' . $product->get_id());
            error_log('Categories: ' . implode(', ', wp_get_post_terms($product->get_id(), 'product_cat', ['fields' => 'names'])));
        }
    }
});

Этот фрагмент не нужен в продакшене постоянно. Он помогает понять, какие товары реально попадают в корзину и какие термины у них назначены.

Решение через фильтр доступных способов оплаты

Самый надёжный вариант — пройтись по товарам в корзине, проверить наличие нужной категории и убрать конкретные gateways из массива доступных методов. Логику лучше держать в дочерней теме или в небольшом mu-plugin, чтобы она не пропала после обновления темы.

Пример: скрыть наложенный платёж для категории digital

add_filter('woocommerce_available_payment_gateways', function ($gateways) {
    if ( is_admin() && ! wp_doing_ajax() ) {
        return $gateways;
    }

    if ( ! function_exists('WC') || ! WC()->cart ) {
        return $gateways;
    }

    $restricted_category = 'digital';
    $payment_methods_to_hide = ['cod'];

    $has_restricted_category = false;

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $product_id = $cart_item['product_id'];

        if ( has_term($restricted_category, 'product_cat', $product_id) ) {
            $has_restricted_category = true;
            break;
        }
    }

    if ( ! $has_restricted_category ) {
        return $gateways;
    }

    foreach ( $payment_methods_to_hide as $method_id ) {
        if ( isset($gateways[$method_id]) ) {
            unset($gateways[$method_id]);
        }
    }

    return $gateways;
});

Здесь cod — стандартный ID метода «Оплата при доставке». Если вы скрываете другой шлюз, подставьте его реальный ID. Его можно увидеть в настройках платежей или в коде плагина шлюза.

Если нужно ограничить несколько категорий и несколько методов

Когда правил больше одного, удобнее хранить их в массиве. Так код проще поддерживать и расширять без переписывания логики.

add_filter('woocommerce_available_payment_gateways', function ($gateways) {
    if ( is_admin() && ! wp_doing_ajax() ) {
        return $gateways;
    }

    if ( ! function_exists('WC') || ! WC()->cart ) {
        return $gateways;
    }

    $rules = [
        'digital' => ['cod'],
        'b2b'     => ['paypal', 'cod'],
        'preorder'=> ['cod'],
    ];

    $matched_methods = [];

    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $product_id = $cart_item['product_id'];

        foreach ( $rules as $category_slug => $methods ) {
            if ( has_term($category_slug, 'product_cat', $product_id) ) {
                $matched_methods = array_merge($matched_methods, $methods);
            }
        }
    }

    $matched_methods = array_unique($matched_methods);

    foreach ( $matched_methods as $method_id ) {
        if ( isset($gateways[$method_id]) ) {
            unset($gateways[$method_id]);
        }
    }

    return $gateways;
});

Этот вариант удобен, если у вас несколько бизнес-правил и они могут пересекаться. Например, один товар может одновременно относиться к категории b2b и preorder.

Плагин, код или гибридный подход

Если задача простая и правила не меняются часто, код обычно надёжнее. Если менеджеры магазина сами должны переключать условия без разработчика, тогда имеет смысл смотреть в сторону плагина с условиями для checkout. Но у плагинов есть компромисс: они добавляют ещё один слой логики и могут конфликтовать с другими расширениями.

ПодходКогда подходитПлюсыМинусы
Код в теме / mu-pluginПравило одно или несколько, логика стабильнаяПрозрачно, быстро, без лишних зависимостейНужен разработчик для правок
Плагин условий оплатыПравила часто меняются менеджеромУдобный интерфейс, меньше кодаРиск конфликтов, лишняя нагрузка
ГибридБазовая логика в коде, исключения в плагинеБаланс контроля и удобстваСложнее поддерживать

Как проверить, что всё работает

Проверка должна быть не формальной, а по сценарию покупки. Не ограничивайтесь просмотром страницы товара.

  1. Добавьте в корзину товар из целевой категории.
  2. Откройте checkout в режиме инкогнито или после очистки сессии.
  3. Проверьте, что скрытый способ оплаты не отображается.
  4. Добавьте товар из обычной категории и убедитесь, что метод снова доступен.
  5. Если в корзине смешанные товары, проверьте, срабатывает ли правило на весь заказ.

Если используете кэширование, тестируйте именно на реальном checkout URL, а не на закэшированной странице. Для WooCommerce это особенно важно: платёжные методы зависят от содержимого корзины и не должны отдаваться из статического кэша.

Частые ошибки и как их исправить

Неправильный ID платёжного метода

В коде часто указывают название метода вместо его ID. В массиве $gateways ключи — это именно идентификаторы шлюзов. Если вы укажете не тот ключ, метод не скроется.

Проверка категории по неправильному полю

У товара в корзине есть product_id, а у вариации — отдельный variation_id. Если правило должно работать для вариативных товаров, проверяйте именно родительский товар или учитывайте оба ID, в зависимости от структуры категорий.

Срабатывание в админке

Если не добавить защиту is_admin() и wp_doing_ajax(), можно случайно сломать отображение методов оплаты в бэкенде или в AJAX-обновлении checkout.

Конфликт с другим плагином

Некоторые плагины оплаты тоже фильтруют woocommerce_available_payment_gateways. Если ваш метод исчезает не всегда, временно отключите сторонние расширения и проверьте поведение на чистом WooCommerce.

Практические советы по безопасности и поддержке

Не вставляйте такой код в файл functions.php активной родительской темы, если тема часто обновляется. Лучше использовать дочернюю тему или отдельный mu-plugin. Тогда правило не исчезнет после обновления и его проще перенести между проектами.

Если у вас несколько условий для checkout, держите их в одном небольшом файле и комментируйте бизнес-логику. Через полгода это сэкономит время больше, чем кажется.

  • не хардкодьте названия категорий, если в проекте уже есть соглашение по slug;
  • проверяйте поведение на товарах-variations и grouped products;
  • не кэшируйте checkout как обычную страницу;
  • после обновления платёжного плагина перепроверьте ID шлюза;
  • если правило зависит от региона доставки, тестируйте связку «категория + адрес + способ доставки».

Если нужен более широкий контроль над техническими настройками магазина, в экосистеме WPShop есть Clearfy Pro: он полезен для чистки лишнего и снижения количества конфликтов на сайте, но саму логику ограничений оплаты всё равно лучше держать в коде, а не в оптимизаторе.

После внедрения ещё раз проверьте корзину с каждой проблемной категорией, затем сделайте тестовый заказ в песочнице платёжного шлюза. Если метод скрывается только на части сценариев, значит правило нужно уточнить: по категории, по тегу товара, по роли пользователя или по сумме заказа.

Автоматическое удаление неиспользуемых записей в WordPress
16.12.2025
Как создать уникальный фильтрованный список постов в WordPress с помощью WP_Query и AJAX
01.03.2026
WooCommerce: как принудительно потребовать авторизацию пользователя при оформлении заказа
13.07.2026
WooCommerce: как запретить повторное создание заказа при наличии активного
03.06.2026
Как создать собственный шорткод в WordPress
08.11.2025