SMS — Twilio bilan
Muammodan boshlaylik
Foydalanuvchi hisobga kirishmoqda. Emailni tasdiqlash — yaxshi. Lekin telefon raqami bilan kiruvchilar uchun SMS kodi kerak. Yoki bank: har bir to'lovda SMS kod talab qiladi.
Email ko'p vaqt oladi, spamga tushishi mumkin, internet bo'lmasa ham kelmaydi. SMS esa — telefonni yoqsangiz yetib keladi. Shuning uchun bank, taxi, delivery xizmatlari SMS ishlatadi.
Twilio nima?
Twilio — SMS, qo'ng'iroq va WhatsApp yuborish uchun xizmat. Sizning serveringiz Twilio API ga so'rov yuboradi, Twilio esa foydalanuvchi telefoniga SMS yetkazadi.
Sizning server Twilio API Foydalanuvchi telefoni
| | |
|--- SMS so'rovi ------>| |
|<-- OK ----------------| |
| |--- SMS yubor --------->|
💡 O'zbekistonda Twilio ishlaydi, lekin mahalliy xizmatlar (Eskiz, SMS.uz) arzonroq bo'lishi mumkin. API tuzilishi o'xshash — Twilio o'rgansangiz boshqasiga o'tish oson.
O'rnatish
npm install twilio
Twilio sozlash
- twilio.com da ro'yxatdan o'ting
- Bepul hisob: $15 kredit (test uchun yetarli)
- Console da oling:
Account SIDAuth Token- Twilio telefon raqami (bepul bitta beriladi)
TWILIO_ACCOUNT_SID=ACxxxxxxxxxxxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxx
TWILIO_PHONE=+12345678900
SMS yuborish
import twilio from 'twilio';
const client = twilio(
process.env.TWILIO_ACCOUNT_SID,
process.env.TWILIO_AUTH_TOKEN,
);
const smsYuborish = async (telefon, matn) => {
await client.messages.create({
from: process.env.TWILIO_PHONE, // ← Twilio raqami
to: telefon, // ← foydalanuvchi raqami (+998901234567)
body: matn, // ← SMS matni
});
};
// Ishlatish
await smsYuborish('+998901234567', 'Tasdiqlash kodi: 4829');
OTP (bir martalik kod) bilan ikki bosqichli kirish
import express from 'express';
import twilio from 'twilio';
import crypto from 'crypto';
const router = express.Router();
const client = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
// Kodlarni vaqtincha saqlash
const otpStore = new Map(); // { telefon: { kod, muddati } }
// 1. SMS kod yuborish
router.post('/sms/yuborish', async (req, res) => {
const { telefon } = req.body;
// 6 xonali tasodifiy kod
const kod = crypto.randomInt(100000, 999999).toString();
const muddati = Date.now() + 5 * 60 * 1000; // 5 daqiqa
otpStore.set(telefon, { kod, muddati }); // ← xotirada saqlash
await client.messages.create({
from: process.env.TWILIO_PHONE,
to: telefon,
body: `DevDocs tasdiqlash kodi: ${kod}. 5 daqiqa davomida amal qiladi.`,
});
res.json({ xabar: 'SMS yuborildi' });
});
// 2. Kodni tekshirish
router.post('/sms/tasdiqlash', (req, res) => {
const { telefon, kod } = req.body;
const saqlangan = otpStore.get(telefon);
if (!saqlangan) {
return res.status(400).json({ xabar: 'Kod yuborilmagan' });
}
if (Date.now() > saqlangan.muddati) {
otpStore.delete(telefon);
return res.status(400).json({ xabar: 'Kod muddati tugagan' });
}
if (saqlangan.kod !== kod) {
return res.status(400).json({ xabar: 'Kod noto\'g\'ri' });
}
otpStore.delete(telefon); // ← bir marta ishlatildi, o'chir
res.json({ xabar: 'Tasdiqlandi' });
});
⚠️
Map— server xotirasida. Server qayta ishga tushsa — kodlar yo'qoladi. Production da Redis ishlatgan ma'qul (TTL bilan).
Redis bilan OTP (production)
import { createClient } from 'redis';
const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();
// Saqlash — 5 daqiqadan keyin avtomatik o'chadi
await redis.setEx(`otp:${telefon}`, 300, kod); // 300 sekund = 5 daqiqa
// O'qish
const saqlangan = await redis.get(`otp:${telefon}`);
// O'chirish
await redis.del(`otp:${telefon}`);
Brute force himoyasi
Bir telefon raqamiga cheksiz urinish — xavfli. Rate limiting qo'shing:
import rateLimit from 'express-rate-limit';
const smsLimit = rateLimit({
windowMs: 10 * 60 * 1000, // 10 daqiqa
max: 3, // ← 3 ta urinish
keyGenerator: (req) => req.body.telefon, // ← raqam bo'yicha hisoblash
message: { xabar: '10 daqiqa kutib, qayta urinib ko\'ring' },
});
router.post('/sms/yuborish', smsLimit, async (req, res) => {
// ...
});
Tez-tez uchraydigan xatolar
1. "Unverified number" xatosi (Trial hisob)
Error: The number +998... is unverified. Trial accounts can only send messages to verified numbers.
Sababi: Twilio trial (bepul) hisob faqat oldindan tasdiqlangan raqamlarga yuboradi.
Yechim: Twilio console → Verified Caller IDs → raqamingizni qo'shing.
2. Telefon raqam formati
// ❌ — noto'g'ri format
'998901234567'
'8901234567'
'9012 34 567'
// ✅ — E.164 format (+ va mamlakat kodi)
'+998901234567'
3. Kod bir necha marta ishlatilishi
// ❌ — delete yo'q
if (saqlangan.kod === kod) {
res.json({ xabar: 'Tasdiqlandi' });
// kod hali Map da turibdi — qayta ishlatish mumkin!
}
// ✅
otpStore.delete(telefon); // ← tasdiqlangandan keyin o'chir
res.json({ xabar: 'Tasdiqlandi' });
Xulosa
- Twilio — SMS yuborish API;
client.messages.create()bilan bir qatorda - OTP — 6 xonali tasodifiy kod, 5 daqiqa muddati
- Kodlarni Redis da saqlang (production) — xotira emas, TTL bepul
- Bir martalik: tasdiqlangandan keyin kodni o'chiring
- Rate limiting — bir raqamga cheksiz urinishni to'sing
Keyingi dars: 49-dars: Push Notification — Firebase Cloud Messaging