Проблема: как реализовать авторизацию по телефону без сторонних SMS-сервисов
Многие владельцы WooCommerce хотят упростить процесс входа для пользователей, используя телефонный номер вместо email и пароля. Однако интеграция с SMS-провайдерами часто связана с дополнительными расходами и сложностями. Задача — реализовать авторизацию или регистрацию по номеру телефона с подтверждением через email, вместо SMS, либо с использованием временного кода без участия внешних SMS-сервисов.
Диагностика задачи: что нужно учесть при реализации
- WooCommerce по умолчанию не поддерживает вход по номеру телефона.
- Поле телефонного номера хранится в метаданных пользователя, а не в стандартном поле для логина.
- Нужно заменить стандартный механизм входа на кастомный с проверкой телефона.
- Нужно обеспечить безопасность: проверять владельца номера без SMS.
- Необходимо не нарушать работу других плагинов, не ломать стандартные хуки WooCommerce.
Пошаговое решение: реализация авторизации по телефону с подтверждением через email
1. Добавляем поле телефонного номера в форму входа и регистрации
Для регистрации и входа расширим формы WooCommerce, добавим поле phone_number и обработаем его.
add_action('woocommerce_register_form_start', function() {
echo '<p class="form-row form-row-wide"><label for="reg_phone_number">Телефонный номер <span class="required">*</span></label><input type="text" class="input-text" name="phone_number" id="reg_phone_number" value="' . ( isset( $_POST['phone_number'] ) ? esc_attr( $_POST['phone_number'] ) : '' ) . '" /></p>';
});
add_action('woocommerce_login_form', function() {
echo '<p class="form-row form-row-wide"><label for="login_phone_number">Телефонный номер</label><input type="text" class="input-text" name="phone_number" id="login_phone_number" value="' . ( isset( $_POST['phone_number'] ) ? esc_attr( $_POST['phone_number'] ) : '' ) . '" /></p>';
});2. Валидация и сохранение телефона при регистрации
Проверяем поле и сохраняем телефон в метаданных пользователя.
add_action('woocommerce_register_post', function($username, $email, $validation_errors) {
if ( empty( $_POST['phone_number'] ) ) {
$validation_errors->add('phone_number_error', 'Пожалуйста, введите телефонный номер.');
} elseif ( ! preg_match('/^[0-9]{10,15}$/', $_POST['phone_number']) ) {
$validation_errors->add('phone_number_format_error', 'Введите корректный телефонный номер (только цифры, 10-15 символов).');
}
return $validation_errors;
}, 10, 3);
add_action('woocommerce_created_customer', function($customer_id) {
if ( ! empty( $_POST['phone_number'] ) ) {
update_user_meta( $customer_id, 'phone_number', sanitize_text_field($_POST['phone_number']) );
}
});3. Авторизация по телефону с подтверждением через email (временный код)
Реализуем механизм, при котором пользователь вводит телефон, получает на email ссылку с временным токеном для входа.
Шаги:
- Проверяем номер телефона, ищем пользователя по метаданным.
- Генерируем одноразовый токен, сохраняем в user_meta с временем истечения.
- Отправляем email с ссылкой на вход, содержащей токен.
- При переходе по ссылке проверяем токен и авторизуем пользователя.
function send_login_link_by_email($phone_number) {
$users = get_users([
'meta_key' => 'phone_number',
'meta_value' => $phone_number,
'number' => 1,
]);
if (empty($users)) {
return new WP_Error('no_user', 'Пользователь с таким номером не найден.');
}
$user = $users[0];
$token = wp_generate_password(20, false);
update_user_meta($user->ID, 'login_token', $token);
update_user_meta($user->ID, 'login_token_expiry', time() + 900); // 15 минут
$login_url = add_query_arg([
'phone_login_token' => $token,
'user_id' => $user->ID
], site_url('/')); // можно заменить на страницу входа
wp_mail($user->user_email, 'Ссылка для входа', 'Перейдите по ссылке для входа: ' . $login_url);
return true;
}
add_action('init', function() {
if ( isset($_GET['phone_login_token'], $_GET['user_id']) ) {
$user_id = intval($_GET['user_id']);
$token = sanitize_text_field($_GET['phone_login_token']);
$saved_token = get_user_meta($user_id, 'login_token', true);
$expiry = get_user_meta($user_id, 'login_token_expiry', true);
if ($token === $saved_token && time() <= $expiry) {
wp_set_auth_cookie($user_id);
delete_user_meta($user_id, 'login_token');
delete_user_meta($user_id, 'login_token_expiry');
wp_redirect(home_url());
exit;
} else {
wp_die('Ссылка недействительна или истекла.');
}
}
});4. Форма для запроса ссылки на вход по телефону
Добавим простую форму на страницу входа, чтобы пользователь мог запросить ссылку.
add_action('woocommerce_login_form', function() {
echo '<form method="post" style="margin-top:20px;">'
. '<p><label for="phone_login">Телефон для входа по ссылке</label><br/>'
. '<input type="text" name="phone_login" id="phone_login" required /></p>'
. '<p><input type="submit" name="send_phone_login_link" value="Получить ссылку" /></p>'
. '</form>';
if ( isset($_POST['send_phone_login_link']) && !empty($_POST['phone_login']) ) {
$result = send_login_link_by_email(sanitize_text_field($_POST['phone_login']));
if (is_wp_error($result)) {
echo '<p style="color:red;">' . esc_html($result->get_error_message()) . '</p>';
} else {
echo '<p style="color:green;">Ссылка для входа отправлена на ваш email.</p>';
}
}
});Проверка результата
- Зарегистрируйтесь с номером телефона, проверьте сохранение в профиле (в базе в usermeta).
- На странице входа введите номер телефона в форму запроса ссылки.
- Проверьте, что на email пользователя приходит письмо со ссылкой.
- Перейдите по ссылке, убедитесь, что происходит вход без пароля.
- Проверьте, что после входа токен удаляется и ссылка не работает повторно.
Частые ошибки и как исправить
- Пользователь с номером не найден. — проверьте, что номер сохраняется в usermeta, формат совпадает, нет пробелов.
- Письмо не приходит. — проверьте конфигурацию wp_mail, используйте SMTP-плагин.
- Ссылка не работает или всегда выдает ошибку. — проверьте, что токен и время истечения корректно сохраняются и сравниваются.
- Форма запроса ссылки не отображается. — убедитесь, что хук
woocommerce_login_formактивен и код не конфликтует с другими плагинами.
Практические советы по безопасности и производительности
- Ограничьте количество запросов на отправку ссылки по телефону с одного IP за промежуток времени.
- Используйте SSL для защиты передачи токенов по ссылке.
- Очищайте устаревшие токены периодически с помощью wp_cron.
- Используйте фильтры и проверки для предотвращения SQL-инъекций и XSS, особенно для номеров телефонов.
Сравнение вариантов реализации авторизации по телефону
| Метод | Требования | Плюсы | Минусы |
|---|---|---|---|
| SMS через провайдер | Аккаунт у SMS-провайдера, смс-отправка | Прямое подтверждение номера, быстрый вход | Стоимость, зависимость от сервиса, сложность настройки |
| Подтверждение через email | Доступ к email, настройки почты WordPress | Без затрат на SMS, простота реализации | Зависимость от email, задержки доставки |
| Временные ссылки с токеном | Хранение токенов, отправка email | Безопасно, легко отменить токены | Требует внимательности к срокам и безопасности |