Сценарий типичный: магазин работает с несколькими способами оплаты, но письма клиенту или менеджеру должны уходить не всегда. Например, при оплате наличными курьеру уведомление нужно, а при банковском переводе — нет, потому что заказ сначала проверяет менеджер. В WooCommerce это нельзя нормально настроить только через стандартные экраны писем: нужно привязаться к способу оплаты и отключать конкретные уведомления кодом.
Ниже разберём рабочий вариант без выдуманных хуков и без правки ядра. Подход подходит для случаев, когда нужно отключить именно email-уведомления, а не менять статус заказа или скрывать сам способ оплаты.
Когда стандартных настроек WooCommerce недостаточно
В админке WooCommerce можно включать и выключать письма по типам событий: новый заказ, отменённый заказ, возврат и так далее. Но там нет условия вида «не отправлять письмо, если выбран bacs или cod». Поэтому при смешанной логике оплаты приходится либо мириться с лишними письмами, либо добавлять фильтр.
Если задача звучит как «при оплате банковским переводом не отправлять письмо клиенту о новом заказе», то решение обычно строится на фильтре woocommerce_email_enabled_{$email_id}. Он позволяет отключить конкретный email в зависимости от текущего заказа.
Диагностика: что именно нужно отключать
Перед правкой кода важно понять три вещи:
- какой email нужно отключить — клиентский, админский или оба;
- по какому способу оплаты фильтровать —
cod,bacs,chequeили кастомный gateway; - на каком этапе заказ создаётся — сразу после оформления или после смены статуса.
Если этого не проверить заранее, легко отключить не то письмо. Например, клиенту перестанет приходить подтверждение, а менеджер всё равно будет получать уведомление о новом заказе. Или наоборот — письмо клиенту останется, а внутреннее уведомление пропадёт.
Как узнать ID способа оплаты
Откройте заказ в админке и посмотрите значение способа оплаты в метаданных заказа или в коде шлюза. У стандартных методов WooCommerce обычно используются такие ID:
bacs— банковский перевод;cod— наличные при доставке;cheque— чек;- у сторонних плагинов ID зависит от самого шлюза.
Если способ оплаты кастомный, его ID можно посмотреть в настройках плагина или в коде класса, который наследуется от WC_Payment_Gateway.
Решение: отключаем email по способу оплаты через фильтр
Самый надёжный вариант — добавить небольшой сниппет в functions.php дочерней темы или в собственный мини-плагин. Ниже пример, который отключает письмо клиенту о новом заказе, если оплата выбрана через банковский перевод или наличные при доставке.
<?php
add_filter( 'woocommerce_email_enabled_customer_processing_order', 'wpteam_disable_customer_email_by_payment_method', 10, 2 );
function wpteam_disable_customer_email_by_payment_method( $enabled, $order ) {
if ( ! $order instanceof WC_Order ) {
return $enabled;
}
$payment_method = $order->get_payment_method();
$disabled_methods = array( 'bacs', 'cod' );
if ( in_array( $payment_method, $disabled_methods, true ) ) {
return false;
}
return $enabled;
}Что делает этот код:
- перехватывает только письмо
customer_processing_order; - проверяет объект заказа;
- смотрит ID способа оплаты;
- отключает письмо, если способ оплаты входит в список.
Если нужно отключить не письмо клиенту, а письмо администратору о новом заказе, используйте тот же принцип, но другой email ID.
<?php
add_filter( 'woocommerce_email_enabled_new_order', 'wpteam_disable_admin_email_by_payment_method', 10, 2 );
function wpteam_disable_admin_email_by_payment_method( $enabled, $order ) {
if ( ! $order instanceof WC_Order ) {
return $enabled;
}
$payment_method = $order->get_payment_method();
if ( 'bacs' === $payment_method ) {
return false;
}
return $enabled;
}Если нужно отключать письма только для одного статуса
Иногда способ оплаты сам по себе не важен. Например, письма не должны уходить только тогда, когда заказ остаётся в статусе on-hold после выбора перевода. В этом случае лучше проверять и статус, и способ оплаты одновременно. Это снижает риск случайно отключить уведомления для других сценариев.
<?php
add_filter( 'woocommerce_email_enabled_customer_processing_order', 'wpteam_disable_email_for_on_hold_bacs', 10, 2 );
function wpteam_disable_email_for_on_hold_bacs( $enabled, $order ) {
if ( ! $order instanceof WC_Order ) {
return $enabled;
}
if ( 'on-hold' !== $order->get_status() ) {
return $enabled;
}
if ( 'bacs' === $order->get_payment_method() ) {
return false;
}
return $enabled;
}Такой вариант полезен, если вы хотите оставить уведомления для оплаченных заказов, но убрать лишнюю почту на этапе ожидания оплаты.
Сравнение подходов
| Подход | Когда подходит | Минус |
|---|---|---|
| Настройки WooCommerce | Если нужно отключить письмо целиком | Нет фильтра по способу оплаты |
Код через woocommerce_email_enabled_* | Если нужна точная логика по gateway | Нужно аккуратно тестировать |
| Плагин для кастомной логики | Если правил много и ими управляет менеджер | Лишняя зависимость и возможные конфликты |
Если у вас уже стоит плагин для оптимизации и чистки WordPress, например Clearfy Pro, проверьте, не дублирует ли он часть почтовой логики через дополнительные настройки. Но для точечного отключения по способу оплаты код обычно проще и прозрачнее.
Пошаговая настройка без лишнего риска
- Определите, какое письмо нужно отключить: клиентское или админское.
- Уточните ID способа оплаты, для которого письмо не должно уходить.
- Добавьте код в дочернюю тему или в отдельный мини-плагин.
- Очистите кэш сайта и, если есть, кэш почтового плагина или SMTP-плагина.
- Сделайте тестовый заказ с нужным способом оплаты.
- Проверьте, что письмо не отправилось именно в этом сценарии.
Как проверить, что всё сработало
Проверка должна быть не визуальной, а фактической. Откройте тестовый заказ и убедитесь в трёх вещах:
- в заказе выбран нужный способ оплаты;
- статус заказа соответствует сценарию, который вы закладывали в код;
- письмо не появилось в почтовом ящике клиента или администратора.
Если используете SMTP-плагин, посмотрите его журнал отправки. Это самый быстрый способ понять, был ли email вообще сформирован WooCommerce или он был отключён фильтром до отправки.
Дополнительно можно временно включить логирование в коде, чтобы увидеть, сработало ли условие:
<?php
add_filter( 'woocommerce_email_enabled_customer_processing_order', 'wpteam_debug_email_by_payment_method', 10, 2 );
function wpteam_debug_email_by_payment_method( $enabled, $order ) {
if ( ! $order instanceof WC_Order ) {
return $enabled;
}
error_log( 'Order #' . $order->get_id() . ' payment: ' . $order->get_payment_method() );
return $enabled;
}После проверки этот код лучше убрать, чтобы не засорять лог-файл.
Частые ошибки и как их исправить
- Используют неправильный email ID. Например, пытаются отключить
customer_processing_order, хотя письмо уходит черезnew_order. Решение: сначала уточните, какое именно уведомление приходит. - Проверяют не тот способ оплаты. У кастомных шлюзов ID часто отличается от названия на витрине. Решение: смотрите именно технический ID.
- Добавляют код в родительскую тему. После обновления он пропадёт. Решение: используйте дочернюю тему или мини-плагин.
- Не учитывают кэш и SMTP-лог. Кажется, что письмо всё ещё отправляется, хотя проверяется старый заказ или старый код. Решение: тестируйте на новом заказе и смотрите журнал отправки.
- Отключают письмо слишком широко. Если не проверять статус заказа, можно случайно убрать важные уведомления. Решение: добавляйте дополнительные условия, если сценарий сложный.
Безопасность и производительность
Сам по себе такой фильтр почти не влияет на производительность, если не делать внутри него тяжёлые запросы к базе. Не стоит в этом месте обращаться к внешним API или запускать сложные выборки. Проверка способа оплаты и статуса заказа уже есть в объекте WC_Order, этого достаточно.
С точки зрения безопасности важно не вставлять код в произвольные плагины с неизвестным происхождением и не править ядро WooCommerce. Если логика нужна надолго, лучше оформить её как маленький кастомный плагин: так проще отключать, тестировать и переносить между окружениями.
Если правил становится много — например, разные письма для разных способов оплаты, статусов и ролей менеджеров — имеет смысл вынести это в отдельный плагин с понятной структурой. Тогда не придётся искать сниппеты по файлам темы.