Отключение оплаты в WooCommerce для товаров с заданным статусом

Диагностика проблемы: зачем отключать оплату для товаров с определённым статусом

В WooCommerce нередко возникает задача сделать товары с определённым статусом (например, "в ожидании", "черновик", "тестовый" или пользовательский статус) недоступными для оплаты, но при этом оставить их видимыми в каталоге. Это может понадобиться, если товар временно не продаётся, но его нужно оставить на сайте для показа или тестирования.

Как понять, что стандартных настроек WooCommerce недостаточно

В стандартном WooCommerce нет возможности напрямую запретить оплату для товаров по статусу. Можно скрыть товар (через видимость), но это удалит товар из каталога. Плагинов с точечной функцией обычно нет, и универсальные решения требуют кастомизации.

Пошаговое решение: отключение оплаты для товаров с определённым статусом

1. Добавление пользовательского статуса товара (если нужно)

Если у вас нет готового статуса, добавим пользовательский статус 'waiting_payment' для товаров. Добавьте код в functions.php вашей темы или в плагин для кастомизации:

function register_product_custom_status() {
    register_post_status( 'wc-waiting_payment', array(
        'label'                     => _x( 'Waiting Payment', 'Product status', 'woocommerce' ),
        'public'                    => true,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop( 'Waiting Payment <span class="count">(%s)</span>', 'Waiting Payment <span class="count">(%s)</span>', 'woocommerce' ),
    ) );
}
add_action( 'init', 'register_product_custom_status' );

2. Запрет оплаты для товаров с этим статусом

Добавим фильтр, который проверит содержимое корзины и заблокирует оформление заказа, если в корзине есть товары с заданным статусом.

function wc_disable_checkout_if_product_status_pending( $valid ) {
    if ( ! $valid ) {
        return false;
    }
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $product = $cart_item['data'];
        $status = get_post_status( $product->get_id() );
        if ( $status === 'wc-waiting_payment' ) {
            wc_add_notice( 'Оплата отключена для некоторых товаров в корзине.', 'error' );
            return false;
        }
    }
    return $valid;
}
add_filter( 'woocommerce_checkout_process', 'wc_disable_checkout_if_product_status_pending' );

3. Скрытие кнопки «Купить» на страницах товаров с этим статусом

Чтобы пользователь не мог добавить товар с таким статусом в корзину, скроем кнопку «Добавить в корзину» для таких товаров:

function wc_hide_add_to_cart_button_for_custom_status() {
    global $product;
    if ( ! $product ) {
        return;
    }
    $status = get_post_status( $product->get_id() );
    if ( $status === 'wc-waiting_payment' ) {
        remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
    }
}
add_action( 'woocommerce_before_single_product', 'wc_hide_add_to_cart_button_for_custom_status' );

Проверка результата после внедрения

  • Создайте товар с пользовательским статусом wc-waiting_payment.
  • Зайдите на страницу товара — кнопка "Добавить в корзину" должна отсутствовать.
  • Если товар каким-то образом окажется в корзине (например, через прямой запрос), при попытке оформления заказа должно появиться сообщение об ошибке и процесс должен прерваться.
  • Для товаров с другими статусами оплата должна работать штатно.

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

  • Ошибка: Товар с нужным статусом по-прежнему можно добавить в корзину.
    Причина: Не сработал хук удаления кнопки или статус указан неверно.
    Решение: Проверьте правильность регистраций статусов и используйте error_log для отладки get_post_status().
  • Ошибка: Сообщение об ошибке на оформлении заказа не появляется.
    Причина: Фильтр woocommerce_checkout_process не возвращает false.
    Решение: Убедитесь, что функция возвращает false при обнаружении запрещённых товаров.
  • Ошибка: Пользователь видит кнопку, но при клике ничего не происходит.
    Причина: Кнопка не удалена, а только скрыта стилями.
    Решение: Используйте remove_action() для удаления кнопки, а не CSS-стили.

Практические советы по безопасности и производительности

  • Регистрация пользовательских статусов должна происходить на init с приоритетом по умолчанию.
  • Проверка статуса товара в корзине выполняется по ID продукта — это эффективно и не создаёт дополнительных запросов.
  • Для крупных магазинов с большим количеством товаров стоит дополнительно кэшировать статусы, чтобы снизить нагрузку.
  • Проверяйте совместимость с плагинами кеширования: сообщения об ошибках лучше выводить через wc_add_notice.

Сравнение вариантов реализации

ВариантПлюсыМинусыПрименимость
Код в functions.php (описанный выше)Полный контроль, отсутствие лишних плагинов, точечное решениеТребует базовых знаний PHP, поддержка на разработчикеЛучший вариант для кастомных проектов
Плагины ограничения покупки (например, "WooCommerce Catalog Mode")Простая настройка, UI для управленияЧасто общий режим каталога, нет гибкой фильтрации по статусуПодойдёт для простых случаев без кастомных статусов
Использование видимости товара WooCommerceВстроенный функционал, простой в использованииТовар скрывается из каталога, нельзя просто отключить оплатуЕсли нужно скрыть товар полностью
Как автоматизировать управление скоростью загрузки в WordPress
24.01.2026
Запрет доступа к страницам WooCommerce для неавторизованных пользователей
16.03.2026
Как создать динамическую выводную страницу в WordPress с помощью мета записей
20.11.2025
Как создать собственный шорткод в WordPress: пошаговое руководство
17.11.2025
Как создать высокопроизводительный кэш в WordPress: практическое руководство
18.02.2026