# apps/account/send_sms.py """ ارسال پیامک OTP. فقط دو مقدار از .env خوانده می‌شود (تنظیمات در config/settings.py): - SMS_PATTERN_NAME: نام/کد قالبی که نزد سرویس‌دهنده‌ی پیامک ثبت شده - SMS_TOKEN_URL: آدرسی که با یک درخواست POST، قالب+شماره+کد را برایش می‌فرستیم (سرویس‌دهنده‌ی تو باید چنین آدرسی در اختیارت گذاشته باشد) اگر ساختار درخواست سرویس‌دهنده‌ی واقعی‌ات با payload زیر فرق دارد، فقط تابع `_call_token_url` را با مستندات سرویس‌دهنده‌ات هماهنگ کن؛ بقیه‌ی پروژه با این ماژول کاری ندارد و فقط send_otp_message را صدا می‌زند. """ import logging from threading import Thread import requests from django.conf import settings logger = logging.getLogger(__name__) REQUEST_TIMEOUT_SECONDS = 10 def _call_token_url(phone: str, code: str) -> bool: token_url = settings.SMS_TOKEN_URL pattern_name = settings.SMS_PATTERN_NAME if not token_url or not pattern_name: logger.error("SMS_TOKEN_URL یا SMS_PATTERN_NAME در .env تنظیم نشده است") return False payload = { "pattern": pattern_name, "receptor": phone, "token": code, } try: response = requests.post(token_url, json=payload, timeout=REQUEST_TIMEOUT_SECONDS) response.raise_for_status() logger.info(f"✅ OTP sent to {phone} via {token_url}") return True except requests.RequestException as exc: logger.error(f"❌ خطا در ارسال پیامک به {phone}: {exc}") return False def send_otp_message(phone: str, code: str) -> None: """ارسال غیربلاکینگ کد تایید (شکست ارسال، درخواست HTTP کاربر را کند نمی‌کند)""" def _send(): try: _call_token_url(phone, code) except Exception as exc: # noqa: BLE001 - لاگ و رد شدن، نباید کل ترد را بترکاند logger.error(f"❌ خطای غیرمنتظره در ارسال OTP: {exc}") Thread(target=_send, daemon=True).start()