Диагностика проблемы: почему стандартного функционала отмены заказа в WooCommerce нет
WooCommerce по умолчанию не предоставляет пользователям возможность самостоятельно отменять заказы в личном кабинете. Это связано с тем, что отмена заказа — сложный процесс, который может включать возврат средств, изменение статусов и уведомления. Если вы хотите добавить такую возможность, придется реализовать её самостоятельно через кастомный код или использовать плагины.
Пошаговое решение: добавляем кнопку отмены заказа с подтверждением
1. Добавляем кнопку «Отменить заказ» в список заказов пользователя
Для начала выведем кнопку отмены рядом с каждым заказом, если его статус позволяет отмену (например, processing или on-hold).
add_filter('woocommerce_my_account_my_orders_actions', 'add_cancel_order_button', 10, 2);
function add_cancel_order_button($actions, $order) {
if (in_array($order->get_status(), array('processing', 'on-hold'))) {
$actions['cancel'] = array(
'url' => wp_nonce_url(add_query_arg('cancel_order', $order->get_id()), 'cancel_order'),
'name' => __('Отменить заказ', 'woocommerce'),
);
}
return $actions;
}2. Обработка запроса на отмену с подтверждением
Добавим перехват запроса с параметром cancel_order и выведем окно подтверждения. Если пользователь подтвердил, поменяем статус заказа на cancelled.
add_action('template_redirect', 'handle_order_cancellation');
function handle_order_cancellation() {
if (!is_account_page() || !isset($_GET['cancel_order'])) {
return;
}
$order_id = absint($_GET['cancel_order']);
if (!$order_id || !wp_verify_nonce($_GET['_wpnonce'], 'cancel_order')) {
wp_die('Неверный запрос.');
}
$order = wc_get_order($order_id);
if (!$order || $order->get_user_id() !== get_current_user_id()) {
wp_die('Доступ запрещён.');
}
if (isset($_GET['confirm']) && $_GET['confirm'] === 'yes') {
if (in_array($order->get_status(), array('processing', 'on-hold'))) {
$order->update_status('cancelled', 'Заказ отменён пользователем.');
wc_add_notice(__('Ваш заказ успешно отменён.', 'woocommerce'), 'success');
} else {
wc_add_notice(__('Этот заказ нельзя отменить.', 'woocommerce'), 'error');
}
wp_safe_redirect(wc_get_account_endpoint_url('orders'));
exit;
} else {
wc_get_template('myaccount/cancel-order-confirmation.php', array('order' => $order));
exit;
}
}3. Создаём шаблон подтверждения отмены
Создайте в вашей теме (или дочерней теме) папку woocommerce/myaccount и файл cancel-order-confirmation.php со следующим содержимым:
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<h2><?php _e('Подтверждение отмены заказа', 'woocommerce'); ?></h2>
<p><?php printf(__('Вы действительно хотите отменить заказ #%d?', 'woocommerce'), $order->get_order_number()); ?></p>
<a href="<?php echo esc_url(add_query_arg(array('cancel_order' => $order->get_id(), 'confirm' => 'yes', '_wpnonce' => wp_create_nonce('cancel_order')))); ?>" class="button button-primary"><?php _e('Да, отменить заказ', 'woocommerce'); ?></a>
<a href="<?php echo esc_url(wc_get_account_endpoint_url('orders')); ?>" class="button"><?php _e('Отмена', 'woocommerce'); ?></a>
Проверка результата после внедрения
- Зайдите в аккаунт пользователя и откройте страницу заказов.
- Убедитесь, что у заказов со статусом
processingилиon-holdпоявилась кнопка «Отменить заказ». - Нажмите на кнопку — должно открыться окно подтверждения.
- После подтверждения статус заказа должен измениться на
cancelled, а пользователь увидит уведомление об успешной отмене.
Частые ошибки и как их исправить
- Кнопка не появляется — проверьте, что статус заказа совпадает с проверяемыми в функции (processing, on-hold). Возможно, статус другой.
- Ошибка проверки nonce — убедитесь, что ссылка с nonce формируется и проверяется правильно, без лишних символов.
- Отмена заказа с чужим ID — всегда проверяйте, что заказ принадлежит текущему пользователю, иначе возможность отменить чужой заказ — уязвимость.
- Статус заказа не меняется — проверьте, что WooCommerce обновляет статус, и что нет конфликтов с другими плагинами, блокирующими изменения.
Практические советы по безопасности и производительности
- Обязательно используйте
wp_nonceдля защиты от CSRF-атак при отмене заказа. - Проверяйте принадлежность заказа текущему пользователю, чтобы исключить возможность отмены чужих заказов.
- Не позволяйте отменять заказ, если он уже отправлен или завершён — расширьте проверку статусов по бизнес-логике.
- Добавьте логирование отмен заказов для аудита — это поможет отслеживать действия пользователей.
- Минимизируйте количество запросов и проверок в
template_redirect, чтобы не замедлять загрузку других страниц.
Сравнение вариантов реализации отмены заказа
| Метод | Плюсы | Минусы |
|---|---|---|
| Кастомный код (описанный подход) | Полный контроль, бесплатный, можно адаптировать под бизнес-логику | Требует навыков разработки, нужно тестировать и поддерживать |
| Плагины отмены заказа (например, WooCommerce Cancel Order) | Быстрое решение, готовый функционал | Может конфликтовать с темой/плагинами, часто платные, не всегда гибкие |
| Запрет отмены заказов пользователями | Простота, отсутствие рисков с возвратами | Плохо с точки зрения UX, может вызвать недовольство клиентов |