docs: 二轮 CR P0 整改 (定制师反查 by-userid/by-openid)
PR #2924 后端内部 Feign 链路重构,前端无感知。 - 手机号不再走 Feign URL query (不出 user-service 进程) - mp /mp/customizer/me + order-v2 sharerOpenid 反查从 2 次 Feign 减为 1 次 - SMS helper 抽取 + GlobalExceptionHandler.handleLoginFail 补单测 测试服真测 T1/T2/T3 全绿 + 单测 194 全绿。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
这个提交包含在:
父节点
0bbb1bb9f9
当前提交
2d38dcd139
@ -0,0 +1,127 @@
|
|||||||
|
# refactor: 定制师反查链路改 by-userid / by-openid (手机号 PII 不出 user-service + 性能减半)
|
||||||
|
|
||||||
|
> **仓库**: HL (后端 hl-user-service + hl-mp-service + hl-order-service-v2 + hl-common-feign + hl-common-log)
|
||||||
|
> **关联 PR/Issue**: PR #2924,**无关联工单**(二轮深度 CR 整改)
|
||||||
|
> **日期**: 2026-05-23
|
||||||
|
> **影响范围**: 内部反查接口签名变化,前端**无感知**
|
||||||
|
> **接收方**: mmg (前端)
|
||||||
|
> **前端**: **无需变更** — 本 PR 全是后端内部 Feign 链路重构,`/mp/customizer/me` 和下单 `sharerOpenid` 反查的对外行为完全一致
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 核心改动 (二轮 CR P0 整改)
|
||||||
|
|
||||||
|
PR #2913 (定制师分享反查) 引入的反查链路把客人/定制师真实手机号通过 Feign URL query 在内网服务间明文流转:
|
||||||
|
|
||||||
|
- mp 端 `/mp/customizer/me`: `getProfile(userId)` 取 `rawPhone` → `getCustomizerByPhone(phone)` 两次串行
|
||||||
|
- order-v2 端分享下单: `getUserByOpenid(openid)` 取 `phone` → `getCustomizerByPhone(phone)` 两次串行
|
||||||
|
|
||||||
|
**问题**:
|
||||||
|
- 手机号会出现在 nginx access log + SkyWalking 分布式 trace 中,**绕过 `maskPhone` 脱敏**
|
||||||
|
- 串行 2 次 Feign,P99 延迟翻倍
|
||||||
|
|
||||||
|
**重构方案**: user-service 内部一次性完成 `userId/openid → user.phone → admin_user.mobile → CUSTOMIZER 校验`,**phone 永不出 user-service 进程**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、新增内部接口 (Feign,不经网关)
|
||||||
|
|
||||||
|
### `GET /internal/user/customizer/by-userid?userId=xxx` (mp 端用)
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| code | int | 200 |
|
||||||
|
| data | `CustomizerByPhoneInternalVO` 或 null | 命中的 CUSTOMIZER admin 信息 |
|
||||||
|
|
||||||
|
匹配规则: `user.user_id → user.phone → admin_user.mobile == phone + status=ACTIVE + 拥有 CUSTOMIZER 角色`
|
||||||
|
|
||||||
|
### `GET /internal/user/customizer/by-openid?openid=xxx` (order-v2 端用)
|
||||||
|
|
||||||
|
参数/返回同上,只是入口换成 `openid`(`user.openid → user.phone → admin_user.mobile`).
|
||||||
|
|
||||||
|
### 旧 endpoint `/internal/user/admin/by-phone?phone=xxx` 保留
|
||||||
|
|
||||||
|
兼容其他可能的调用方,暂不下线 (后续会陆续迁移)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、调用方变化 (对前端零影响)
|
||||||
|
|
||||||
|
### `GET /mp/customizer/me`
|
||||||
|
|
||||||
|
| 项 | 之前 | 现在 |
|
||||||
|
|----|------|------|
|
||||||
|
| Feign 调用次数 | 2 次串行 (`getProfile` + `getCustomizerByPhone`) | **1 次** (`getCustomizerByUserId`) |
|
||||||
|
| 真实手机号传输 | 走第二次 Feign URL query | **不出 user-service** |
|
||||||
|
| 响应字段 | 不变 | 不变 |
|
||||||
|
| 行为 | 不变 | 不变 |
|
||||||
|
|
||||||
|
### `POST /mp/order/create` 的 `sharerOpenid` 反查
|
||||||
|
|
||||||
|
| 项 | 之前 | 现在 |
|
||||||
|
|----|------|------|
|
||||||
|
| Feign 调用次数 | 2 次串行 (`getUserByOpenid` + `getCustomizerByPhone`) | **1 次** (`getCustomizerByOpenid`) |
|
||||||
|
| 真实手机号传输 | 走第二次 Feign URL query | **不出 user-service** |
|
||||||
|
| 行为 | 不变 (兜底 / 命中 / 反查异常 三个分支保留) | 不变 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚨 前端需要做的事
|
||||||
|
|
||||||
|
**什么都不需要做**。
|
||||||
|
|
||||||
|
- `/mp/customizer/me` 响应字段无变化,前端按既有逻辑渲染即可
|
||||||
|
- `POST /mp/order/create` 接口无变化
|
||||||
|
- 错码无新增
|
||||||
|
|
||||||
|
可选自查:
|
||||||
|
```bash
|
||||||
|
grep -rE "/mp/customizer/me|sharerOpenid" hl-ui/src mp-cli/src
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、附带优化 (二轮 CR P1)
|
||||||
|
|
||||||
|
### P1#11 — SMS 登录路径重复代码抽 helper
|
||||||
|
|
||||||
|
`AdminAuthService.loginBySms` 中 3 段几乎一模一样的「incr fail count + judge locked/remaining + throw」(码错 / mobile 不绑 / 非定制师 3 个分支),抽 private `buildSmsFailOrLocked(failKey, currentFail)`。**行为完全不变**,既有 16 个 SMS 单测全部通过。
|
||||||
|
|
||||||
|
### P1#13 — GlobalExceptionHandler.handleLoginFail 补单测
|
||||||
|
|
||||||
|
PR #2913 引入的 `handleLoginFail` 拦截器原本 0 覆盖率,补 3 个 case:
|
||||||
|
- `remainingAttempts → LoginFailDetailVO{remainingAttempts=3, lockedMinutes=null}`
|
||||||
|
- `locked → LoginFailDetailVO{remainingAttempts=null, lockedMinutes=15}`
|
||||||
|
- `zeroRemaining` 边界 → `remainingAttempts=0` 如实回传
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、测试服验证记录
|
||||||
|
|
||||||
|
部署 user + mp + order-v2 三服务 (rolling-deploy-all,2026-05-23 00:11) 后真测:
|
||||||
|
|
||||||
|
| # | 场景 | 实测 |
|
||||||
|
|---|------|------|
|
||||||
|
| T1 | CUSTOMIZER user (wx, userId=...4314) → SMS 登录 → `/mp/customizer/me` | ✅ `isCustomizer=true, adminId=...8914, customizerName=王骁` (新 `getCustomizerByUserId` 走通) |
|
||||||
|
| T2 | 未登录直接调 `/mp/customizer/me` | ✅ 200 + `isCustomizer=false` (P1#13 拦截器返 200 兜底) |
|
||||||
|
| T3 | nginx access log + user-service 自身日志 grep `phone=18*` | ✅ 0 命中 (手机号不再出现在日志) |
|
||||||
|
| 单测 | hl-user-service 129 + order-v2 OrderCreateServiceTest 28 + mp MpCustomizerAggregationServiceTest 4 + common-log GlobalExceptionHandlerTest 33 | ✅ 全绿 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、不在本期范围 (有意保留,二轮 CR 评估后)
|
||||||
|
|
||||||
|
- VO 命名 8 元组改名 (`AdminLoginResponse → AdminLoginRespVO` 等) — changelog 已发字段名不能动,改类名/移包风险大于收益
|
||||||
|
- `@Transactional` 边界缩窄 — 改动面大,既有测试容易破
|
||||||
|
- `getCustomizerByMobileForFeign` 加 Redis 缓存 — P2 性能优化,QPS 未观察到瓶颈
|
||||||
|
- `doSendSms` 异步化防 timing 攻击 — 实际可利用性低 (要先拿到正确的 SMS code)
|
||||||
|
- `MpUserFeignClient.getProfile` Map<String,Object> 改 UserVO — 历史包袱,mp 端已不再用 `getProfile` 取 phone (被新 by-userid 替代),问题自然消解
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、联系人
|
||||||
|
|
||||||
|
后端: wx (呼籁旅行)
|
||||||
|
前端: mmg
|
||||||
|
|
||||||
|
如有疑问可在 [PR #2924](https://git.1814.love:8443/wx/HL/pulls/2924) 评论区留言。
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户