refactor: P3c 服务层迁入 src/modules/ → service.py(29 服务)
- 22 个单服务 + 3 组合并(config+config_item、dict+dict_item、login_log+operation_log) - 特殊命名:job_executor→executor、scheduler→scheduler_service、 mail_svc→mail_service、sms_svc→sms_service(含使用处标识符改写) - 重写引用:跨服务(module 别名/子模块)、models/forms→src.modules、 db/extensions→src.core、utils→src.common|core、R→src.core.response - application/services/ 全部替换为 shim 【验收】全部服务文件编译通过;应用启动;pytest 5 passed;核心服务导入正常 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
2586c0aace
commit
87aec4e26e
@@ -1,193 +1,8 @@
|
||||
"""
|
||||
短信发送服务模块
|
||||
兼容 shim(绞杀者迁移期间保留)
|
||||
=============================================================
|
||||
|
||||
封装阿里云短信 SDK 提供短信发送能力,供业务模块和定时任务调用。
|
||||
|
||||
使用方式:
|
||||
from application.services import sms_svc
|
||||
|
||||
# 模板短信(推荐)
|
||||
sms_svc.send_sms(
|
||||
phone='13800138000',
|
||||
template_code='SMS_123456',
|
||||
template_params={'code': '123456'}
|
||||
)
|
||||
|
||||
# 指定签名(覆盖默认签名)
|
||||
sms_svc.send_sms(
|
||||
phone='13800138000',
|
||||
template_code='SMS_123456',
|
||||
template_params={'code': '123456'},
|
||||
sign_name='我的应用'
|
||||
)
|
||||
|
||||
# 群发(多号码)
|
||||
sms_svc.send_sms(
|
||||
phone=['13800138000', '13900139000'],
|
||||
template_code='SMS_123456',
|
||||
template_params={'name': '张三'}
|
||||
)
|
||||
服务已迁移至 src.modules.job.sms_service。
|
||||
本文件仅作兼容转发,最终在 P7(切尾)阶段删除。
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, List, Optional, Union
|
||||
|
||||
from config import (
|
||||
SMS_ALIYUN_ACCESS_KEY_ID,
|
||||
SMS_ALIYUN_ACCESS_KEY_SECRET,
|
||||
SMS_ALIYUN_CONNECT_TIMEOUT,
|
||||
SMS_ALIYUN_ENDPOINT,
|
||||
SMS_ALIYUN_READ_TIMEOUT,
|
||||
SMS_ALIYUN_SIGN_NAME,
|
||||
SMS_PROVIDER,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 阿里云短信客户端(延迟初始化)
|
||||
# ============================================================
|
||||
|
||||
_client = None
|
||||
|
||||
|
||||
def _get_client():
|
||||
"""
|
||||
获取阿里云短信客户端(单例,延迟初始化)
|
||||
|
||||
Returns:
|
||||
dysmsapi.Client: 阿里云短信客户端实例
|
||||
|
||||
Raises:
|
||||
ImportError: 阿里云 SDK 未安装
|
||||
Exception: 客户端创建失败
|
||||
"""
|
||||
global _client
|
||||
if _client is not None:
|
||||
return _client
|
||||
|
||||
try:
|
||||
from alibabacloud_dysmsapi20170525.client import Client
|
||||
from alibabacloud_tea_openapi.models import Config
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"阿里云短信 SDK 未安装,请执行: "
|
||||
"pip install alibabacloud-dysmsapi20170525 alibabacloud-tea-openapi"
|
||||
)
|
||||
|
||||
config = Config(
|
||||
access_key_id=SMS_ALIYUN_ACCESS_KEY_ID,
|
||||
access_key_secret=SMS_ALIYUN_ACCESS_KEY_SECRET,
|
||||
endpoint=SMS_ALIYUN_ENDPOINT,
|
||||
connect_timeout=SMS_ALIYUN_CONNECT_TIMEOUT,
|
||||
read_timeout=SMS_ALIYUN_READ_TIMEOUT,
|
||||
)
|
||||
_client = Client(config)
|
||||
return _client
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 短信发送
|
||||
# ============================================================
|
||||
|
||||
def send_sms(
|
||||
phone: Union[str, List[str]],
|
||||
template_code: str,
|
||||
template_params: Optional[Dict] = None,
|
||||
sign_name: Optional[str] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
发送短信(阿里云模板短信)
|
||||
|
||||
Args:
|
||||
phone: 手机号,字符串或列表(群发时传入多个号码)
|
||||
template_code: 短信模板CODE(在阿里云控制台获取,如 SMS_123456)
|
||||
template_params: 模板变量,如 {'code': '123456'} 对应模板中的 ${code}
|
||||
sign_name: 短信签名(可选,默认使用配置中的 SMS_ALIYUN_SIGN_NAME)
|
||||
|
||||
Returns:
|
||||
bool: 全部发送成功返回 True,任一失败返回 False
|
||||
"""
|
||||
if not phone:
|
||||
logger.warning("发送短信失败:手机号不能为空")
|
||||
return False
|
||||
|
||||
if not template_code:
|
||||
logger.warning("发送短信失败:模板CODE不能为空")
|
||||
return False
|
||||
|
||||
if not sign_name:
|
||||
sign_name = SMS_ALIYUN_SIGN_NAME
|
||||
|
||||
if not sign_name:
|
||||
logger.warning("发送短信失败:短信签名未配置")
|
||||
return False
|
||||
|
||||
# 统一转为列表
|
||||
phones = [phone] if isinstance(phone, str) else phone
|
||||
|
||||
# 检查 AccessKey 配置
|
||||
if not SMS_ALIYUN_ACCESS_KEY_ID or not SMS_ALIYUN_ACCESS_KEY_SECRET:
|
||||
logger.warning("发送短信失败:阿里云 AccessKey 未配置")
|
||||
return False
|
||||
|
||||
# 模板变量序列化
|
||||
params_str = json.dumps(template_params, ensure_ascii=False) if template_params else ''
|
||||
|
||||
# 逐条发送(阿里云短信 API 不支持批量同发)
|
||||
all_success = True
|
||||
for p in phones:
|
||||
if not _send_one(p, sign_name, template_code, params_str):
|
||||
all_success = False
|
||||
|
||||
return all_success
|
||||
|
||||
|
||||
def _send_one(phone: str, sign_name: str, template_code: str, template_params: str) -> bool:
|
||||
"""
|
||||
发送单条短信
|
||||
|
||||
Args:
|
||||
phone: 手机号
|
||||
sign_name: 短信签名
|
||||
template_code: 模板CODE
|
||||
template_params: 模板变量 JSON 字符串
|
||||
|
||||
Returns:
|
||||
bool: 发送成功返回 True
|
||||
"""
|
||||
try:
|
||||
from alibabacloud_dysmsapi20170525 import models as dysms_models
|
||||
|
||||
client = _get_client()
|
||||
|
||||
request = dysms_models.SendSmsRequest(
|
||||
phone_numbers=phone,
|
||||
sign_name=sign_name,
|
||||
template_code=template_code,
|
||||
template_param=template_params,
|
||||
)
|
||||
|
||||
response = client.send_sms(request)
|
||||
body = response.body
|
||||
|
||||
if body.code == 'OK':
|
||||
logger.info(f"短信发送成功: phone={phone}, template={template_code}, biz_id={body.biz_id}")
|
||||
return True
|
||||
else:
|
||||
logger.warning(
|
||||
f"短信发送失败: phone={phone}, template={template_code}, "
|
||||
f"code={body.code}, message={body.message}"
|
||||
)
|
||||
return False
|
||||
|
||||
except ImportError as e:
|
||||
logger.error(f"阿里云短信 SDK 未安装: {str(e)}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"短信发送异常: phone={phone}, template={template_code}, error={str(e)}")
|
||||
return False
|
||||
from src.modules.job.sms_service import * # noqa: F401,F403
|
||||
|
||||
Reference in New Issue
Block a user