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

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

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація авторизації через номер телефону з SMS-кодом на сайті
Середня
~2-3 робочих дні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Впровадження 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 еndpoints + rate limiting 0.5 дня
Frontend флоу (форма + таймер) 1 день
Тести + edge cases 1 день

Разом: 4–5 днів.