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

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

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

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

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

Диагностика перед правкой

Сначала проверьте, как у вас называются методы доставки и какие ID они получают. В WooCommerce на checkout важны не названия, а идентификаторы вроде flat_rate:3, local_pickup:1 или free_shipping:2. Если вы будете сравнивать только текстовое название, правило быстро сломается после изменения настроек.

  • Откройте страницу оформления заказа и выберите каждый способ доставки вручную.
  • Посмотрите, какие способы оплаты показываются в каждом сценарии.
  • Проверьте, есть ли у доставки разные instance ID в разных зонах.
  • Убедитесь, что кэш страницы не фиксирует старый набор методов оплаты.

Если у вас включён кэш на checkout, сначала исключите из кэширования страницу оформления заказа и корзину. Иначе вы можете отлаживать не WooCommerce, а сохранённый HTML.

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

Ниже пример для темы или небольшого кастомного плагина. Он скрывает часть способов оплаты в зависимости от выбранного метода доставки. Логика простая: при самовывозе оставляем только наличные и оплату при получении, при курьерской доставке — только онлайн-эквайринг.

<?php
add_filter( 'woocommerce_available_payment_gateways', 'cyrtolat_filter_payment_gateways_by_shipping' );
function cyrtolat_filter_payment_gateways_by_shipping( $gateways ) {
    if ( is_admin() ) {
        return $gateways;
    }

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

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

    // Самовывоз
    if ( strpos( $chosen_shipping, 'local_pickup' ) === 0 ) {
        foreach ( $gateways as $gateway_id => $gateway ) {
            if ( ! in_array( $gateway_id, array( 'cod', 'bacs' ), true ) ) {
                unset( $gateways[ $gateway_id ] );
            }
        }
    }

    // Курьерская доставка
    if ( strpos( $chosen_shipping, 'flat_rate' ) === 0 ) {
        foreach ( $gateways as $gateway_id => $gateway ) {
            if ( in_array( $gateway_id, array( 'cod' ), true ) ) {
                unset( $gateways[ $gateway_id ] );
            }
        }
    }

    return $gateways;
}

Этот код нужно адаптировать под ваши реальные ID доставок и оплат. Например, если у вас самовывоз должен разрешать только bacs, уберите cod из массива. Если курьерская доставка должна разрешать только stripe или другой онлайн-метод, оставьте только его.

Как не ошибиться с ID

У способов оплаты ID обычно совпадает с ID шлюза: cod, bacs, stripe, paypal и т.д. У доставки ID сложнее: это не только тип, но и instance, поэтому одно и то же flat_rate может существовать в нескольких зонах. Если нужно привязаться к конкретной зоне, сравнивайте полное значение из сессии, например flat_rate:3.

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

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

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

    if ( $chosen_shipping === 'local_pickup:1' ) {
        foreach ( $gateways as $gateway_id => $gateway ) {
            if ( ! in_array( $gateway_id, array( 'cod', 'bacs' ), true ) ) {
                unset( $gateways[ $gateway_id ] );
            }
        }
    }

    return $gateways;
}

Какой вариант выбрать: код, плагин или настройка в платёжке

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

ПодходКогда подходитМинус
Код через фильтр2–5 понятных сценариев доставки и оплатыНужно следить за ID методов и обновлениями темы
ПлагинНужен интерфейс для менеджера без правки кодаДополнительная зависимость и риск конфликтов
Настройки платёжного шлюзаОграничения уже предусмотрены самим шлюзомОбычно покрывает только часть сценариев

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

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

  1. Сохраните резервную копию файлов темы или вынесите код в мини-плагин.
  2. Определите реальные ID способов доставки и оплаты в вашем магазине.
  3. Добавьте фильтр woocommerce_available_payment_gateways.
  4. Проверьте сценарии в тестовом заказе: самовывоз, курьер, бесплатная доставка.
  5. Очистите кэш страницы оформления заказа, если он используется.
  6. Сделайте пробный заказ в каждом сценарии и убедитесь, что лишние шлюзы не отображаются.

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

Проверка должна быть не визуальной, а сценарной. Откройте checkout в режиме инкогнито и последовательно меняйте доставку. После каждого изменения список способов оплаты должен обновляться без ручной перезагрузки страницы, если у вас стандартный checkout WooCommerce и включён AJAX-обновляемый блок доставки.

  • При самовывозе видны только разрешённые методы оплаты.
  • При курьерской доставке исчезают запрещённые методы.
  • После оформления заказа в админке сохраняется корректный payment method.
  • На мобильной версии поведение не отличается от десктопа.

Если список оплат не меняется, откройте консоль браузера и проверьте, нет ли JS-ошибок на checkout. Иногда проблема не в PHP-коде, а в скрипте темы или конфликте с оптимизацией JS.

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

Сравнивают название доставки вместо ID

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

Код добавили в functions.php дочерней темы, а потом обновили тему

Если правка лежит в родительской теме, она может исчезнуть. Для стабильности лучше использовать дочернюю тему или небольшой mu-plugin.

Не учли несколько зон доставки

Один и тот же тип доставки в разных зонах получает разные instance ID. Если ограничение должно работать только в конкретной зоне, сравнивайте полное значение, например flat_rate:3.

Checkout кэшируется

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

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

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

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

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

Добавь в закладки и поделись с друзьями:

⭐⭐⭐⭐⭐
Как сделать автоматическую удаленную очистку базы данных WordPress
15.01.2026
Автоматическое удаление товаров без остатка со склада WooCommerce
06.08.2026
Как создать адаптивный шорткод в WordPress для вывода контента
01.11.2025
Как удалить дублирующийся контент в WordPress: практические методы и примеры
22.11.2025
Как автоматизировать удалённую оптимизацию базы данных WordPress
14.02.2026
×

AI-плагин от WPShop.ru

анализирует конкурентов

пишет статьи

готовит SEO

генерирует изображения

и еще кое-что...
WPGPT
Плагин, который наполняет ваш сайт WordPress
Узнать больше