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

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

Безопасность пользовательских аккаунтов в WooCommerce — критический аспект для интернет-магазинов, особенно при работе с персональными данными и оплатой. Пароли можно украсть, забыть или подобрать. Внедрение одноразового пароля (OTP, One-Time Password) через SMS повышает безопасность, минимизирует риск взлома и упрощает вход для пользователей, не требуя запоминать сложные пароли.

Задача: реализовать в WooCommerce авторизацию пользователей по SMS OTP вместо стандартного пароля или как дополнительный фактор.

Как проверить, что в WooCommerce нужна SMS OTP авторизация

  • Анализ обращений службы поддержки по вопросам взлома аккаунтов;
  • Высокий процент забытых паролей и запросов на восстановление;
  • Желание улучшить UX и безопасность без внедрения сложных двухфакторных систем;
  • Проверка наличия плагинов для OTP и их возможностей. Если их нет — нужна разработка кастомного решения.

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

1. Выбор SMS-сервиса

Для отправки OTP понадобится SMS-шлюз (например, Twilio, Nexmo, или российские провайдеры). Регистрация и получение API-ключей обязательны. Ниже пример для Twilio (один из самых популярных международных сервисов):

require_once 'vendor/autoload.php';
use Twilio\Rest\Client;

function send_sms_otp($phone, $otp) {
    $sid = 'TWILIO_SID';
    $token = 'TWILIO_TOKEN';
    $client = new Client($sid, $token);
    try {
        $message = $client->messages->create(
            $phone,
            [
                'from' => 'TWILIO_PHONE_NUMBER',
                'body' => "Ваш код подтверждения: $otp"
            ]
        );
        return true;
    } catch (Exception $e) {
        error_log('Ошибка отправки SMS: ' . $e->getMessage());
        return false;
    }
}

2. Генерация и хранение OTP кода

Код OTP генерируется при попытке входа, сохраняется в сессии или transient с ограниченным временем жизни (например, 5 минут).

function generate_otp_code() {
    return rand(100000, 999999);
}

function save_otp_for_user($user_id, $otp) {
    set_transient('otp_code_' . $user_id, $otp, 5 * MINUTE_IN_SECONDS);
}

function get_saved_otp($user_id) {
    return get_transient('otp_code_' . $user_id);
}

3. Перехват стандартной авторизации WooCommerce

Подменяем стандартную форму входа на форму с номером телефона, отправляем OTP, а затем принимаем ввод кода для подтверждения.

Пример фильтра для кастомного логина:

add_action('woocommerce_login_form', 'custom_otp_login_form');
function custom_otp_login_form() {
    ?>
    <p class="form-row form-row-wide">
        <label for="otp_phone">Номер телефона <span class="required">*</span></label>
        <input type="text" class="input-text" name="otp_phone" id="otp_phone" autocomplete="off" />
    </p>
    <p class="form-row form-row-wide">
        <button type="button" id="send_otp_btn">Получить код</button>
    </p>
    <p class="form-row form-row-wide" style="display:none;" id="otp_input_field">
        <label for="otp_code">Введите код <span class="required">*</span></label>
        <input type="text" class="input-text" name="otp_code" id="otp_code" autocomplete="off" />
    </p>
    <p class="form-row form-row-wide" style="display:none;" id="otp_submit_field">
        <button type="submit" class="button" name="otp_login">Войти</button>
    </p>
    <script>
    jQuery(document).ready(function($){
        $('#send_otp_btn').click(function(){
            var phone = $('#otp_phone').val();
            if(!phone) {
                alert('Введите номер телефона');
                return;
            }
            $.post(ajaxurl, {action: 'send_sms_otp', phone: phone}, function(response){
                if(response.success) {
                    alert('Код отправлен');
                    $('#otp_input_field, #otp_submit_field').show();
                    $('#send_otp_btn').hide();
                } else {
                    alert('Ошибка: ' + response.data);
                }
            });
        });
    });
    </script>
    <?php
}

4. Обработка AJAX-запроса для отправки OTP

add_action('wp_ajax_send_sms_otp', 'ajax_send_sms_otp');
add_action('wp_ajax_nopriv_send_sms_otp', 'ajax_send_sms_otp');

function ajax_send_sms_otp() {
    $phone = sanitize_text_field($_POST['phone']);
    if (!$phone) {
        wp_send_json_error('Номер телефона не указан');
    }
    // Поиск пользователя по номеру телефона (предполагается, что номер хранится в user meta 'billing_phone')
    $user_query = new WP_User_Query(array(
        'meta_key' => 'billing_phone',
        'meta_value' => $phone,
        'number' => 1
    ));
    $users = $user_query->get_results();
    if (empty($users)) {
        wp_send_json_error('Пользователь с таким номером не найден');
    }
    $user = $users[0];
    $otp = generate_otp_code();
    save_otp_for_user($user->ID, $otp);
    if(send_sms_otp($phone, $otp)) {
        wp_send_json_success();
    } else {
        wp_send_json_error('Не удалось отправить SMS');
    }
}

5. Валидация OTP при отправке формы входа

add_action('init', 'process_otp_login');
function process_otp_login() {
    if(isset($_POST['otp_login'])) {
        $phone = sanitize_text_field($_POST['otp_phone']);
        $code = sanitize_text_field($_POST['otp_code']);
        if(!$phone || !$code) {
            wc_add_notice('Введите номер телефона и код из SMS', 'error');
            return;
        }
        $user_query = new WP_User_Query(array(
            'meta_key' => 'billing_phone',
            'meta_value' => $phone,
            'number' => 1
        ));
        $users = $user_query->get_results();
        if(empty($users)) {
            wc_add_notice('Пользователь не найден', 'error');
            return;
        }
        $user = $users[0];
        $saved_otp = get_saved_otp($user->ID);
        if(!$saved_otp || $saved_otp != $code) {
            wc_add_notice('Неверный код подтверждения или срок действия истек', 'error');
            return;
        }
        // Авторизация пользователя
        wp_set_auth_cookie($user->ID);
        wp_redirect(wc_get_page_permalink('myaccount'));
        exit;
    }
}

Проверка результата после внедрения

  • Перейдите на страницу входа WooCommerce, проверьте, что форма запрашивает номер телефона и отправку OTP;
  • Введите зарегистрированный номер, нажмите «Получить код», проверьте получение SMS;
  • Введите полученный код, убедитесь, что происходит успешный вход и перенаправление на аккаунт;
  • Попробуйте ввести неверный код — должна появиться ошибка;
  • Проверьте, что код не действует после 5 минут (или заданного срока);
  • Анализируйте логи ошибок отправки SMS;
  • Тестируйте на разных устройствах и браузерах.

Частые ошибки и как их исправить

  • Не приходит SMS: проверьте правильность API-ключей и номера отправителя в SMS-сервисе, убедитесь, что баланс аккаунта положительный;
  • Пользователь не найден по номеру: убедитесь, что номера телефонов пользователей корректно и однородно сохранены (формат, без пробелов/скобок); можно добавить нормализацию номера перед поиском;
  • Код OTP не сохраняется или не совпадает: проверьте работу transient, не очищается ли слишком быстро, убедитесь, что пользователь ID передаётся корректно;
  • Форма не меняется: проверьте подключение скриптов, отсутствие конфликтов с темой или другими плагинами;
  • Безопасность передачи данных: используйте HTTPS, убедитесь, что AJAX-запросы проходят с nonce и проверкой прав.

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

  • Ограничьте количество попыток отправки OTP за короткий период, чтобы предотвратить спам и атаки перебором;
  • Используйте WP Nonce для AJAX-запросов, чтобы защититься от CSRF;
  • Храните OTP в transient с небольшим сроком действия (3-5 минут);
  • Используйте валидацию и нормализацию номера телефона (например, с библиотекой libphonenumber);
  • Кэшируйте страницы WooCommerce аккуратно, исключая страницы входа и аккаунта;
  • Для WooCommerce с большим трафиком рекомендуем использовать очереди для отправки SMS (например, через WP Cron или внешние сервисы);
  • Логи ошибок отправки SMS сохраняйте в отдельный файл для быстрого мониторинга.

Сравнение способов реализации авторизации через SMS OTP

МетодПлюсыМинусыПример
Плагин готовый (например, "OTP Login for WooCommerce") Быстрая установка, минимум кода Могут быть платными, ограниченные настройки, зависимость от стороннего кода Clearfy Pro может помочь с оптимизацией, но OTP лучше отдельным плагином
Кастомный код с SMS API Полный контроль, можно интегрировать с любыми сервисами, гибкая логика Требует знаний, времени на разработку, поддержку Пример из статьи
Двухфакторная авторизация на базе плагинов (Google Authenticator и т.п.) Доп. уровень защиты Сложнее для пользователей, не всегда удобно Плагины типа Two-Factor

Добавь в закладки и поделись с друзьями:

⭐⭐⭐⭐⭐
Автоматическое удаление проблемных изображений в WordPress: решение для оптимизации сайта
22.02.2026
Как установить ограничения на сохранение данных через REST API в WordPress
12.04.2026
WooCommerce: как правильно удалять товары с очисткой связанных данных
16.05.2026
Как удалить старые ревизии записей в WordPress для оптимизации базы данных
14.01.2026
Как использовать хук pre_get_posts для фильтрации записей в WordPress
04.03.2026
×

AI-плагин

WPGPT
Сам создает статьи для вашего сайта WordPress

SEO и мета-теги

Парсинг конкурентов

Изображения

Комментарии

Подробнее