|
@@ -737,6 +737,134 @@ class AlipayBatchPayServiceTest {
|
|
|
verify(batchAuthorizeMapper).insert(any());
|
|
verify(batchAuthorizeMapper).insert(any());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // ==================== 用户反馈轮 2: 付款方 UID 自动带出 + 授权可重新生成 ====================
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void authorizeApply_blankParticipantId_defaultsToEnterpriseId() throws AlipayApiException {
|
|
|
|
|
+ // Ruling 19/21: 付款方即企业自己,participant_id 为空时默认企业 enterprise_id(防绕过前端直调)
|
|
|
|
|
+ AlipayFundAuthorizeUniApplyResponse resp = new AlipayFundAuthorizeUniApplyResponse();
|
|
|
|
|
+ resp.setAuthorizeLink("https://ur.alipay.com/abc");
|
|
|
|
|
+ when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class))).thenReturn(resp);
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, String> result = service.authorizeApply("E100", " ");
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals("AUTHING", result.get("status"));
|
|
|
|
|
+ ArgumentCaptor<AlipayFundAuthorizeUniApplyRequest> cap = ArgumentCaptor.forClass(AlipayFundAuthorizeUniApplyRequest.class);
|
|
|
|
|
+ verify(alipayClient).certificateExecute(cap.capture());
|
|
|
|
|
+ AlipayFundAuthorizeUniApplyModel m = (AlipayFundAuthorizeUniApplyModel) cap.getValue().getBizModel();
|
|
|
|
|
+ assertEquals("E100", m.getPrincipalInfo().getParticipantId());
|
|
|
|
|
+ ArgumentCaptor<BatchAuthorizeEntity> ent = ArgumentCaptor.forClass(BatchAuthorizeEntity.class);
|
|
|
|
|
+ verify(batchAuthorizeMapper).insert(ent.capture());
|
|
|
|
|
+ assertEquals("E100", ent.getValue().getParticipantId());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void authorizeApply_nullEnterpriseId_throws() {
|
|
|
|
|
+ // requireEnterpriseId 防御: 企业都不存在时直接拒绝而非默认空串申请
|
|
|
|
|
+ assertThrows(BusinessException.class, () -> service.authorizeApply(null, null));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void authorizeRebind_noExisting_appliesFresh() throws AlipayApiException {
|
|
|
|
|
+ // 无既有授权记录 → 直接申请(付款方 = 企业自己)
|
|
|
|
|
+ AlipayFundAuthorizeUniApplyResponse resp = new AlipayFundAuthorizeUniApplyResponse();
|
|
|
|
|
+ resp.setAuthorizeLink("https://ur.alipay.com/abc");
|
|
|
|
|
+ when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class))).thenReturn(resp);
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, String> result = service.authorizeRebind("E100");
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals("AUTHING", result.get("status"));
|
|
|
|
|
+ ArgumentCaptor<AlipayFundAuthorizeUniApplyRequest> cap = ArgumentCaptor.forClass(AlipayFundAuthorizeUniApplyRequest.class);
|
|
|
|
|
+ verify(alipayClient).certificateExecute(cap.capture());
|
|
|
|
|
+ AlipayFundAuthorizeUniApplyModel m = (AlipayFundAuthorizeUniApplyModel) cap.getValue().getBizModel();
|
|
|
|
|
+ assertEquals("E100", m.getPrincipalInfo().getParticipantId());
|
|
|
|
|
+ verify(batchAuthorizeMapper, never()).updateById(any());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void authorizeRebind_authingExisting_unbindsAndReapplies() throws AlipayApiException {
|
|
|
|
|
+ // 最新 AUTHING 记录 → 置 UNBIND(旧链接作废)→ 换新 out_biz_no 重新申请
|
|
|
|
|
+ BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
+ existing.setId(1L);
|
|
|
|
|
+ existing.setEnterpriseId("E100");
|
|
|
|
|
+ existing.setParticipantId("E100");
|
|
|
|
|
+ existing.setOutBizNo("OLD1");
|
|
|
|
|
+ existing.setStatus("AUTHING");
|
|
|
|
|
+ // 序列 stub: rebind 预检命中旧记录 → 作废后 doAuthorizeApply 的二次预检(ne UNBIND)应返回 null
|
|
|
|
|
+ when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing, null);
|
|
|
|
|
+
|
|
|
|
|
+ AlipayFundAuthorizeUniApplyResponse resp = new AlipayFundAuthorizeUniApplyResponse();
|
|
|
|
|
+ resp.setAuthorizeLink("https://ur.alipay.com/abc");
|
|
|
|
|
+ when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class))).thenReturn(resp);
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, String> result = service.authorizeRebind("E100");
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals("AUTHING", result.get("status"));
|
|
|
|
|
+ verify(batchAuthorizeMapper).updateById(argThat(e -> "UNBIND".equals(e.getStatus()) && "OLD1".equals(e.getOutBizNo())));
|
|
|
|
|
+ ArgumentCaptor<BatchAuthorizeEntity> ent = ArgumentCaptor.forClass(BatchAuthorizeEntity.class);
|
|
|
|
|
+ verify(batchAuthorizeMapper).insert(ent.capture());
|
|
|
|
|
+ assertFalse(ent.getValue().getOutBizNo().equals("OLD1"), "应换新 out_biz_no 重新申请");
|
|
|
|
|
+ assertEquals("E100", ent.getValue().getParticipantId());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void authorizeRebind_authedExisting_throws() throws AlipayApiException {
|
|
|
|
|
+ // AUTHED 是终态(永久生效授权),重新生成无意义 → 拒绝
|
|
|
|
|
+ BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
+ existing.setId(1L);
|
|
|
|
|
+ existing.setEnterpriseId("E100");
|
|
|
|
|
+ existing.setParticipantId("E100");
|
|
|
|
|
+ existing.setOutBizNo("OLD1");
|
|
|
|
|
+ existing.setStatus("AUTHED");
|
|
|
|
|
+ when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
+
|
|
|
|
|
+ BusinessException ex = assertThrows(BusinessException.class, () -> service.authorizeRebind("E100"));
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(400, ex.getCode());
|
|
|
|
|
+ assertTrue(ex.getMessage().contains("生效授权"), ex.getMessage());
|
|
|
|
|
+ verify(alipayClient, never()).certificateExecute(any());
|
|
|
|
|
+ verify(batchAuthorizeMapper, never()).updateById(any());
|
|
|
|
|
+ verify(batchAuthorizeMapper, never()).insert(any());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void authorizeRebind_blankEnterpriseId_throws() {
|
|
|
|
|
+ assertThrows(BusinessException.class, () -> service.authorizeRebind(""));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void batchCreate_blankPayerUid_defaultsToEnterpriseId() throws AlipayApiException {
|
|
|
|
|
+ // Ruling 21: payer_uid 为空时默认企业 enterprise_id(付款方即企业自己)
|
|
|
|
|
+ AlipayFundBatchCreateResponse resp = new AlipayFundBatchCreateResponse();
|
|
|
|
|
+ resp.setOutBatchNo("B1");
|
|
|
|
|
+ when(alipayClient.certificateExecute(any(AlipayFundBatchCreateRequest.class))).thenReturn(resp);
|
|
|
|
|
+
|
|
|
|
|
+ BatchCreateDTO dto = new BatchCreateDTO();
|
|
|
|
|
+ dto.setEnterpriseId("E100");
|
|
|
|
|
+ dto.setOutBatchNo("B1");
|
|
|
|
|
+ dto.setOrderTitle("t");
|
|
|
|
|
+ dto.setPayerUid(" ");
|
|
|
|
|
+ BatchCreateDTO.BatchDetailDTO detail = new BatchCreateDTO.BatchDetailDTO();
|
|
|
|
|
+ detail.setOutBizNo("D1");
|
|
|
|
|
+ detail.setAmount(new BigDecimal("10"));
|
|
|
|
|
+ detail.setPayeeIdentity("a@b.com");
|
|
|
|
|
+ detail.setPayeeIdentityType("ALIPAY_LOGON_ID");
|
|
|
|
|
+ detail.setPayeeName("张三");
|
|
|
|
|
+ dto.setDetails(List.of(detail));
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> result = service.batchCreate(dto);
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals("B1", result.get("out_batch_no"));
|
|
|
|
|
+ ArgumentCaptor<AlipayFundBatchCreateRequest> cap = ArgumentCaptor.forClass(AlipayFundBatchCreateRequest.class);
|
|
|
|
|
+ verify(alipayClient).certificateExecute(cap.capture());
|
|
|
|
|
+ AlipayFundBatchCreateModel m = (AlipayFundBatchCreateModel) cap.getValue().getBizModel();
|
|
|
|
|
+ assertEquals("E100", m.getPayerInfo().getIdentity());
|
|
|
|
|
+ // DB 回写 payer_uid 同样默认企业 ID
|
|
|
|
|
+ ArgumentCaptor<BatchOrderEntity> order = ArgumentCaptor.forClass(BatchOrderEntity.class);
|
|
|
|
|
+ verify(batchOrderMapper).insert(order.capture());
|
|
|
|
|
+ assertEquals("E100", order.getValue().getPayerUid());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// ==================== M3: batchClose INIT 守卫 ====================
|
|
// ==================== M3: batchClose INIT 守卫 ====================
|
|
|
|
|
|
|
|
@Test
|
|
@Test
|