Files
life-echo/api/app/adapters/sms/tencent.py

84 lines
2.8 KiB
Python
Raw Normal View History

"""Tencent Cloud SMS adapter — implements SmsSender port."""
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import (
TencentCloudSDKException,
)
from tencentcloud.sms.v20210111 import models as sms_models
from tencentcloud.sms.v20210111 import sms_client
from app.core.logging import get_logger
logger = get_logger(__name__)
CODE_EXPIRE_MINUTES = 5
class TencentSmsSender:
def __init__(
self,
secret_id: str,
secret_key: str,
sdk_app_id: str,
sign_name: str,
template_id: str,
template_param_count: int = 2,
):
self._secret_id = secret_id
self._secret_key = secret_key
self._sdk_app_id = sdk_app_id
self._sign_name = sign_name
self._template_id = template_id
self._template_param_count = template_param_count
def send_verification_code(self, phone: str, code: str) -> bool:
if not self._secret_id or not self._secret_key:
logger.error("Tencent SMS credentials not configured")
return False
cred = credential.Credential(self._secret_id, self._secret_key)
client = sms_client.SmsClient(cred, "ap-guangzhou")
param_configs = [
[code, str(CODE_EXPIRE_MINUTES)],
[code],
]
if self._template_param_count == 1:
param_configs = [[code], [code, str(CODE_EXPIRE_MINUTES)]]
for template_params in param_configs:
try:
req = sms_models.SendSmsRequest()
req.SmsSdkAppId = self._sdk_app_id
req.SignName = self._sign_name
req.TemplateId = self._template_id
req.TemplateParamSet = template_params
req.PhoneNumberSet = [f"+86{phone}"]
resp = client.SendSms(req)
if resp.SendStatusSet and resp.SendStatusSet[0].Code == "Ok":
return True
status = resp.SendStatusSet[0] if resp.SendStatusSet else None
error_code = status.Code if status else "UNKNOWN"
if "TemplateParamSetNotMatchApprovedTemplate" in error_code:
continue
2026-03-19 14:36:14 +08:00
logger.error(
"SMS send failed: {} - {}",
2026-03-19 14:36:14 +08:00
error_code,
status.Message if status else "",
)
return False
except TencentCloudSDKException as e:
if "TemplateParamSetNotMatchApprovedTemplate" in str(e):
continue
logger.error("Tencent SMS SDK error: {}", e)
return False
except Exception as e:
logger.error("SMS send exception: {}", e)
return False
logger.error("All SMS template param configs failed")
return False