Реализация авторизации через номер телефона с SMS-кодом на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация авторизации через номер телефона с SMS-кодом на сайте
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Реализация авторизации через номер телефона с SMS-кодом на сайте

Аутентификация через SMS-код (OTP) — стандарт для российского рынка в e-commerce, сервисах доставки, финтехе. Пользователь вводит номер телефона, получает 4–6 значный код в SMS, вводит его — и авторизован. Вопрос пароля при этом либо отсутствует, либо задаётся отдельно после первого входа.

Провайдеры SMS для России и СНГ

Провайдер Особенности
SMSC.ru Популярный, есть HTTP API и SMPP
SMS.ru Простой API, хорошая доставляемость
Exolve (МТС) Оператор уровня, виртуальные номера
Infobip Международный, дорогой, надёжный
Twilio Международный, недоступен в РФ без VPN
FirebaseSMS Для мобильных приложений, не для веба

Для большинства веб-проектов в России — SMSC.ru или SMS.ru.

Архитектура флоу

1. POST /auth/phone/send-code  { phone: "+79001234567" }
   → валидация номера
   → генерация OTP
   → сохранение hash(OTP) в Redis с TTL 5 мин
   → отправка SMS
   → ответ: { expires_in: 300 }

2. POST /auth/phone/verify  { phone: "...", code: "123456" }
   → проверка OTP из Redis
   → создание/поиск пользователя
   → выдача сессии или JWT

Генерация и хранение OTP

class PhoneOtpService
{
    public function sendOtp(string $phone): int
    {
        $this->checkRateLimit($phone);

        $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);

        // Хранить хэш, не сам код
        Cache::put(
            "phone_otp:{$phone}",
            [
                'hash'     => hash('sha256', $code),
                'attempts' => 0,
            ],
            now()->addMinutes(5)
        );

        $this->smsProvider->send($phone, "Ваш код: {$code}");

        return 300; // expires_in seconds
    }

    public function verifyOtp(string $phone, string $code): bool
    {
        $data = Cache::get("phone_otp:{$phone}");

        if (!$data) {
            throw new OtpExpiredException();
        }

        // Ограничение попыток
        if ($data['attempts'] >= 3) {
            Cache::forget("phone_otp:{$phone}");
            throw new OtpAttemptsExceededException();
        }

        if (!hash_equals($data['hash'], hash('sha256', $code))) {
            Cache::put("phone_otp:{$phone}", array_merge($data, [
                'attempts' => $data['attempts'] + 1,
            ]), now()->addMinutes(5));
            return false;
        }

        Cache::forget("phone_otp:{$phone}");
        return true;
    }
}

Rate limiting

// Не более 3 SMS в час с одного номера
RateLimiter::for('sms-otp', function (Request $request) {
    return [
        Limit::perHour(3)->by('phone:' . $request->phone),
        Limit::perMinute(1)->by('phone:' . $request->phone),
    ];
});

Нормализация номера телефона

use libphonenumber\PhoneNumberUtil;

$phoneUtil = PhoneNumberUtil::getInstance();
$parsed = $phoneUtil->parse($rawPhone, 'RU');

if (!$phoneUtil->isValidNumber($parsed)) {
    throw new InvalidPhoneNumberException();
}

$normalized = $phoneUtil->format($parsed, \libphonenumber\PhoneNumberFormat::E164);
// +79001234567

Библиотека giggsey/libphonenumber-for-php — порт Google libphonenumber на PHP.

Интеграция с SMSC.ru

class SmscProvider implements SmsProviderInterface
{
    public function send(string $phone, string $text): void
    {
        $response = Http::get('https://smsc.ru/sys/send.php', [
            'login'  => config('sms.smsc_login'),
            'psw'    => config('sms.smsc_password'),
            'phones' => $phone,
            'mes'    => $text,
            'fmt'    => 3, // JSON
        ]);

        $data = $response->json();

        if (isset($data['error'])) {
            Log::error('SMSC error', ['code' => $data['error_code'], 'message' => $data['error']]);
            throw new SmsDeliveryException($data['error']);
        }
    }
}

Создание пользователя при первом входе

public function authenticate(string $phone): User
{
    return User::firstOrCreate(
        ['phone' => $phone],
        [
            'phone_verified_at' => now(),
            'name'              => 'Пользователь',
        ]
    );
}

UX-детали

  • Показывать таймер обратного отсчёта до возможности повторной отправки
  • Автофокус на поле кода после отправки
  • Автосабмит при вводе последней цифры (если 6-значный код)
  • Кнопка «Изменить номер» — возможность вернуться назад

Сроки работ

Этап Время
OTP-сервис + Redis 1 день
Интеграция с SMS-провайдером 0.5 дня
API эндпоинты + rate limiting 0.5 дня
Frontend флоу (форма + таймер) 1 день
Тесты + edge cases 1 день

Итого: 4–5 рабочих дней.