接入汇付结算账户异常待办

This commit is contained in:
jsowell
2026-07-22 16:26:15 +08:00
parent b8342ebe5e
commit b86d60df8b
5 changed files with 107 additions and 24 deletions

View File

@@ -40,7 +40,7 @@ class AdapayAccountTodoServiceImplTest {
verify(dependencies.todoTaskService).createTask(captor.capture()); verify(dependencies.todoTaskService).createTask(captor.capture());
TodoTaskCreateCommand command = captor.getValue(); TodoTaskCreateCommand command = captor.getValue();
assertEquals(AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED, command.getTaskType()); 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("100", command.getBusinessId());
assertEquals("accountUserInfo", command.getRouteName()); assertEquals("accountUserInfo", command.getRouteName());
assertEquals(8L, command.getAssigneeUserId()); assertEquals(8L, command.getAssigneeUserId());
@@ -56,7 +56,32 @@ class AdapayAccountTodoServiceImplTest {
verify(dependencies.accountService).updateAdapayMemberAccount(account); verify(dependencies.accountService).updateAdapayMemberAccount(account);
verify(dependencies.todoTaskService).completeByBusinessAsSystem( 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<TodoTaskCreateCommand> 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() { private static AdapayMemberAccount account() {

View File

@@ -74,6 +74,9 @@ public class AdapayService {
@Autowired @Autowired
private AdapayMemberAccountService adapayMemberAccountService; private AdapayMemberAccountService adapayMemberAccountService;
@Autowired
private AdapayAccountTodoService adapayAccountTodoService;
@Autowired @Autowired
private ClearingWithdrawInfoService clearingWithdrawInfoService; private ClearingWithdrawInfoService clearingWithdrawInfoService;
@@ -340,6 +343,7 @@ public class AdapayService {
updateRecord.setMerchantId(dto.getMerchantId()); updateRecord.setMerchantId(dto.getMerchantId());
updateRecord.setSettleAccountId((String) settleCount.get("id")); updateRecord.setSettleAccountId((String) settleCount.get("id"));
adapayMemberAccountService.updateAdapayMemberAccountByMemberId(updateRecord); adapayMemberAccountService.updateAdapayMemberAccountByMemberId(updateRecord);
adapayAccountTodoService.completeSettleAccountConsistencyTodos(dto.getMerchantId());
} }
/** /**
@@ -1853,7 +1857,9 @@ public class AdapayService {
int cleared = adapayMemberAccountService.clearCurrentSettleAccount( int cleared = adapayMemberAccountService.clearCurrentSettleAccount(
adapayMemberAccount.getId(), dto.getMerchantId(), adapayMemberId, settleAccountId); adapayMemberAccount.getId(), dto.getMerchantId(), adapayMemberId, settleAccountId);
if (cleared != 1) { if (cleared != 1) {
throw new BusinessException("", "汇付结算账户已删除,但本地账户状态更新失败,请联系管理员处理"); String reason = "汇付结算账户已删除,但本地账户状态更新失败,请联系管理员处理";
adapayAccountTodoService.createSettleAccountConsistencyTodo(dto.getMerchantId(), reason);
throw new BusinessException("", reason);
} }
} }

View File

@@ -5,7 +5,9 @@ package com.jsowell.pile.constant;
*/ */
public final class AdapayAccountTodoConstants { public final class AdapayAccountTodoConstants {
public static final String TASK_TYPE_CORP_MEMBER_FAILED = "ADAPAY_CORP_MEMBER_FAILED"; 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"; public static final String ROUTE_NAME = "accountUserInfo";
private AdapayAccountTodoConstants() { private AdapayAccountTodoConstants() {

View File

@@ -9,4 +9,8 @@ public interface AdapayAccountTodoService {
void handleCorpMemberFailed(AdapayMemberAccount account); void handleCorpMemberFailed(AdapayMemberAccount account);
void handleCorpMemberSucceeded(AdapayMemberAccount account); void handleCorpMemberSucceeded(AdapayMemberAccount account);
void createSettleAccountConsistencyTodo(String merchantId, String reason);
void completeSettleAccountConsistencyTodos(String merchantId);
} }

View File

@@ -58,29 +58,58 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService {
validateAccount(account); validateAccount(account);
adapayMemberAccountService.updateAdapayMemberAccount(account); adapayMemberAccountService.updateAdapayMemberAccount(account);
if (StringUtils.isNotBlank(account.getMerchantId())) { if (StringUtils.isNotBlank(account.getMerchantId())) {
todoTaskService.completeByBusinessAsSystem(AdapayAccountTodoConstants.BUSINESS_TYPE, todoTaskService.completeByBusinessAsSystem(AdapayAccountTodoConstants.BUSINESS_TYPE_CORP_MEMBER,
account.getMerchantId(), null, CALLBACK_OPERATOR); 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) { private void createCorpMemberFailedTodos(AdapayMemberAccount account) {
if (StringUtils.isBlank(account.getMerchantId())) { if (StringUtils.isBlank(account.getMerchantId())) {
log.warn("汇付企业开户失败记录缺少运营商无法创建待办accountId={}, adapayMemberId={}", log.warn("汇付企业开户失败记录缺少运营商无法创建待办accountId={}, adapayMemberId={}",
account.getId(), account.getAdapayMemberId()); account.getId(), account.getAdapayMemberId());
return; 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; PileMerchantInfo merchantInfo;
try { try {
merchantInfo = pileMerchantInfoService.selectPileMerchantInfoById( merchantInfo = pileMerchantInfoService.selectPileMerchantInfoById(
Long.parseLong(account.getMerchantId())); Long.parseLong(merchantId));
} catch (NumberFormatException exception) { } catch (NumberFormatException exception) {
log.warn("汇付企业开户失败记录运营商 ID 非法无法创建待办merchantId={}", log.warn("汇付账户异常记录运营商 ID 非法无法创建待办merchantId={}, taskType={}",
account.getMerchantId()); merchantId, taskType);
return; return;
} }
if (merchantInfo == null || StringUtils.isBlank(merchantInfo.getDeptId())) { if (merchantInfo == null || StringUtils.isBlank(merchantInfo.getDeptId())) {
log.warn("汇付企业开户失败记录未找到运营商部门无法创建待办merchantId={}", log.warn("汇付账户异常记录未找到运营商部门无法创建待办merchantId={}, taskType={}",
account.getMerchantId()); merchantId, taskType);
return; return;
} }
@@ -88,34 +117,32 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService {
try { try {
deptId = Long.parseLong(merchantInfo.getDeptId()); deptId = Long.parseLong(merchantInfo.getDeptId());
} catch (NumberFormatException exception) { } catch (NumberFormatException exception) {
log.warn("汇付企业开户失败记录运营商部门 ID 非法无法创建待办merchantId={}, deptId={}", log.warn("汇付账户异常记录运营商部门 ID 非法无法创建待办merchantId={}, deptId={}, taskType={}",
account.getMerchantId(), merchantInfo.getDeptId()); merchantId, merchantInfo.getDeptId(), taskType);
return; return;
} }
List<Long> assigneeUserIds = todoTaskAssigneeService.findActiveOperatorAdminUserIdsByDeptTree(deptId); List<Long> assigneeUserIds = todoTaskAssigneeService.findActiveOperatorAdminUserIdsByDeptTree(deptId);
if (CollectionUtils.isEmpty(assigneeUserIds)) { if (CollectionUtils.isEmpty(assigneeUserIds)) {
log.warn("汇付企业开户失败记录运营商部门下没有正常管理员无法创建待办merchantId={}, deptId={}", log.warn("汇付账户异常记录运营商部门下没有正常管理员无法创建待办merchantId={}, deptId={}, taskType={}",
account.getMerchantId(), deptId); merchantId, deptId, taskType);
return; return;
} }
String summary = buildSummary(account.getAuditDesc()); String routeParams = buildRouteParams(merchantId);
String routeParams = buildRouteParams(account.getMerchantId());
for (Long assigneeUserId : assigneeUserIds) { for (Long assigneeUserId : assigneeUserIds) {
String idempotentKey = AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED + ":" String idempotentKey = taskType + ":" + businessType + ":" + merchantId + ":"
+ AdapayAccountTodoConstants.BUSINESS_TYPE + ":" + account.getMerchantId() + ":"
+ assigneeUserId; + assigneeUserId;
todoTaskService.createTask(TodoTaskCreateCommand.builder() todoTaskService.createTask(TodoTaskCreateCommand.builder()
.taskType(AdapayAccountTodoConstants.TASK_TYPE_CORP_MEMBER_FAILED) .taskType(taskType)
.title("汇付企业开户失败") .title(title)
.summary(summary) .summary(summary)
.content(truncate(account.getAuditDesc(), 20000)) .content(content)
.businessType(AdapayAccountTodoConstants.BUSINESS_TYPE) .businessType(businessType)
.businessId(account.getMerchantId()) .businessId(merchantId)
.routeName(AdapayAccountTodoConstants.ROUTE_NAME) .routeName(AdapayAccountTodoConstants.ROUTE_NAME)
.routeParams(routeParams) .routeParams(routeParams)
.assigneeUserId(assigneeUserId) .assigneeUserId(assigneeUserId)
.assigneeMerchantId(account.getMerchantId()) .assigneeMerchantId(merchantId)
.priority(TodoTaskConstants.PRIORITY_IMPORTANT) .priority(TodoTaskConstants.PRIORITY_IMPORTANT)
.idempotentKey(idempotentKey) .idempotentKey(idempotentKey)
.createBy(CALLBACK_OPERATOR) .createBy(CALLBACK_OPERATOR)
@@ -131,6 +158,14 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService {
return summary.length() <= 500 ? summary : summary.substring(0, 500); 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) { private String truncate(String value, int maxLength) {
if (value == null || value.length() <= maxLength) { if (value == null || value.length() <= maxLength) {
return value; return value;
@@ -151,4 +186,15 @@ public class AdapayAccountTodoServiceImpl implements AdapayAccountTodoService {
throw new ServiceException("汇付账户记录不能为空"); 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;
}
} }