TorbatYar/backend/services/communication/app/providers/payamak.py
Mortezakoohjani e41ecfad4c Sync platform docs, infra, and module services with Accounting integration.
Include Loyalty/Communication/Sports Center backends and registry updates alongside production nginx and compose wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 22:35:23 +03:30

86 lines
3.3 KiB
Python

"""Payamak SMS provider adapter — only used inside Communication service."""
from __future__ import annotations
import time
from typing import Any
from uuid import uuid4
import httpx
from app.providers.contracts import (
BalanceResult,
ProviderHealth,
SendRequest,
SendResult,
)
class PayamakSMSProvider:
provider_kind = "payamak"
channel = "sms"
async def send(self, request: SendRequest, credentials: dict[str, Any]) -> SendResult:
username = credentials.get("username") or credentials.get("api_key")
password = credentials.get("password") or credentials.get("api_key")
from_number = request.from_address or credentials.get("from")
if not username or not password:
# Dev-safe path: simulate send when credentials absent
return SendResult(
success=True,
provider_message_id=f"payamak-dev-{uuid4()}",
raw_response={"mode": "dev_simulated"},
latency_ms=0,
)
started = time.perf_counter()
try:
async with httpx.AsyncClient(timeout=15.0) as client:
response = await client.post(
credentials.get(
"endpoint",
"https://api.payamak-panel.com/post/Send.asmx/SendSimpleSMS",
),
data={
"username": username,
"password": password,
"to": request.to_address,
"from": from_number or "",
"text": request.body,
"isflash": "false",
},
)
latency = int((time.perf_counter() - started) * 1000)
if response.status_code >= 400:
return SendResult(
success=False,
error_code="payamak_http_error",
error_message=response.text[:500],
latency_ms=latency,
raw_response={"status_code": response.status_code},
)
return SendResult(
success=True,
provider_message_id=response.text.strip()[:200] or f"payamak-{uuid4()}",
raw_response={"body": response.text[:500]},
latency_ms=latency,
)
except Exception as exc: # noqa: BLE001 — provider boundary
latency = int((time.perf_counter() - started) * 1000)
return SendResult(
success=False,
error_code="payamak_exception",
error_message=str(exc),
latency_ms=latency,
)
async def get_balance(self, credentials: dict[str, Any]) -> BalanceResult:
raw = credentials.get("cached_balance")
if raw is not None:
return BalanceResult(balance=float(raw), currency="IRR")
return BalanceResult(balance=None, currency="IRR")
async def health_check(self, credentials: dict[str, Any]) -> ProviderHealth:
if credentials.get("username") or credentials.get("api_key"):
return ProviderHealth(healthy=True, detail="credentials present")
return ProviderHealth(healthy=True, detail="dev mode without credentials")