WooCommerce

Как отключить наложенный платёж для конкретных товаров в WooCommerce

M
Markabus
·20 ноября 2019 г.
Как отключить наложенный платёж для конкретных товаров в WooCommerce

Наложенный платёж удобен покупателю и рискован магазину: товар едет к клиенту, а деньги — под вопросом, пока он не заберёт посылку. Для дешёвых и ходовых позиций риск терпимый, но для дорогих, хрупких или сделанных под заказ вещей многие магазины предпочитают предоплату. WooCommerce позволяет убрать «Наложенный платёж» из списка способов оплаты, если в корзине оказался хотя бы один такой товар.

Как это работает

Список способов оплаты на чекауте проходит через фильтр woocommerce_available_payment_gateways. Он получает массив доступных шлюзов, где ключ — идентификатор способа оплаты. У встроенного «Наложенного платежа» это cod. Удаляем ключ из массива — способ исчезает с чекаута. Код добавляется в functions.php дочерней темы.

Вариант 1: по списку товаров

add_filter( 'woocommerce_available_payment_gateways', 'shop_disable_cod_for_products' );
function shop_disable_cod_for_products( $gateways ) {
    // В админке и там, где корзины ещё нет, ничего не трогаем
    if ( is_admin() || ! WC()->cart || ! isset( $gateways['cod'] ) ) {
        return $gateways;
    }

    // ID товаров, для которых наложенный платёж недоступен
    $no_cod_products = array( 37, 40, 53 );

    foreach ( WC()->cart->get_cart() as $item ) {
        if ( in_array( $item['product_id'], $no_cod_products, true ) ) {
            unset( $gateways['cod'] );
            break; // достаточно одного совпадения
        }
    }

    return $gateways;
}

Три момента, которые здесь важны. Проверка в начале защищает от ошибок: фильтр срабатывает не только на чекауте, но и в админке при ручном создании заказа, где объекта корзины может не быть. Проверка isset( $gateways['cod'] ) экономит цикл, если наложенный платёж и так выключен. А break останавливает перебор после первого совпадения — искать дальше незачем.

ID товара видно в админке в списке товаров при наведении на название, либо в адресной строке на странице редактирования.

Вариативные товары

У товара с вариациями два идентификатора: product_id — общий родительский, и variation_id — конкретной вариации. Код выше сравнивает родительский, то есть отключает наложенный платёж для всех вариаций товара сразу. Если нужно ограничить только одну вариацию, скажем, самую дорогую, сравнивайте $item['variation_id'] и указывайте в списке ID вариаций.

Вариант 2: по категории — удобнее в поддержке

Список ID в коде — это то, что придётся править при каждом новом товаре. Практичнее завести категорию, например «Без наложенного платежа», и относить к ней товары прямо из админки. Код при этом не меняется никогда:

add_filter( 'woocommerce_available_payment_gateways', 'shop_disable_cod_for_category' );
function shop_disable_cod_for_category( $gateways ) {
    if ( is_admin() || ! WC()->cart || ! isset( $gateways['cod'] ) ) {
        return $gateways;
    }

    foreach ( WC()->cart->get_cart() as $item ) {
        // has_term принимает slug или ID категории; проверяем по родительскому товару
        if ( has_term( 'bez-nalozhennogo-platezha', 'product_cat', $item['product_id'] ) ) {
            unset( $gateways['cod'] );
            break;
        }
    }

    return $gateways;
}

Категория может быть скрытой от каталога — покупателю её видеть не обязательно. Тот же приём работает и с метками (product_tag) или классом доставки, если товары уже размечены таким образом: у класса доставки «Хрупкое» логично сразу отключать и наложенный платёж.

Другие условия

Фильтр не ограничен товарами — внутри доступна вся корзина, поэтому по той же схеме отключают наложенный платёж по сумме заказа (например, свыше 20 000 ₽), по выбранному способу доставки (курьером — можно, почтой — нет) или по региону покупателя. Логика та же: проверили условие, удалили ключ, вернули массив.

Идентификаторы других способов оплаты отличаются от cod и зависят от плагина. Посмотреть их можно в WooCommerce → Настройки → Платежи, либо один раз вывести в лог array_keys( $gateways ) внутри фильтра.

Классический и блочный чекаут

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

Коротко

Отключение наложенного платежа для отдельных товаров — это один фильтр и один цикл по корзине. Для пары позиций хватит списка ID, для живого каталога заведите категорию или метку и управляйте всем из админки. Не забудьте защиту от контекстов без корзины и помните про разницу между родительским товаром и вариацией.

Частые вопросы

Q.Как узнать идентификатор способа оплаты?

У встроенного наложенного платежа это cod. У других шлюзов — свои: смотрите в WooCommerce → Настройки → Платежи или один раз выведите array_keys( $gateways ) внутри фильтра.

Q.Сработает ли это на блочном чекауте?

Да. Блок запрашивает доступные способы оплаты с сервера, и фильтр woocommerce_available_payment_gateways отрабатывает на этом запросе — в отличие от многих шаблонных хуков классического чекаута.

Q.Как отключить наложенный платёж только для одной вариации товара?

Сравнивайте $item['variation_id'] вместо $item['product_id'] и указывайте в списке ID вариаций. Родительский product_id отключает наложку для всех вариаций сразу.

Q.Можно ли обойтись без списка ID в коде?

Да — заведите категорию или метку «Без наложенного платежа» и проверяйте её через has_term(). Тогда товары добавляются и убираются из админки, а код не меняется.

Источники

Предыдущая
Поиск только по товарам в WooCommerce: убираем записи и страницы из выдачи
Следующая
Получить все данные товара по его ID

Читайте также