WooCommerce: как реализовать авторизацию через SMS с OTP и кодом подтверждения

Диагностика задачи: зачем нужна авторизация через SMS в WooCommerce

Стандартная авторизация в WooCommerce и WordPress чаще всего реализована через email и пароль. Однако для интернет-магазинов важно повысить безопасность и упростить процесс входа, особенно на мобильных устройствах. Авторизация через SMS с одноразовым паролем (OTP) решает эту задачу, минимизируя риски взлома пароля и сокращая количество забытых паролей. В этой статье разберём, как по шагам реализовать такую систему без сторонних плагинов с примерами кода.

Как работает OTP-авторизация: общий принцип

Пользователь вводит номер телефона на странице входа. После отправки формы генерируется одноразовый код (обычно 4–6 цифр), который отправляется через SMS. Пользователь вводит код на сайте, и после успешного подтверждения происходит вход в систему с привязкой к пользователю WooCommerce/WordPress.

Основные компоненты решения:

  • Форма ввода номера телефона и формы подтверждения кода.
  • Генерация и хранение OTP с ограничением по времени жизни.
  • Отправка SMS (через API SMS-провайдера).
  • Обработка подтверждения OTP и авторизация пользователя.

Пошаговое решение: реализация авторизации через SMS с OTP в WooCommerce

1. Добавляем форму входа с номером телефона

Создайте файл шаблона или добавьте код в functions.php вашей дочерней темы, чтобы заменить стандартную форму входа WooCommerce на форму с полем телефона.

add_shortcode('wc_sms_login_form', function() {
    ob_start();
    ?>
    <form id="sms-login-form" method="post">
        <label for="phone">Введите номер телефона:</label><br>
        <input type="tel" id="phone" name="phone" pattern="\+?\d{10,15}" required>
        <button type="submit" name="send_otp">Получить код</button>
    </form>
    <form id="otp-confirm-form" method="post" style="display:none;">
        <label for="otp">Введите код из SMS:</label><br>
        <input type="text" id="otp" name="otp" pattern="\d{4,6}" required>
        <button type="submit" name="verify_otp">Войти</button>
    </form>
    <div id="sms-login-message"></div>
    <script>
        const smsForm = document.getElementById('sms-login-form');
        const otpForm = document.getElementById('otp-confirm-form');
        const messageDiv = document.getElementById('sms-login-message');

        smsForm.addEventListener('submit', e => {
            e.preventDefault();
            const phone = smsForm.phone.value;
            fetch('', {
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: 'send_otp=1&phone=' + encodeURIComponent(phone)
            }).then(res => res.json()).then(data => {
                messageDiv.textContent = data.message;
                if(data.success) {
                    smsForm.style.display = 'none';
                    otpForm.style.display = 'block';
                }
            });
        });

        otpForm.addEventListener('submit', e => {
            e.preventDefault();
            const otp = otpForm.otp.value;
            const phone = smsForm.phone.value;
            fetch('', {
                method: 'POST',
                headers: {'Content-Type': 'application/x-www-form-urlencoded'},
                body: 'verify_otp=1&phone=' + encodeURIComponent(phone) + '&otp=' + encodeURIComponent(otp)
            }).then(res => res.json()).then(data => {
                messageDiv.textContent = data.message;
                if(data.success) {
                    window.location.reload();
                }
            });
        });
    </script>
    <?php
    return ob_get_clean();
});

2. Обработка отправки OTP и верификация кода

Добавим обработчики в functions.php, чтобы генерировать OTP, сохранять его в пользовательском мета и отправлять SMS. Для отправки SMS используйте API вашего провайдера, например Twilio, SMS.ru, или любой другой.

add_action('init', function() {
    if(isset($_POST['send_otp']) && isset($_POST['phone'])) {
        header('Content-Type: application/json');
        $phone = sanitize_text_field($_POST['phone']);
        // Поиск пользователя по номеру телефона (в user meta 'phone')
        $user = get_users(array(
            'meta_key' => 'phone',
            'meta_value' => $phone,
            'number' => 1,
            'count_total' => false
        ));
        if(empty($user)) {
            echo json_encode(['success' => false, 'message' => 'Пользователь с таким номером не найден']);
            exit;
        }
        $user = $user[0];

        // Генерация OTP
        $otp = wp_rand(100000, 999999);
        update_user_meta($user->ID, 'sms_otp', $otp);
        update_user_meta($user->ID, 'sms_otp_time', time());

        // Отправка SMS (пример для SMS.ru, замените на вашего провайдера)
        $api_key = 'ВАШ_API_КЛЮЧ';
        $text = 'Ваш код подтверждения: ' . $otp;
        $url = 'https://sms.ru/sms/send?api_id=' . $api_key . '&to=' . rawurlencode($phone) . '&msg=' . rawurlencode($text);
        $response = wp_remote_get($url);
        if(is_wp_error($response)) {
            echo json_encode(['success' => false, 'message' => 'Ошибка отправки SMS']);
            exit;
        }
        echo json_encode(['success' => true, 'message' => 'Код отправлен на ваш телефон']);
        exit;
    }

    if(isset($_POST['verify_otp']) && isset($_POST['phone']) && isset($_POST['otp'])) {
        header('Content-Type: application/json');
        $phone = sanitize_text_field($_POST['phone']);
        $otp = sanitize_text_field($_POST['otp']);

        $user = get_users(array(
            'meta_key' => 'phone',
            'meta_value' => $phone,
            'number' => 1,
            'count_total' => false
        ));
        if(empty($user)) {
            echo json_encode(['success' => false, 'message' => 'Пользователь не найден']);
            exit;
        }
        $user = $user[0];
        $saved_otp = get_user_meta($user->ID, 'sms_otp', true);
        $otp_time = get_user_meta($user->ID, 'sms_otp_time', true);

        if(!$saved_otp || !$otp_time || (time() - $otp_time) > 300) { // 5 минут
            echo json_encode(['success' => false, 'message' => 'Код устарел или отсутствует']);
            exit;
        }

        if($otp !== $saved_otp) {
            echo json_encode(['success' => false, 'message' => 'Неверный код']);
            exit;
        }

        // Удаляем OTP после успешной проверки
        delete_user_meta($user->ID, 'sms_otp');
        delete_user_meta($user->ID, 'sms_otp_time');

        // Авторизация пользователя
        wp_clear_auth_cookie();
        wp_set_current_user($user->ID);
        wp_set_auth_cookie($user->ID);

        echo json_encode(['success' => true, 'message' => 'Авторизация успешна']);
        exit;
    }
});

Проверка результата: как убедиться, что авторизация работает

  • Добавьте шорткод [wc_sms_login_form] на тестовую страницу.
  • Попробуйте ввести номер телефона, зарегистрированный у пользователя (укажите его в user meta с ключом phone).
  • Проверьте получение SMS с OTP (важно, чтобы SMS API был настроен корректно).
  • Введите код на форме подтверждения и убедитесь, что происходит вход в аккаунт без ввода пароля.
  • После успешного входа проверьте, что is_user_logged_in() возвращает true, и пользователь видит свой профиль.

Частые ошибки и их устранение

  • Пользователь не найден по номеру телефона: убедитесь, что у всех ваших пользователей есть мета ключ phone с корректным номером. Для массового добавления можно использовать SQL-запрос или WP CLI.
  • SMS не отправляются: проверьте правильность API ключа, формат номера, и ответы от SMS-провайдера. Для отладки используйте error_log(print_r($response,true)).
  • Код OTP не проходит проверку: убедитесь, что время жизни кода (5 минут в примере) не истекло, и что коды сравниваются строго (строгое сравнение строк).
  • Форма не переключается между вводом номера и вводом кода: проверьте корректность JS-кода и отсутствие конфликтов с другими скриптами.

Практические советы по безопасности и производительности

  • OTP должен быть одноразовым и иметь ограниченный срок действия (5 минут оптимально).
  • Храните OTP в зашифрованном виде, если требуется дополнительная безопасность (например, через hash_hmac).
  • Ограничьте количество попыток ввода OTP, чтобы избежать перебора кодов.
  • Используйте nonce и проверку прав пользователя при обработке форм, чтобы избежать CSRF-атак.
  • Кэширование страницы с формой отключите, чтобы всегда отображалась актуальная форма.
  • Для повышения удобства можно интегрировать WPShop Clearfy Pro для удаления лишних дублей и оптимизации сайта после внедрения новых функций.

Сравнение вариантов реализации авторизации через SMS в WooCommerce

МетодПлюсыМинусыПример
Плагин (например, OTP Verification)Быстрая настройка, поддержка функционалаЗависимость от стороннего кода, возможные конфликтыClearfy
Собственная реализация на PHP и JSПолный контроль, гибкость, минимальные зависимостиТребует разработки и поддержки, нужно настроить SMS APIКод в статье выше
Использование внешних сервисов авторизации (Auth0, Firebase)Надёжность, масштабируемость, готовые решенияЗависимость от сторонних сервисов, стоимостьИнтеграция через SDK и WP плагины
WooCommerce: как автоматически удалять записи по увязанным товарам после удаления товара
30.05.2026
Как использовать вебхуки в WordPress для автоматизации задач
02.03.2026
Автоматическое отключение плагинов по расписанию в WordPress
06.03.2026
Как создать автoобновляемый отпуск для постов в WordPress
28.11.2025
Автоматический импорт данных из Excel в WordPress
06.12.2025