|
@@ -3,18 +3,12 @@ package com.payment.platform.module.payment.batch.service;
|
|
|
import com.alipay.api.AlipayClient;
|
|
import com.alipay.api.AlipayClient;
|
|
|
import com.alipay.api.AlipayApiException;
|
|
import com.alipay.api.AlipayApiException;
|
|
|
import com.alipay.api.domain.AccDetailModel;
|
|
import com.alipay.api.domain.AccDetailModel;
|
|
|
-import com.alipay.api.domain.AlipayFundAuthorizeUniApplyModel;
|
|
|
|
|
-import com.alipay.api.domain.AlipayFundAuthorizeUniQueryModel;
|
|
|
|
|
import com.alipay.api.domain.AlipayFundBatchCreateModel;
|
|
import com.alipay.api.domain.AlipayFundBatchCreateModel;
|
|
|
import com.alipay.api.domain.AlipayFundTransRenderPayModel;
|
|
import com.alipay.api.domain.AlipayFundTransRenderPayModel;
|
|
|
-import com.alipay.api.request.AlipayFundAuthorizeUniApplyRequest;
|
|
|
|
|
-import com.alipay.api.request.AlipayFundAuthorizeUniQueryRequest;
|
|
|
|
|
import com.alipay.api.request.AlipayFundBatchCloseRequest;
|
|
import com.alipay.api.request.AlipayFundBatchCloseRequest;
|
|
|
import com.alipay.api.request.AlipayFundBatchCreateRequest;
|
|
import com.alipay.api.request.AlipayFundBatchCreateRequest;
|
|
|
import com.alipay.api.request.AlipayFundBatchDetailQueryRequest;
|
|
import com.alipay.api.request.AlipayFundBatchDetailQueryRequest;
|
|
|
import com.alipay.api.request.AlipayFundTransRenderPayRequest;
|
|
import com.alipay.api.request.AlipayFundTransRenderPayRequest;
|
|
|
-import com.alipay.api.response.AlipayFundAuthorizeUniApplyResponse;
|
|
|
|
|
-import com.alipay.api.response.AlipayFundAuthorizeUniQueryResponse;
|
|
|
|
|
import com.alipay.api.response.AlipayFundBatchCloseResponse;
|
|
import com.alipay.api.response.AlipayFundBatchCloseResponse;
|
|
|
import com.alipay.api.response.AlipayFundBatchCreateResponse;
|
|
import com.alipay.api.response.AlipayFundBatchCreateResponse;
|
|
|
import com.alipay.api.response.AlipayFundBatchDetailQueryResponse;
|
|
import com.alipay.api.response.AlipayFundBatchDetailQueryResponse;
|
|
@@ -85,96 +79,6 @@ class AlipayBatchPayServiceTest {
|
|
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(configuration, ""), BatchAuthorizeEntity.class);
|
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(configuration, ""), BatchAuthorizeEntity.class);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_returnsShortLinkAndPersists() throws AlipayApiException {
|
|
|
|
|
- AlipayFundAuthorizeUniApplyResponse resp = new AlipayFundAuthorizeUniApplyResponse();
|
|
|
|
|
- resp.setAuthorizeLink("https://ur.alipay.com/abc");
|
|
|
|
|
- resp.setOutBizNo("A1");
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class))).thenReturn(resp);
|
|
|
|
|
-
|
|
|
|
|
- Map<String, String> result = service.authorizeApply("E100");
|
|
|
|
|
-
|
|
|
|
|
- assertEquals("https://ur.alipay.com/abc", result.get("authorize_link"));
|
|
|
|
|
- assertEquals("AUTHING", result.get("status"));
|
|
|
|
|
-
|
|
|
|
|
- ArgumentCaptor<AlipayFundAuthorizeUniApplyRequest> cap = ArgumentCaptor.forClass(AlipayFundAuthorizeUniApplyRequest.class);
|
|
|
|
|
- verify(alipayClient).certificateExecute(cap.capture());
|
|
|
|
|
- AlipayFundAuthorizeUniApplyModel m = (AlipayFundAuthorizeUniApplyModel) cap.getValue().getBizModel();
|
|
|
|
|
- assertEquals("TRANSFER_API_STANDARD_AUTHORIZATION", m.getProductCode());
|
|
|
|
|
- assertEquals("STANDARD_CREATE_FUND_ORDER", m.getBizScene());
|
|
|
|
|
- assertEquals("SHORT_URL", m.getAuthorizeLinkType());
|
|
|
|
|
- assertEquals("pc", m.getChannel());
|
|
|
|
|
- // Ruling 19/22: 付款方恒为企业自身 UID(enterprise_id),不接受客户端指定
|
|
|
|
|
- assertEquals("E100", m.getPrincipalInfo().getParticipantId());
|
|
|
|
|
-
|
|
|
|
|
- ArgumentCaptor<BatchAuthorizeEntity> ent = ArgumentCaptor.forClass(BatchAuthorizeEntity.class);
|
|
|
|
|
- verify(batchAuthorizeMapper).insert(ent.capture());
|
|
|
|
|
- assertEquals("E100", ent.getValue().getEnterpriseId());
|
|
|
|
|
- assertEquals("AUTHING", ent.getValue().getStatus());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_failure_throwsBusinessException() throws AlipayApiException {
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class)))
|
|
|
|
|
- .thenThrow(new AlipayApiException("network error"));
|
|
|
|
|
-
|
|
|
|
|
- assertThrows(BusinessException.class, () -> service.authorizeApply("E100"));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void queryAuthorize_returnsAgreementNo() throws AlipayApiException {
|
|
|
|
|
- AlipayFundAuthorizeUniQueryResponse resp = new AlipayFundAuthorizeUniQueryResponse();
|
|
|
|
|
- resp.setAgreementNo("AGMT001");
|
|
|
|
|
- resp.setStatus("AUTHED");
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniQueryRequest.class))).thenReturn(resp);
|
|
|
|
|
-
|
|
|
|
|
- Map<String, String> result = service.queryAuthorize("E100", "A1");
|
|
|
|
|
-
|
|
|
|
|
- assertEquals("AGMT001", result.get("agreement_no"));
|
|
|
|
|
- assertEquals("AUTHED", result.get("status"));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_existingAuthorization_throwsBusinessException() throws AlipayApiException {
|
|
|
|
|
- BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
- existing.setEnterpriseId("E100");
|
|
|
|
|
- existing.setParticipantId("2088123412341234");
|
|
|
|
|
- existing.setStatus("AUTHED");
|
|
|
|
|
- when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
-
|
|
|
|
|
- assertThrows(BusinessException.class, () -> service.authorizeApply("E100"));
|
|
|
|
|
-
|
|
|
|
|
- verify(alipayClient, never()).certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class));
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).insert(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_nullAuthorizeLink_returnsEmptyString() throws AlipayApiException {
|
|
|
|
|
- AlipayFundAuthorizeUniApplyResponse resp = new AlipayFundAuthorizeUniApplyResponse();
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class))).thenReturn(resp);
|
|
|
|
|
-
|
|
|
|
|
- Map<String, String> result = service.authorizeApply("E100");
|
|
|
|
|
-
|
|
|
|
|
- assertEquals("", result.get("authorize_link"));
|
|
|
|
|
- assertEquals("AUTHING", result.get("status"));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void queryAuthorize_unbind_doesNotOverwriteLocalStatus() throws AlipayApiException {
|
|
|
|
|
- AlipayFundAuthorizeUniQueryResponse resp = new AlipayFundAuthorizeUniQueryResponse();
|
|
|
|
|
- resp.setAgreementNo("AGMT001");
|
|
|
|
|
- resp.setStatus("UNBIND");
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniQueryRequest.class))).thenReturn(resp);
|
|
|
|
|
-
|
|
|
|
|
- Map<String, String> result = service.queryAuthorize("E100", "A1");
|
|
|
|
|
-
|
|
|
|
|
- assertEquals("AGMT001", result.get("agreement_no"));
|
|
|
|
|
- assertEquals("UNBIND", result.get("status"));
|
|
|
|
|
- // UNBIND 下协议号非空也不得回写本地状态
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).selectOne(any());
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).updateById(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Test
|
|
@Test
|
|
|
void batchCreate_persistsOrderAndDetails() throws AlipayApiException {
|
|
void batchCreate_persistsOrderAndDetails() throws AlipayApiException {
|
|
|
AlipayFundBatchCreateResponse resp = new AlipayFundBatchCreateResponse();
|
|
AlipayFundBatchCreateResponse resp = new AlipayFundBatchCreateResponse();
|
|
@@ -450,22 +354,6 @@ class AlipayBatchPayServiceTest {
|
|
|
assertEquals(400, ex.getCode());
|
|
assertEquals(400, ex.getCode());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Test
|
|
|
|
|
- void queryAuthorize_notExist_returnsAUTHINGInsteadOfError() throws AlipayApiException {
|
|
|
|
|
- // Task 8 全链路验证: 支付宝 40004 AUTHORIZATION_NOT_EXIST(未授权)是正常业务状态而非查询失败
|
|
|
|
|
- AlipayFundAuthorizeUniQueryResponse resp = new AlipayFundAuthorizeUniQueryResponse();
|
|
|
|
|
- resp.setCode("40004");
|
|
|
|
|
- resp.setSubCode("AUTHORIZATION_NOT_EXIST");
|
|
|
|
|
- resp.setMsg("Business Failed");
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniQueryRequest.class))).thenReturn(resp);
|
|
|
|
|
-
|
|
|
|
|
- Map<String, String> result = service.queryAuthorize("E100", "A1");
|
|
|
|
|
-
|
|
|
|
|
- assertEquals("", result.get("agreement_no"));
|
|
|
|
|
- assertEquals("AUTHING", result.get("status"));
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).updateById(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Test
|
|
@Test
|
|
|
void batchCreate_authInfoNotExists_friendlyMessage() throws AlipayApiException {
|
|
void batchCreate_authInfoNotExists_friendlyMessage() throws AlipayApiException {
|
|
|
// Task 8 全链路验证: AUTH_INFO_NOT_EXISTS(付款方未授权)应提示明确动作而非透传支付宝原文案
|
|
// Task 8 全链路验证: AUTH_INFO_NOT_EXISTS(付款方未授权)应提示明确动作而非透传支付宝原文案
|
|
@@ -700,261 +588,6 @@ class AlipayBatchPayServiceTest {
|
|
|
verify(batchOrderMapper).updateById(order);
|
|
verify(batchOrderMapper).updateById(order);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // ==================== M1: 授权并发 DB 兜底 ====================
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_insertDuplicateKey_throwsFriendlyMessage() throws AlipayApiException {
|
|
|
|
|
- AlipayFundAuthorizeUniApplyResponse resp = new AlipayFundAuthorizeUniApplyResponse();
|
|
|
|
|
- resp.setAuthorizeLink("https://ur.alipay.com/abc");
|
|
|
|
|
- when(alipayClient.certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class))).thenReturn(resp);
|
|
|
|
|
- // 并发双击: 预检通过后 insert 命中 uk_batch_authorize_active 唯一索引
|
|
|
|
|
- doThrow(new DuplicateKeyException("duplicate key")).when(batchAuthorizeMapper).insert(any());
|
|
|
|
|
-
|
|
|
|
|
- BusinessException ex = assertThrows(BusinessException.class,
|
|
|
|
|
- () -> service.authorizeApply("E100"));
|
|
|
|
|
-
|
|
|
|
|
- assertEquals(400, ex.getCode());
|
|
|
|
|
- assertTrue(ex.getMessage().contains("请勿重复操作"), ex.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // ==================== M2: AUTHING 过期重申请 ====================
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_authingNotExpired_throws() {
|
|
|
|
|
- BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
- existing.setEnterpriseId("E100");
|
|
|
|
|
- existing.setParticipantId("2088123412341234");
|
|
|
|
|
- existing.setStatus("AUTHING");
|
|
|
|
|
- existing.setAuthorizeExpireTime(OffsetDateTime.now().plusHours(1));
|
|
|
|
|
- when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
-
|
|
|
|
|
- BusinessException ex = assertThrows(BusinessException.class,
|
|
|
|
|
- () -> service.authorizeApply("E100"));
|
|
|
|
|
-
|
|
|
|
|
- assertEquals(400, ex.getCode());
|
|
|
|
|
- assertTrue(ex.getMessage().contains("未完成"), ex.getMessage());
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).updateById(any());
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).insert(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_authingFreshCreatedTime_throws() {
|
|
|
|
|
- // authorize_expire_time 为空时按 created_time + 24h 判定: 刚创建的 AUTHING 未过期 → 拒绝
|
|
|
|
|
- BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
- existing.setEnterpriseId("E100");
|
|
|
|
|
- existing.setParticipantId("2088123412341234");
|
|
|
|
|
- existing.setStatus("AUTHING");
|
|
|
|
|
- existing.setCreatedTime(OffsetDateTime.now());
|
|
|
|
|
- when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
-
|
|
|
|
|
- assertThrows(BusinessException.class, () -> service.authorizeApply("E100"));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_authingExpired_rebindWithNewOutBizNo() throws AlipayApiException {
|
|
|
|
|
- BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
- existing.setId(1L);
|
|
|
|
|
- existing.setEnterpriseId("E100");
|
|
|
|
|
- existing.setParticipantId("2088123412341234");
|
|
|
|
|
- existing.setOutBizNo("OLD1");
|
|
|
|
|
- existing.setStatus("AUTHING");
|
|
|
|
|
- existing.setAuthorizeExpireTime(OffsetDateTime.now().minusHours(1));
|
|
|
|
|
- when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
-
|
|
|
|
|
- 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"));
|
|
|
|
|
- // 旧记录作废置 UNBIND(与 uk_batch_authorize_active 的 WHERE status <> 'UNBIND' 协同)
|
|
|
|
|
- verify(batchAuthorizeMapper).updateById(argThat(e -> "UNBIND".equals(e.getStatus())));
|
|
|
|
|
- // 新记录插入 + 新 out_biz_no
|
|
|
|
|
- ArgumentCaptor<BatchAuthorizeEntity> ent = ArgumentCaptor.forClass(BatchAuthorizeEntity.class);
|
|
|
|
|
- verify(batchAuthorizeMapper).insert(ent.capture());
|
|
|
|
|
- assertEquals("AUTHING", ent.getValue().getStatus());
|
|
|
|
|
- assertFalse(ent.getValue().getOutBizNo().equals("OLD1"), "应换新 out_biz_no 重新申请");
|
|
|
|
|
- assertEquals("E100", ent.getValue().getEnterpriseId());
|
|
|
|
|
- // 支付宝侧使用新 out_biz_no
|
|
|
|
|
- ArgumentCaptor<AlipayFundAuthorizeUniApplyRequest> cap = ArgumentCaptor.forClass(AlipayFundAuthorizeUniApplyRequest.class);
|
|
|
|
|
- verify(alipayClient).certificateExecute(cap.capture());
|
|
|
|
|
- AlipayFundAuthorizeUniApplyModel m = (AlipayFundAuthorizeUniApplyModel) cap.getValue().getBizModel();
|
|
|
|
|
- assertEquals(ent.getValue().getOutBizNo(), m.getOutBizNo());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_authingExpiredByCreatedTimeFallback_allowsReapply() throws AlipayApiException {
|
|
|
|
|
- // expire 为空 + created_time 超过 24h → 视为过期,允许重新申请
|
|
|
|
|
- BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
- existing.setId(1L);
|
|
|
|
|
- existing.setEnterpriseId("E100");
|
|
|
|
|
- existing.setParticipantId("2088123412341234");
|
|
|
|
|
- existing.setOutBizNo("OLD1");
|
|
|
|
|
- existing.setStatus("AUTHING");
|
|
|
|
|
- existing.setCreatedTime(OffsetDateTime.now().minusDays(2));
|
|
|
|
|
- when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
-
|
|
|
|
|
- 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");
|
|
|
|
|
-
|
|
|
|
|
- assertNotNull(result.get("authorize_link"));
|
|
|
|
|
- verify(batchAuthorizeMapper).updateById(argThat(e -> "UNBIND".equals(e.getStatus())));
|
|
|
|
|
- verify(batchAuthorizeMapper).insert(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // ==================== 用户反馈轮 2: 付款方 UID 自动带出 + 授权可重新生成 ====================
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_alwaysUsesEnterpriseAsPayer() throws AlipayApiException {
|
|
|
|
|
- // Ruling 19/22: 付款方恒为企业自身 UID(enterprise_id),方法不接受客户端传入的 participant_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_usesEnterpriseIdentityWhenPresent() throws AlipayApiException {
|
|
|
|
|
- // Ruling 23: 企业入驻身份 identity 优先(配套 identityType),与 AlipayTransferService.createOnboard 惯例一致
|
|
|
|
|
- EnterpriseEntity ent = new EnterpriseEntity();
|
|
|
|
|
- ent.setEnterpriseId("E100");
|
|
|
|
|
- ent.setIdentity("2088IDENTITY");
|
|
|
|
|
- ent.setIdentityType("ALIPAY_OPEN_ID");
|
|
|
|
|
- when(enterpriseMapper.selectByEnterpriseIdIgnoreTenant("E100")).thenReturn(ent);
|
|
|
|
|
-
|
|
|
|
|
- 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("2088IDENTITY", m.getPrincipalInfo().getParticipantId());
|
|
|
|
|
- assertEquals("ALIPAY_OPEN_ID", m.getPrincipalInfo().getParticipantIdType());
|
|
|
|
|
- ArgumentCaptor<BatchAuthorizeEntity> entCap = ArgumentCaptor.forClass(BatchAuthorizeEntity.class);
|
|
|
|
|
- verify(batchAuthorizeMapper).insert(entCap.capture());
|
|
|
|
|
- assertEquals("2088IDENTITY", entCap.getValue().getParticipantId());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_normalExisting_throws() throws AlipayApiException {
|
|
|
|
|
- // NORMAL 为通知归一前落库的支付宝生效状态 — 视同 AUTHED,拒绝重复授权
|
|
|
|
|
- BatchAuthorizeEntity existing = new BatchAuthorizeEntity();
|
|
|
|
|
- existing.setEnterpriseId("E100");
|
|
|
|
|
- existing.setParticipantId("2088123412341234");
|
|
|
|
|
- existing.setStatus("NORMAL");
|
|
|
|
|
- when(batchAuthorizeMapper.selectOne(any())).thenReturn(existing);
|
|
|
|
|
-
|
|
|
|
|
- BusinessException ex = assertThrows(BusinessException.class, () -> service.authorizeApply("E100"));
|
|
|
|
|
-
|
|
|
|
|
- assertEquals(400, ex.getCode());
|
|
|
|
|
- verify(alipayClient, never()).certificateExecute(any(AlipayFundAuthorizeUniApplyRequest.class));
|
|
|
|
|
- verify(batchAuthorizeMapper, never()).insert(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_enterpriseNotFound_throws() throws AlipayApiException {
|
|
|
|
|
- // requireEnterprise 防御: 企业不存在直接拒绝,不发起授权
|
|
|
|
|
- when(enterpriseMapper.selectByEnterpriseIdIgnoreTenant("E100")).thenReturn(null);
|
|
|
|
|
-
|
|
|
|
|
- BusinessException ex = assertThrows(BusinessException.class, () -> service.authorizeApply("E100"));
|
|
|
|
|
-
|
|
|
|
|
- assertEquals(400, ex.getCode());
|
|
|
|
|
- assertTrue(ex.getMessage().contains("企业不存在"), ex.getMessage());
|
|
|
|
|
- verify(alipayClient, never()).certificateExecute(any());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Test
|
|
|
|
|
- void authorizeApply_nullEnterpriseId_throws() {
|
|
|
|
|
- // requireEnterpriseId 防御: 企业都不存在时直接拒绝而非默认空串申请
|
|
|
|
|
- assertThrows(BusinessException.class, () -> service.authorizeApply(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
|
|
@Test
|
|
|
void batchCreate_alwaysUsesEnterpriseAsPayer() throws AlipayApiException {
|
|
void batchCreate_alwaysUsesEnterpriseAsPayer() throws AlipayApiException {
|
|
|
// Ruling 19/22: 付款方恒为企业自身 UID(enterprise_id),DTO 已移除 payer_uid 不接受客户端指定
|
|
// Ruling 19/22: 付款方恒为企业自身 UID(enterprise_id),DTO 已移除 payer_uid 不接受客户端指定
|