چرا فریم‌ورک FastAPI بهترین گزینه برای توسعه وب‌سرویس‌های پیامکی مدرن است؟

در سال‌های اخیر، FastAPI به محبوب‌ترین فریم‌ورک پایتون برای ساخت میکروسرویس‌های مدرن با کارایی بالا تبدیل شده است. معماری غیرهمزمان (Asynchronous) بر پایه asyncio و Starlette به FastAPI اجازه می‌دهد تا ده‌ها هزار درخواست همزمان I/O-bound (مانند فراخوانی API ارسال پیامک) را بدون مسدود شدن حلقه رویداد (Event Loop) پردازش نماید.

هنگام ارسال کدهای تایید OTP یا کمپین‌های پیامکی، اگر برنامه از کلاینت‌های مسدودکننده سنتی نظیر requests استفاده کند، تاخیر شبکه موجب کندی کل سرور خواهد شد. در این راهنما، نحوه پیاده‌سازی سرویس پیامک با httpx و پیاده‌سازی اندپوینت Webhook دریافت گزارش وضعیت تحویل (DLR) در فری اس ام اس را بررسی می‌کنیم.

معماری کلاینت غیرهمزمان با httpx در FastAPI

با تعریف یک نشست کلاینت پایدار با استفاده از lifespan در FastAPI، می‌توان کانکشن‌های TCP را باز نگه داشت و تاخیر Handshake را به حداقل ممکن رساند.


from fastapi import FastAPI, HTTPException, status
from pydantic import BaseModel, Field
import httpx
from contextlib import asynccontextmanager

FREE_SMS_API_URL = "https://api.free-sms.ir/v1/otp/send"
API_KEY = "YOUR_FREE_SMS_API_KEY"

http_client: httpx.AsyncClient = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    global http_client
    # ایجاد کانکشن پول پایدار برای ارتباطات وب‌سرویس
    http_client = httpx.AsyncClient(timeout=5.0)
    yield
    await http_client.aclose()

app = FastAPI(title="Free SMS FastAPI Microservice", lifespan=lifespan)

class OTPRequest(BaseModel):
    mobile: str = Field(..., pattern=r"^09[0-9]{9}$", example="09123456789")
    code: str = Field(..., min_length=4, max_length=6, example="8492")

@app.post("/api/v1/auth/send-otp", status_code=status.HTTP_200_OK)
async def send_verification_otp(payload: OTPRequest):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }
    payload_data = {
        "mobile": payload.mobile,
        "template_id": 104,
        "parameters": {"code": payload.code}
    }

    try:
        response = await http_client.post(FREE_SMS_API_URL, headers=headers, json=payload_data)
        response.raise_for_status()
        data = response.json()
        return {"status": "success", "message_id": data.get("message_id")}
    except httpx.HTTPStatusError as exc:
        raise HTTPException(status_code=exc.response.status_code, detail="SMS Gateway Error")
    except Exception as exc:
        raise HTTPException(status_code=500, detail=str(exc))

پیاده‌سازی وب‌هوک وضعیت تحویل پیامک (Delivery Status Webhook)

هنگامی که پیامک به گوشی مخاطب می‌رسد، دیتاسنتر فری اس ام اس یک رویداد HTTP POST به آدرس وب‌هوک شما ارسال می‌کند. در FastAPI می‌توانید این گزارش را بلافاصله دریافت و وضعیت را در دیتابیس (مانند PostgreSQL یا MongoDB) به‌روزرسانی کنید:


from fastapi import Request

class WebhookDeliveryPayload(BaseModel):
    message_id: int
    status: str  # e.g., 'delivered', 'failed', 'blacklisted'
    delivered_at: str

@app.post("/api/v1/sms/webhook")
async def handle_delivery_report(payload: WebhookDeliveryPayload):
    # لاگ یا آپدیت وضعیت پیامک در دیتابیس
    print(f"Message {payload.message_id} status updated to: {payload.status}")
    
    # پاسخ سریع 200 جهت تایید دریافت وب‌هوک
    return {"received": True}

جدول مقایسه عملکرد معماری همگام (Sync) در برابر ناهمگام (Async)

معیار بررسی عملکرد کتابخانه requests (همگام / Blocking) FastAPI + httpx (ناهمگام / Non-blocking)
تعداد ارسال در ثانیه در یک هسته CPU حدود ۳۰ تا ۵۰ درخواست بیش از ۲,۵۰۰ درخواست در ثانیه
اشغال حافظه RAM و مدیریت رشته‌ها نیاز به Thread Pool حجیم تک‌ترد سبک بر پایه Co-routines
رفتار در صورت تاخیر شبکه مخابرات قفل شدن تمام سرویس و خطای تایم‌اوت مدیریت مستقل بدون کوچک‌ترین اثر بر سایر تسک‌ها
پشتیبانی از کدهای پترن OTP مستلزم تنظیمات دستی پشتیبانی ذاتی با خط خدماتی زیر ۲ ثانیه
نکته امنیت امضای وب‌هوک (HMAC Signature): برای اعتبارسنجی اصالت درخواست‌های وب‌هوک دریافتی، می‌توانید هدر X-Signature را با کلید مخفی خود با الگوریتم SHA256 تطبیق دهید تا از عدم جعل داده‌ها اطمینان حاصل شود.

سوالات متداول (FAQ)

چرا نباید از کتابخانه requests در FastAPI برای ارسال پیامک استفاده کرد؟+

چون کتابخانه requests همگام (blocking) است و زمان انتظار برای پاسخ وب‌سرویس پیامک، حلقه رویداد اصلی سرور FastAPI را قفل می‌کند و ظرفیت پذیرش همزمان کاربران را به شدت کاهش می‌دهد.

وب‌هوک تحویل (DLR) در فری اس ام اس چگونه کار می‌کند؟+

به محض تحویل پیامک به آنتن موبایل کاربر، سرور فری اس ام اس یک درخواست POST با فرمت JSON شامل شناسه پیامک و وضعیت تحویل به URL تعریف‌شده توسط شما ارسال می‌نماید.

آیا خط خدماتی اشتراکی در پایتون بدون سفته فعال می‌شود؟+

بله؛ خط خدماتی اشتراکی رایگان بلافاصله پس از ثبت‌نام در فری اس ام اس بدون سفته در اختیار شما قرار می‌گیرد و کدهای OTP را به بلک‌لیست می‌رساند.

سرعت ارسال پیامک با وب‌سرویس فری اس ام اس در پایتون چقدر است؟+

پاسخ HTTP وب‌سرویس پترن زیر ۱۰۰ میلی‌ثانیه برگردانده شده و کد تایید ظرف کمتر از ۲ ثانیه بر روی تلفن همراه کاربر زنگ می‌خورد.