Диагностика проблемы: почему нужны альтернативы SMS-провайдерам
Многие интернет-магазины на WooCommerce хотят реализовать авторизацию по телефону, но без использования платных SMS-провайдеров. Это может быть вызвано желанием избежать затрат, задержек с доставкой SMS или ограничениями по региону. При этом стандартные плагины либо требуют подключения к внешним сервисам, либо не обеспечивают достаточную безопасность.
Основная задача — реализовать подтверждение входа и регистрации по номеру телефона с минимальными затратами и без внешних SMS-сервисов.
Пошаговое решение: как реализовать авторизацию по телефону без SMS-провайдеров
1. Использование Email для отправки кода подтверждения вместо SMS
Самый простой способ — отправлять одноразовый код подтверждения на Email, связанный с номером телефона, или на Email, введённый пользователем. Это снимает зависимость от SMS и позволяет использовать встроенную функцию WordPress wp_mail().
2. Добавление поля телефон в форму регистрации WooCommerce
Для начала расширим форму регистрации, чтобы пользователь вводил телефон:
add_action('woocommerce_register_form_start', function() {
?>
<p class="form-row form-row-wide">
<label for="reg_billing_phone">Телефон <span class="required">*</span></label>
<input type="tel" class="input-text" name="billing_phone" id="reg_billing_phone" value="" required />
</p>
<?php
});3. Валидация и сохранение номера телефона
Проверяем, что номер введён и сохраняем его в метаданные пользователя:
add_action('woocommerce_register_post', function($username, $email, $validation_errors) {
if (empty($_POST['billing_phone']) || !preg_match('/^\+?\d{10,15}$/', $_POST['billing_phone'])) {
$validation_errors->add('billing_phone_error', 'Введите корректный номер телефона.');
}
}, 10, 3);
add_action('woocommerce_created_customer', function($customer_id) {
if (!empty($_POST['billing_phone'])) {
update_user_meta($customer_id, 'billing_phone', sanitize_text_field($_POST['billing_phone']));
}
});4. Генерация и хранение одноразового кода (OTP)
Создадим функцию генерации 6-значного кода и сохраним его в пользовательском мета с ограничением по времени:
function generate_otp($user_id) {
$otp = wp_rand(100000, 999999);
update_user_meta($user_id, '_login_otp', $otp);
update_user_meta($user_id, '_login_otp_expiry', time() + 300); // 5 минут
return $otp;
}5. Отправка OTP на Email при попытке входа
Перехватим процесс логина и отправим код на email пользователя с указанным номером телефона:
add_action('wp_authenticate', function($username) {
$user = get_user_by('login', $username);
if ($user) {
$otp = generate_otp($user->ID);
$email = $user->user_email;
$subject = 'Ваш код для входа';
$message = "Ваш код подтверждения для входа: $otp. Код действителен 5 минут.";
wp_mail($email, $subject, $message);
// Можно добавить логику временной блокировки входа до ввода OTP
}
});6. Создание формы для ввода OTP и проверка кода
Добавим отдельную страницу или форму для ввода OTP и сравним введённый код с сохранённым, проверяя срок действия:
function verify_otp($user_id, $input_otp) {
$saved_otp = get_user_meta($user_id, '_login_otp', true);
$expiry = get_user_meta($user_id, '_login_otp_expiry', true);
if (!$saved_otp || !$expiry) return false;
if (time() > $expiry) return false;
if ($input_otp == $saved_otp) {
delete_user_meta($user_id, '_login_otp');
delete_user_meta($user_id, '_login_otp_expiry');
return true;
}
return false;
}Проверка результата после внедрения
- Зарегистрируйтесь новым пользователем, убедитесь, что номер телефона сохраняется и валидируется.
- Попробуйте войти под этим пользователем — проверьте, что на связанный email приходит код OTP.
- Введите код на странице подтверждения и убедитесь, что вход разрешён.
- Попробуйте ввести неправильный или просроченный код — вход должен запрещаться.
Частые ошибки и как их исправить
- Код OTP не приходит на email: проверьте работу
wp_mail(), настройте SMTP или плагин для отправки почты (например, WP Mail SMTP). - Номер телефона не сохраняется: убедитесь, что поле
billing_phoneесть в форме и правильно обрабатывается в хуках сохранения. - Код OTP не совпадает или постоянно истекает: проверьте логику генерации и удаления кода, а также корректность сравнения.
- Пользователь может войти без ввода OTP: реализуйте блокировку авторизации до проверки OTP, например, через фильтр
authenticate.
Практические советы по безопасности и производительности
- Не храните OTP в открытом виде — для усиления безопасности можно хранить хэш кода.
- Ограничьте количество попыток ввода OTP, чтобы избежать перебора.
- Используйте HTTPS для защиты передачи кода.
- Для почтовых отправок используйте SMTP-серверы с авторизацией для повышения надежности доставки.
- Удаляйте устаревшие OTP через крон или при успешном вводе.
Сравнение вариантов реализации авторизации по телефону без SMS
| Метод | Описание | Плюсы | Минусы |
|---|---|---|---|
| Код на Email (через wp_mail()) | Отправка OTP на email, связанный с телефоном | Без доп. затрат, быстро реализуется | Зависит от email, не подходит если нет email |
| Временные ссылки на телефон (через URL) | Отправка ссылки с токеном на email, подтверждающая вход | Удобно, не требует ввода кода | Нужно корректно обрабатывать безопасность токена |
| Использование внешних мессенджеров (Telegram, WhatsApp) | Отправка кода через бота или чат | Отделение от SMS, часто бесплатно | Сложнее в реализации, требует интеграции |