This commit is contained in:
yumoqing 2026-03-23 11:13:29 +08:00
parent 6b875adeb2
commit e95e3b8893

View File

@ -9,6 +9,7 @@ Features:
- 配置从文件读取 - 配置从文件读取
""" """
import os import os
from functools import partial
import datetime import datetime
import random import random
import string import string
@ -22,6 +23,7 @@ from appPublic.uniqueID import getID as uuid
from ahserver.serverenv import ServerEnv from ahserver.serverenv import ServerEnv
from sqlor.dbpools import get_sor_context from sqlor.dbpools import get_sor_context
from appPublic.worker import awaitify from appPublic.worker import awaitify
from appPublic.log import debug, exception, error
SMS_TEMPLATE_TABLE = { SMS_TEMPLATE_TABLE = {
"summary": [{"name": "sms_template", "primary": "id"}], "summary": [{"name": "sms_template", "primary": "id"}],
@ -85,24 +87,23 @@ class SMSEngine:
required_vars) if val is None] required_vars) if val is None]
raise EnvironmentError(f"Missing required environment variables: {', '.join(missing)}") raise EnvironmentError(f"Missing required environment variables: {', '.join(missing)}")
self.sms_client = awaitify(self.create_client()) self.sms_client = self.create_client()
self.sms_types = {} self.sms_types = {}
def create_client(self): def create_client(self):
baiDuSmsConfig = awaitify(BceClientConfiguration( baiDuSmsConfig = BceClientConfiguration(
credentials=awaitify(BceCredentials(self.access_key, self.access_key_secret)), credentials=BceCredentials(self.access_key, self.access_key_secret),
endpoint=self.host endpoint=self.host
)) )
return awaitify(sms.SmsClient(baiDuSmsConfig)) return sms.SmsClient(baiDuSmsConfig)
async def send(self, stype, template_id, phone, params) -> dict: async def send(self, stype, template_id, phone, params) -> dict:
try: try:
resp = self.sms_client.send_message( f = partial(self.sms_client.send_message, signature_id=self.signature_id,
signature_id=self.signature_id,
template_id=template_id, template_id=template_id,
mobile=phone, mobile=phone,
content_var_dict=params content_var_dict=params)
) resp = await awaitify(f)()
return await self.__validation(stype, template_id, params, phone, resp) return await self.__validation(stype, template_id, params, phone, resp)
except ex.BceHttpClientError as e: except ex.BceHttpClientError as e:
if isinstance(e.last_error, ex.BceServerError): if isinstance(e.last_error, ex.BceServerError):
@ -114,8 +115,9 @@ class SMSEngine:
async def send_vcode(self, phone: str, stype: str, vcode) -> dict: async def send_vcode(self, phone: str, stype: str, vcode) -> dict:
env = ServerEnv() env = ServerEnv()
async with get_sor_context(env, 'kboss') as sor: async with get_sor_context(env, 'smssend') as sor:
template_info = await sor.R('sms_template', {'name': stype, 'del_flg': '0'}) template_info = await sor.R('sms_template', {'name': stype, 'del_flg': '0'})
debug(f'{phone=},{stype=}, {vcode=}, {template_info=}')
if template_info: if template_info:
template_id = template_info[0]['code'] template_id = template_info[0]['code']
else: else:
@ -134,7 +136,7 @@ class SMSEngine:
async def __validation(self, stype, template_id, params, phone, resp) -> dict: async def __validation(self, stype, template_id, params, phone, resp) -> dict:
env = ServerEnv() env = ServerEnv()
async with get_sor_context(env, 'kboss') as sor: async with get_sor_context(env, 'smssend') as sor:
send_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") send_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log = { log = {
'id': uuid(), 'id': uuid(),
@ -156,14 +158,14 @@ class SMSEngine:
await sor.C('sms_record', log) await sor.C('sms_record', log)
return {'status': False, 'msg': msg} return {'status': False, 'msg': msg}
async def generate_sms_code(self, length=None, expire_minutes=None, phone=None): async def generate_sms_code(self, phone, length=None, expire_minutes=None):
length = int(length) if length is not None else 6 length = int(length) if length is not None else 6
expire_minutes = int(expire_minutes) if expire_minutes is not None else 5 expire_minutes = int(expire_minutes) if expire_minutes is not None else 5
code = ''.join(random.choices(string.digits, k=length)) code = ''.join(random.choices(string.digits, k=length))
code_id = uuid() code_id = uuid()
expire_time = datetime.datetime.now() + datetime.timedelta(minutes=expire_minutes) expire_time = datetime.datetime.now() + datetime.timedelta(minutes=expire_minutes)
env = ServerEnv() env = ServerEnv()
async with get_sor_context(env, 'kboss') as sor: async with get_sor_context(env, 'smssend') as sor:
await sor.C('validatecode', { await sor.C('validatecode', {
'id': code_id, 'id': code_id,
'vcode': code, 'vcode': code,
@ -171,17 +173,26 @@ class SMSEngine:
'del_flg': '0', 'del_flg': '0',
'create_at': datetime.datetime.now() 'create_at': datetime.datetime.now()
}) })
vcode = {'SMSvCode': code}
# d = await self.send_vcode(phone, "用户注册登录验证", vcode)
d = await self.send_vcode(phone, "用户注册登录验证", vcode)
debug(f'{d=}, {code=}, {phone=}')
if d['status']:
return code_id, code return code_id, code
else:
return None
async def check_sms_code(self, code_id: str, vcode: str) -> bool: async def check_sms_code(self, code_id: str, vcode: str) -> bool:
env = ServerEnv() env = ServerEnv()
async with get_sor_context(env, 'kboss') as sor: async with get_sor_context(env, 'smssend') as sor:
code_info = await sor.R('validatecode', {'id': code_id, 'del_flg': '0'}) code_info = await sor.R('validatecode', {'id': code_id})
if not code_info: if not code_info:
debug(f'check_sms_code():{code_id=} validatecode not found')
return False return False
code_info = code_info[0] code_info = code_info[0]
if code_info['vcode'] != vcode: if code_info['vcode'] != vcode:
debug(f'check_sms_code():{vcode=} , {code_info["vcode"]} not match')
return False return False
now = datetime.datetime.now() now = datetime.datetime.now()
@ -190,12 +201,15 @@ class SMSEngine:
code_info['expire_time'] = datetime.datetime.fromisoformat(code_info['expire_time']) code_info['expire_time'] = datetime.datetime.fromisoformat(code_info['expire_time'])
if now > code_info['expire_time']: if now > code_info['expire_time']:
debug(f'check_sms_code():timeout ')
return False return False
await sor.U('validatecode', {'id': code_id, 'del_flg': '1'}) await sor.U('validatecode', {'id': code_id, 'del_flg': '1'})
debug(f'check_sms_code(): return True ')
return True return True
async def send_sms(self, phone: str, stype: str) -> dict: async def send_sms(self, phone: str, stype: str, code: str) -> dict:
"""
code_id, code = await self.generate_sms_code() code_id, code = await self.generate_sms_code()
if code_id is None: if code_id is None:
return { return {
@ -204,7 +218,7 @@ class SMSEngine:
'message': '生成的手机号出错' 'message': '生成的手机号出错'
} }
} }
"""
vcode = {'SMSvCode': code} vcode = {'SMSvCode': code}
result = await self.send_vcode(phone, stype, vcode) result = await self.send_vcode(phone, stype, vcode)