Проблема: необходимость обязательной авторизации покупателей по телефону с подтверждением OTP
В стандартном WooCommerce авторизация пользователей происходит по email и паролю. В ряде случаев требуется дополнительная проверка — подтверждение номера телефона через одноразовый код (OTP, One-Time Password). Это повышает безопасность и качество контактов с клиентами, снижает количество фейковых заказов и упрощает коммуникацию.
Диагностика задачи и ограничения стандартного WooCommerce
WooCommerce из коробки не поддерживает обязательную авторизацию по телефону, а также отправку и проверку OTP. Для реализации подобной функциональности требуется:
- Добавить поле ввода телефона на страницу регистрации/входа.
- Реализовать отправку OTP на указанный телефон.
- Проверить введённый пользователем код OTP.
- Запретить оформление заказа без подтверждения телефона.
Без кастомной доработки или сторонних плагинов эту задачу не решить.
Пошаговое решение: реализация авторизации с OTP в WooCommerce
1. Добавление поля телефона в форму регистрации 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
});2. Валидация поля телефона при регистрации
add_filter('woocommerce_registration_errors', function($errors, $username, $email) {
if (empty($_POST['billing_phone']) || !preg_match('/^\+?\d{10,15}$/', $_POST['billing_phone'])) {
$errors->add('billing_phone_error', 'Введите корректный номер телефона в международном формате');
}
return $errors;
}, 10, 3);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 кода на телефон
Для отправки OTP понадобится интеграция с SMS-шлюзом (например, Twilio, SMS.ru, или другой). Ниже пример отправки с использованием SMS.ru:
function send_otp_sms($phone, $otp) {
$api_id = 'ВАШ_API_КЛЮЧ_SMSRU';
$message = "Ваш код подтверждения: $otp";
$url = "https://sms.ru/sms/send?api_id=$api_id&to=" . urlencode($phone) . "&msg=" . urlencode($message) . "&json=1";
$response = wp_remote_get($url);
if (is_wp_error($response)) {
return false;
}
$body = json_decode(wp_remote_retrieve_body($response), true);
return isset($body['status']) && $body['status'] == 'OK';
}5. Генерация и сохранение OTP в сессии
add_action('woocommerce_register_post', function($username, $email, $validation_errors) {
if (!session_id()) {
session_start();
}
if (empty($_POST['billing_phone'])) {
return;
}
$otp = rand(100000, 999999);
$_SESSION['otp_code'] = $otp;
$_SESSION['otp_phone'] = sanitize_text_field($_POST['billing_phone']);
send_otp_sms($_SESSION['otp_phone'], $otp);
}, 10, 3);6. Добавление формы подтверждения OTP на страницу регистрации
После отправки телефона покажем поле для ввода кода OTP:
add_action('woocommerce_register_form', function() {
if (!empty($_POST['billing_phone'])) {
?>
<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" required />
</p>
<?php
}
});7. Валидация OTP при регистрации
add_filter('woocommerce_registration_errors', function($errors, $username, $email) {
if (!session_id()) {
session_start();
}
if (empty($_POST['otp_code']) || !isset($_SESSION['otp_code']) || $_POST['otp_code'] != $_SESSION['otp_code']) {
$errors->add('otp_code_error', 'Код подтверждения неверен или не введён');
}
return $errors;
}, 20, 3);8. Очистка сессии после успешной регистрации
add_action('woocommerce_created_customer', function($customer_id) {
if (session_id()) {
unset($_SESSION['otp_code']);
unset($_SESSION['otp_phone']);
}
});Проверка результата после внедрения
- Перейдите на страницу регистрации WooCommerce — поле телефона и ввода OTP должны отображаться.
- При вводе телефона должен прийти SMS с кодом (проверьте реальные номера).
- Если код введён неправильно, регистрация должна блокироваться с ошибкой.
- При правильном коде пользователь успешно регистрируется, телефон сохраняется в метаданных.
Частые ошибки и их исправление
- OTP не приходит на телефон: Проверьте ключ API SMS-сервиса, корректность номера, баланс и лимиты в сервисе.
- Сессия не сохраняется: Убедитесь, что вызов
session_start()происходит один раз и до вывода контента. - Ошибка валидации телефона: Используйте регулярное выражение для проверки номера, адаптируйте под формат вашего региона.
- Код OTP не проверяется: Проверьте, что ключ сессии совпадает с введённым кодом, и что сессия не очищается преждевременно.
Практические советы по безопасности и производительности
- Ограничьте количество попыток ввода OTP, чтобы избежать перебора.
- Сохраняйте OTP в сессии или transient с ограничением по времени (например, 5 минут).
- Используйте HTTPS для защиты данных пользователей.
- Для продвинутых задач рассмотрите интеграцию с плагинами 2FA, совместимыми с WooCommerce.
- Кэширование страниц с формами регистрации отключите, чтобы не мешать работе сессий.
Сравнение вариантов реализации авторизации по телефону с OTP
| Метод | Плюсы | Минусы | Пример |
|---|---|---|---|
| Кастомный код на PHP | Полный контроль, гибкость | Нужны навыки программирования, поддержка | Этот пример |
| Плагин с OTP (например, "WooCommerce SMS Verification") | Быстрая установка, поддержка | Может быть платным, ограничена кастомизация | Clearfy Pro помогает оптимизировать сайт, но для OTP лучше специализированные плагины |
| Внешний сервис авторизации | Высокая безопасность, масштабируемость | Сложность интеграции, стоимость | Twilio, Firebase Auth |