Сценарий знакомый: в магазине есть самовывоз, но при выборе этого способа доставки нужно показывать не все методы оплаты. Например, при самовывозе доступен только наличный расчёт, а онлайн-эквайринг и наложенный платёж надо скрыть. В WooCommerce это лучше решать на уровне условий, а не вручную в настройках каждого метода.
Когда проблема проявляется и что именно ломается
Обычно всё выглядит так: вы добавили зону доставки, включили самовывоз, а на checkout покупатель всё равно видит банковскую карту, оплату через агрегатор и другие варианты, которые в этом сценарии не нужны. Иногда наоборот — вы уже отключили метод в настройках, но он продолжает появляться из-за кеша, стороннего плагина доставки или кастомной логики темы.
Проверять нужно не только сам список методов оплаты, но и то, какой shipping method реально выбран в сессии. В WooCommerce это важно, потому что на checkout метод доставки может меняться после AJAX-обновления, а значит и список оплат должен пересчитываться динамически.
Что стоит проверить до правки кода
- Самовывоз действительно добавлен как способ доставки в нужной зоне.
- На странице оформления заказа нет кеширования HTML-формы checkout.
- Сторонний плагин не переопределяет список платежей через свои фильтры.
- Вы тестируете не в админке, а в реальной корзине с обновлением доставки.
Какие есть варианты решения
Есть три рабочих подхода: настройка через плагин, код в теме или мини-плагине, и более жёсткая кастомизация через фильтры WooCommerce. Для точечного сценария «самовывоз → скрыть оплату» код обычно надёжнее: он прозрачен, не зависит от интерфейса плагина и легко проверяется.
| Подход | Плюсы | Минусы |
|---|---|---|
| Плагин для условий оплаты | Быстро настраивается без кода | Дополнительная зависимость, иногда конфликтует с checkout-расширениями |
| Код через фильтр WooCommerce | Точно управляет логикой, легко отлаживать | Нужно аккуратно поддерживать при обновлениях |
| Правка шаблонов checkout | Можно глубоко менять интерфейс | Хрупко, хуже переносится между темами и обновлениями |
Пошаговое решение через фильтр WooCommerce
Ниже пример, который скрывает выбранные способы оплаты, если в заказе выбран самовывоз. Код можно добавить в functions.php дочерней темы или в небольшой кастомный плагин. Второй вариант предпочтительнее, если логика нужна надолго.
add_filter( 'woocommerce_available_payment_gateways', 'wpcode_hide_gateways_for_local_pickup' );
function wpcode_hide_gateways_for_local_pickup( $gateways ) {
if ( is_admin() ) {
return $gateways;
}
if ( ! function_exists( 'WC' ) || ! WC()->session ) {
return $gateways;
}
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
if ( empty( $chosen_methods ) || ! is_array( $chosen_methods ) ) {
return $gateways;
}
$chosen_shipping = reset( $chosen_methods );
// Для самовывоза в WooCommerce обычно используется метод local_pickup.
if ( false === strpos( $chosen_shipping, 'local_pickup' ) ) {
return $gateways;
}
// Скрываем конкретные методы оплаты при самовывозе.
$blocked_gateways = array( 'stripe', 'paypal', 'cod' );
foreach ( $blocked_gateways as $gateway_id ) {
if ( isset( $gateways[ $gateway_id ] ) ) {
unset( $gateways[ $gateway_id ] );
}
}
return $gateways;
}Что здесь важно: мы не пытаемся угадать доставку по названию на русском языке. WooCommerce хранит технический идентификатор метода, и для самовывоза это обычно local_pickup. Если у вас несколько способов доставки, фильтр сработает только тогда, когда выбран именно самовывоз.
Как подстроить код под свой магазин
Список $blocked_gateways нужно заменить на реальные ID платёжных шлюзов в вашем магазине. У разных плагинов они отличаются: у одного это stripe, у другого woocommerce_payments, у третьего — собственный ID расширения. Перед правкой лучше посмотреть массив доступных шлюзов через временный лог или отладочный вывод.
add_filter( 'woocommerce_available_payment_gateways', function( $gateways ) {
if ( current_user_can( 'manage_woocommerce' ) ) {
error_log( print_r( array_keys( $gateways ), true ) );
}
return $gateways;
} );Этот фрагмент не стоит оставлять в продакшене надолго. Он полезен только для того, чтобы понять, какие ID реально доступны на checkout.
Если нужно скрывать оплату не только для самовывоза
Часто условие шире: например, при самовывозе и сумме заказа выше определённого порога нужно оставить только один метод оплаты, а при доставке курьером — другой набор. Тогда лучше строить логику от массива условий, а не от одного if. В WooCommerce это всё равно делается через тот же фильтр, просто проверок становится больше.
add_filter( 'woocommerce_available_payment_gateways', 'wpcode_payment_gateways_by_shipping_and_total' );
function wpcode_payment_gateways_by_shipping_and_total( $gateways ) {
if ( is_admin() || ! function_exists( 'WC' ) || ! WC()->session || ! WC()->cart ) {
return $gateways;
}
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = is_array( $chosen_methods ) ? reset( $chosen_methods ) : '';
$cart_total = (float) WC()->cart->get_total( 'edit' );
if ( false !== strpos( $chosen_shipping, 'local_pickup' ) ) {
unset( $gateways['stripe'], $gateways['paypal'] );
}
if ( $cart_total < 1000 ) {
unset( $gateways['cod'] );
}
return $gateways;
}Здесь есть нюанс: WC()->cart->get_total( 'edit' ) может возвращать значение в формате, который зависит от версии и контекста. Если вам нужна строгая числовая проверка, лучше использовать данные корзины до форматирования и отдельно протестировать поведение на вашей версии WooCommerce.
Как проверить, что решение сработало
После внедрения не ограничивайтесь визуальной проверкой на одной странице. WooCommerce пересчитывает checkout через AJAX, и ошибка может проявиться только после смены доставки или обновления адреса.
- Очистите кеш страницы оформления заказа, если он есть.
- Добавьте товар в корзину и перейдите к checkout.
- Выберите самовывоз и дождитесь обновления блока оплаты.
- Убедитесь, что скрытые методы исчезли из списка.
- Смените доставку на другой способ и проверьте, что методы оплаты возвращаются.
- Проверьте мобильную версию и гостевой сценарий без авторизации.
Если методы не меняются, откройте консоль браузера и посмотрите, нет ли ошибок AJAX. Иногда проблема не в фильтре, а в том, что тема или плагин ломает обновление checkout-формы.
Частые ошибки и как их исправить
Скрывают не тот ID платёжного шлюза
Самая частая ошибка — использовать название метода из интерфейса вместо технического ID. В коде нужен именно ключ массива шлюза. Если ID указан неверно, фильтр отработает, но ничего не скроет.
Проверяют доставку по тексту, а не по техническому идентификатору
Сравнение с русским названием вроде Самовывоз ненадёжно: оно зависит от перевода, темы и плагина локализации. Используйте local_pickup или другой реальный ID способа доставки.
Добавляют код в родительскую тему
После обновления темы правка исчезнет. Для такой логики лучше дочерняя тема или отдельный мини-плагин. Это особенно важно, если магазин живой и обновляется регулярно.
Не учитывают кеш checkout
Если страница оформления заказа кешируется на уровне сервера или CDN, покупатель может видеть устаревший набор методов оплаты. Для checkout кеш обычно нужно отключать или хотя бы исключать динамические блоки WooCommerce.
Оставляют код без проверки в админке
Фильтр woocommerce_available_payment_gateways может срабатывать и в административных сценариях. Поэтому в примере есть проверка is_admin(). Без неё можно случайно повлиять на внутренние операции WooCommerce и усложнить отладку.
Безопасность и производительность
Логика скрытия оплат сама по себе лёгкая, но проблемы начинаются, если в ней появляются тяжёлые запросы к базе или обращения к внешним API на каждом обновлении checkout. Для такого сценария это лишнее: решение должно быть быстрым и предсказуемым.
- Не делайте запросы к удалённым сервисам внутри фильтра оплаты.
- Не используйте сложные SQL-запросы на каждом AJAX-обновлении корзины.
- Храните список заблокированных шлюзов в коде или в настройках, а не в произвольных опциях без необходимости.
- Если логика зависит от роли пользователя, проверяйте её явно и не полагайтесь на фронтенд-скрипты.
Если вам нужно не только скрывать оплату, но и менять тексты, подсказки или порядок методов, лучше разделить эти задачи. Один фильтр — для доступности шлюзов, другой — для отображения интерфейса. Так проще отлаживать и не ломать checkout при следующем обновлении WooCommerce.
Для магазинов, где подобных условий много, удобнее вынести правила в отдельный мини-плагин и хранить их в одном месте. Тогда не придётся искать логику по нескольким файлам темы, а при переносе на staging можно быстро проверить, какие шлюзы скрываются и почему.