计划:.claude/plan/2026-09-24-har-refund.md(同批入库)
| 提交 | 内容 |
|---|---|
4b896a0 |
上游客户端加退款 —— kf.alipay.trade.refund(HarClient#refund + 出站 URL 用例) |
b36f397 |
退款服务 —— 先抢占「退款中」,再调上游(HarOrderService#openRefund + 12 条用例) |
2f54088 |
退款端点 —— POST /payment/openapi/har/refund(控制器 + 5 条用例 + 认证清单一行) |
ff7f517 |
租户文档补 10.4 退款,回调/状态顺延为 10.5/10.6 |
a631b9f |
顺带:LeshouyingPropertiesTest 的 yml 取值限定段内(并入 HAR 时 har.base-url 排在 leshouying.base-url 之前导致取错键;与退款无关,先前遗留未提交) |
设计裁定(见计划):只有开放 API 入口、不建 pay_har_refund 表、先抢占后退款、
上游明确拒绝才回退、结果未知不回退、不解析上游 detail、不加 @Transactional。
mvn test 全量 871 条,0 失败 0 错误(logs/_har-refund-full.log)HarOrderServiceTest 46 条(原 34 + 新 12)、HarOpenControllerTest 11 条(原 6 + 新 5)logs/_har-refund-svc-mutate.py、logs/_har-ctl-mutate.py;每次还原后复核 sha256 与注入前逐字节一致):| 变异体 | 结果 |
|---|---|
去掉抢占守卫 WHERE trade_status='1' |
红 1(openRefund_preemptCarriesPaidGuardAndSchedulesPoll) |
| 上游调用挪到抢占之前 | 红 3(含 openRefund_preemptsToRefundingBeforeCallingUpstream) |
| 超时分支也回退 | 红 1(openRefund_upstreamTimeout_keepsRefundingState) |
认证清单漏列 /refund |
红 1(everyEndpoint_isListedInTheAuthFilterInventory) |
| 控制器不设闸 | 红 3 |
闸挪到 openRefund 之后 |
红 2(404 照样抛得出,是 verifyNoInteractions 抓住的顺序) |
新端点,必须重新部署才生效。 无 SQL、无配置项、无菜单权限串改动。
kf.alipay.trade.refund。上游规范里三处写它、表 8 的 method 备注格写 kf.jh.stage.trade.refund;precreate 的先例证明备注格那一列不可信,所以按多数取值 —— 但这是推断,不是实测。detail 结构从未公开,我们不解析它。成功判据只用了 biz_content / response_code / msg。若上游实际语义与此不符,只会在联调中暴露。4 → 2)没有任何用例钉住:findPendingForPoll 用 HarOrderStatus.PENDING = {0,4},而全测试树里 HarOrderStatus.PENDING / isPending / FINAL 的引用数为 0。谁把这个集合里的 4 去掉,退款会永远停在「退款中」而没有任何测试变红。pay_har_refund 表不存在(裁定:全额退款 + 状态是订单状态的一个维度 + detail 不公开 ⇒ 没有列可存)。order_no / third_order_no。third_shop_code 取值契约仍与上游互相矛盾(明文 19 位 ⇒ 被私钥解密报错;342 字符密文 ⇒ 「最长 32 位」)。已按单变量方式重发请求待上游答复。auth_code)仍未联调 —— 它由 auth_code 非空触发(HarOrderService.java:339),我们没有模式开关。