3f2ec19ec2
新增统一限制规则、临时不限和风控免告警白名单,接入比价、短信登录、广告、引导视频与账号冷却等业务链路。补充设备选择、权限、审计、迁移及回归测试。
49 lines
2.1 KiB
Python
49 lines
2.1 KiB
Python
"""短信验证码服务 —— provider 分派入口。
|
|
|
|
对外只暴露 `send_code` / `verify_code` / `SmsError`,api 层无需关心用哪个 provider。
|
|
provider 由 `settings.SMS_PROVIDER` 选择(**每次调用读取**,支持运行时切换 + 灰度回退):
|
|
- `jiguang`(默认):自管码(本服务生成、内存存/校验,极光只发)。见 [jiguang.py](jiguang.py)。
|
|
- `aliyun`:阿里云号码认证(阿里云生成+下发+校验,Mode A)。见 [aliyun.py](aliyun.py)。
|
|
- `chuanglan`:创蓝云智(253)模板短信,自管码 Mode B(本服务生成、内存存/校验,创蓝只发)。见 [chuanglan.py](chuanglan.py)。
|
|
|
|
mock(`SMS_MOCK=true`)与各 provider 的行为差异都封在 provider 内部;本层只做路由。
|
|
拆包前本模块是单文件 `sms.py`;拆包后极光逻辑迁入 `jiguang` 子模块,行为零改动。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from app.core.config import settings
|
|
|
|
from . import aliyun, chuanglan, jiguang
|
|
from .base import SmsError
|
|
|
|
__all__ = ["SmsError", "send_code", "verify_code"]
|
|
|
|
# provider 名 -> 模块;未知/缺省值回退 jiguang(默认兜底,防误配把登录打挂)。
|
|
_PROVIDERS = {"aliyun": aliyun, "chuanglan": chuanglan}
|
|
|
|
|
|
def _provider():
|
|
"""按配置选 provider 模块(每次调用读 settings,支持运行时切换 / 测试注入)。"""
|
|
return _PROVIDERS.get(settings.SMS_PROVIDER, jiguang)
|
|
|
|
|
|
def send_code(phone: str, *, cooldown_sec: int | None = None) -> int:
|
|
"""发送验证码,返回距下次可发的冷却秒数;失败抛 SmsError。委托给当前 provider。"""
|
|
provider = _provider()
|
|
if cooldown_sec is None:
|
|
return provider.send_code(phone)
|
|
return provider.send_code(phone, cooldown_sec=cooldown_sec)
|
|
|
|
|
|
def verify_code(
|
|
phone: str,
|
|
code: str,
|
|
*,
|
|
max_failed_attempts: int | None = None,
|
|
) -> bool:
|
|
"""校验验证码,返回是否通过;provider 异常降级抛 SmsError。委托给当前 provider。"""
|
|
provider = _provider()
|
|
if max_failed_attempts is None:
|
|
return provider.verify_code(phone, code)
|
|
return provider.verify_code(phone, code, max_failed_attempts=max_failed_attempts)
|