В WooCommerce иногда нужно не просто скрыть товар, а изменить поведение оформления заказа в зависимости от его статуса. Типичный сценарий: товар помечен как draft, pending, private или имеет собственный служебный статус, и для него нельзя показывать оплату. Это полезно, если каталог наполняется вручную, товары проходят модерацию или часть ассортимента доступна только после согласования.
Самый надёжный путь — не править шаблоны оформления заказа, а отфильтровать доступные способы оплаты на сервере. Так логика остаётся в одном месте и не ломается при обновлении темы.
Когда это действительно нужно
Сценарий обычно выглядит так: товар уже добавлен в корзину, но оплачивать его нельзя до смены статуса. Например, менеджер создал карточку, но ещё не подтвердил цену; или товар должен быть доступен только по счёту и после ручной проверки. В таких случаях недостаточно спрятать кнопку на странице товара — WooCommerce всё равно покажет методы оплаты на чекауте, если корзина собрана из разрешённых позиций.
Что именно будем делать
Мы добавим фильтр, который проверяет товары в корзине и отключает оплату, если среди них есть позиции с нужным статусом. Это решение работает на этапе расчёта доступных платежей и не требует вмешательства в фронтенд.
Диагностика проблемы перед изменениями
Сначала проверьте, как именно у вас хранится статус товара. В WordPress есть стандартный статус записи, а в WooCommerce могут использоваться и кастомные статусы, добавленные плагином или кодом. Важно не путать:
- статус записи в админке WordPress;
- статус товара в WooCommerce;
- мета-поля, которые лишь визуально обозначают состояние товара.
Если вы не уверены, откройте товар в админке и посмотрите, как он отображается в списке записей. Для стандартных статусов WordPress это обычно publish, draft, pending, private.
Если проблема уже проявляется на сайте, проверьте такой сценарий:
- добавьте в корзину товар с нужным статусом;
- перейдите к оформлению заказа;
- посмотрите, отображаются ли способы оплаты;
- сравните поведение с обычным опубликованным товаром.
Если оплата всё ещё доступна, значит текущая логика магазина не учитывает статус товара на этапе чекаута.
Решение через фильтр доступных способов оплаты
Ниже пример, который отключает оплату, если в корзине есть товар со статусом draft или pending. Код лучше добавить в мини-плагин или в functions.php дочерней темы, если у вас нет отдельного места для кастомной логики.
add_filter( 'woocommerce_available_payment_gateways', 'wpstock_disable_payments_for_unpublished_products' );
function wpstock_disable_payments_for_unpublished_products( $gateways ) {
if ( is_admin() ) {
return $gateways;
}
if ( ! function_exists( 'WC' ) || ! WC()->cart ) {
return $gateways;
}
$blocked_statuses = array( 'draft', 'pending', 'private' );
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( empty( $cart_item['product_id'] ) ) {
continue;
}
$product_id = (int) $cart_item['product_id'];
$status = get_post_status( $product_id );
if ( in_array( $status, $blocked_statuses, true ) ) {
return array();
}
}
return $gateways;
}Этот вариант жёсткий: если в корзине есть хотя бы один товар с запрещённым статусом, WooCommerce не покажет ни один способ оплаты. Это удобно, когда заказ вообще не должен быть оплачен до публикации товара.
Если нужно отключать только часть способов оплаты
Иногда полностью скрывать оплату не нужно. Например, вы хотите оставить bacs для счёта, но убрать онлайн-эквайринг. Тогда лучше удалить только конкретные шлюзы.
add_filter( 'woocommerce_available_payment_gateways', 'wpstock_hide_selected_gateways_for_unpublished_products' );
function wpstock_hide_selected_gateways_for_unpublished_products( $gateways ) {
if ( is_admin() || ! function_exists( 'WC' ) || ! WC()->cart ) {
return $gateways;
}
$blocked_statuses = array( 'draft', 'pending', 'private' );
$hide_gateways = array( 'stripe', 'paypal' );
foreach ( WC()->cart->get_cart() as $cart_item ) {
$product_id = ! empty( $cart_item['product_id'] ) ? (int) $cart_item['product_id'] : 0;
if ( ! $product_id ) {
continue;
}
if ( in_array( get_post_status( $product_id ), $blocked_statuses, true ) ) {
foreach ( $hide_gateways as $gateway_id ) {
if ( isset( $gateways[ $gateway_id ] ) ) {
unset( $gateways[ $gateway_id ] );
}
}
break;
}
}
return $gateways;
}Здесь логика мягче: покупатель видит только разрешённые методы оплаты. Это полезно, если заказ должен оформляться, но оплата возможна только по безналичному сценарию.
Пошаговая настройка без лишнего риска
- Сделайте резервную копию файлов и базы данных.
- Добавьте код в дочернюю тему или в собственный мини-плагин.
- Проверьте, что в корзине есть товар с целевым статусом.
- Откройте страницу оформления заказа в режиме инкогнито.
- Убедитесь, что способы оплаты скрылись или изменились так, как задумано.
- Проверьте обычный опубликованный товар: для него оплата должна остаться доступной.
Если у вас включён кэш страниц, очистите его после внедрения. Иначе вы можете увидеть старую версию чекаута и сделать ложный вывод, что код не работает.
Как проверить, что решение сработало
Проверка должна быть не визуальной, а сценарной. Откройте корзину с проблемным товаром и пройдите весь путь до чекаута. Обратите внимание на три точки:
- в корзине товар отображается нормально;
- на чекауте способы оплаты скрыты или ограничены;
- после удаления проблемного товара из корзины платежи возвращаются.
Если хотите быстро убедиться в статусе товара, временно добавьте логирование в код:
error_log( 'Product ' . $product_id . ' status: ' . $status );Логи помогут понять, действительно ли WooCommerce видит тот статус, который вы ожидаете. Это особенно полезно, если статус задаёт не WordPress, а сторонний плагин.
Сравнение подходов: код, плагин, компромисс
| Подход | Когда подходит | Минус |
|---|---|---|
| Код через фильтр | Нужна точная логика по статусу товара | Требует аккуратного внедрения и теста |
| Плагин для условной логики оплат | Нужно настраивать без разработки | Может быть избыточным и конфликтовать с другими расширениями |
| Ручное отключение методов оплаты в WooCommerce | Правило одно для всего магазина | Не учитывает статус конкретного товара |
Если у вас уже есть набор технических настроек для WooCommerce, иногда удобнее держать такие правила в одном месте. Для чистки дубликатов, отключения лишнего мусора и базовой оптимизации админки можно посмотреть Clearfy Pro: https://wpshop.ru/plugins/clearfy. Но для самой логики оплаты всё равно нужен код или специализированный плагин условных правил.
Частые ошибки и как их исправить
Проверяют не тот статус
Частая ошибка — сравнивать статус с тем, что видно в интерфейсе, а не с реальным значением из базы. Например, товар может выглядеть как «На проверке», но фактически иметь другой кастомный статус. Решение: сначала выясните точный slug статуса через код или через документацию плагина, который его создаёт.
Код добавили в активную тему
Если вставить логику в родительскую тему, она может исчезнуть после обновления. Надёжнее использовать дочернюю тему или мини-плагин. Для бизнес-логики WooCommerce это стандартная практика.
Не учитывают кэш
Если на сайте есть серверный кэш, page cache или кэш от CDN, старая версия чекаута может сохраняться. После изменений очистите кэш на всех уровнях и проверьте страницу в приватном окне.
Скрывают оплату только на фронтенде
Если убрать блок оплаты через CSS или JavaScript, это не решает задачу. Пользователь может обойти скрытие, а сервер всё равно примет заказ. Нужна именно серверная фильтрация через woocommerce_available_payment_gateways.
Что учесть по безопасности и производительности
Фильтр вызывается на этапе формирования доступных шлюзов оплаты, поэтому не стоит делать в нём тяжёлые запросы к базе или сложные внешние вызовы. Достаточно проверить товары в корзине и их статусы. Чем проще логика, тем меньше риск замедлить оформление заказа.
Если правило станет сложнее — например, будет зависеть от роли пользователя, страны, категории товара и статуса записи — лучше вынести условия в отдельную функцию и документировать их прямо в коде. Так проще сопровождать решение, когда магазин начнёт расти.
Если вам нужно не только отключать оплату, но и показывать покупателю понятное сообщение, можно дополнительно использовать уведомление WooCommerce через wc_add_notice(). Но не злоупотребляйте этим: лишние сообщения на чекауте часто мешают конверсии и усложняют диагностику.
Для магазинов, где много технических правил вокруг каталога, статусов и видимости контента, полезно держать в порядке и общую гигиену сайта: убрать лишние дубли, отключить ненужные элементы и не плодить конфликтующие фильтры. Это снижает шанс, что условная логика оплаты сломается после очередного обновления темы или плагина.