WooCommerce: как отключить оплату для определённых заказов по условиям

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

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

Когда вообще нужно отключать оплату по условиям

Типовые сценарии в WooCommerce выглядят одинаково на уровне задачи, но отличаются по условиям:

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

Если задача повторяется и зависит от нескольких признаков заказа, лучше решать её кодом. Плагин подойдёт только если логика очень простая и не меняется. Иначе вы быстро упрётесь в ограничения интерфейса.

Диагностика проблемы: что проверить до правки кода

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

Проверьте базовые настройки

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

Если способ оплаты исчезает только после выбора доставки, это нормальное поведение: WooCommerce пересчитывает доступные шлюзы на основе адреса и shipping method. Если же он пропадает всегда, значит условие в коде слишком жёсткое или проверяется не тот объект.

Что смотреть в отладке

Для проверки удобно временно вывести список доступных шлюзов в лог. Это безопаснее, чем гадать по интерфейсу. Включите логирование в wp-config.php, если оно ещё не включено:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );

После этого можно писать в лог названия доступных методов оплаты на этапе фильтра. Это помогает понять, что именно приходит в массив $available_gateways.

Решение: отключаем способы оплаты через фильтр WooCommerce

Самый надёжный вариант — использовать фильтр woocommerce_available_payment_gateways. Он позволяет убрать конкретный шлюз уже после того, как WooCommerce собрал список доступных методов для текущего заказа.

Ниже пример для functions.php дочерней темы или для собственного мини-плагина. Код отключает оплату cod и bacs, если в корзине есть товар из категории preorder.

add_filter( 'woocommerce_available_payment_gateways', 'wpticket_disable_gateways_for_preorder' );

function wpticket_disable_gateways_for_preorder( $available_gateways ) {
    if ( is_admin() && ! wp_doing_ajax() ) {
        return $available_gateways;
    }

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

    $has_preorder_product = false;

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

        if ( has_term( 'preorder', 'product_cat', $product_id ) ) {
            $has_preorder_product = true;
            break;
        }
    }

    if ( $has_preorder_product ) {
        unset( $available_gateways['cod'] );
        unset( $available_gateways['bacs'] );
    }

    return $available_gateways;
}

Здесь важно два момента. Первый: проверка делается по WC()->cart, а не по заказу, потому что на странице оформления заказа заказ ещё не создан. Второй: мы не трогаем все шлюзы подряд, а убираем только нужные ID. У каждого платёжного метода свой идентификатор, и его надо брать из настроек или из кода шлюза.

Пример для отключения оплаты при самовывозе

Если логика завязана на способ доставки, лучше проверять выбранный shipping method. В WooCommerce он приходит как массив, и в нём обычно лежит строка вида local_pickup:3 или flat_rate:1.

add_filter( 'woocommerce_available_payment_gateways', 'wpticket_disable_gateways_for_local_pickup' );

function wpticket_disable_gateways_for_local_pickup( $available_gateways ) {
    if ( is_admin() && ! wp_doing_ajax() ) {
        return $available_gateways;
    }

    if ( ! WC()->session ) {
        return $available_gateways;
    }

    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_method   = is_array( $chosen_methods ) && ! empty( $chosen_methods[0] ) ? $chosen_methods[0] : '';

    if ( strpos( $chosen_method, 'local_pickup' ) !== false ) {
        unset( $available_gateways['cod'] );
    }

    return $available_gateways;
}

Такой вариант полезен, если вы не хотите принимать наличные при самовывозе или наоборот хотите оставить только оплату на месте. Но если у вас несколько складов и разные правила по каждому, лучше расширить условие и проверять не только метод доставки, но и ID зоны доставки или метаданные заказа.

Сравнение подходов: плагин, код, гибрид

ПодходКогда подходитМинус
ПлагинПростое правило без исключенийСложно поддерживать, если логика меняется
Код через фильтрНужны точные условия по корзине, доставке, странеНужно аккуратно тестировать
ГибридЧасть правил в плагине, часть — в кодеЛегко запутаться в приоритетах

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

Пошаговая настройка без лишних рисков

  1. Создайте дочернюю тему или отдельный мини-плагин для кастомного кода.
  2. Определите, по какому признаку нужно отключать оплату: товар, категория, сумма, доставка, страна.
  3. Найдите ID платёжных шлюзов, которые нужно скрывать.
  4. Добавьте фильтр woocommerce_available_payment_gateways.
  5. Проверьте условие сначала на одной странице оформления заказа.
  6. Протестируйте сценарий с гостевым покупателем и с авторизованным пользователем.
  7. Проверьте, не ломается ли пересчёт после смены доставки и адреса.

Если нужно отключать оплату по сумме заказа, пример будет похожим, только вместо категории проверяется WC()->cart->get_total() или сумма товаров до доставки и налогов. Но здесь важно не сравнивать строку с валютным символом, а приводить значение к числу.

add_filter( 'woocommerce_available_payment_gateways', 'wpticket_disable_gateways_by_cart_total' );

function wpticket_disable_gateways_by_cart_total( $available_gateways ) {
    if ( ! WC()->cart ) {
        return $available_gateways;
    }

    $cart_total = (float) WC()->cart->get_cart_contents_total();

    if ( $cart_total < 3000 ) {
        unset( $available_gateways['cod'] );
    }

    return $available_gateways;
}

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

Как проверить, что решение сработало

Проверка должна быть не только визуальной. Нужны минимум три сценария:

  • корзина без условий — все нужные способы оплаты видны;
  • корзина с условием — лишний способ оплаты исчезает;
  • смена доставки или адреса — список методов обновляется корректно без ошибки в checkout.

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

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

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

Проверяют не тот ID шлюза

Самая частая причина — в коде указан не тот ключ. Например, вы отключаете cod, а у вас установлен другой плагин наложенного платежа с собственным ID. Сначала посмотрите массив $available_gateways через лог или временный error_log().

Используют условие в админке без исключения AJAX

Если не добавить проверку ! wp_doing_ajax(), фильтр может мешать обновлению checkout в админке или при AJAX-пересчёте. В результате появляются странные ошибки при редактировании заказа.

Пишут логику слишком рано

Если проверять доставку до того, как WooCommerce сохранил выбранный метод в сессии, условие не сработает. Для таких сценариев лучше опираться на WC()->session и на фильтр доступных шлюзов, а не на ранние хуки загрузки страницы.

Сравнивают сумму как строку

Когда сумма берётся из отображаемого значения с валютой, сравнение ломается. Всегда приводите данные к числу и учитывайте, включён ли налог в сумму корзины.

Чек-лист перед публикацией на боевом сайте

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

Безопасность и производительность

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

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

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

Как добавить автоматическое возвращение тикетов в WordPress
02.04.2026
Как избежать проблем с множественными сессиями входа в WordPress
03.07.2026
Как настроить robots.txt в WordPress для закрытия технических страниц
16.08.2026
Как создать автоматические эскалации в тикет-системе WordPress
09.02.2026
Как отключить индексацию технических страниц WordPress
19.08.2026