Как реализовать отмену заказа в WooCommerce с подтверждением пользователя

Диагностика проблемы: почему стандартного функционала отмены заказа в 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, может вызвать недовольство клиентов

Сервис определения шаблона и плагинов на сайте