Parcourir la source

fix(汇安融): 地区编码填错统一返回 400 —— 与只读端点同一个码

同一个错误(省市编码对不上目录)在两个入口返回了两个不同的码:
只读端点 HarRegionController 是 400(两参构造),门店创建的
HarShopService#requireKnownCity 是 500 —— 单参 BusinessException 的默认码。
后者是开放 API 也会走到的路径,外部调用方传错码会看到「服务器错误」,
照着去排查我们这边。

两处都改成显式 400,文案一字未动(「省份编码不存在: <省码>」/
「城市编码不属于该省: <市码>(省 <省码>)」)—— 控制器那条测试断言过这句话
与 service 同源,现在码也同源了。

先红后绿:给 HarShopServiceTest 的两条地区拒收用例各加一条
assertEquals(400, e.getCode()),实测红在 expected: <400> but was: <500>;
改完 18/18 绿,整包 1212/0/0/0。

开放文档 10.1 同步:city_code 那行补上码值(原文只写了 msg 形状,没写码)。
jar 重打 sha256 b6b64c8a…,dist 重打(文档经 ?raw 打进包)sha256 80038a66…。

未动:third_shop_id 重复仍是 code=500(文档既有说法,不在本次裁定范围内)。
alphaH il y a 1 semaine
Parent
commit
300a27f9dd

+ 1 - 1
frontend/src/views/module_payment/apikey/docs/har-openapi.md

@@ -50,7 +50,7 @@ POST /payment/openapi/har/shop/create
 | `third_shop_id` | string | 是 | 你方的门店编码,≤32 字符。**重复提交会被拒绝**,见下 |
 | `shop_name` | string | 是 | 门店名称,≤128 字符 |
 | `province_code` | string | **是**(2026-10-08 起) | 门店所在省,GB/T 2260 两位码,如 `32`(江苏省)、`11`(北京市) |
-| `city_code` | string | **是**(2026-10-08 起) | 门店所在市,GB/T 2260 四位码,如 `3201`(南京市)、`1101`(北京市)。**必须是 `province_code` 下的市**,不属于该省的编码会被拒(`msg` 形如 `城市编码不属于该省: 1101(省 32)`;省码写错则为 `省份编码不存在: 99`) |
+| `city_code` | string | **是**(2026-10-08 起) | 门店所在市,GB/T 2260 四位码,如 `3201`(南京市)、`1101`(北京市)。**必须是 `province_code` 下的市**,编码填错一律 `code=400` 拒绝(`msg` 形如 `城市编码不属于该省: 1101(省 32)`;省码写错则为 `省份编码不存在: 99`)—— 是调用方的输入错误,改对再调即可 |
 
 > ⚠️ **`province_code` / `city_code` 自 2026-10-08 起为必填。** 在此之前提交成功的门店不传这两个字段也能建号,**现在不传会返回 `code=400`**(`msg` 为 `省份不能为空` / `城市不能为空`)。取值用国标 GB/T 2260 的行政区划代码:省级两位、地级四位,直辖市取 `1101`(北京市)/ `1201`(天津市)/ `3101`(上海市)/ `5001`(重庆市)、`5002`(重庆市县)。
 

+ 7 - 2
java/src/main/java/com/payment/platform/module/payment/har/service/HarShopService.java

@@ -290,16 +290,21 @@ public class HarShopService {
      * <p>省码与市码分开报错,是为了让运营照着字面就能改对 —— 「省市不匹配」这种笼统提示
      * 会让人去翻数据字典。
      *
+     * <p>两句都带**显式 400**:码是调用方填错的,不是我们这边出了故障。单参
+     * {@code BusinessException} 的默认码是 500(见 {@code BusinessException} 构造),
+     * 对外开放 API 的调用方会照着「服务器错误」来排查我们。同一份目录在只读端点
+     * ({@code HarRegionController})上也是 400,两处得是同一个码、同一句话。
+     *
      * @return 目录里那条地级记录,调用方用它的 code 落库/发上游(即**规范化后的**编码)
      */
     private HarRegionCatalog.City requireKnownCity(String provinceCode, String cityCode) {
         String pc = provinceCode == null ? "" : provinceCode.trim();
         boolean provinceKnown = regionCatalog.provinces().stream().anyMatch(p -> pc.equals(p.code()));
         if (!provinceKnown) {
-            throw new BusinessException("省份编码不存在: " + provinceCode);
+            throw new BusinessException(400, "省份编码不存在: " + provinceCode);
         }
         return regionCatalog.cityByCode(pc, cityCode)
-                .orElseThrow(() -> new BusinessException(
+                .orElseThrow(() -> new BusinessException(400,
                         "城市编码不属于该省: " + cityCode + "(省 " + provinceCode + ")"));
     }
 

+ 5 - 0
java/src/test/java/com/payment/platform/module/payment/har/service/HarShopServiceTest.java

@@ -270,6 +270,10 @@ class HarShopServiceTest {
 
         assertTrue(e.getMessage() != null && e.getMessage().contains("城市"),
                 "提示要让运营看得懂,实际: " + e.getMessage());
+        // 码是自己填错的 ⇒ 调用方的输入错误,不是服务器故障。单参 BusinessException 默认 code=500,
+        // 对外开放 API 的调用方会照着「服务器错误」去排查我们这边。
+        // 同一份目录在只读端点上也是 400(见 HarRegionControllerTest),两处得是同一个码。
+        assertEquals(400, e.getCode(), "编码不认识该是 400,实际: " + e.getCode());
         verify(harClient, never()).createShop(any());
         verify(shopMapper, never()).insert(any());
     }
@@ -283,6 +287,7 @@ class HarShopServiceTest {
 
         assertTrue(e.getMessage() != null && e.getMessage().contains("省"),
                 "实际: " + e.getMessage());
+        assertEquals(400, e.getCode(), "编码不认识该是 400,实际: " + e.getCode());
         verify(harClient, never()).createShop(any());
         verify(shopMapper, never()).insert(any());
     }