Сценарий типичный: магазин работает в нескольких странах, но часть платёжных методов доступна только для конкретных регионов. Например, банковский перевод нужен только для локальных заказов, а наложенный платёж — только для одной страны. Если это не ограничить, покупатель увидит лишние варианты на этапе оформления заказа, а потом получит отказ уже после выбора оплаты.
В WooCommerce это лучше решать на уровне доступных платёжных шлюзов, а не через визуальное скрытие элементов в шаблоне. Тогда метод не попадёт в расчёт заказа и не сломает оформление при обновлении страницы checkout.
Когда это действительно нужно
Ограничение по стране полезно не только для платёжных систем. Оно помогает, если:
- эквайринг работает только в одной стране;
- наложенный платёж допустим только для локальной доставки;
- часть способов оплаты не поддерживает валюту магазина;
- нужно убрать ручные методы оплаты для зарубежных заказов;
- разные юрлица принимают оплату в разных регионах.
Диагностика: почему метод оплаты виден всем
Сначала проверьте, где именно WooCommerce принимает решение о доступности шлюза. Частая ошибка — пытаться скрыть метод через CSS или JS. Это работает только визуально: в заказе метод всё равно может остаться доступным, а при пересчёте checkout он снова появится.
Посмотрите на три вещи:
- какие платёжные шлюзы активны в WooCommerce → Настройки → Платежи;
- какая страна указана в адресе доставки или оплаты;
- используется ли плагин, который уже фильтрует методы оплаты по условиям.
Если у вас включены плагины для доставки, мультивалютности или checkout-кастомизации, сначала проверьте их настройки. Иногда они уже меняют список шлюзов через стандартные фильтры WooCommerce, и дополнительный код нужно писать аккуратно, чтобы не конфликтовать.
Рабочее решение через фильтр доступных шлюзов
Для такой задачи подходит фильтр woocommerce_available_payment_gateways. Он позволяет убрать конкретные методы оплаты в зависимости от страны в адресе доставки или оплаты.
Ниже пример для functions.php дочерней темы или собственного мини-плагина. В примере:
- для России оставляем все методы;
- для других стран скрываем
bacsиcod; - если страна не определена, ничего не ломаем и не удаляем методы принудительно.
add_filter( 'woocommerce_available_payment_gateways', 'wpstart_limit_payment_gateways_by_country' );
function wpstart_limit_payment_gateways_by_country( $gateways ) {
if ( is_admin() ) {
return $gateways;
}
if ( ! function_exists( 'WC' ) || ! WC()->customer ) {
return $gateways;
}
$country = WC()->customer->get_billing_country();
// Если страна оплаты не заполнена, не вмешиваемся.
if ( empty( $country ) ) {
$country = WC()->customer->get_shipping_country();
}
// Для России оставляем все доступные методы.
if ( 'RU' === $country ) {
return $gateways;
}
// Для остальных стран скрываем банковский перевод и наложенный платёж.
$blocked_gateways = array( 'bacs', 'cod' );
foreach ( $blocked_gateways as $gateway_id ) {
if ( isset( $gateways[ $gateway_id ] ) ) {
unset( $gateways[ $gateway_id ] );
}
}
return $gateways;
}Если нужно ограничить не два метода, а разные наборы для разных стран, удобнее вынести правила в массив. Так код проще поддерживать, когда магазин растёт.
add_filter( 'woocommerce_available_payment_gateways', 'wpstart_payment_gateways_by_country_map' );
function wpstart_payment_gateways_by_country_map( $gateways ) {
if ( is_admin() || ! function_exists( 'WC' ) || ! WC()->customer ) {
return $gateways;
}
$country = WC()->customer->get_billing_country();
if ( empty( $country ) ) {
$country = WC()->customer->get_shipping_country();
}
$rules = array(
'RU' => array(),
'KZ' => array( 'cod' ),
'BY' => array( 'cod', 'bacs' ),
'US' => array( 'cod', 'cheque' ),
);
if ( empty( $rules[ $country ] ) ) {
return $gateways;
}
foreach ( $rules[ $country ] as $gateway_id ) {
unset( $gateways[ $gateway_id ] );
}
return $gateways;
}Если страна зависит от доставки, а не от адреса оплаты
В некоторых магазинах покупатель сначала вводит адрес доставки, а платёжный метод должен зависеть именно от него. Тогда логика по billing country может быть недостаточной. В таком случае лучше использовать shipping country, но с оговоркой: на раннем этапе checkout оно может быть пустым.
Практически это означает, что:
- на первом рендере списка методов часть шлюзов может быть видна;
- после заполнения адреса WooCommerce пересчитает checkout и список обновится;
- если у вас кастомный checkout, нужно убедиться, что он триггерит обновление заказа.
Если магазин работает только с одной страной доставки, можно жёстко опираться на shipping country. Если стран несколько, лучше использовать оба поля с приоритетом billing → shipping, как в примерах выше.
Проверка результата после внедрения
После добавления кода проверьте не только внешний вид checkout, но и сам заказ. Нужна именно серверная проверка, а не только то, что вы видите в браузере.
- Откройте checkout как гость и как авторизованный пользователь.
- Проверьте страну в адресе оплаты и доставки.
- Убедитесь, что скрытые методы не отображаются в списке.
- Попробуйте оформить заказ с разрешённым методом и завершите тестовый платёж.
- Откройте созданный заказ в админке и проверьте, какой способ оплаты сохранился.
Если используете кэш страниц, обязательно очистите кэш после изменений. Checkout обычно не должен кэшироваться целиком, но на практике плагины кэша и CDN иногда вмешиваются в динамические фрагменты.
Что смотреть в логах и отладке
Если метод не скрывается, временно добавьте логирование в код, чтобы понять, какая страна реально приходит в объекте клиента. Это особенно полезно, когда адрес подставляется из геолокации или автозаполнения.
add_filter( 'woocommerce_available_payment_gateways', 'wpstart_debug_payment_country', 20 );
function wpstart_debug_payment_country( $gateways ) {
if ( function_exists( 'WC' ) && WC()->customer ) {
error_log( 'Billing country: ' . WC()->customer->get_billing_country() );
error_log( 'Shipping country: ' . WC()->customer->get_shipping_country() );
}
return $gateways;
}После проверки этот код нужно убрать. Постоянный error_log в checkout быстро засоряет логи и мешает искать реальные ошибки.
Сравнение подходов: код, плагин, CSS
| Подход | Когда подходит | Плюсы | Минусы |
|---|---|---|---|
| Фильтр WooCommerce | Нужна точная логика по стране | Работает на сервере, не ломает оформление | Нужно поддерживать код |
| Плагин с правилами оплаты | Есть сложные условия без разработки | Быстро настраивается | Может конфликтовать с checkout и доставкой |
| CSS/JS скрытие | Только временный визуальный обход | Просто внедрить | Не решает задачу корректно, метод остаётся доступным |
Частые ошибки и как их исправить
Ошибка 1. Используют неправильный ID шлюза. В WooCommerce ID метода оплаты не всегда совпадает с его названием в интерфейсе. Проверьте реальный идентификатор в коде плагина или через отладку массива $gateways.
Ошибка 2. Проверяют только billing country. Если покупатель меняет адрес доставки, логика может работать не так, как ожидается. Для магазинов с доставкой по регионам лучше учитывать оба поля.
Ошибка 3. Пишут код в основной теме. После обновления темы правило пропадёт. Используйте дочернюю тему или небольшой кастомный плагин.
Ошибка 4. Скрывают метод только на фронтенде. Это не ограничение оплаты, а косметика. Метод должен быть удалён из доступных шлюзов на сервере.
Ошибка 5. Не тестируют гостевой checkout. У авторизованного пользователя адрес может подтягиваться из профиля, а у гостя — нет. Это разные сценарии, и оба нужно проверить.
Как сделать правило безопаснее и проще в поддержке
Если ограничение по странам у вас не одно, не размножайте отдельные if на каждый метод. Лучше хранить правила в одном массиве и документировать, почему тот или иной шлюз скрывается. Это облегчает поддержку, когда меняется платёжный провайдер или список стран доставки.
Ещё один практический момент: если вы уже используете плагины для чистки и оптимизации сайта, например Clearfy Pro, не смешивайте в одном месте логику оплаты и общую оптимизацию. Для checkout лучше держать отдельный маленький модуль, чтобы при отладке не искать правило среди десятков unrelated-настроек.
И наконец, не забывайте про резервную копию перед правками. Для платёжной логики это не формальность: одна неверная проверка может скрыть все методы оплаты и остановить продажи.