Как отключить способы оплаты в WooCommerce в зависимости от зоны доставки

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

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

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

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

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

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

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

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

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

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

Как понять, какая зона сработала

WooCommerce определяет зону доставки по адресу и затем подставляет доступные методы. На практике удобнее сначала вывести в лог, какой shipping method выбран на checkout, а потом уже привязывать к нему оплату. Для этого можно временно добавить небольшой отладочный код в functions.php дочерней темы или в собственный мини-плагин.

add_action( 'woocommerce_checkout_update_order_review', function( $posted_data ) {
    parse_str( $posted_data, $data );

    if ( ! empty( $data['shipping_method'] ) ) {
        error_log( 'Selected shipping method: ' . print_r( $data['shipping_method'], true ) );
    }
} );

После смены доставки на checkout проверьте debug.log. Это поможет понять, какой идентификатор метода доставки приходит в запросе.

Решение: скрываем способы оплаты по зоне доставки

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

Ниже пример: если выбрана доставка из зоны pickup, оставляем только оплату при получении. Если зона local, скрываем cod и оставляем онлайн-оплату.

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

    if ( ! 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 ( ! $chosen_method ) {
        return $gateways;
    }

    // Пример идентификаторов shipping method:
    // local_pickup:3, flat_rate:1, free_shipping:2
    if ( strpos( $chosen_method, 'local_pickup' ) !== false ) {
        // Для самовывоза оставляем только оплату при получении.
        foreach ( $gateways as $gateway_id => $gateway ) {
            if ( 'cod' !== $gateway_id ) {
                unset( $gateways[ $gateway_id ] );
            }
        }
    }

    if ( strpos( $chosen_method, 'flat_rate' ) !== false ) {
        // Для курьерской доставки убираем наложенный платеж.
        unset( $gateways['cod'] );
    }

    return $gateways;
} );

Это базовый шаблон. В реальном магазине лучше привязываться не к общему названию метода, а к конкретному shipping method ID, если у вас несколько зон с одинаковым типом доставки.

Если нужно ориентироваться на конкретную зону

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

function wpbono_get_shipping_zone_name() {
    if ( ! function_exists( 'WC' ) || ! WC()->customer ) {
        return '';
    }

    $package = array(
        'destination' => array(
            'country'   => WC()->customer->get_shipping_country(),
            'state'     => WC()->customer->get_shipping_state(),
            'postcode'  => WC()->customer->get_shipping_postcode(),
            'city'      => WC()->customer->get_shipping_city(),
            'address'   => WC()->customer->get_shipping_address(),
            'address_2' => WC()->customer->get_shipping_address_2(),
        ),
    );

    $zone = WC_Shipping_Zones::get_zone_matching_package( $package );

    return $zone ? $zone->get_zone_name() : '';
}

Дальше эту функцию можно использовать внутри фильтра и отключать шлюзы по имени зоны. Такой вариант удобен, если у вас зоны называются осмысленно: Самовывоз, Москва, Регионы.

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

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

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

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

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

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

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

Методы оплаты не меняются после смены доставки

Обычно причина в кэше фрагментов checkout или в том, что тема/плагин не триггерит обновление заказа. Проверьте, что на странице оформления заказа не отключён стандартный JavaScript WooCommerce и что нет конфликтов с оптимизаторами скриптов.

Фильтр срабатывает, но не на всех страницах

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

Отключается не тот способ оплаты

Частая ошибка — сравнивать человекочитаемое название доставки вместо технического идентификатора. В WooCommerce важен не текст Самовывоз, а строка вроде local_pickup:3 или flat_rate:1.

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

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

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

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

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

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

Для магазинов на WooCommerce с большим количеством правил по доставке и оплате имеет смысл держать такие изменения отдельно от темы — в мини-плагине или mu-plugin. Тогда при смене дизайна логика не потеряется и её проще сопровождать.

Как оптимизировать загрузку библиотеки jQuery в WordPress
31.12.2025
Как создать собственный виджет в WordPress с примерами кода
06.01.2026
WooCommerce: принудительная авторизация пользователя при оформлении заказа
23.04.2026
WooCommerce: как установить уникальный код для отложенных заказов
24.05.2026
WooCommerce: как автоматически отменять заказ после неуспешной оплаты
20.07.2026