Files
shaguabijia-app-server/docs/integrations/sms.md
T
marco b50495bebe feat: 短信接入极光真实发送 + 新增运营 admin 后台子应用
短信(SMS_MOCK 切 mock/real):
- integrations/sms.py 重写: real 模式走极光短信 REST /v1/messages 自定义验证码(本服务 secrets
  生成 6 位码 + 进程内存 + 本地校验一次性/防爆破), 鉴权复用极光一键登录 JG_APP_KEY/MASTER_SECRET
  (同一极光应用, 上线只需 SMS_MOCK=false); mock 仍"任意6位通过"不动其余测试
- 防刷四层: 单号冷却 + 单号每日上限 + 单IP rate_limit(/sms/send 10/min、/sms/login 20/min)
  + 单码失败次数作废; SmsError 带 status_code 映射 429/503/400
- config 增 SMS_SEND_ENDPOINT/SIGN_ID/TEMPLATE_ID/CODE_LENGTH/DAILY_LIMIT/MAX_VERIFY_ATTEMPTS;
  test_auth 加 real 模式单测; sms.md/后端技术实现/待办账本同步

admin 后台(app/admin/ 独立子应用, uvicorn app.admin.main:admin_app :8771):
- 复用主仓 models/repositories/integrations + 同库, 鉴权完全隔离(ADMIN_JWT_SECRET≠JWT_SECRET_KEY
  + payload typ=admin + bcrypt 密码 + 可选 IP 白名单); 主 app 不 import 本包, admin 崩不影响主进程
- 路由: 登录 / 账号管理(RBAC: super_admin·finance·operator) / 用户列表+360详情+封禁+手动调币 /
  钱包流水 / 提现重试对账 / 反馈工单 / 数据大盘; 全写操作落 admin_audit_log(涉钱与业务写同事务)
- 涉钱逻辑(调微信/退款/对账)复用 app.repositories.wallet 不重写
- 新增 models/admin.py(AdminUser/AdminAuditLog) + admin_tables 迁移 + create_admin.py +
  deploy/shaguabijia-admin.service; 依赖加 bcrypt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 03:02:41 +08:00

3.6 KiB
Raw Blame History

短信验证码(sms

文件:app/integrations/sms.py | 关联接口:auth-sms-send · auth-sms-login | ← 集成索引

作用

手机号 + 验证码登录的验证码发送 / 校验。已接极光短信 REST,由 SMS_MOCK 切 mock / real。

mock(SMS_MOCK=true,默认 / 开发测试) real(SMS_MOCK=false,生产)
发送 不真发,验证码打日志 调极光 /v1/messages 真发
校验 放行任意 6 位数字(测试便利) 比对本服务存的码(一次性 / 过期 / 防爆破)

为什么是"自己生成码"模式

极光有两种验证码玩法:① /v1/codes 极光生成 + /codes/{msg_id}/valid 极光校验;② /v1/messages 本服务生成码、极光只负责发。选 ②:校验本地完成(不依赖极光二次往返)、有效期/错误次数/作废完全可控、跟原 mock 口子结构一致。

函数 / 异常

函数 行为
send_code(phone) -> int 防刷检查(冷却 + 每日上限)→ secrets 生成 N 位码 → 预占(冷却/计数/存码)→ mock 打日志 / real 调极光 → 失败回滚预占。返回距下次可发秒数
verify_code(phone, code) -> bool mock 放行任意 6 位;real 比对存码,匹配即作废,失败累计到上限作废
SmsError(msg, status_code) status_code 决定 HTTP 码:过频/每日超限 429、供应商失败 503、号码无效 400

配置

配置项 默认 说明
SMS_MOCK true mock / real 切换。生产置 false
SMS_CODE_TTL_SEC 300 验证码有效期(秒),与极光模板文案"5分钟"一致
SMS_SEND_INTERVAL_SEC 60 单号两次发送最小间隔(冷却)
SMS_SEND_ENDPOINT 极光 /v1/messages 短信发送地址
SMS_SIGN_ID 31729 极光签名 ID
SMS_TEMPLATE_ID 1 极光模板 ID(变量名 code)
SMS_CODE_LENGTH 6 验证码位数(本服务生成;前端 code 4-8 位兼容)
SMS_DAILY_LIMIT_PER_PHONE 10 单号每日发送上限(防刷 + 控费)
SMS_MAX_VERIFY_ATTEMPTS 5 单码最多校验失败次数,超过作废(防爆破)

鉴权复用极光一键登录:/v1/messagesbase64(JG_APP_KEY:JG_MASTER_SECRET) 做 HTTP Basic Auth——短信与一键登录是同一个极光应用(同 AppKey)。上线不需要额外凭证,只需 SMS_MOCK=false(JG_* 一键登录已配)。

防刷(短信花钱 + /sms/send 在登录前无法 JWT 鉴权)

  1. 单号 SMS_SEND_INTERVAL_SEC 冷却
  2. 单号每日 SMS_DAILY_LIMIT_PER_PHONE 条上限
  3. 单 IP 频控:/sms/sendrate_limit(10,60)/sms/loginrate_limit(20,60)
  4. 单码校验失败 SMS_MAX_VERIFY_ATTEMPTS 次即作废
  5. 运维侧建议在极光控制台叠加:IP 白名单(只许服务器 IP)+ 防轰炸设置

极光错误码(节选,映射在 _send_via_jiguang)

code 含义 处理
50014 余额不足 logger.critical 告警 + 503
50009 极光侧超频 429
50006 手机号无效 400
其他 503

上线步骤

  1. 极光控制台:企业实名 + 短信充值 + 签名审核(sign_id=31729)+ 模板审核(temp_id=1)——均已就绪
  2. .envSMS_MOCK=false(JG_APP_KEY/JG_MASTER_SECRET 一键登录已配)
  3. 真机发一条验证:收到短信 + 能登录

已知局限

验证码存进程内存:单 worker uvicorn 够用;重启丢码(用户重发即可);多 worker / 多机不共享 → 冷却 / 每日上限 / 校验失效,扩 worker 前迁移到 DB/Redis。见 待办与技术债