From 2d38dcd139247c68ce91681c5b5856e70805209f Mon Sep 17 00:00:00 2001 From: API Changelog Bot Date: Sat, 23 May 2026 00:18:17 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E4=BA=8C=E8=BD=AE=20CR=20P0=20?= =?UTF-8?q?=E6=95=B4=E6=94=B9=20(=E5=AE=9A=E5=88=B6=E5=B8=88=E5=8F=8D?= =?UTF-8?q?=E6=9F=A5=20by-userid/by-openid)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- ...ctor_customizer_lookup_by_userid_openid.md | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 changelogs/2026-05/23_refactor_customizer_lookup_by_userid_openid.md diff --git a/changelogs/2026-05/23_refactor_customizer_lookup_by_userid_openid.md b/changelogs/2026-05/23_refactor_customizer_lookup_by_userid_openid.md new file mode 100644 index 0000000..a6e4693 --- /dev/null +++ b/changelogs/2026-05/23_refactor_customizer_lookup_by_userid_openid.md @@ -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 改 UserVO — 历史包袱,mp 端已不再用 `getProfile` 取 phone (被新 by-userid 替代),问题自然消解 + +--- + +## 六、联系人 + +后端: wx (呼籁旅行) +前端: mmg + +如有疑问可在 [PR #2924](https://git.1814.love:8443/wx/HL/pulls/2924) 评论区留言。