Задача: авторизация по номеру заказа в WooCommerce
В стандартном WooCommerce авторизация пользователя происходит через email и пароль. Иногда требуется реализовать сценарий, когда покупатель может войти или получить доступ к заказу, указав его номер, без регистрации или пароля. Это удобно для сайтов с ограниченным функционалом аккаунтов или для быстрого доступа к информации о заказе.
Диагностика проблемы: почему стандартный вход не подходит
По умолчанию WooCommerce не предоставляет возможности авторизации по номеру заказа.
- Номер заказа — это уникальный идентификатор, но не связанный напрямую с учетной записью пользователя.
- Для гостей номер заказа — единственный параметр для проверки доступа.
- Без дополнительной реализации невозможно проверить права доступа к заказу только по номеру.
Пошаговое решение: создание формы авторизации по номеру заказа и проверка доступа
1. Создаем форму для ввода номера заказа
Добавим шорткод, который выводит форму с полем для ввода номера заказа:
function woocommerce_order_login_form() {
if ( is_user_logged_in() ) {
return '<p>Вы уже авторизованы.</p>';
}
$html = '<form method="POST">';
$html .= '<label for="order_number">Введите номер заказа:</label>';
$html .= '<input type="text" name="order_number" id="order_number" required />';
$html .= '<input type="submit" name="order_login_submit" value="Войти" />';
$html .= '</form>';
return $html;
}
add_shortcode('order_login_form', 'woocommerce_order_login_form');2. Обработка данных формы и проверка заказа
Добавим хук для обработки отправки формы, проверки номера заказа и создания сессии для доступа:
function woocommerce_process_order_login() {
if ( isset($_POST['order_login_submit']) && !empty($_POST['order_number']) ) {
$order_number = sanitize_text_field($_POST['order_number']);
// Получаем ID заказа по номеру
$order_id = wc_get_order_id_by_order_key($order_number); // Не подходит, так как order_key не совпадает с номером
// Вместо order_key используем WC_Order_Query
$orders = wc_get_orders(array(
'limit' => 1,
'order_number' => $order_number // Такой параметр отсутствует, поэтому реализуем поиск вручную
));
// Альтернативный способ: поиск по посту
global $wpdb;
$order_id = $wpdb->get_var($wpdb->prepare(
"SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_order' AND ID = %d",
intval($order_number)
));
if ( $order_id ) {
// Сохраняем ID заказа в сессии
WC()->session->set('order_login', $order_id);
wp_redirect( wc_get_endpoint_url('view-order', $order_id, wc_get_page_permalink('myaccount')) );
exit;
} else {
wc_add_notice('Заказ с таким номером не найден.', 'error');
}
}
}
add_action('init', 'woocommerce_process_order_login');Важно: Поиск заказа по номеру не всегда однозначен, так как номер заказа в WooCommerce — это ID поста. Если используются префиксы или кастомные номера, поиск нужно адаптировать под них.
3. Ограничение доступа к заказам по сессии
Чтобы пользователь видел только заказ, по которому он авторизовался, добавим проверку доступа в шаблон просмотра заказа:
function restrict_order_view_to_session($is_allowed, $order) {
$session_order_id = WC()->session->get('order_login');
if ( $session_order_id && $order->get_id() == $session_order_id ) {
return true;
}
// Если пользователь не авторизован и заказ не совпадает с сессией - доступ закрыт
if ( !is_user_logged_in() ) {
return false;
}
return $is_allowed;
}
add_filter('woocommerce_order_is_editable', 'restrict_order_view_to_session', 10, 2);
add_filter('woocommerce_my_account_my_orders_query', function($args) {
$session_order_id = WC()->session->get('order_login');
if ( $session_order_id ) {
$args['include'] = array($session_order_id);
}
return $args;
});Проверка результата после внедрения
- Добавьте на страницу шорткод
[order_login_form]. - Откройте страницу в браузере, введите номер существующего заказа (ID заказа в базе WordPress).
- После отправки должно произойти перенаправление на страницу просмотра заказа.
- Попытка доступа к другим заказам вне сессии должна быть запрещена.
Частые ошибки и как их исправить
- Номер заказа не соответствует ID заказа в базе: WooCommerce может использовать префиксы или кастомные номера, поэтому поиск по ID не сработает. Используйте фильтры или сторонние плагины для получения правильного номера.
- Сессия не сохраняется: Проверьте, включены ли сессии WooCommerce и работают ли cookie в браузере.
- Доступ к заказу не ограничен: Проверьте, что фильтры на доступ к заказам подключены и возвращают правильное значение.
- После ввода номера происходит ошибка или пустая страница: Проверьте правильность редиректа и отсутствие конфликтов с другими плагинами.
Практические советы по безопасности и производительности
- Не используйте простой номер заказа без дополнительной проверки, чтобы избежать доступа к чужим данным.
- Добавьте капчу на форму для защиты от брутфорса.
- Ограничьте количество попыток ввода номера заказа с одного IP.
- Храните в сессии только ID заказа, не сохраняйте чувствительные данные.
- Для больших магазинов используйте кеширование и оптимизацию запросов к базе данных.
Итоги: когда использовать данный подход
Авторизация по номеру заказа подойдет для сайтов с минимальными требованиями к аккаунтам и быстрым доступом к информации о заказе без регистрации. Если требуется более сложная персонализация, лучше использовать стандартную авторизацию WooCommerce.
Сравнение вариантов реализации
| Способ | Плюсы | Минусы |
|---|---|---|
| Авторизация по номеру заказа через сессию и кастомный код | Простой, не требует плагинов, гибко настраивается | Требует доработки, возможны ошибки с номерами заказов |
| Использование плагинов для доступа к заказам по номеру | Готовое решение, поддержка и обновления | Может быть платным, менее гибкий |
| Стандартная авторизация WooCommerce | Безопасно, встроенный функционал | Требует регистрацию и пароль, не подходит для быстрого доступа |