Files
thebet365/docs/短信调试与日志说明.md
Mars cb9a1e8708 feat: 短信调试日志、Tawk 客服、手机号校验放宽与 Docker 文档
API
- 短信发码/验码/创蓝全链路结构化日志(手机号脱敏)
- 新增 SMS_DEBUG_LOG_CODE,联调时可输出验证码与 sessionId(对应创蓝批次号)
- 注册成功、短信找回密码成功写入审计相关日志
- 放宽手机号归一化:移除区号白名单与 10~15 位长度限制

Player
- 公告走马灯滚动周期调整为 35 秒
- 在线客服接入 Tawk.to(tawk.html),登录用户透传昵称/头像/ID
- 三语补充 support.connecting 文案

部署与文档
- docker-compose 与 .env.docker.example 增加 SMS_DEBUG_LOG_CODE
- 新增 docs/短信调试与日志说明.md、docs/docker 镜像构建导出脚本与说明
- Docker 部署指南补充镜像构建文档链接
- .gitignore 忽略 thebet365-images.tar 与 docker-build.log

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 14:08:00 +08:00

214 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 短信验证码调试与日志说明
本文档说明 thebet365 **玩家端短信验证码**(注册 / 找回密码)在后端的日志行为,以及如何与创蓝控制台对账、排查「收不到码」问题。
相关代码:`apps/api/src/domains/identity/sms/`
创蓝接入总览见 [chuanglan-sms-js-guide.md](./chuanglan-sms-js-guide.md)。
---
## 一、整体流程
```text
玩家端 POST /api/player/sms/send
→ SmsService 生成 6 位验证码
→ 拼短信正文,调用创蓝 APIuid = sessionId
→ 验证码写入 Redissms:code:{sessionId}(默认 5 分钟)
玩家注册 / 找回密码
→ POST 携带 phone、sessionId、smsCode
→ SmsService.verifyCode 校验 Redis 后删除
```
| 字段 | 说明 |
|------|------|
| `sessionId` | 后端生成的 UUID作为创蓝请求的 `uid`**对应创蓝控制台「批次号」** |
| `messageId` | 创蓝返回的发送 ID出现在成功日志中 |
| 验证码 | 仅存于 Redis 与发信正文,**默认不写入 Docker 日志** |
---
## 二、环境变量
`.env.docker`(或本地 API 的 `.env`)中配置:
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `CHUANGLAN_ACCOUNT` | — | 创蓝账号(必填) |
| `CHUANGLAN_PASSWORD` | — | 创蓝密码(必填) |
| `CHUANGLAN_ENDPOINT` | `https://sgap.253.com/send/sms` | 国际短信网关 |
| `SMS_CODE_TTL_SECONDS` | `300` | 验证码 Redis 有效期(秒) |
| `SMS_RATE_LIMIT_SECONDS` | `60` | 同一手机号 / IP 发码冷却(秒) |
| `SMS_DEBUG_LOG_CODE` | `false` | **联调专用**:为 `true` 时在日志输出验证码明文 |
`docker-compose.prod.yml` 已将 `SMS_DEBUG_LOG_CODE` 传入 `thebet365-api` 容器。
---
## 三、常规日志(生产推荐)
`SMS_DEBUG_LOG_CODE=false`API 会记录短信链路,但**不打印验证码**,手机号仅保留末 4 位(如 `****1234`)。
### 3.1 查看方式
**SSH推荐**
```bash
docker logs -f thebet365-api 2>&1 | grep -E 'SMS|Chuanglan|Player registered|Password reset'
```
**宝塔:** 容器 `thebet365-api`**容器日志** → 搜索 `SMS``Chuanglan`。若显示「暂无日志」,优先用上面 `docker logs` 命令;面板偶发读不到 Docker 日志。
### 3.2 日志含义
| 日志前缀 / 关键字 | 级别 | 含义 |
|-------------------|------|------|
| `SMS send request purpose=...` | log | 收到发码请求 |
| `SMS rate limited` | warn | 触发频控(手机号或 IP |
| `SMS reset_password blocked reason=...` | warn | 找回密码前置校验失败 |
| `Chuanglan request` | log | 已向创蓝发起 HTTP 请求 |
| `Chuanglan success` | log | 创蓝受理成功(含 `messageId` |
| `Chuanglan rejected` | warn | 创蓝返回业务错误码 |
| `Chuanglan HTTP error` | error | 网络超时或 HTTP 异常 |
| `SMS sent` | log | 发码完成并已写入 Redis |
| `SMS send failed` | error | 创蓝失败,前端收到 `SMS_SEND_FAILED` |
| `SMS verify request / success / failed` | log / warn | 验码过程 |
| `Player registered` | log | 注册成功(已通过验码) |
| `Password reset by phone` | log | 短信找回密码成功 |
`session=abc12345…``sessionId` 前 8 位,便于与创蓝批次号前缀对照。
---
## 四、调试模式(输出验证码)
联调或排查「创蓝有记录、手机没收到」时,可临时开启:
```env
SMS_DEBUG_LOG_CODE=true
```
修改 `.env.docker` 后重启 API
```bash
cd /www/wwwroot/thebet365 # 按实际路径
docker compose -f docker-compose.prod.yml --env-file .env.docker up -d api
```
若代码有更新,需先重新构建并加载 API 镜像再执行上述命令。
### 4.1 调试日志格式
每次发码会多一行 **warn** 级别日志:
```text
[SmsService] [SMS_DEBUG] purpose=register phone=0088613812345678 sessionId=ed08fe51-e9b7-4fec-9381-8249f4c65f4b code=123456 content=您的验证码是123456。5分钟内有效。
```
### 4.2 与创蓝控制台对照
| 后端 `[SMS_DEBUG]` 字段 | 创蓝控制台列 |
|-------------------------|--------------|
| `sessionId` | **批次号** |
| `phone` | **手机号** |
| `code` / `content` | **发送内容** |
| 常规日志 `messageId` | 发送详情中的 messageId |
筛选调试行:
```bash
docker logs -f thebet365-api 2>&1 | grep SMS_DEBUG
```
### 4.3 安全提醒
- **生产环境务必保持 `SMS_DEBUG_LOG_CODE=false`**,否则验证码会留在 Docker 日志中。
- 调试结束后改回 `false` 并重启 API。
- 不要将含 `[SMS_DEBUG]` 的日志片段对外分享。
---
## 五、从 Redis 读取验证码(可选)
发码接口返回的 `sessionId` 有效期内,可直接查 Redis
```bash
docker exec thebet365-redis redis-cli GET "sms:code:完整的sessionId"
```
返回示例:
```json
{"phone":"0088613812345678","code":"123456","purpose":"register"}
```
列出当前未过期的 keykey 带 TTL验码或过期后会消失
```bash
docker exec thebet365-redis redis-cli KEYS "sms:code:*"
```
---
## 六、常见问题
### 6.1 创蓝显示「接收失败 / UNDELIV」
表示创蓝已提交,但**运营商未送达终端**。常见原因:
- 号码格式或国家码不正确(国际号需与创蓝侧开通路由一致)
- 目标地区/运营商拦截或关机、空号
- 短信内容或发送频率触发运营商过滤
后端若已有 `Chuanglan success` + `SMS sent`,说明 **API 与创蓝侧发送正常**,需从号码与运营商侧继续排查。
### 6.2 日志里完全没有 `SMS` / `Chuanglan`
1. 确认请求是否打到 APINginx 是否将 `/api` 反代到 `thebet365-api:3000`)。
2. 确认运行的是**包含短信日志的新版 API 镜像**。
3.`docker logs thebet365-api --tail 200` 查看,不要仅依赖宝塔面板。
### 6.3 创蓝控制台有记录,后端没有 `[SMS_DEBUG]`
- 检查 `.env.docker` 是否 `SMS_DEBUG_LOG_CODE=true`
- 重启后是否加载了新环境变量:`docker exec thebet365-api printenv SMS_DEBUG_LOG_CODE`
### 6.4 发码太频繁
日志会出现 `SMS rate limited`。默认同一手机号 60 秒内只能发一次,可在 `.env.docker` 调整 `SMS_RATE_LIMIT_SECONDS`(生产不建议设过小)。
### 6.5 找回密码发码失败
关注 `SMS reset_password blocked reason=`
| reason | 含义 |
|--------|------|
| `phone_not_registered` | 手机号未注册玩家 |
| `account_disabled` | 账号已禁用 |
| `password_change_disabled` | 系统配置禁止改密 |
---
## 七、相关 API
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | `/api/player/sms/send` | 发验证码,`purpose`: `register`(默认)或 `reset_password` |
| POST | `/api/player/auth/register` | 注册,需 `sessionId` + `smsCode` |
| POST | `/api/player/auth/forgot-password` | 找回密码,需 `sessionId` + `smsCode` |
SwaggerAPI 容器启动后):`http://<主机>:3000/api/docs`
---
## 八、检查清单
联调短信时建议按序确认:
- [ ] `.env.docker``CHUANGLAN_ACCOUNT` / `CHUANGLAN_PASSWORD` 正确
- [ ] 需要看验证码时 `SMS_DEBUG_LOG_CODE=true`,上线前改回 `false`
- [ ] `docker logs` 能看到 `Chuanglan success``SMS sent`
- [ ] 创蓝批次号与日志 `sessionId` 一致
- [ ] 若创蓝为 `DELIVRD` 仍收不到,检查手机拦截 / 地区路由
- [ ] 若创蓝为 `UNDELIV`,优先排查号码与运营商,而非后端代码