Files
shopship/apps/account/send_sms.py
T

100 lines
3.7 KiB
Python
Raw Normal View History

2026-08-24 15:54:08 +03:30
# apps/account/send_sms.py
"""
2026-08-31 15:11:52 +03:30
ارسال پیامک OTP با کاوه‌نگار
2026-08-24 15:54:08 +03:30
"""
import logging
from threading import Thread
import requests
from django.conf import settings
logger = logging.getLogger(__name__)
REQUEST_TIMEOUT_SECONDS = 10
def _call_lookup(phone: str, template: str, token: str, *, log_label: str = "OTP") -> bool:
2026-08-31 15:11:52 +03:30
"""
ارسال پیامکِ پترنی (lookup) با API کاوه‌نگار — همان endpoint برای OTP و
هر پترنِ تک‌token دیگری (مثلا هدیه‌ی جم) به کار می‌رود.
2026-08-31 15:11:52 +03:30
"""
api_key = settings.KAVENEGAR_API_KEY
2026-08-24 15:54:08 +03:30
logger.info(f"📤 Sending {log_label} to {phone} with template: {template}")
2026-08-31 15:11:52 +03:30
if not api_key or not template:
logger.error(f"❌ KAVENEGAR_API_KEY یا نام قالبِ «{log_label}» در .env تنظیم نشده است")
2026-08-31 15:11:52 +03:30
logger.error(f" KAVENEGAR_API_KEY: {'✅' if api_key else '❌'}")
logger.error(f" نام قالب: {'✅' if template else '❌'}")
2026-08-24 15:54:08 +03:30
return False
2026-08-31 15:11:52 +03:30
# ساخت آدرس کامل
url = f"https://api.kavenegar.com/v1/{api_key}/verify/lookup.json"
# پیلود مورد نیاز کاوه‌نگار
2026-08-24 15:54:08 +03:30
payload = {
"receptor": phone,
"token": token,
2026-08-31 15:11:52 +03:30
"template": template,
2026-08-24 15:54:08 +03:30
}
try:
2026-08-31 15:11:52 +03:30
logger.info(f"📤 POST {url}")
response = requests.post(url, data=payload, timeout=REQUEST_TIMEOUT_SECONDS)
response_data = response.json()
# بررسی پاسخ
if response.status_code == 200:
return_status = response_data.get("return", {}).get("status")
if return_status == 200:
logger.info(f"✅ {log_label} sent to {phone} via Kavenegar")
2026-08-31 15:11:52 +03:30
return True
else:
error_msg = response_data.get("return", {}).get("message", "Unknown error")
logger.error(f"❌ Kavenegar error: {error_msg}")
return False
else:
logger.error(f"❌ Kavenegar HTTP error: {response.status_code} - {response.text}")
return False
except requests.Timeout:
logger.error(f"❌ Kavenegar timeout for {phone}")
return False
2026-08-24 15:54:08 +03:30
except requests.RequestException as exc:
logger.error(f"❌ خطا در ارسال پیامک به {phone}: {exc}")
return False
def _call_token_url(phone: str, code: str) -> bool:
return _call_lookup(phone, settings.SMS_PATTERN_NAME, code, log_label="OTP")
2026-08-24 15:54:08 +03:30
def send_otp_message(phone: str, code: str) -> None:
2026-08-31 15:11:52 +03:30
"""ارسال غیربلاکینگ کد تایید"""
2026-08-24 15:54:08 +03:30
def _send():
try:
_call_token_url(phone, code)
2026-08-31 15:11:52 +03:30
except Exception as exc:
2026-08-24 15:54:08 +03:30
logger.error(f"❌ خطای غیرمنتظره در ارسال OTP: {exc}")
Thread(target=_send, daemon=True).start()
def send_gift_gem_sms(phone: str, amount: int) -> None:
"""اطلاع‌رسانیِ غیربلاکینگِ «هدیه‌ی جم از پنل ادمین» — دقیقا هم‌الگوی
send_otp_message، فقط با قالبِ جداگانه‌ی SMS_GIFT_PATTERN_NAME و
token=تعدادِ جمِ هدیه‌داده‌شده. اگر آن قالب در .env تنظیم نشده باشد،
فقط لاگ می‌کند و هدیه‌دادنِ جم را (که قبلا در دیتابیس ثبت شده) بلاک
نمی‌کند."""
def _send():
try:
_call_lookup(
phone, settings.SMS_GIFT_PATTERN_NAME, str(amount), log_label="هدیه‌ی جم"
)
except Exception as exc:
logger.error(f"❌ خطای غیرمنتظره در ارسال پیامکِ هدیه‌ی جم: {exc}")
2026-08-31 15:11:52 +03:30
Thread(target=_send, daemon=True).start()