hl-api-changelog/changelogs/2026-05/22_fix_customizer_role_check_bug.md

4.9 KiB

fix: /mp/customizer/me 错把非定制师 admin 当定制师 + 网关白名单 + sharerOpenid 空串 (P0)

仓库: HL (后端 hl-user-service + hl-mp-service + hl-gateway + hl-order-service-v2) 关联 PR/Issue: PR #2923, Closes #2922 日期: 2026-05-22 影响范围: /mp/customizer/me 接口 + 客人下单 sharerOpenid 反查 + 网关白名单 接收方: mmg (前端) 前端: 可能需要调整 — 之前依赖 /mp/customizer/me 给非定制师 admin 显示分享按钮的行为现在不再生效(本就是 bug),前端逻辑无需改


🚨 关键修复

1. P0: 非定制师 admin 被错判成定制师

GET /mp/customizer/me 之前的实现 (#2907 引入) 仅过滤 admin_user.mobile + status=ACTIVE,不校验 CUSTOMIZER 角色。导致:

  • 运营/财务/客服等任意活跃 admin 用本人手机号 SMS 登录 C 端小程序,前端会看到「分享」按钮
  • 转发后客人下单时被 CustomizerValidator 角色校验拒绝
  • 订单悄悄给随机定制师,前端无任何感知
  • 生产风险: 分润纠纷 / 「为啥我分享了订单没给我」客诉

修复:AdminUserService.getCustomizerByMobileForFeign 加 CUSTOMIZER 角色过滤,非定制师 admin 直接返 null。

联动收益: OrderCreateService.resolveSharedCustomizerId 反查链路也自动受益,sharerOpenid 反查到的 admin 必然是定制师身份。

2. P1-2: /mp/customizer/me 未登录直接 401 卡 UI

JwtAuthFilter.OPTIONAL_AUTH_URLS 之前只含 /mp/product/* /mp/explore/*,/mp/customizer/me 走 MANDATORY 未登录直接 401,跟 MpCustomizerController.userId == null 兜底分支设计冲突。

修复: 加 /mp/customizer/me 到 OPTIONAL_AUTH_URLS,未登录返 isCustomizer: false

3. P1-4: sharerOpenid 空串导致下单 400

MpCreateOrderRequest.sharerOpenid + MpOrderSaveReqVO.sharerOpenid @Pattern("^[a-zA-Z0-9_-]+$") 不接受空串。前端从 onLaunch.options.sharerOpenid 拿值,误传 "" 整个下单 400

修复: @Pattern^$|^[a-zA-Z0-9_-]+$ 接受空串。


一、API 行为变化

GET /mp/customizer/me

调用方 / 场景 之前 现在
未登录 401 Missing Authorization 200 + {isCustomizer: false, adminId: null, customizerName: null, customizerAvatar: null}
已登录但 user.phone 为空 同左 同左 (isCustomizer: false)
已登录, user.phone 在 admin_user 找到对应 ACTIVE admin 但不是 CUSTOMIZER 角色 错误返 isCustomizer: true + 该 admin 信息 (P0 bug) isCustomizer: false (修复后)
已登录, user.phone 对应有 CUSTOMIZER 角色的 admin isCustomizer: true + admin 信息 同左

POST /mp/order/create

场景 之前 现在
sharerOpenid 字段传 "" 空串 400 Bad Request @Pattern 不匹配 200 OK (走兜底 assignRandomCustomizer)
sharerOpenid 传定制师 openid 反查 user.phone → admin 任意活跃 admin (P0 bug) 反查仅 CUSTOMIZER 角色 admin,非定制师 sharerOpenid 走兜底

🚨 前端需要做的事

1. 不再依赖 P0 bug

之前如果前端依赖"非定制师 admin 也能看到分享按钮"的行为 (这本身是 bug),现在该行为修正。前端按 data.isCustomizer 字段渲染即可,逻辑无需改

2. 可选: 未登录场景预渲染

由于 /mp/customizer/me 现在支持未登录调用,分享落地页 (客人从分享链接打开小程序首页) 可以在未登录态调一次 /mp/customizer/me,根据返回的 isCustomizer: false 跳过分享按钮渲染。这是设计原意。

3. sharerOpenid 字段值标准化(建议)

前端尽量保证 sharerOpenid 字段为 string | null 而不是空串。空串虽然现在不再卡 400,但语义不规范。

4. 自查

grep -rE "isCustomizer|sharerOpenid|/mp/customizer/me" hl-ui/src mp-cli/src

二、测试服验证记录

部署 user + mp + gateway 三服务到测试服 (2026-05-22 22:45) 后真测:

# 场景 实测
T1 CUSTOMIZER 角色 admin SMS 登录 → /mp/customizer/me isCustomizer: true, adminId, customizerName
T2 非 CUSTOMIZER admin (运营/客服) SMS 登录 → /mp/customizer/me isCustomizer: false (P0-1 修复后正确拦截)
T3 未登录直接调 /mp/customizer/me 200 + isCustomizer: false (P1-2 网关 OPTIONAL 加白生效)

三、不在本期范围 (留尾巴另起工单)

  • P0-2 AdminUserService 注入 WechatUserMapper(类头部已备案,历史包袱)
  • P1-3 selectAnyByPhone LIMIT 1 无 ORDER BY(业务唯一性约束,概率极低)
  • P1-5 反查 Feign 重复调用合并优化(P99 未观察)

四、联系人

后端: wx(呼籁旅行) 前端: mmg

如有疑问可在 #2922 评论区留言。