Как скрыть способы оплаты при выборе самовывоза в WooCommerce

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

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

Когда проблема проявляется

Обычно ошибка заметна в одном из трёх случаев:

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

Если у вас checkout на AJAX, сначала проверьте, действительно ли WooCommerce получает выбранный метод доставки. Иногда проблема не в фильтре оплат, а в том, что выбранный shipping method не сохраняется в сессии.

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

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

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

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

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

add_filter( 'woocommerce_available_payment_gateways', 'wpbono_hide_gateways_for_local_pickup' );
function wpbono_hide_gateways_for_local_pickup( $gateways ) {
    if ( is_admin() ) {
        return $gateways;
    }

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

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

    if ( strpos( $chosen_method, 'local_pickup' ) === false ) {
        return $gateways;
    }

    // Оставляем только оплату при получении.
    $allowed_gateways = array( 'cod' );

    foreach ( $gateways as $gateway_id => $gateway ) {
        if ( ! in_array( $gateway_id, $allowed_gateways, true ) ) {
            unset( $gateways[ $gateway_id ] );
        }
    }

    return $gateways;
}

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

add_filter( 'woocommerce_available_payment_gateways', 'wpbono_hide_card_gateway_for_pickup' );
function wpbono_hide_card_gateway_for_pickup( $gateways ) {
    if ( is_admin() || ! function_exists( 'WC' ) || ! WC()->session ) {
        return $gateways;
    }

    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_method   = is_array( $chosen_methods ) ? reset( $chosen_methods ) : '';

    if ( strpos( $chosen_method, 'local_pickup' ) !== false && isset( $gateways['stripe'] ) ) {
        unset( $gateways['stripe'] );
    }

    return $gateways;
}

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

Если задача точечная и не требует отдельного плагина, действуйте так:

  1. Определите, какой именно shipping method используется для самовывоза. Это важно: у разных плагинов доставки идентификатор может отличаться.
  2. Решите, какие способы оплаты должны остаться видимыми при самовывозе.
  3. Добавьте фильтр в дочернюю тему или в небольшой mu-plugin, а не в файлы родительской темы.
  4. Проверьте checkout в обычном режиме и в режиме инкогнито, чтобы исключить влияние сохранённой сессии.
  5. Протестируйте сценарий с разными адресами и разными товарами, если у вас есть ограничения по категориям или складу.

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

Сравнение подходов

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

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

Проверка должна быть не визуальной, а функциональной. Откройте checkout и выполните несколько сценариев:

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

Если методы оплаты не меняются сразу, откройте консоль браузера и проверьте, нет ли ошибок JavaScript. Иногда сторонний плагин доставки не отправляет корректный AJAX-ответ, и тогда WooCommerce не обновляет блок оплаты.

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

Неверный ID способа доставки

Самая частая причина — в коде проверяют local_pickup, а фактически метод называется иначе. Посмотрите реальный идентификатор в настройках доставки или временно выведите его в лог.

Скрывают не тот платёжный шлюз

У многих шлюзов ID не совпадает с названием на витрине. Например, в интерфейсе может быть «Оплата картой», а в коде нужен stripe, yookassa или другой внутренний идентификатор плагина.

Код добавили в functions.php родительской темы

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

Кэш мешает обновлению checkout

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

Логика конфликтует с другими условиями

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

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

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

Если код выносите в отдельный мини-плагин, не забудьте:

  • проверять наличие WooCommerce перед выполнением логики;
  • не обращаться к WC()->session без проверки;
  • не использовать жёстко захардкоженные ID без комментария, откуда они взялись;
  • тестировать правило после обновления плагина доставки или платёжного шлюза.

Когда правил становится много, имеет смысл вынести их в отдельный слой конфигурации или использовать специализированный плагин условий. Но для задачи «самовывоз = ограниченный набор оплат» код обычно остаётся самым чистым вариантом.

Как удалить неиспользуемые метаданные в WordPress: практические решения и примеры
11.04.2026
WooCommerce: как избежать конфликтов между платежными шлюзами
30.05.2026
Как ограничить способы оплаты по методам доставки в WooCommerce
16.08.2026
Как скрыть способы оплаты при выборе самовывоза в WooCommerce
28.08.2026
Как использовать хуки WordPress для удаления стилей и скриптов: практические решения и примеры
06.12.2025