Сценарий типичный: клиент выбирает самовывоз, а магазин всё равно показывает онлайн-оплату, наложенный платёж или лишние способы, которые в этом сценарии не нужны. В WooCommerce это можно решить без тяжёлых плагинов, если правильно отфильтровать доступные методы оплаты на основе выбранного способа доставки.
Ниже разберём рабочие варианты: когда хватает настроек, когда нужен код, как проверить, что ограничение срабатывает только для самовывоза, и где чаще всего ломают checkout.
Когда проблема действительно в способах оплаты
Сначала стоит убедиться, что дело не в настройках самовывоза, а в логике доставки и платежей. WooCommerce не умеет “из коробки” скрывать оплату по условию доставки на уровне интерфейса без дополнительной настройки или кода. Поэтому если вы видите все методы оплаты при выборе самовывоза, это обычно нормальное поведение, а не баг.
Что проверить в админке
- Включён ли самовывоз в WooCommerce → Настройки → Доставка.
- Нет ли у способа доставки отдельной зоны, где подключены другие методы, кроме самовывоза.
- Не влияет ли плагин для checkout, доставки или оплаты на список доступных методов.
- Не используется ли кэширование страницы оформления заказа на стороне темы, плагина или CDN.
Если самовывоз настроен корректно, а оплату нужно скрывать только в этом случае, проще всего сделать это фильтром WooCommerce.
Как отключить оплату при самовывозе через код
Самый надёжный вариант — отфильтровать методы оплаты через хук woocommerce_available_payment_gateways. Он позволяет убрать лишние способы оплаты на этапе расчёта доступных gateway.
Ниже пример, который скрывает все способы оплаты, если выбран метод доставки local_pickup. Важно: в WooCommerce ID самовывоза может отличаться, если у вас несколько зон доставки или сторонние плагины. Для стандартного самовывоза обычно используется строка с local_pickup.
<?php
add_filter( 'woocommerce_available_payment_gateways', 'two_wp_disable_payments_for_local_pickup' );
function two_wp_disable_payments_for_local_pickup( $available_gateways ) {
if ( is_admin() ) {
return $available_gateways;
}
if ( ! function_exists( 'WC' ) || ! WC()->session ) {
return $available_gateways;
}
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
if ( empty( $chosen_methods ) || ! is_array( $chosen_methods ) ) {
return $available_gateways;
}
foreach ( $chosen_methods as $chosen_method ) {
if ( strpos( $chosen_method, 'local_pickup' ) !== false ) {
return array();
}
}
return $available_gateways;
}
Этот вариант жёсткий: при самовывозе он скрывает вообще все способы оплаты. Подходит, если заказ оплачивается только на месте или менеджером вручную.
Если нужно оставить только один способ оплаты
Иногда при самовывозе не нужно отключать оплату полностью — достаточно оставить, например, только оплату наличными при получении. Тогда лучше не возвращать пустой массив, а отфильтровать конкретные gateway по ID.
<?php
add_filter( 'woocommerce_available_payment_gateways', 'two_wp_keep_only_cod_for_local_pickup' );
function two_wp_keep_only_cod_for_local_pickup( $available_gateways ) {
if ( is_admin() || ! function_exists( 'WC' ) || ! WC()->session ) {
return $available_gateways;
}
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
if ( empty( $chosen_methods ) || ! is_array( $chosen_methods ) ) {
return $available_gateways;
}
$is_local_pickup = false;
foreach ( $chosen_methods as $chosen_method ) {
if ( strpos( $chosen_method, 'local_pickup' ) !== false ) {
$is_local_pickup = true;
break;
}
}
if ( ! $is_local_pickup ) {
return $available_gateways;
}
foreach ( $available_gateways as $gateway_id => $gateway ) {
if ( 'cod' !== $gateway_id ) {
unset( $available_gateways[ $gateway_id ] );
}
}
return $available_gateways;
}
Здесь остаётся только cod — стандартный способ “оплата при доставке”. Если у вас другой метод, замените ID на свой.
Сравнение подходов: настройки, плагин или код
| Подход | Когда подходит | Минусы |
|---|---|---|
| Настройки WooCommerce | Если плагин доставки уже умеет ограничивать оплату | Не во всех конфигурациях есть нужная логика |
| Плагин для conditional payment methods | Если нужно без кода и с несколькими условиями | Дополнительная нагрузка и зависимость от стороннего решения |
| Код через фильтр | Если условие простое и нужно контролировать поведение точно | Нужно аккуратно проверить ID доставки и оплаты |
Если у вас уже стоит плагин, который добавляет условную логику для checkout, сначала проверьте его возможности. Но для одной простой зависимости “самовывоз = без онлайн-оплаты” код обычно надёжнее и прозрачнее.
Пошаговая настройка без лишних рисков
Шаг 1. Определите, какой метод доставки считается самовывозом
Откройте оформление заказа и посмотрите, как называется выбранный shipping method в сессии. В стандартном WooCommerce это обычно local_pickup, но при сложной конфигурации строка может содержать номер зоны или instance ID.
Шаг 2. Добавьте код в дочернюю тему или мини-плагин
Не вставляйте такой код в файлы основной темы, если она обновляется. Лучше использовать дочернюю тему или небольшой собственный плагин. Так вы не потеряете правки после обновления.
Шаг 3. Очистите кэш checkout-страницы
Если на сайте есть кэширование, исключите страницу оформления заказа и страницу корзины. Иначе можно увидеть старый список способов оплаты даже после внесения правок.
Шаг 4. Проверьте несколько сценариев
- Самовывоз выбран — нужные способы оплаты скрыты.
- Курьерская доставка выбрана — способы оплаты отображаются как обычно.
- Гость и авторизованный пользователь видят одинаковое поведение.
- На мобильной версии checkout логика не ломается после обновления блока доставки.
Как проверить, что решение сработало
Проверка должна быть не визуальной “на глаз”, а по сценариям. Откройте checkout в режиме инкогнито и последовательно переключайте способы доставки. После выбора самовывоза список платежей должен обновиться без ручной перезагрузки страницы, если у вас стандартный AJAX checkout.
Полезно проверить и технически: временно добавьте логирование или используйте отладку в браузере, чтобы убедиться, что выбранный shipping method действительно попадает в сессию WooCommerce.
Если хотите быстро увидеть, какой метод доставки хранится в сессии, можно временно вывести его в лог:
<?php
add_action( 'woocommerce_checkout_update_order_review', function( $post_data ) {
if ( function_exists( 'WC' ) && WC()->session ) {
error_log( print_r( WC()->session->get( 'chosen_shipping_methods' ), true ) );
}
} );
После проверки этот код нужно удалить. Логи не должны оставаться в рабочем проекте без необходимости.
Частые ошибки и как их исправить
Неправильный ID способа доставки
Самая частая проблема — код ищет local_pickup, а у вас другой идентификатор. Это бывает при нескольких зонах доставки или сторонних расширениях. Решение простое: посмотрите фактическое значение в сессии и подставьте его в условие.
Код добавлен в не то место
Если вставить фильтр в файл, который не загружается на checkout, он просто не сработает. Проверьте, что код находится в активной дочерней теме, в плагине или в другом реально исполняемом месте.
Кэш мешает обновлению checkout
Даже рабочий код не поможет, если страница оформления заказа отдаётся из кэша. Исключите /checkout/, /cart/ и, если есть, страницу оплаты из кэширования на уровне плагина, сервера и CDN.
Сторонний плагин переопределяет оплату
Некоторые плагины для доставки и оплаты добавляют собственные фильтры и могут возвращать gateway после вашего кода. В таком случае проверьте приоритеты хуков и временно отключите конфликтующий плагин для теста.
Что учесть по безопасности и производительности
Сам фильтр лёгкий и почти не влияет на производительность, если не делать лишних запросов к базе. Не нужно в этом месте запускать сложные WP_Query или обращаться к внешним API. Логика должна опираться на данные сессии WooCommerce и простую проверку строки.
С точки зрения безопасности важно не полагаться только на фронтенд-скрытие. Даже если вы убрали способы оплаты на странице, серверная логика заказа должна оставаться согласованной. Именно поэтому фильтр на стороне WooCommerce лучше, чем попытка спрятать блок через CSS или JavaScript.
Если вам нужна более сложная логика — например, скрывать оплату при самовывозе только для определённых ролей, стран или сумм заказа — лучше вынести правила в отдельную функцию и протестировать каждый сценарий отдельно. Чем больше условий, тем выше шанс сломать checkout на редком кейсе.
В магазинах, где checkout часто меняется, удобно держать такие правки в маленьком кастомном плагине. Это проще сопровождать, чем искать код по шаблонам темы. Если нужно ещё и чистить лишние элементы оформления заказа, иногда помогает связка с Clearfy Pro, но условную логику оплаты всё равно лучше оставлять в коде, а не в наборе разрозненных настроек.