Диагностика проблемы: почему корзина не очищается после отмены заказа
По умолчанию WooCommerce не очищает корзину пользователя, если заказ был отменен или не оплачен. Это приводит к тому, что товары остаются в корзине, и пользователь может случайно повторно оформить тот же заказ или запутаться в содержимом корзины. Такая ситуация особенно критична для магазинов с ограниченным запасом товара или с динамическими ценами.
Для диагностики проверьте следующие моменты:
- Стандартное поведение WooCommerce не предусматривает очистку корзины при смене статуса заказа.
- Пользователь не выходит из аккаунта после отмены заказа, и сессия корзины сохраняется.
- Нет сторонних плагинов, которые могут влиять на сессию или содержимое корзины.
Пошаговое решение: очистка корзины при отмене заказа
Реализуем автоматическое очищение корзины пользователя при смене статуса заказа на «отменён» (cancelled) или «отклонён» (failed). Для этого используем хук woocommerce_order_status_changed.
add_action('woocommerce_order_status_changed', 'clear_cart_after_order_cancelled', 10, 4);
function clear_cart_after_order_cancelled($order_id, $old_status, $new_status, $order) {
if (in_array($new_status, array('cancelled', 'failed'))) {
// Получаем ID пользователя, сделавшего заказ
$user_id = $order->get_user_id();
// Очищаем корзину, если пользователь авторизован
if ($user_id) {
// Загружаем сессию WooCommerce пользователя
$session_handler = WC()->session;
if ($session_handler) {
// Очистка корзины для текущей сессии
WC()->cart->empty_cart();
// Удаляем данные сессии корзины для пользователя
// Важно: для работы с сессиями других пользователей нужен дополнительный код, см. ниже.
}
} else {
// Для гостей очищаем корзину текущей сессии
WC()->cart->empty_cart();
}
}
}
Важно: данный код очищает корзину только текущей сессии, то есть если пользователь отменил заказ в текущем браузере и сессии. Если необходимо очищать корзину другого пользователя (например, в админке), потребуется работа с пользовательскими сессиями, что усложняет реализацию.
Очистка корзины гостя
Для гостей (неавторизованных пользователей) очистка сессии корзины происходит автоматически при вызове WC()->cart->empty_cart() в их текущей сессии.
Как очистить корзину авторизованного пользователя при отмене заказа, если пользователь не на сайте
WooCommerce хранит сессии в базе данных в таблице wp_woocommerce_sessions. Можно попробовать удалить сессионные данные у пользователя, но это не всегда эффективно и требует аккуратности. Вот пример для удаления сессии пользователя:
function clear_user_cart_sessions($user_id) {
global $wpdb;
$meta_key = '_woocommerce_persistent_cart_' . get_current_blog_id();
delete_user_meta($user_id, $meta_key);
// Удаляем записи сессий из таблицы woocommerce_sessions
$sessions_table = $wpdb->prefix . 'woocommerce_sessions';
$wpdb->query($wpdb->prepare("DELETE FROM $sessions_table WHERE session_key LIKE %s", $user_id . '%'));
}
Однако использование такого метода требует тестирования, чтобы не нарушить другие сессии.
Проверка результата после внедрения
- Создайте тестовый заказ в WooCommerce с авторизованным пользователем.
- Войдите под этим пользователем, добавьте товары в корзину, оформите заказ.
- В админке измените статус заказа на
cancelledилиfailed. - Вернитесь на сайт под тем же пользователем и проверьте, что корзина пустая.
- Для гостя повторите процедуру, проверив очистку корзины в текущей сессии.
Если корзина не пустая, проверьте, срабатывает ли хук woocommerce_order_status_changed с помощью временного error_log или var_dump.
Частые ошибки и как исправить
- Код не очищает корзину другого пользователя: WooCommerce хранит корзину в сессии, которая привязана к текущему сеансу браузера. Чтобы очистить корзину другого пользователя, нужно работать с пользовательскими мета-данными или сессиями, что гораздо сложнее.
- Корзина не очищается для гостей: убедитесь, что вызов
WC()->cart->empty_cart()происходит в правильном месте и сессия активна. - Хук срабатывает, но корзина не очищается: возможно, корзина кешируется плагином оптимизации или кэшом сервера. Добавьте исключения для кэширования на страницах корзины.
- Удаление сессий нарушает авторизацию: будьте осторожны при удалении сессий напрямую из базы, тестируйте на тестовом сайте.
Практические советы по производительности и безопасности
- Не используйте прямые запросы к базе для удаления сессий в продакшене без резервных копий.
- Для массовой очистки корзин лучше уведомлять пользователей или делать это через интерфейс админки.
- Оптимизируйте работу с сессиями, чтобы не создавать лишних запросов к базе.
- Избегайте очистки корзины сразу после смены статуса, если пользователь может еще оплатить заказ — продумайте бизнес-логику.
Сравнение способов очистки корзины после отмены заказа
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Очистка текущей сессии (WC()->cart->empty_cart()) | Простая реализация, хорошо работает для активного пользователя | Не очищает корзину, если пользователь не на сайте | Для сайтов с активными сессиями пользователей |
| Удаление пользовательских мета данных корзины | Удаляет сохранённую корзину для пользователя | Не всегда очищает текущие сессии, требует дополнительного кода | Если нужно очистить корзину зарегистрированного пользователя |
| Удаление записей из таблицы woocommerce_sessions | Удаляет сессионные данные полностью | Риск сломать сессии, требует осторожности | Для опытных разработчиков, при необходимости массовой очистки |