This commit is contained in:
debu-2 2026-10-07 02:50:28 +05:30
parent e98036cd31
commit 614cf1e7f5
4 changed files with 398 additions and 15 deletions

View file

@ -6,7 +6,8 @@ from sqlalchemy.orm import Session
from .log_service import record_otp_log
from .message_send_service import SendMessageError, normalize_recipients
from .models import UrmiOtpProject, UserAccount
from .urmiotp_catalog import OTP_TEMPLATES
from .ultronsms_client import UltronsmsClient
from .urmiotp_catalog import OTP_TEMPLATES, URMI_OTP_SMS_CONFIG, build_dlt_otp_message
TEMPLATE_TYPES = {template["type"] for template in OTP_TEMPLATES}
@ -18,11 +19,7 @@ class GenerateOtpPayload(BaseModel):
variables: dict[str, str] = Field(default_factory=dict)
def _build_otp_message(template_type: str, message_label: str, variables: dict[str, str]) -> str:
template = next((item for item in OTP_TEMPLATES if item["type"] == template_type), None)
if not template:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Unknown template type")
def _require_otp_variables(variables: dict[str, str]) -> None:
otp_value = variables.get("otp", "").strip()
validity = variables.get("validity_minutes", "").strip()
if not otp_value or not validity:
@ -31,11 +28,6 @@ def _build_otp_message(template_type: str, message_label: str, variables: dict[s
detail="variables.otp and variables.validity_minutes are required",
)
content = template["content"].replace("{message_label}", message_label)
for value in (otp_value, validity):
content = content.replace("{#var#}", value, 1)
return content
def generate_otp_for_user(
db: Session,
@ -68,7 +60,52 @@ def generate_otp_for_user(
raise HTTPException(status_code=exc.status_code, detail=exc.detail) from exc
recipient = recipients[0]
message = _build_otp_message(payload.template_type, project.message_label, payload.variables)
_require_otp_variables(payload.variables)
try:
message = build_dlt_otp_message(payload.variables, project.message_label)
except ValueError as exc:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(exc)) from exc
client = UltronsmsClient()
try:
send_result = client.send_template_sms(
mobile=recipient,
message=message,
sender_id=URMI_OTP_SMS_CONFIG["sender_id"],
pe_id=URMI_OTP_SMS_CONFIG["pe_id"],
dlt_template_id=URMI_OTP_SMS_CONFIG["dlt_template_id"],
sender_type="transactional",
)
except RuntimeError as exc:
entry = record_otp_log(
db,
user,
project_name=project.project_name,
template_type=payload.template_type,
to_number=recipient,
status="failed",
error_message=str(exc),
)
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail=str(exc),
) from exc
if not send_result.success:
error_message = send_result.raw.get("ErrorMessage") or "SMS gateway rejected the request"
entry = record_otp_log(
db,
user,
project_name=project.project_name,
template_type=payload.template_type,
to_number=recipient,
status="failed",
error_message=error_message,
)
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail=error_message,
)
entry = record_otp_log(
db,
@ -76,7 +113,9 @@ def generate_otp_for_user(
project_name=project.project_name,
template_type=payload.template_type,
to_number=recipient,
status="accepted",
status="sent",
job_id=send_result.job_id,
message_id=send_result.message_id,
)
return {
@ -84,7 +123,9 @@ def generate_otp_for_user(
"log_id": str(entry.id),
"project_name": project.project_name,
"template_type": payload.template_type,
"to": recipient,
"to": send_result.number or recipient,
"message_preview": message,
"status": entry.status,
"job_id": send_result.job_id,
"message_id": send_result.message_id,
}