Почему WooCommerce отправляет повторные письма при изменении статуса заказа
По умолчанию WooCommerce отправляет уведомления клиенту и администратору каждый раз при смене статуса заказа, если для этого статуса настроена рассылка. Это хорошо для информирования, но вызывает проблемы, если статус меняется несколько раз подряд или вручную, и письма отправляются повторно без необходимости.
Частая причина — использование стандартных хуков woocommerce_order_status_{$status}_notification, которые срабатывают при каждом изменении. Если заказ переводится в один и тот же статус несколько раз, письмо уйдет повторно.
Диагностика проблемы повторной отправки писем
- Проверьте логи почты (если настроены через SMTP-плагин или WP Mail Logging) на повторяющиеся уведомления со схожим временем и содержанием.
- Просмотрите статус заказа в админке WooCommerce: если он меняется несколько раз в один и тот же статус, вероятность повторной отправки высока.
- Оцените, используются ли кастомные скрипты или плагины, которые программно меняют статус и вызывают уведомления.
Пошаговое решение: запретить повторную отправку писем при повторном установлении статуса
Основная идея — использовать мета-данные заказа для фиксации факта отправки письма и проверять это перед повторной отправкой.
Шаг 1. Добавьте проверку перед отправкой письма
В functions.php вашей темы или в кастомном плагине добавьте следующий код:
add_filter('woocommerce_email_enabled_customer_processing_order', 'disable_duplicate_processing_email', 10, 2);
add_filter('woocommerce_email_enabled_customer_completed_order', 'disable_duplicate_completed_email', 10, 2);
function disable_duplicate_processing_email($enabled, $order) {
return prevent_duplicate_email($enabled, $order, 'processing_email_sent');
}
function disable_duplicate_completed_email($enabled, $order) {
return prevent_duplicate_email($enabled, $order, 'completed_email_sent');
}
function prevent_duplicate_email($enabled, $order, $meta_key) {
if (!$enabled || !$order instanceof WC_Order) {
return $enabled;
}
// Проверяем, отправлялось ли письмо
if ($order->get_meta($meta_key)) {
return false; // Блокируем повторную отправку
}
// Сохраняем метаданные после успешной отправки
add_action('woocommerce_email_after_send', function($email_sent, $email, $order_obj) use ($meta_key, $order) {
if ($email_sent && $order->get_id() === $order_obj->get_id()) {
$order->update_meta_data($meta_key, 'yes');
$order->save();
}
}, 10, 3);
return $enabled;
}Этот пример отключает повторную отправку писем для статусов "processing" и "completed". При первой отправке сохраняется мета-данное, которое служит флагом.
Шаг 2. Удаление мета-данных для повторной отправки при необходимости
Если нужно повторно отправить письмо (например, после исправления ошибки), можно удалить мета-данные через консоль или вручную:
$order = wc_get_order(123); // ID заказа
$order->delete_meta_data('processing_email_sent');
$order->delete_meta_data('completed_email_sent');
$order->save();Проверка результата после внедрения
- Создайте тестовый заказ и переведите его в статус "Обработка" (processing). Убедитесь, что письмо уходит.
- Переведите заказ снова в "Обработка" — письмо повторно не должно отправиться.
- Повторите для статуса "Выполнен" (completed).
- Проверьте логи почты и убедитесь, что уведомления не дублируются.
Частые ошибки и как их исправить
- Письма продолжают отправляться повторно: возможно, мета-данные не сохраняются из-за конфликтов в коде или кэширования. Проверьте права на запись в базу и отключите кэширование при тестах.
- Код не работает для других статусов: добавьте новые фильтры для нужных статусов, например
woocommerce_email_enabled_customer_on-hold_order. - Ошибка «Call to undefined function»: убедитесь, что код добавлен в правильное место (functions.php или плагин), и что WooCommerce активен.
Практические советы по безопасности и производительности
- Используйте конкретные хуки WooCommerce для управления почтовыми уведомлениями, чтобы не влиять на другие процессы.
- Кэширование мета-данных заказа снижает нагрузку на базу, но при работе с почтой лучше кэш временно отключать.
- Тестируйте изменения на staging-сайте, чтобы избежать сбоев в рабочем магазине.
Таблица сравнения решений для исключения повторной отправки писем
| Способ | Преимущества | Недостатки |
|---|---|---|
| Кастомный фильтр с мета-данными | Гибкий, не требует сторонних плагинов, легко расширяется | Нужно писать код, возможно конфликт с другими кастомизациями |
| Плагины для управления письмами | Простота настройки, готовые функции | Могут замедлять сайт, не всегда гибкие под уникальные задачи |
| Отключение писем полностью | Простой способ избежать дублирования | Потеря информирования клиентов, неудобно |