|
|
@@ -177,7 +177,7 @@ class HarOrderServiceTest {
|
|
|
assertEquals(vo.getOrderNo(), captor.getValue().getThirdOrderNo());
|
|
|
assertNotEquals("BIZ-0001", captor.getValue().getThirdOrderNo());
|
|
|
assertEquals("BIZ-0001", vo.getOutBizNo());
|
|
|
- assertTrue(vo.getOrderNo().startsWith("HAR"));
|
|
|
+ assertTrue(vo.getOrderNo().startsWith("AP"));
|
|
|
}
|
|
|
|
|
|
/** 下单时排入轮询:上游通知窗口只有约 25 秒,超时后只能靠主动查询收敛 */
|
|
|
@@ -260,6 +260,88 @@ class HarOrderServiceTest {
|
|
|
assertEquals("har_ali_un_stage", req.getValue().getBiz());
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 订单号前缀是**中性**的 {@code AP},不带上游品牌(2026-10-09 去上游化)。
|
|
|
+ *
|
|
|
+ * <p>order_no 出现在开放 API 响应、顾客收款页和上游的 third_order_no 里 ——
|
|
|
+ * 是调用方每天都看得到的字符串,HAR 前缀等于把上游名字印在上面。
|
|
|
+ * 存量单不动(改不了也不该改),这里只钉新生成的那一串。
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ void create_orderNoUsesNeutralPrefix_notUpstreamBrand() {
|
|
|
+ when(merchantService.requireByEnterpriseId("E1")).thenReturn(merchant());
|
|
|
+ when(harClient.precreate(any())).thenReturn(response("10000", precreateDetail()));
|
|
|
+
|
|
|
+ service.create(dto(), "E1", "KEY1");
|
|
|
+
|
|
|
+ ArgumentCaptor<HarOrderEntity> captor = ArgumentCaptor.forClass(HarOrderEntity.class);
|
|
|
+ verify(orderMapper).insert(captor.capture());
|
|
|
+ String orderNo = captor.getValue().getOrderNo();
|
|
|
+ assertTrue(orderNo.startsWith("AP"), "订单号前缀应为中性词 AP。实测: " + orderNo);
|
|
|
+ assertFalse(orderNo.startsWith("HAR"), "订单号不得带上游品牌。实测: " + orderNo);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * {@code biz} 留空 + 非分期 ⇒ 平台按 trade_type 派生上游要的取值(2026-10-09 去上游化:
|
|
|
+ * 这串带上游品牌,从调用方契约里拿掉,文档改为「留空即可」)。
|
|
|
+ * 落库与发给上游必须是**同一份** —— 两份不同的话对账时对不上。
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ void create_bizBlank_nonStage_derivesTheUpstreamValue() {
|
|
|
+ HarOrderCreateDTO dto = dto(); // dto() 的 trade_type 已是 alipay_un_stage,biz 未设
|
|
|
+ when(merchantService.requireByEnterpriseId("E1")).thenReturn(merchant());
|
|
|
+ when(harClient.precreate(any())).thenReturn(response("10000", precreateDetail()));
|
|
|
+
|
|
|
+ service.create(dto, "E1", "KEY1");
|
|
|
+
|
|
|
+ ArgumentCaptor<HarPrecreateRequest> req = ArgumentCaptor.forClass(HarPrecreateRequest.class);
|
|
|
+ verify(harClient).precreate(req.capture());
|
|
|
+ assertEquals("har_ali_un_stage", req.getValue().getBiz(),
|
|
|
+ "调用方留空时由平台派生 —— 这串不再要求调用方知道");
|
|
|
+
|
|
|
+ ArgumentCaptor<HarOrderEntity> entity = ArgumentCaptor.forClass(HarOrderEntity.class);
|
|
|
+ verify(orderMapper).insert(entity.capture());
|
|
|
+ assertEquals("har_ali_un_stage", entity.getValue().getBiz(),
|
|
|
+ "落库的与发给上游的必须是同一份");
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 留空 + 分期 ⇒ 保持空:分期没有对应的规范取值,不替上游编一个。 */
|
|
|
+ @Test
|
|
|
+ void create_bizBlank_stageTradeType_leavesItBlank() {
|
|
|
+ HarOrderCreateDTO dto = dto();
|
|
|
+ dto.setTradeType("alipay_stage");
|
|
|
+ when(merchantService.requireByEnterpriseId("E1")).thenReturn(merchant());
|
|
|
+ when(harClient.precreate(any())).thenReturn(response("10000", precreateDetail()));
|
|
|
+
|
|
|
+ service.create(dto, "E1", "KEY1");
|
|
|
+
|
|
|
+ ArgumentCaptor<HarPrecreateRequest> req = ArgumentCaptor.forClass(HarPrecreateRequest.class);
|
|
|
+ verify(harClient).precreate(req.capture());
|
|
|
+ assertNull(req.getValue().getBiz(), "分期没有派生依据,保持空而不是编一个");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 显式给了 biz ⇒ 原样透传、派生不覆盖(后台表单与既有调用方那条路)。
|
|
|
+ *
|
|
|
+ * <p>夹具特意用分期 + 一个与派生值**不同**的串:若实现变成「无条件派生」,
|
|
|
+ * 这条立刻红 —— 拿非分期 + 派生值同串作夹具的话,两种实现在改前改后都绿。
|
|
|
+ */
|
|
|
+ @Test
|
|
|
+ void create_bizExplicit_passesThroughEvenOnStage() {
|
|
|
+ HarOrderCreateDTO dto = dto();
|
|
|
+ dto.setTradeType("alipay_stage");
|
|
|
+ dto.setBiz("caller_knows_best");
|
|
|
+ when(merchantService.requireByEnterpriseId("E1")).thenReturn(merchant());
|
|
|
+ when(harClient.precreate(any())).thenReturn(response("10000", precreateDetail()));
|
|
|
+
|
|
|
+ service.create(dto, "E1", "KEY1");
|
|
|
+
|
|
|
+ ArgumentCaptor<HarPrecreateRequest> req = ArgumentCaptor.forClass(HarPrecreateRequest.class);
|
|
|
+ verify(harClient).precreate(req.capture());
|
|
|
+ assertEquals("caller_knows_best", req.getValue().getBiz(),
|
|
|
+ "显式传了就不许被派生覆盖");
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 上游**明确拒绝**(参数错误之类)⇒ 本地这一行必须跟着收尾。
|
|
|
*
|