Диагностика задачи: зачем нужна авторизация через SMS в WooCommerce
Стандартная регистрация и авторизация в WooCommerce основаны на пароле, что может отпугнуть часть пользователей из-за сложности запоминания или опасений по безопасности. Авторизация через одноразовые коды по SMS (OTP) повышает удобство и безопасность входа, особенно для мобильной аудитории.
Однако встроенных средств для реализации такой схемы в WooCommerce нет, и многие прибегают к плагинам. Но плагины могут создавать нагрузку и конфликты. В статье разберём, как реализовать авторизацию через SMS без плагинов, используя собственный код и сервис SMS-рассылки.
Требования и подготовка
- WooCommerce установлен и работает на сайте.
- Аккаунт и API у SMS-провайдера (например, sms.ru, Twilio, или любой другой.
- Базовые знания PHP и работы с WordPress/WooCommerce хуками.
Как работает схема авторизации через SMS
- Пользователь вводит номер телефона вместо логина и пароля.
- На номер отправляется одноразовый код (OTP).
- Пользователь вводит код на сайте.
- Если код верный и актуальный, пользователь авторизуется или создаётся новый аккаунт.
Шаг 1. Добавляем поля для номера телефона и кода на страницу входа WooCommerce
Добавим в шаблон входа два поля: для телефона и для одноразового кода.
add_action('woocommerce_login_form', function() {
echo '<p class="form-row form-row-wide">';
echo '<label for="phone_number">Номер телефона (введите без +)</label>';
echo '<input type="text" name="phone_number" id="phone_number" class="input-text" autocomplete="tel" />';
echo '</p>';
echo '<p class="form-row form-row-wide">';
echo '<label for="sms_code">Код из SMS</label>';
echo '<input type="text" name="sms_code" id="sms_code" class="input-text" autocomplete="one-time-code" />';
echo '</p>';
echo '<p class="form-row"><button type="button" id="send_sms_code" class="button">Отправить код</button></p>';
});Шаг 2. Обработка отправки SMS кода через AJAX
Добавим обработчик на стороне сервера, который будет принимать номер телефона, генерировать код, сохранять его и отправлять SMS.
add_action('wp_ajax_send_sms_code', 'send_sms_code_handler');
add_action('wp_ajax_nopriv_send_sms_code', 'send_sms_code_handler');
function send_sms_code_handler() {
if ( empty($_POST['phone']) ) {
wp_send_json_error('Номер телефона не указан');
}
$phone = preg_replace('/[^0-9]/', '', sanitize_text_field($_POST['phone']));
if (strlen($phone) < 10) {
wp_send_json_error('Неверный формат номера');
}
// Генерируем 6-значный код
$code = wp_rand(100000, 999999);
$expires = time() + 300; // код действителен 5 минут
// Сохраняем код и время в сессии
if ( !session_id() ) {
session_start();
}
$_SESSION['sms_code_'.$phone] = ['code' => $code, 'expires' => $expires];
// Отправляем SMS через API (пример для sms.ru)
$api_id = 'ВАШ_API_ID';
$message = "Ваш код для входа: $code";
$url = "https://sms.ru/sms/send?api_id={$api_id}&to={$phone}&msg=" . rawurlencode($message) . "&json=1";
$response = wp_remote_get($url);
if (is_wp_error($response)) {
wp_send_json_error('Ошибка отправки SMS');
}
$body = json_decode(wp_remote_retrieve_body($response), true);
if ($body['status'] !== 'OK') {
wp_send_json_error('Ошибка сервера SMS: ' . $body['status_text']);
}
wp_send_json_success('Код отправлен');
}
add_action('wp_enqueue_scripts', function() {
if (is_account_page()) {
wp_enqueue_script('sms-login', get_stylesheet_directory_uri() . '/sms-login.js', ['jquery'], null, true);
wp_localize_script('sms-login', 'smsLogin', ['ajaxurl' => admin_url('admin-ajax.php')]);
}
});Шаг 3. Скрипт для отправки кода при клике
Создайте файл sms-login.js в вашей теме с таким содержимым:
jQuery(document).ready(function($){
$('#send_sms_code').on('click', function(e){
e.preventDefault();
var phone = $('#phone_number').val();
if(!phone) {
alert('Введите номер телефона');
return;
}
$.post(smsLogin.ajaxurl, {action: 'send_sms_code', phone: phone}, function(response){
if(response.success) {
alert('Код отправлен');
} else {
alert('Ошибка: ' + response.data);
}
});
});
});Шаг 4. Проверяем код и авторизуем пользователя
Добавим проверку кода при попытке логина. Если код валиден, авторизуем пользователя по номеру телефона или создаём его.
add_filter('authenticate', 'sms_code_authenticate', 30, 3);
function sms_code_authenticate($user, $username, $password) {
if ( !empty($_POST['phone_number']) && !empty($_POST['sms_code']) ) {
$phone = preg_replace('/[^0-9]/', '', sanitize_text_field($_POST['phone_number']));
$code = sanitize_text_field($_POST['sms_code']);
if ( !session_id() ) {
session_start();
}
if ( empty($_SESSION['sms_code_'.$phone]) ) {
return new WP_Error('invalid_code', 'Код не отправлялся на этот номер');
}
$data = $_SESSION['sms_code_'.$phone];
if ( time() > $data['expires'] ) {
unset($_SESSION['sms_code_'.$phone]);
return new WP_Error('expired_code', 'Код истёк');
}
if ( $code !== $data['code'] ) {
return new WP_Error('wrong_code', 'Неверный код');
}
unset($_SESSION['sms_code_'.$phone]);
// Ищем пользователя по метаполю с номером телефона
$user_query = new WP_User_Query(array(
'meta_key' => 'phone_number',
'meta_value' => $phone,
'number' => 1
));
if ( !empty($user_query->results) ) {
return $user_query->results[0];
} else {
// Создаём пользователя без пароля
$userdata = array(
'user_login' => 'user_' . $phone,
'user_pass' => wp_generate_password(12, false),
'user_email' => '',
'display_name' => $phone
);
$user_id = wp_insert_user($userdata);
if (is_wp_error($user_id)) {
return $user_id;
}
update_user_meta($user_id, 'phone_number', $phone);
return get_user_by('id', $user_id);
}
}
return $user;
}Проверка результата
- Зайдите на страницу входа WooCommerce.
- Введите корректный номер телефона и нажмите "Отправить код".
- Получите SMS с кодом (проверьте логи или реально получите на телефон).
- Введите код и отправьте форму входа.
- Если код верный, вы должны войти или зарегистрироваться без пароля.
Частые ошибки и их исправление
- Код не отправляется: проверьте API ID, корректность запроса и ограничения SMS-провайдера.
- Сессии нет или код не сохраняется: убедитесь, что
session_start()вызывается корректно, без ошибок. - Пользователь не авторизуется: проверьте, что метаполе
phone_numberиспользуется одинаково и что пользователь создаётся без ошибок. - Код просрочен слишком быстро: увеличьте время жизни кода в переменной
$expires.
Практические советы по безопасности и производительности
- Используйте HTTPS для защиты данных формы и запросов.
- Ограничьте количество запросов на отправку SMS с одного IP или номера телефона, чтобы избежать спама.
- Храните одноразовые коды в серверной сессии, не в базе данных, чтобы избежать избыточной нагрузки.
- Обрабатывайте ошибки API SMS, чтобы не вводить пользователя в заблуждение.
- Для больших проектов рассмотрите кеширование и более сложное управление сессиями.
Сравнение вариантов реализации авторизации через SMS
| Метод | Плюсы | Минусы | Ресурсы |
|---|---|---|---|
| Плагины (например, OTP Login) | Быстрая настройка, готовый функционал | Вес, возможные конфликты, ограниченная кастомизация | WordPress.org |
| Кастомный код + SMS API | Полный контроль, легковесность, гибкость | Требует знаний PHP, поддержка и доработка на разработчике | SMS API, документация WooCommerce |
| Внешние сервисы (Authy, Firebase) | Высокая надёжность, расширенный функционал | Сложность интеграции, стоимость | API сервисов |