From b86d60df8b6b61b69f8339b613bb125155a8eb44 Mon Sep 17 00:00:00 2001 From: jsowell <123@jsowell.com> Date: Wed, 22 Jul 2026 16:26:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5=E6=B1=87=E4=BB=98=E7=BB=93?= =?UTF-8?q?=E7=AE=97=E8=B4=A6=E6=88=B7=E5=BC=82=E5=B8=B8=E5=BE=85=E5=8A=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdapayAccountTodoServiceImplTest.java | 29 ++++++- .../jsowell/adapay/service/AdapayService.java | 8 +- .../constant/AdapayAccountTodoConstants.java | 4 +- .../service/AdapayAccountTodoService.java | 4 + .../impl/AdapayAccountTodoServiceImpl.java | 86 ++++++++++++++----- 5 files changed, 107 insertions(+), 24 deletions(-) diff --git a/jsowell-admin/src/test/java/com/jsowell/pile/service/AdapayAccountTodoServiceImplTest.java b/jsowell-admin/src/test/java/com/jsowell/pile/service/AdapayAccountTodoServiceImplTest.java index bcc67165d..8c9997bd0 100644 --- a/jsowell-admin/src/test/java/com/jsowell/pile/service/AdapayAccountTodoServiceImplTest.java +++ b/jsowell-admin/src/test/java/com/jsowell/pile/service/AdapayAccountTodoServiceImplTest.java @@ -40,7 +40,7 @@ class AdapayAccountTodoServiceImplTest { verify(dependencies.todoTaskService).createTask(captor.capture()); TodoTaskCreateCommand command = captor.getValue(); assertEquals(AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED, command.getTaskType()); - assertEquals(AdapayAccountTodoConstants.BUSINESS_TYPE, command.getBusinessType()); + assertEquals(AdapayAccountTodoConstants.BUSINESS_TYPE_CORP_MEMBER, command.getBusinessType()); assertEquals("100", command.getBusinessId()); assertEquals("accountUserInfo", command.getRouteName()); assertEquals(8L, command.getAssigneeUserId()); @@ -56,7 +56,32 @@ class AdapayAccountTodoServiceImplTest { verify(dependencies.accountService).updateAdapayMemberAccount(account); verify(dependencies.todoTaskService).completeByBusinessAsSystem( - AdapayAccountTodoConstants.BUSINESS_TYPE, "100", null, "adapay-callback"); + AdapayAccountTodoConstants.BUSINESS_TYPE_CORP_MEMBER, "100", null, "adapay-callback"); + } + + @Test + void settleAccountInconsistency_shouldCreateAndCompleteAdminTodo() { + Dependencies dependencies = new Dependencies(); + AdapayAccountTodoServiceImpl service = dependencies.createService(); + PileMerchantInfo merchantInfo = new PileMerchantInfo(); + merchantInfo.setDeptId("200"); + when(dependencies.merchantService.selectPileMerchantInfoById(100L)).thenReturn(merchantInfo); + when(dependencies.assigneeService.findActiveOperatorAdminUserIdsByDeptTree(200L)) + .thenReturn(Collections.singletonList(8L)); + + service.createSettleAccountConsistencyTodo("100", "远端已删除但本地更新失败"); + + ArgumentCaptor captor = ArgumentCaptor.forClass(TodoTaskCreateCommand.class); + verify(dependencies.todoTaskService).createTask(captor.capture()); + assertEquals(AdapayAccountTodoConstants.TASK_TYPE_SETTLE_ACCOUNT_EXCEPTION, + captor.getValue().getTaskType()); + assertEquals(AdapayAccountTodoConstants.BUSINESS_TYPE_SETTLE_ACCOUNT, + captor.getValue().getBusinessType()); + + service.completeSettleAccountConsistencyTodos("100"); + verify(dependencies.todoTaskService).completeByBusinessAsSystem( + AdapayAccountTodoConstants.BUSINESS_TYPE_SETTLE_ACCOUNT, + "100", null, "adapay-callback"); } private static AdapayMemberAccount account() { diff --git a/jsowell-pile/src/main/java/com/jsowell/adapay/service/AdapayService.java b/jsowell-pile/src/main/java/com/jsowell/adapay/service/AdapayService.java index 5290c483b..b43d67cca 100644 --- a/jsowell-pile/src/main/java/com/jsowell/adapay/service/AdapayService.java +++ b/jsowell-pile/src/main/java/com/jsowell/adapay/service/AdapayService.java @@ -74,6 +74,9 @@ public class AdapayService { @Autowired private AdapayMemberAccountService adapayMemberAccountService; + @Autowired + private AdapayAccountTodoService adapayAccountTodoService; + @Autowired private ClearingWithdrawInfoService clearingWithdrawInfoService; @@ -340,6 +343,7 @@ public class AdapayService { updateRecord.setMerchantId(dto.getMerchantId()); updateRecord.setSettleAccountId((String) settleCount.get("id")); adapayMemberAccountService.updateAdapayMemberAccountByMemberId(updateRecord); + adapayAccountTodoService.completeSettleAccountConsistencyTodos(dto.getMerchantId()); } /** @@ -1853,7 +1857,9 @@ public class AdapayService { int cleared = adapayMemberAccountService.clearCurrentSettleAccount( adapayMemberAccount.getId(), dto.getMerchantId(), adapayMemberId, settleAccountId); if (cleared != 1) { - throw new BusinessException("", "汇付结算账户已删除,但本地账户状态更新失败,请联系管理员处理"); + String reason = "汇付结算账户已删除,但本地账户状态更新失败,请联系管理员处理"; + adapayAccountTodoService.createSettleAccountConsistencyTodo(dto.getMerchantId(), reason); + throw new BusinessException("", reason); } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/constant/AdapayAccountTodoConstants.java b/jsowell-pile/src/main/java/com/jsowell/pile/constant/AdapayAccountTodoConstants.java index dcf7c4eec..60989dfce 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/constant/AdapayAccountTodoConstants.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/constant/AdapayAccountTodoConstants.java @@ -5,7 +5,9 @@ package com.jsowell.pile.constant; */ public final class AdapayAccountTodoConstants { public static final String TASK_TYPE_CORP_MEMBER_FAILED = "ADAPAY_CORP_MEMBER_FAILED"; - public static final String BUSINESS_TYPE = "ADAPAY_CORP_MEMBER_ACCOUNT"; + public static final String BUSINESS_TYPE_CORP_MEMBER = "ADAPAY_CORP_MEMBER_ACCOUNT"; + public static final String TASK_TYPE_SETTLE_ACCOUNT_EXCEPTION = "ADAPAY_SETTLE_ACCOUNT_EXCEPTION"; + public static final String BUSINESS_TYPE_SETTLE_ACCOUNT = "ADAPAY_SETTLE_ACCOUNT"; public static final String ROUTE_NAME = "accountUserInfo"; private AdapayAccountTodoConstants() { diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/AdapayAccountTodoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/AdapayAccountTodoService.java index 8a4f93a43..d366db478 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/AdapayAccountTodoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/AdapayAccountTodoService.java @@ -9,4 +9,8 @@ public interface AdapayAccountTodoService { void handleCorpMemberFailed(AdapayMemberAccount account); void handleCorpMemberSucceeded(AdapayMemberAccount account); + + void createSettleAccountConsistencyTodo(String merchantId, String reason); + + void completeSettleAccountConsistencyTodos(String merchantId); } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayAccountTodoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayAccountTodoServiceImpl.java index 0643fb873..9a4a5e9e3 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayAccountTodoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/AdapayAccountTodoServiceImpl.java @@ -58,29 +58,58 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService { validateAccount(account); adapayMemberAccountService.updateAdapayMemberAccount(account); if (StringUtils.isNotBlank(account.getMerchantId())) { - todoTaskService.completeByBusinessAsSystem(AdapayAccountTodoConstants.BUSINESS_TYPE, + todoTaskService.completeByBusinessAsSystem(AdapayAccountTodoConstants.BUSINESS_TYPE_CORP_MEMBER, account.getMerchantId(), null, CALLBACK_OPERATOR); } } + @Override + @Transactional(rollbackFor = Exception.class) + public void createSettleAccountConsistencyTodo(String merchantId, String reason) { + String safeMerchantId = requireMerchantId(merchantId); + String summary = buildSettleAccountSummary(reason); + createMerchantAdminTodos(safeMerchantId, + AdapayAccountTodoConstants.TASK_TYPE_SETTLE_ACCOUNT_EXCEPTION, + AdapayAccountTodoConstants.BUSINESS_TYPE_SETTLE_ACCOUNT, + "汇付结算账户状态不一致", summary, truncate(reason, 20000)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void completeSettleAccountConsistencyTodos(String merchantId) { + String safeMerchantId = requireMerchantId(merchantId); + todoTaskService.completeByBusinessAsSystem( + AdapayAccountTodoConstants.BUSINESS_TYPE_SETTLE_ACCOUNT, + safeMerchantId, null, CALLBACK_OPERATOR); + } + private void createCorpMemberFailedTodos(AdapayMemberAccount account) { if (StringUtils.isBlank(account.getMerchantId())) { log.warn("汇付企业开户失败记录缺少运营商,无法创建待办,accountId={}, adapayMemberId={}", account.getId(), account.getAdapayMemberId()); return; } + createMerchantAdminTodos(account.getMerchantId(), + AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED, + AdapayAccountTodoConstants.BUSINESS_TYPE_CORP_MEMBER, + "汇付企业开户失败", buildSummary(account.getAuditDesc()), + truncate(account.getAuditDesc(), 20000)); + } + + private void createMerchantAdminTodos(String merchantId, String taskType, String businessType, + String title, String summary, String content) { PileMerchantInfo merchantInfo; try { merchantInfo = pileMerchantInfoService.selectPileMerchantInfoById( - Long.parseLong(account.getMerchantId())); + Long.parseLong(merchantId)); } catch (NumberFormatException exception) { - log.warn("汇付企业开户失败记录运营商 ID 非法,无法创建待办,merchantId={}", - account.getMerchantId()); + log.warn("汇付账户异常记录运营商 ID 非法,无法创建待办,merchantId={}, taskType={}", + merchantId, taskType); return; } if (merchantInfo == null || StringUtils.isBlank(merchantInfo.getDeptId())) { - log.warn("汇付企业开户失败记录未找到运营商部门,无法创建待办,merchantId={}", - account.getMerchantId()); + log.warn("汇付账户异常记录未找到运营商部门,无法创建待办,merchantId={}, taskType={}", + merchantId, taskType); return; } @@ -88,34 +117,32 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService { try { deptId = Long.parseLong(merchantInfo.getDeptId()); } catch (NumberFormatException exception) { - log.warn("汇付企业开户失败记录运营商部门 ID 非法,无法创建待办,merchantId={}, deptId={}", - account.getMerchantId(), merchantInfo.getDeptId()); + log.warn("汇付账户异常记录运营商部门 ID 非法,无法创建待办,merchantId={}, deptId={}, taskType={}", + merchantId, merchantInfo.getDeptId(), taskType); return; } List assigneeUserIds = todoTaskAssigneeService.findActiveOperatorAdminUserIdsByDeptTree(deptId); if (CollectionUtils.isEmpty(assigneeUserIds)) { - log.warn("汇付企业开户失败记录运营商部门下没有正常管理员,无法创建待办,merchantId={}, deptId={}", - account.getMerchantId(), deptId); + log.warn("汇付账户异常记录运营商部门下没有正常管理员,无法创建待办,merchantId={}, deptId={}, taskType={}", + merchantId, deptId, taskType); return; } - String summary = buildSummary(account.getAuditDesc()); - String routeParams = buildRouteParams(account.getMerchantId()); + String routeParams = buildRouteParams(merchantId); for (Long assigneeUserId : assigneeUserIds) { - String idempotentKey = AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED + ":" - + AdapayAccountTodoConstants.BUSINESS_TYPE + ":" + account.getMerchantId() + ":" + String idempotentKey = taskType + ":" + businessType + ":" + merchantId + ":" + assigneeUserId; todoTaskService.createTask(TodoTaskCreateCommand.builder() - .taskType(AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED) - .title("汇付企业开户失败") + .taskType(taskType) + .title(title) .summary(summary) - .content(truncate(account.getAuditDesc(), 20000)) - .businessType(AdapayAccountTodoConstants.BUSINESS_TYPE) - .businessId(account.getMerchantId()) + .content(content) + .businessType(businessType) + .businessId(merchantId) .routeName(AdapayAccountTodoConstants.ROUTE_NAME) .routeParams(routeParams) .assigneeUserId(assigneeUserId) - .assigneeMerchantId(account.getMerchantId()) + .assigneeMerchantId(merchantId) .priority(TodoTaskConstants.PRIORITY_IMPORTANT) .idempotentKey(idempotentKey) .createBy(CALLBACK_OPERATOR) @@ -131,6 +158,14 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService { return summary.length() <= 500 ? summary : summary.substring(0, 500); } + private String buildSettleAccountSummary(String reason) { + String summary = "汇付结算账户与本地状态不一致,需要人工核对"; + if (StringUtils.isNotBlank(reason)) { + summary += ",原因:" + reason.trim(); + } + return summary.length() <= 500 ? summary : summary.substring(0, 500); + } + private String truncate(String value, int maxLength) { if (value == null || value.length() <= maxLength) { return value; @@ -151,4 +186,15 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService { throw new ServiceException("汇付账户记录不能为空"); } } + + private String requireMerchantId(String merchantId) { + if (StringUtils.isBlank(merchantId)) { + throw new ServiceException("运营商 ID 不能为空"); + } + String safeMerchantId = merchantId.trim(); + if (safeMerchantId.length() > 64) { + throw new ServiceException("运营商 ID 不能超过64个字符"); + } + return safeMerchantId; + } }