Что такое OTP-авторизация без SMS-провайдеров и зачем она нужна в WooCommerce
Одноразовый пароль (OTP) часто используется для повышения безопасности входа. В WooCommerce стандартно OTP отправляется по SMS через сторонних провайдеров, что влечет за собой дополнительные расходы и сложности с настройкой. Альтернатива — реализовать OTP без SMS, используя email или генерацию кода локально, что снижает затраты и упрощает интеграцию.
Диагностика: проблемы при использовании стандартных SMS-провайдеров
- Высокая стоимость SMS-рассылок при большом числе клиентов.
- Необходимость регистрации и настройки аккаунтов у сторонних провайдеров.
- Зависимость от стабильности API провайдера.
- Задержки в доставке сообщений, влияющие на удобство пользователя.
Пошаговое решение: реализация OTP через email в WooCommerce
1. Генерация одноразового кода при попытке входа
При вводе email на странице входа мы создаем случайный шестизначный код, сохраняем его в пользовательских мета и отправляем на email.
add_action('wp_ajax_nopriv_send_otp_email', 'send_otp_email_callback');
function send_otp_email_callback() {
$user_email = sanitize_email($_POST['email']);
if (!is_email($user_email)) {
wp_send_json_error('Неверный email');
}
$user = get_user_by('email', $user_email);
if (!$user) {
wp_send_json_error('Пользователь не найден');
}
$otp_code = wp_rand(100000, 999999);
update_user_meta($user->ID, '_otp_code', $otp_code);
update_user_meta($user->ID, '_otp_code_time', time());
$subject = 'Ваш одноразовый код для входа';
$message = 'Ваш код: ' . $otp_code . ". Срок действия 10 минут.";
wp_mail($user_email, $subject, $message);
wp_send_json_success('Код отправлен');
}2. Валидация кода и вход пользователя
Проверяем, совпадает ли введенный пользователем код с сохраненным и не истек ли срок его действия (10 минут). Если все верно — авторизуем пользователя.
add_action('wp_ajax_nopriv_verify_otp_login', 'verify_otp_login_callback');
function verify_otp_login_callback() {
$user_email = sanitize_email($_POST['email']);
$otp_input = sanitize_text_field($_POST['otp']);
if (!is_email($user_email) || empty($otp_input)) {
wp_send_json_error('Неверные данные');
}
$user = get_user_by('email', $user_email);
if (!$user) {
wp_send_json_error('Пользователь не найден');
}
$saved_otp = get_user_meta($user->ID, '_otp_code', true);
$otp_time = (int) get_user_meta($user->ID, '_otp_code_time', true);
if (!$saved_otp || !$otp_time || time() - $otp_time > 600) { // 600 секунд = 10 минут
wp_send_json_error('Код истек или не найден');
}
if ($otp_input !== $saved_otp) {
wp_send_json_error('Неверный код');
}
// Удаляем код после успешной проверки
delete_user_meta($user->ID, '_otp_code');
delete_user_meta($user->ID, '_otp_code_time');
wp_clear_auth_cookie();
wp_set_current_user($user->ID);
wp_set_auth_cookie($user->ID);
wp_send_json_success('Успешный вход');
}3. Добавление интерфейса на страницу входа WooCommerce
Встраиваем поля для email и OTP, а также кнопки для отправки кода и входа с проверкой.
add_action('woocommerce_login_form', 'add_otp_login_fields');
function add_otp_login_fields() {
?>
<p class="form-row form-row-wide">
<label for="otp_email">Email <span class="required">*</span></label>
<input type="email" class="input-text" name="otp_email" id="otp_email" autocomplete="email" />
</p>
<p class="form-row form-row-wide">
<button type="button" id="send_otp_code">Отправить код</button>
</p>
<p class="form-row form-row-wide">
<label for="otp_code">Код OTP <span class="required">*</span></label>
<input type="text" class="input-text" name="otp_code" id="otp_code" autocomplete="one-time-code" />
</p>
<p class="form-row form-row-wide">
<button type="button" id="verify_otp_login">Войти по коду</button>
</p>
<script>
jQuery(function($) {
$('#send_otp_code').on('click', function() {
var email = $('#otp_email').val();
$.post(ajaxurl, { action: 'send_otp_email', email: email }, function(response) {
alert(response.data || response.data);
});
});
$('#verify_otp_login').on('click', function() {
var email = $('#otp_email').val();
var otp = $('#otp_code').val();
$.post(ajaxurl, { action: 'verify_otp_login', email: email, otp: otp }, function(response) {
if (response.success) {
location.reload();
} else {
alert(response.data || 'Ошибка');
}
});
});
});
</script>
<?php
}Проверка результата после внедрения
- Откройте страницу входа WooCommerce, введите email зарегистрированного пользователя.
- Нажмите кнопку «Отправить код», проверьте почту – должен прийти шестизначный OTP.
- Введите полученный код в поле «Код OTP» и нажмите «Войти по коду».
- Если код верный и не просрочен, произойдет вход в аккаунт без пароля.
Частые ошибки и как их исправить
- Не приходит письмо с кодом: проверьте настройки почты на сервере, используйте SMTP-плагин для надежной отправки.
- Код всегда считается неверным: убедитесь, что вы используете правильный email, и код совпадает с тем, что пришел на email; проверьте, не превышен ли таймаут 10 минут.
- Ajax-запросы не работают: убедитесь, что
ajaxurlопределен в JS (в админке он есть по умолчанию, для фронтенда нужно подключать локализацию скрипта). - Пользователь не авторизуется после проверки кода: проверьте, что функции
wp_set_current_userиwp_set_auth_cookieвызываются корректно и нет конфликтов с другими плагинами авторизации.
Практические советы для безопасности и производительности
- Ограничьте количество запросов на отправку OTP с одного IP или email за определенный промежуток времени.
- Используйте HTTPS для защиты передачи данных.
- Храните коды OTP в мета-полях с префиксом, чтобы избежать коллизий с другими данными.
- Удаляйте коды после их использования или по истечении срока действия.
- Для улучшения UX добавьте таймер обратного отсчета для повторной отправки кода.
Сравнение вариантов реализации OTP в WooCommerce
| Метод | Плюсы | Минусы | Требования |
|---|---|---|---|
| OTP через SMS-провайдеры | Высокая надежность доставки, знакомый формат для пользователей | Стоимость, настройка, зависимость от сторонних сервисов | Аккаунт у SMS-провайдера, API ключи |
| OTP через Email (локальная генерация) | Бесплатно, просто внедрять, не требует сторонних сервисов | Зависимость от почтового сервера, может попадать в спам | Корректно настроенный email сервер, SMTP |
| Локальная генерация и ввод кода без отправки (например, через приложение) | Максимальная безопасность, отсутствие сетевых задержек | Сложно для пользователей, требует отдельное приложение | Дополнительное ПО для пользователей |