需求原文(用户,指向《支付宝支付接口接入规范261008(1).docx》): 「门店新增了地区相关的字段,需要接上,因为支付宝异地收款会有风控,我们的 checkout 也要做一个调整, 在调起支付时要根据请求者 ip 自动选择对应地区的门店 id,这样才不会风控」
设计裁定(本批开工前已与你确认,未改):IP 归属地取 ipwho.is(进程内缓存,失败⇒空); 粒度 = 城市精确匹配、省作回退;匹配不上拒收(顾客语,不打上游、不落单);同城多店按 IP 稳定散列挑一家;城市未匹配则该省随机一家。
★ 这一批没有写计划文件(前几批是 .claude/plan/<日期>-<主题>.md),需求以 docx + 上述裁定
为准,落地过程与读数都在 logs/ 下的日志里 —— 这点与既有批次不同,先说明。
origin/java 停在 ed24480f;本地 java 领先 5 个提交:
| 提交 | 内容 |
|---|---|
b1c8f6fb |
(一)目录快照 har-region-cn.json(31 省 / 342 地级 / 166 繁简对)+ HarRegionCatalog + HarIpRegionResolver + HarShopService#pickForRegion + 门店/创建请求带地区 |
32384b2b |
(二)结账腿接线:HarCheckoutController 按顾客 IP 挑店填 third_shop_code;挑不出来 400 拒收(两种文案);clientIp 四个头 + unknown 兜底 |
c47b0c63 |
(三)省市目录只读端点 GET /payment/har/region/provinces|cities + db/har-shop-region.sql |
8e352e7e |
(四)前端:门店表单省→市选择器、列表「地区」列、详情一行;开放 API 文档 §10.1 同步 |
ccc34414 |
文档 markdown 空行修正(引用块贴着 --- 会被当成懒惰续行) |
★ b1c8f6fb 里夹带了一份 支付宝支付接口接入规范261008(1).docx(87512 字节) ——
那是开工时会话开始前就已经 git add 进索引的文件,提交时没有指定路径,于是跟着这一刀进去了。
我没有改写历史(改写会动到你已经能看到的提交),要不要摘出来请你定:留着无功能影响,
摘掉需要 rebase/改写。后续提交都改成「显式路径 git add + git commit -F <msg> -- <显式路径>」。
mvn test:1212 条,0 失败 0 错误 0 跳过,BUILD SUCCESS(12:44:08;
HarCheckoutControllerTest 24 + HarRegionControllerTest 5 都在内)| 变异体 | 结果 |
|---|---|
结账腿:4 个(挑到不填 third_shop_code / 两句拒收文案合并 / 不取 XFF 第一跳 / 去掉 unknown 兜底) |
预测红集 6,实测恰为那 6 条,其余 18 条作正对照仍绿;还原后 sha256 与变异前一致(24/0) |
目录端点:3 个(省码不校验 / 用空表代替 400 / 权限串只留 :create) |
预测红集 3,实测 cities_returnsOnlyThatProvincesCities、cities_unknownProvinceCode_400_notAnEmptyList、contract_pathAndPermissionAreTheOnesTheFrontendCalls;2 条对照仍绿;还原后 sha256 一致(5/0) |
前端(本仓无测试框架,ts:check 基线本就非零 ⇒ 只能同机差分):
pnpm ts:check:基线 289 条 error TS(exit 2)→ 改动后 289 条,逐条集合比对
新增 0、消失 0;pnpm build:exit 0(两次,12:42 与 12:46,各约 57s);已回读产物确认新代码真进了包:
dist/js/index.x_9MozyF.js 含 region/provinces、dist/js/index.SNmFzXAj.js 含文档新句
「城市编码不属于该省」、province_code 出现在 3 个 chunk(注意:一开始我按 dist/assets/*.js
搜,3 个都查成 0 —— 是本仓产物在 dist/js/,是检索式错不是文件缺失,换路径后同一条搜索命中);select.mjs):loading: Boolean
「whether Select is loading data from server」、disabled: Boolean —— 不是凭记忆。产物指纹:
java/target/payment-platform-1.0.0.jar,143,146,829 字节,sha256 977da28010f737bdde382af5a34b5a46a0967e607a62573231e5867ef0d0f4f9,
重打于 12:45:02;已开包确认含 HarRegionController.class、HarRegionVO.class,
且包内 har-region-cn.json 与源码 sha256 一致(23c713b1…)frontend/dist.zip,9,375,221 字节,sha256 dd4cf524bc11bc32d4a4e831793035b2ba2ca53b6ed0f957682c43708750dab1,
281 个条目(与上一版同形:dist/ 开头、全为正斜杠、testzip() 无坏成员)java/src/main/resources/db/har-shop-region.sql(本工程未接 Flyway,只能你执行)。
★ 反了不是静默降级而是直接报错:实体带上 province_code/city_code 后,门店列表与
挑店的每一句 SELECT 都会取这两列 ⇒ 门店列表 500,且每一笔收款链接下单都失败。frontend/dist.zip。module_payment:har:shop:list / :create 权限串(@perm.hasAny 两条),菜单不动。province_code/city_code 为空的门店(2026-10-08 之前建的)在挑店时必然落选。
上游没有门店更新接口,补不上,要收款只能换新的 third_shop_id 重开。pay_url 仍然没有被真机扫过(上一批就挂着的问题,本批没变);挑店在真实顾客 IP
下的表现(真挑到哪个地区的哪家店)没有端到端跑过,只跑到「挑店逻辑 + 端口」这一层。HarCheckoutController 的类 javadoc
「已知的边界」里)。后果是把顾客导到收款方自己的另一家门店,不涉资金与租户边界,
要堵得在网关上 —— 本批不动。HarCheckoutController 三个偏差未改(都在代码注释里标了,属规范与现状不一致,
不是本次引入):shopName 我方 @Size(128) vs 规范 varchar(16);thirdShopCode 32 vs 30;
实体列宽按规范 16 建。HarRegionController 返回 code=400(我写的,两参构造),
而 HarShopService#requireKnownCity 返回 code=500(单参 BusinessException 的默认码)。
后者是对外开放 API 也会走到的路径 ⇒ 外部调用方传错码会看到「服务器错误」。我没有改它
(改的是既有端点契约 + 要动它的用例),只把开放文档按实测口径写成 500。要不要统一成 400,
请你定。third_shop_id 重复被判 code=500 是文档里的既有说法,同上一类,本次未动。另:probe 结论提醒 —— 顾客端拒收文案能上屏,是因为 GlobalExceptionHandler 对
BusinessException 不带 @ResponseStatus(HTTP 200 + body code),顾客页自建实例
读的是 res.data.msg;如果哪天有人把它改成真 4xx/5xx,顾客页会 fallback 成
「网络异常,请检查网络后重试」,那句「你所在地区未开通」就再也到不了顾客眼前。