Commit a2458c50 by 王德峰

bb 项目初始化

清理部分
parent 301a6da8
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.api.plan;
import com.abssqr.plat.biz.shared.handler.PlanAllocHandler;
import com.abssqr.plat.biz.support.ServiceSupport;
import com.abssqr.plat.common.facade.enums.AccountAttributeEnum;
import com.abssqr.plat.common.facade.enums.AccountTypeEnum;
import com.abssqr.plat.common.facade.enums.PlanAllocStatusEnum;
import com.abssqr.plat.common.facade.enums.PlanTypeEnum;
import com.abssqr.plat.common.facade.model.account.Account;
import com.abssqr.plat.common.facade.model.plan.PlanAlloc;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.facade.param.plan.alloc.PlanAllocHandleParam;
import com.abssqr.plat.common.facade.param.plan.alloc.PlanAllocPayParam;
import com.abssqr.plat.common.facade.result.plan.PlanAllocPayInfoVO;
import com.abssqr.plat.common.facade.service.plan.PlanAllocPayService;
import com.abssqr.plat.common.facade.validation.Valid;
import com.abssqr.plat.common.model.repo.plan.PlanAllocRepo;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.core.service.acct.AcctManager;
import com.general.system.common.util.VarChecker;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 分配支付或入账
*
* @author hanfei
* @version $Id: PlanAllocPayServiceImpl.java, v 0.1 2019-07-09 4:48 PM hanfei Exp $
*/
@Service
public class PlanAllocPayServiceImpl extends ServiceSupport implements PlanAllocPayService {
@Autowired
private PlanAllocRepo planAllocRepo;
@Autowired
private PlanAllocHandler planAllocHandler;
@Autowired
private PlanRepo planRepo;
@Autowired
private AcctManager acctManager;
/**
* 分配支付或人工分配入账
*
* @param param
*/
@Override
public void allocPay(@Valid PlanAllocPayParam param) {
super.doOpr(param, () -> {
// 获取对应分配计划进行支付
PlanAlloc alloc = planAllocRepo.getPlanAllocDetail(param.getAllocNo());
if (alloc.getStatus() == PlanAllocStatusEnum.ASSIGNED) {
return null;
}
PlanAllocHandleParam handleParam = new PlanAllocHandleParam();
handleParam.setAlloc(alloc);
handleParam.setOutTransNo(param.getOutTransNo());
handleParam.setOffLine(param.getOffLine());
// 判断线上线下操作
if (param.getOffLine()) {
// 线下支付 创建支付单,同时进行入账等后续操作
planAllocHandler.execute(handleParam);
} else {
// 在线支付,只创建支付单
planAllocHandler.handle(handleParam);
}
return null;
});
}
/**
* 查询分配详情
*
* @param param
* @return
*/
@Override
public PlanAllocPayInfoVO allocInfo(@Valid PlanAllocPayParam param) {
return super.doQry(param, () -> {
// 获取对应分配计划进行支付
PlanAlloc alloc = planAllocRepo.getPlanAllocDetail(param.getAllocNo());
// 获取对应计划
PlanBase plan = planRepo.getPlanByNo(alloc.getPlanNo());
//回款账户状态
AccountAttributeEnum sourceAcct = PlanTypeEnum.SPV == alloc.getPlanType() ?
AccountAttributeEnum.RECV : AccountAttributeEnum.NORMAL;
// 获取账户信息
List<Account> accounts = acctManager.getAllAcctByPlanNo(alloc.getPlanNo(),
Lists.newArrayList(AccountTypeEnum.BANK, AccountTypeEnum.PLAT_VIRTUAL));
VarChecker.checkNotEmpty(accounts, "计划[{0}]找不到对应的账户信息", alloc.getPlanNo());
// 组装模型
PlanAllocPayInfoVO infoVO = new PlanAllocPayInfoVO();
infoVO.setPlanNo(alloc.getPlanNo());
infoVO.setPlanName(plan.getPlanName());
infoVO.setPayAmt(alloc.getTotalConfirmAllocAmt());
for (Account account : accounts) {
// 源账户 为 银行一般业务户
if (account.getActAttr() == sourceAcct
&& account.getActType() == AccountTypeEnum.BANK) {
infoVO.setSourceAcct(infoVO.installAccount(account));
}
// 目标账户为 银行 托管户
if (account.getActAttr() == AccountAttributeEnum.HOSTED
&& account.getActType() == AccountTypeEnum.BANK) {
infoVO.setTargetAcct(infoVO.installAccount(account));
}
}
return infoVO;
});
}
}
...@@ -8,7 +8,6 @@ import java.util.List; ...@@ -8,7 +8,6 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherLoader; import com.abssqr.plat.biz.shared.dispatcher.DispatcherLoader;
import com.abssqr.plat.biz.shared.dispatcher.planAstStat.PlanAstStatTaskStarter;
import com.abssqr.plat.common.facade.enums.CommonTaskTypeEnum; import com.abssqr.plat.common.facade.enums.CommonTaskTypeEnum;
import com.abssqr.plat.common.model.domain.plan.PlanAstStatTask; import com.abssqr.plat.common.model.domain.plan.PlanAstStatTask;
import com.abssqr.plat.common.model.domain.task.CommonTask; import com.abssqr.plat.common.model.domain.task.CommonTask;
......
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.dispatcher.planAstStat;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherExecutorTemp;
import com.abssqr.plat.biz.shared.handler.PlanAstClearingStatHandler;
import com.abssqr.plat.common.dal.mysql.auto.dao.PlanAstStatTaskDAO;
import com.abssqr.plat.common.facade.enums.OrgAstStatStatusEnum;
import com.abssqr.plat.common.model.domain.plan.PlanAstStatTask;
import com.abssqr.plat.core.service.system.TimeStampUtil;
import com.general.system.common.util.DateTimeUtil;
import com.general.system.common.util.SystemDateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 计划统计任务
*
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.task.task: PlanAstStatTaskExecutor.java, v 0.1 2018-01-08 02:15 hongwei.wang Exp $
*/
@Component
public class PlanAstStatTaskExecutor extends DispatcherExecutorTemp<PlanAstStatTask> {
private final static Logger logger = LoggerFactory.getLogger(
PlanAstStatTaskExecutor.class);
@Autowired
private PlanAstClearingStatHandler planAstClearingStatHandler;
@Autowired
private PlanAstStatTaskDAO planAstStatTaskDAO;
@Override
protected PlanAstStatTask doExecute(PlanAstStatTask node) {
String execTms = TimeStampUtil.getCurrentBufferedTimestamp();
return planAstClearingStatHandler.execute(node, execTms);
}
@Override
protected PlanAstStatTask markSuccess(PlanAstStatTask node) {
// 在内部处理,不单独标记
return node;
}
@Override
protected PlanAstStatTask markFail(PlanAstStatTask node, String failMessage) {
// 因异常引起的重试
Date nextTime = DateTimeUtil.addSecond(SystemDateUtil.getSystemDate(), 30);
node.setStatus(OrgAstStatStatusEnum.ACTIVE);
planAstStatTaskDAO.updateTaskExep(nextTime, node.getPlanNo());
return node;
}
@Override
protected PlanAstStatTask markException(PlanAstStatTask node, String failMessage) {
Date nextTime = DateTimeUtil.addSecond(SystemDateUtil.getSystemDate(), 30);
node.setStatus(OrgAstStatStatusEnum.ACTIVE);
planAstStatTaskDAO.updateTaskExep(nextTime, node.getPlanNo());
return node;
}
@Override
protected String getName() {
return "PlanAstStatTaskExecutor";
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.dispatcher.planAstStat;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherLoader;
import com.abssqr.plat.common.model.domain.plan.PlanAstStatTask;
import com.abssqr.plat.common.model.repo.ast.PlanAstStatTaskRepo;
import com.abssqr.plat.common.model.repo.job.JobControlRepository;
import com.abssqr.plat.core.service.host.HostManager;
import com.general.system.common.util.SystemDateUtil;
import com.general.system.common.util.VarChecker;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.List;
import java.util.stream.Collectors;
/**
* 资产转让
*
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.task.task: PlanAstStatTaskLoader.java, v 0.1 2018-01-08 00:59 hongwei.wang Exp $
*/
@Component
public class PlanAstStatTaskLoader implements DispatcherLoader<PlanAstStatTask> {
@Autowired
private PlanAstStatTaskRepo planAstStatTaskRepo;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private HostManager hostManager;
@Autowired
private JobControlRepository jobControlRepository;
/**
* 装载待分发节点
*
* @param size
* @return
*/
@Override
public List<PlanAstStatTask> loadToDoNodes(int size) {
return transactionTemplate.execute(transactionStatus -> {
// 太多乐观锁冲突报错了,还是加个锁吧
jobControlRepository.lockByJobName(PlanAstStatTaskStarter.JOB_NAME);
List<PlanAstStatTask> tasks = planAstStatTaskRepo.getToDo(SystemDateUtil.getSystemDate(), size);
if (CollectionUtils.isEmpty(tasks)) {
return Lists.newArrayList();
}
List<String> planNos = tasks.stream().map(PlanAstStatTask::getPlanNo).collect(Collectors.toList());
int count = planAstStatTaskRepo.updateTaskExec(SystemDateUtil.getSystemDate(),
hostManager.getHostInfo().getHostName(),
planNos);
VarChecker.checkEquals(count, planNos.size(), "[TaskLoader.loadToDoNodes]更新任务数跟期望数不一致,实际更新:{0},期望更新:{1} - {2}",
count,
planNos.size(),
planNos);
return tasks;
});
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.dispatcher.planAstStat;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherExecutor;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherLoader;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherStarter;
import com.abssqr.plat.common.model.domain.plan.PlanAstStatTask;
import com.abssqr.plat.common.model.repo.ast.PlanAstStatTaskRepo;
import com.abssqr.plat.core.service.host.HostManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.task.task: PlanAstStatTaskStarter.java, v 0.1 2018-01-08 02:42 hongwei
* .wang Exp $
*/
@Component
public class PlanAstStatTaskStarter extends DispatcherStarter<PlanAstStatTask> {
public static String JOB_NAME = "PlanAstStatTaskDispatcher";
@Autowired
private PlanAstStatTaskExecutor planAstStatTaskExecutor;
@Autowired
private PlanAstStatTaskLoader planAstStatTaskLoader;
@Autowired
private HostManager hostManager;
@Autowired
private PlanAstStatTaskRepo planAstStatTaskRepo;
private int coreSize = 2;
private int maxSize = 3;
private int hungrySize = 2;
@Override
protected void recovery() {
planAstStatTaskRepo.updateHangTasksByIp(hostManager.getHostInfo().getHostName());
}
@Override
public String getName() {
return JOB_NAME;
}
@Override
protected int getCoreSize() {
return coreSize;
}
@Override
protected int getMaxSize() {
return maxSize;
}
@Override
protected int getQueueSize() {
return 4;
}
@Override
protected int getHungrySize() {
return hungrySize;
}
@Override
protected DispatcherLoader<PlanAstStatTask> getLoader() {
return planAstStatTaskLoader;
}
@Override
protected DispatcherExecutor<PlanAstStatTask> getExecutor() {
return planAstStatTaskExecutor;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.dispatcher.wkPlanReport;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherExecutorTemp;
import com.abssqr.plat.biz.shared.handler.WkPlanReportHandler;
import com.abssqr.plat.common.facade.enums.TaskStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.model.domain.task.CommonTask;
import com.abssqr.plat.common.model.repo.task.CommonTaskRepository;
import com.abssqr.plat.common.util.base.Day;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.abssqr.plat.core.service.plan.PlanManager;
import com.general.system.common.util.DateTimeUtil;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.MessageUtil;
import com.general.system.common.util.SystemDateUtil;
import org.apache.commons.lang3.tuple.MutablePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 计划统计任务
*
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.task.task: PlanAstStatTaskExecutor.java, v 0.1 2018-01-08 02:15 hongwei.wang Exp $
*/
@Component
public class PlanReportTaskExecutor extends DispatcherExecutorTemp<CommonTask> {
private final static Logger LOGGER = LoggerFactory.getLogger(
PlanReportTaskExecutor.class);
@Autowired
private WkPlanReportHandler wkPlanReportHandler;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
@Autowired
private CommonTaskRepository commonTaskRepository;
@Autowired
private PlanManager planManager;
@Override
public CommonTask doExecute(CommonTask node) {
LogUtil.info(LOGGER, "执行计划报表任务[{0}]", node);
PlanBase planBase = planManager.getPlanFullByNo(node.getContext());
Day accountDate = orgAcctDayComponent.getAstAcctDay(orgAcctDayComponent.getOrgCode(planBase));
MutablePair<Boolean, String> rptResult = wkPlanReportHandler.execute(accountDate.getStandardDate(), planBase);
if (rptResult.getLeft()) {
return markSuccess(node);
} else {
return markFail(node, MessageUtil.formatMsg("[{0}]项目[{1}]报表执行暂时退出:{2}",
planBase.getPlanNo(), accountDate.getDayString(), rptResult.getRight()));
}
}
@Override
protected CommonTask markSuccess(CommonTask node) {
commonTaskRepository.updateTaskStatus(node.getId(), TaskStatusEnum.SUCCESS, TaskStatusEnum.EXECUTING, "");
node.setTaskStatus(TaskStatusEnum.SUCCESS);
return node;
}
@Override
protected CommonTask markFail(CommonTask node, String failMessage) {
// 因异常引起的重试
Date nextTime = DateTimeUtil.addSecond(SystemDateUtil.getSystemDate(), 60);
String msg = failMessage.length()>2000?failMessage.substring(0,2000):failMessage;
commonTaskRepository.updateTaskExep(nextTime, node.getId(), msg);
return node;
}
@Override
protected CommonTask markException(CommonTask node, String failMessage) {
return markFail(node, failMessage);
}
@Override
protected String getName() {
return "PlanReportTaskExecutor";
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.dispatcher.wkPlanReport;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherLoader;
import com.abssqr.plat.common.facade.enums.CommonTaskTypeEnum;
import com.abssqr.plat.common.facade.enums.PlanStatusEnum;
import com.abssqr.plat.common.facade.enums.ReportTypeEnum;
import com.abssqr.plat.common.facade.enums.TaskStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.facade.model.report.DailyReportDateField;
import com.abssqr.plat.common.facade.model.report.PlanReport;
import com.abssqr.plat.common.model.domain.task.CommonTask;
import com.abssqr.plat.common.model.repo.job.JobControlRepository;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.common.model.repo.report.PlanReportRepo;
import com.abssqr.plat.common.model.repo.task.CommonTaskRepository;
import com.abssqr.plat.common.model.seq.SequenceUtil;
import com.abssqr.plat.common.util.base.Day;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.abssqr.plat.core.service.host.HostManager;
import com.general.system.common.util.DateTimeUtil;
import com.general.system.common.util.SystemDateUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 计划报表异步处理
*
* @author zhenxuan.luo
* @version com.abssqr.piz.shared.task.task: PlanAstStatTaskLoader.java, v 0.1 2018-01-08 00:59 hongwei.wang Exp $
*/
@Component
public class PlanReportTaskLoader implements DispatcherLoader<CommonTask> {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private HostManager hostManager;
@Autowired
private JobControlRepository jobControlRepository;
@Autowired
private PlanRepo planRepo;
@Autowired
private PlanReportRepo planReportRepo;
@Autowired
private CommonTaskRepository commonTaskRepository;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
/**
* 装载待分发节点
*
* @param size
* @return
*/
@Override
public List<CommonTask> loadToDoNodes(int size) {
List<CommonTask> tasks = Lists.newArrayList();
List<CommonTask> existsTask = commonTaskRepository
.selectUnifinishTaskByType(CommonTaskTypeEnum.PLAN_REPORT);
Map<String, CommonTask> taskMap = existsTask.stream()
.collect(Collectors.toMap(CommonTask::getContext, item -> item));
List<PlanBase> plans = planRepo.getPlansByStatus(null, PlanStatusEnum.ONGOING);
return transactionTemplate.execute(transactionStatus -> {
// 太多乐观锁冲突报错了,还是加个锁吧
jobControlRepository.lockByJobName(PlanReportTaskStarter.JOB_NAME);
for (PlanBase planBase : plans) {
CommonTask commonTask = taskMap.get(planBase.getPlanNo());
// 获取对应机构会计日
Day accountDate = orgAcctDayComponent.getAstAcctDay(orgAcctDayComponent.getOrgCode(planBase));
if (null == commonTask) {
PlanReport planReport = planReportRepo.getLatestReport(planBase.getPlanNo(), ReportTypeEnum.RPT001);
DailyReportDateField reportDateField;
if (null != planReport) {
// 只判断日报,月报没有判断,当天月报失败需要第二天才能执行 或手动触发
reportDateField = (DailyReportDateField) planReport.getRptDate();
if (DateTimeUtil.calcDayDiff(reportDateField.getAccountDate(), accountDate.getStandardDate()) >= 0) {
continue;
}
}
commonTask = new CommonTask();
commonTask.setBizNo(SequenceUtil.genWkSeqNo());
commonTask.setTaskType(CommonTaskTypeEnum.PLAN_REPORT);
commonTask.setContext(planBase.getPlanNo());
commonTask.setEnv(null);
commonTask.setMemo("");
commonTask.setTaskStatus(TaskStatusEnum.INIT);
commonTask.setNextExecTime(SystemDateUtil.getSystemDate());
commonTask.setExecTimes(0L);
commonTaskRepository.create(commonTask);
} else {
if (commonTask.getTaskStatus() != TaskStatusEnum.INIT) {
continue;
} else if (SystemDateUtil.getSystemDate().compareTo(commonTask.getNextExecTime()) < 0) {
continue;
}
}
tasks.add(commonTask);
if (tasks.size() >= size) {
break;
}
}
if (CollectionUtils.isNotEmpty(tasks)) {
commonTaskRepository
.updateTaskExec(SystemDateUtil.getSystemDate(), hostManager.getHostInfo().getHostName(),
tasks);
}
return tasks;
});
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.dispatcher.wkPlanReport;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherExecutor;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherLoader;
import com.abssqr.plat.biz.shared.dispatcher.DispatcherStarter;
import com.abssqr.plat.common.model.domain.task.CommonTask;
import com.abssqr.plat.common.model.repo.task.CommonTaskRepository;
import com.abssqr.plat.core.service.host.HostManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.task.task: PlanAstStatTaskStarter.java, v 0.1 2018-01-08 02:42 hongwei
* .wang Exp $
*/
@Component
public class PlanReportTaskStarter extends DispatcherStarter<CommonTask> {
public static String JOB_NAME = "PlanReportTaskDispatcher";
@Autowired
private PlanReportTaskExecutor planReportTaskExecutor;
@Autowired
private PlanReportTaskLoader planReportTaskLoader;
@Autowired
private HostManager hostManager;
@Autowired
private CommonTaskRepository commonTaskRepository;
private int coreSize = 2;
private int maxSize = 2;
private int hungrySize = 1;
private int queueSize = 2;
@Override
protected void recovery() {
commonTaskRepository.updateHangTasksByIp(hostManager.getHostInfo().getHostName());
}
@Override
public String getName() {
return JOB_NAME;
}
@Override
protected int getCoreSize() {
return coreSize;
}
@Override
protected int getMaxSize() {
return maxSize;
}
@Override
protected int getQueueSize() {
return queueSize;
}
@Override
protected int getHungrySize() {
return hungrySize;
}
@Override
protected DispatcherLoader<CommonTask> getLoader() {
return planReportTaskLoader;
}
@Override
protected DispatcherExecutor<CommonTask> getExecutor() {
return planReportTaskExecutor;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.handler;
import cn.hutool.json.JSONUtil;
import com.abssqr.plat.common.facade.enums.PlanAllocStatusEnum;
import com.abssqr.plat.common.facade.enums.PlanCapitalTransTypeEnum;
import com.abssqr.plat.common.facade.enums.PlanTypeEnum;
import com.abssqr.plat.common.facade.enums.StageChangeTypeEnum;
import com.abssqr.plat.common.facade.enums.TaskStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanAlloc;
import com.abssqr.plat.common.facade.model.plan.PlanAst;
import com.abssqr.plat.common.facade.model.plan.PlanCapitalOrder;
import com.abssqr.plat.common.facade.param.plan.alloc.PlanAllocHandleParam;
import com.abssqr.plat.common.model.domain.plan.PlanAllocFrozen;
import com.abssqr.plat.common.model.domain.plan.PlanAstLog;
import com.abssqr.plat.common.model.enums.TraderTypeEnum;
import com.abssqr.plat.common.model.repo.plan.PlanAllocFrozenRepo;
import com.abssqr.plat.common.util.base.Day;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.abssqr.plat.core.service.plan.PlanAllocManager;
import com.abssqr.plat.core.service.plan.PlanAstManager;
import com.abssqr.plat.core.share.pay.PlanCapitalCreateRequest;
import com.abssqr.plat.core.share.pay.PlanCapitalFinishRequest;
import com.abssqr.plat.core.share.pay.PlanCapitalOrderManager;
import com.alibaba.fastjson.JSON;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.MessageUtil;
import com.general.system.common.util.VarChecker;
import com.general.system.util.adapter.AbstractBaseActionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
/**
* 分配兑付
* 两个调用场景:
* 1. 审批通过后直接发起线上支付 : 调用 handle 方法, 然后获取到支付单结果后执行 allocTitleEntry
*
* 2. 审批通过后修改状态为待支付,有人工手工入账,此时没有支付操作 ,调用 execute 方法执行全部操作
*
* @author hanfei
* @version $Id: PlanAllocHandler.java, v 0.1 2019-07-06 11:46 AM hanfei Exp $
*/
@Component
public class PlanAllocHandler extends AbstractBaseActionHandler<PlanAllocHandleParam, PlanCapitalOrder> {
protected final Logger LOGGER = LoggerFactory.getLogger(getClass());
@Autowired
private PlanCapitalOrderManager planCapitalOrderManager;
@Autowired
private PlanAllocManager planAllocManager;
@Autowired
private PlanAstManager planAstManager;
@Autowired
private PlanAllocFrozenRepo planAllocFrozenRepo;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
/**
* 分配支付的发起
* 1. 生成支付单
*
* -- 分配入账(可能存在两个调用来源:1. 审批通过后直接发起支付,2. 审批通过后修改状态为待支付,有人工手工入账,此时没有支付操作
* 2. 更新分配计划状态为已分配
* 3. 登记分配计划下,各分配事项对应科目的"付"发生额和流水
*/
@Override
public PlanCapitalOrder handle(PlanAllocHandleParam handleParam) {
// 获取转让会计日
Day accountDate = orgAcctDayComponent.getTrfAcctDay();
PlanAlloc alloc = handleParam.getAlloc();
// 对分配计划加锁
PlanAlloc lock = planAllocManager.lockByAllocNo(alloc.getAllocNo());
VarChecker.checkEquals(lock.getStatus(), PlanAllocStatusEnum.UNASSIGNE,
"计划[{0}]当前分配计划[{1}]不能进行分配,状态为[{2}]", alloc.getPlanNo(), alloc.getAllocNo(), alloc.getStatus());
// 分配兑付操作发起支付创建支付订单 明确时分配兑付类型
PlanCapitalTransTypeEnum transTypeEnum;
if (alloc.getPlanType() == PlanTypeEnum.SPV){
transTypeEnum = PlanCapitalTransTypeEnum.NT_DIST;
}else{
transTypeEnum = PlanCapitalTransTypeEnum.DIST;
}
PlanCapitalCreateRequest request = new PlanCapitalCreateRequest();
request.setAccountDate(accountDate.getStandardDate());
// 使用分配计划 编号作为业务编码
request.setBizNo(alloc.getAllocNo());
request.setPlanNo(alloc.getPlanNo());
// 目标机构 填入 计划编号
request.setTargetOrgCode(alloc.getPlanNo());
// 获取分配计划应兑付金额总和
request.setTransAmt(alloc.getTotalConfirmAllocAmt());
// 应付金额
request.setPayableAmt(alloc.getTotalConfirmAllocAmt());
// 交易类型
request.setTransType(transTypeEnum);
request.setMemo(MessageUtil.formatMsg("-日期[{2}]分配兑付", alloc.getPayDate()));
// 1 发起支付 创建支付订单
PlanCapitalOrder order = planCapitalOrderManager.createCapitalOrder(request);
LogUtil.info(LOGGER, "计划[{0}-{1}]创建支付交易单type[{2}]cntPty[{3}]amt[{4}]bizNo[{5}]",
order.getPlanNo(), order.getAccountDate(), transTypeEnum, order.getCntPtyCode(), order.getTransAmt(), order.getBizNo());
// 2 记录清算在资产水位表中 增加支付在途金额 并将冻结金额解冻
planAstManager.changePlanAst(accountDate.getStandardDate(), alloc.getPlanNo(), (planAst,planAstLogList) -> {
// 2.1 分配兑付需要进行解冻记录冻结金额解冻变化
this.unFrozen(planAstLogList, accountDate.getStandardDate(), planAst, order);
// 2.2 更新计划资产水位表,追加在途的支出金额 并登记日志
planAstLogList.add(planAstManager.itemChangeStage(order.getAccountDate(), planAst, TraderTypeEnum.INITIATOR,
StageChangeTypeEnum.ON_WAY, order.getTransAmt(), transTypeEnum,
order.getBizNo(), JSONUtil.toJsonStr(order)));
});
alloc.setStatus(PlanAllocStatusEnum.PENDING);
alloc.setAllocAmt(order.getTransAmt());
// 3 变更分配计划 更新为分配中 记录分配总额
planAllocManager.updateAllocStatus(alloc);
return order;
}
/**
* 发起创建支付单后
* 1、更新分配计划状态为已分配
* 2、登记分配计划下,各分配事项对应科目的"付"发生额和流水
* @param handleParam
* @param order
* @return
*/
@Override
public PlanCapitalOrder afterHandle(PlanAllocHandleParam handleParam, PlanCapitalOrder order) {
// 线下交易,更新资金交易单的状态为成功
if (handleParam.getOffLine()) {
// 线下支付默认成功 确认金额为交易金额
PlanCapitalFinishRequest finishRequest = new PlanCapitalFinishRequest();
finishRequest.setOutTransNo(handleParam.getOutTransNo());
finishRequest.setSeqNo(order.getSeqNo());
finishRequest.setCfrmAmt(order.getTransAmt());
finishRequest.setRes(TaskStatusEnum.SUCCESS);
finishRequest.setMemo("分配线下支付");
// 更新 资金单据 支付结果 、 变更水位 、科目入账
order = planCapitalOrderManager.finishCapitalOrder(finishRequest);
}
return order;
}
/**
* 解冻冻结金额 目前只面向 分配兑付
* @param curDate
* @param planAst
* @param capitalOrder
* @return
*/
private void unFrozen(List<PlanAstLog> planAstLogList, Date curDate,
PlanAst planAst, PlanCapitalOrder capitalOrder) {
// 查询对应的 分配计划冻结记录 同时获取 对应的锁定金额明细进行解冻
PlanAllocFrozen allocFrozen = planAllocFrozenRepo.getByAllocNo(planAst.getPlanNo(), capitalOrder.getBizNo());
VarChecker.checkNotNull(allocFrozen,
"[{0}]未匹配到对应的冻结记录[{1}]", planAst.getPlanNo(), capitalOrder.getBizNo());
// 判断水位冻结金额 减去 冻结记录金额 后不能小于零
VarChecker.checkArgument(!planAst.getFrozenCash().subtract(allocFrozen.getFrozenCash()).isNegtive(),
"[{0}]计划分配编号[{1}]解冻金额{2} 大于 冻结金额{3}",
planAst.getPlanNo(), capitalOrder.getBizNo(), allocFrozen.getFrozenCash(), planAst.getFrozenCash());
// 冻结金额解冻记录
PlanAstLog planAstLog = PlanAstLog.buildAstLog(curDate, planAst, allocFrozen.getAllocNo(),
TraderTypeEnum.INITIATOR, capitalOrder.getTransType().getTransCode(), StageChangeTypeEnum.UNFROZEN);
planAstLog.changeFrozenCash(planAst, allocFrozen.getFrozenCash(), capitalOrder.getTransAmt(), JSON.toJSONString(allocFrozen));
planAstLogList.add(planAstLog);
// 同时删除冻结金额记录
planAllocFrozenRepo.deleteByAllocNo(planAst.getPlanNo(), capitalOrder.getBizNo());
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.keeper.node;
import com.abssqr.plat.common.facade.enums.AbssqrNoticeTypeEnum;
import com.abssqr.plat.common.facade.enums.AccountAttributeEnum;
import com.abssqr.plat.common.facade.enums.AccountTypeEnum;
import com.abssqr.plat.common.facade.enums.PlanStatusEnum;
import com.abssqr.plat.common.facade.enums.PlanTaskTypeEnum;
import com.abssqr.plat.common.facade.enums.PlanTypeEnum;
import com.abssqr.plat.common.facade.model.account.Account;
import com.abssqr.plat.common.facade.model.org.OrganizationEntity;
import com.abssqr.plat.common.facade.model.plan.PlanAst;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
import com.abssqr.plat.common.model.domain.plan.PlanTaskLog;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.common.model.repo.plan.PlanTaskLogRepo;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.abssqr.plat.core.service.acct.AcctManager;
import com.abssqr.plat.core.service.plan.PlanAstManager;
import com.abssqr.plat.core.service.wk.pay.WkPayManager;
import com.general.system.common.model.IEnum;
import com.general.system.common.model.Money;
import com.general.system.common.util.DateTimeUtil;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.MessageUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* 每日余额校验
*
* @author xiachenxiang
* @version com.abssqr.plat.biz.shared.scheduler.job.keeper.node: BalanceCheckKeeper.java, v 0.1 2019-10-08 11:01 AM xiachenxiang Exp $
*/
@Component
public class BalanceCheckKeeper extends AbstractKeeperNode {
@Autowired
private PlanTaskLogRepo planTaskLogRepo;
@Autowired
private PlanRepo planRepo;
@Autowired
private AcctManager acctManager;
@Autowired
private WkPayManager wkPayManager;
@Autowired
private PlanAstManager planAstManager;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
@Value("${wkabs.zhaolian.balancecheck.deadline:8 0 0}")
private String deadline;
@Override
protected Void doHandle(Date currentTime) {
LogUtil.info(LOGGER, "每日余额校验-start");
currentTime = getCurrentStanderDate();
// 判断当前时间是否大于凌晨1点
Date deadlineTime = getDeadLineTime(currentTime, deadline);
if (currentTime.compareTo(deadlineTime) > 0) {
Date bizDate = orgAcctDayComponent.getTrfAcctDay().getStandardDate();
List<PlanTaskLog> tasks = planTaskLogRepo.getTasks(bizDate, PlanTaskTypeEnum.BAL_CHECKER);
// 查询存续中的放款池计划
List<PlanBase> onGoingPlans = planRepo.getPlansByStatus(PlanTypeEnum.SPV, PlanStatusEnum.ONGOING);
StringBuffer sb = new StringBuffer();
for (PlanBase plan : onGoingPlans) {
boolean isExist = false;
boolean isStop = false;
if (CollectionUtils.isNotEmpty(tasks)) {
isExist = tasks.stream().filter(item -> item.getPlanNo().equals(plan.getPlanNo()) && item.getTaskType() == PlanTaskTypeEnum.BAL_CHECKER).findFirst().isPresent();
}
if (plan instanceof OrganizationEntity) {
OrganizationEntity organizationEntity = (OrganizationEntity) plan;
isStop = DateTimeUtil.calcDayDiff(orgAcctDayComponent.getTrfAcctDay().getStandardDate(), organizationEntity.getStopPayDate()) > 0;
if (isStop) {
LogUtil.info(LOGGER, "计划编号{0},当前会计日{1}大于停止放款日期{2},{3}",
plan.getPlanNo(), currentTime, organizationEntity.getStopPayDate(), isStop);
}
}
if (!isExist && !isStop) {
// 获取计划对应资金账户 平台虚拟户
List<Account> accounts = acctManager.getAcctByPlanNoAndType(plan.getPlanNo(), AccountTypeEnum.PLAT_VIRTUAL, false);
// 过滤出对应查询余额的账户
Optional<Account> platAcctOpt = accounts.stream()
.filter(item -> item.getActAttr() == AccountAttributeEnum.RECV)
.findFirst();
// 异常打印后继续
if (!platAcctOpt.isPresent()) {
LogUtil.error(LOGGER, "{0}[{1}]找不到[{2}]对应平台虚拟户", plan.getPlanType().getDesc(), plan.getPlanNo(), AccountAttributeEnum.RECV.getDesc());
continue;
}
Account planAcct = platAcctOpt.get();
Money bankBal = new Money();
try {
// 调用外部接口查询账户余额
WkChannelNoEnum channelNo = WkChannelNoEnum.getPlatChannelNo(planAcct.getChannelNo());
bankBal.addTo(wkPayManager.balance(planAcct.getActNo(), channelNo));
LogUtil.info(LOGGER, "{0}[{1}]查询账户余额: {2}", plan.getPlanType().getDesc(), plan.getPlanNo(), bankBal.getAmount());
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "[{0}]-ChannelNo[{1}]-ActNo[{2}]调用五矿查询账户余额异常",
plan.getPlanNo(), planAcct.getChannelNo(), planAcct.getActNo());
continue;
}
if (bankBal.compareTo(new Money()) > 0) {
PlanAst planAst = planAstManager.getByPlanNo(plan.getPlanNo());
if (bankBal.subtract(planAst.getFrozenCash()).isGreaterThanZero()) {
String msg = MessageUtil.formatMsg("截止到{0}为止,{1}[{2}]查询账户余额为 {3},请排查具体原因 \n", DateTimeUtil.formatYMDHMSSLong(currentTime), plan.getPlanType().getDesc(), plan.getPlanNo(), bankBal.getAmount());
sb.append(msg);
}
}
PlanTaskLog planTaskLog = new PlanTaskLog();
planTaskLog.setExecDate(bizDate);
planTaskLog.setPlanNo(plan.getPlanNo());
planTaskLog.setTaskType(PlanTaskTypeEnum.BAL_CHECKER);
planTaskLogRepo.createTask(planTaskLog);
}
}
if (sb.length() > 0) {
// 获取用户
Set<String> receivers = getAdminReceivers();
sendSystemNotice("每日余额校验异常告警", "ALL", sb.toString(), receivers);
}
}
LogUtil.info(LOGGER, "每日余额校验-end");
return null;
}
@Override
protected String getWatchJob() {
return null;
}
@Override
protected IEnum getBizType() {
return AbssqrNoticeTypeEnum.BalanceCheck;
}
}
package com.abssqr.plat.biz.shared.scheduler.job.keeper.node;
import com.abssqr.plat.common.facade.enums.*;
import com.abssqr.plat.common.facade.model.account.Account;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
import com.abssqr.plat.common.model.domain.plan.PlanTaskLog;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.common.model.repo.plan.PlanTaskLogRepo;
import com.abssqr.plat.core.service.acct.AcctManager;
import com.abssqr.plat.core.service.wk.pay.WkPayManager;
import com.general.system.common.model.IEnum;
import com.general.system.common.model.Money;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.SystemDateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* 每日十点放款池余额通知
*/
@Component
public class BalanceReportKeeper extends AbstractKeeperNode{
@Autowired
private PlanTaskLogRepo planTaskLogRepo;
@Autowired
private PlanRepo planRepo;
@Autowired
private AcctManager acctManager;
@Autowired
private WkPayManager wkPayManager;
@Value("${wkabs.zhaolian.balanceReport.deadline:10 0 0}")
private String deadline;
@Value("${wkabs.org.zhaolian:1009}")
private String zhaolianOrgCode;
@Override
protected Void doHandle(Date date) {
// 判断当前时间是否大于上午十点
Date currentTime = getCurrentStanderDate();
Date deadlineTime = getDeadLineTime(currentTime, deadline);
Map<String,Map<AccountAttributeEnum, Money>> buildMessageMap=new HashMap<>();
if (currentTime.compareTo(deadlineTime) >=0) {
LogUtil.info(LOGGER, "每日放款池余额通知-start");
Date bizDate =getCurrentStanderDate();
List<PlanTaskLog> tasks = planTaskLogRepo.getTasks(bizDate, PlanTaskTypeEnum.BALANCE_REPORT);
Map<String, List<PlanTaskLog>> planTaskLogMap = tasks.stream().collect(Collectors.groupingBy(PlanTaskLog::getPlanNo));
// 查询存续中的放款池计划
List<PlanBase> onGoingPlans = planRepo.getPlansByStatus(PlanTypeEnum.SPV, PlanStatusEnum.ONGOING);
for (PlanBase plan : onGoingPlans) {
boolean isExist=false;
if (tasks != null) {
isExist=planTaskLogMap.containsKey(plan.getPlanNo());
}
if (!isExist) {
Map<AccountAttributeEnum, Money> moneyMap = getMoneyMap(plan);
buildMessageMap.put(plan.getPlanNo(),moneyMap);
}else{
continue;
}
PlanTaskLog planTaskLog = new PlanTaskLog();
planTaskLog.setExecDate(bizDate);
planTaskLog.setPlanNo(plan.getPlanNo());
planTaskLog.setTaskType(PlanTaskTypeEnum.BALANCE_REPORT);
planTaskLogRepo.createTask(planTaskLog);
}
String reportMessage = buildReportMessage(buildMessageMap,date);
if (CollectionUtils.isNotEmpty(buildMessageMap.keySet())&&reportMessage.length() > 0) {
// 获取用户
Set<String> receivers = super.getAdminReceivers();
PlanBase planBase=new PlanBase();
super.sendBussinessNotice(planBase, zhaolianOrgCode, reportMessage, receivers);
}
}
LogUtil.info(LOGGER, "每日放款池余额通知-end");
return null;
}
private Map<AccountAttributeEnum,Money> getMoneyMap(PlanBase plan){
Map<AccountAttributeEnum,Money> accountAttributeEnumMoneyMap=new HashMap<>();
// 获取计划对应资金账户 平台虚拟户
List<Account> accounts = acctManager.getAcctByPlanNoAndType(plan.getPlanNo(), AccountTypeEnum.PLAT_VIRTUAL, false);
accounts.forEach(v->{
Money bankBal = new Money();
try {
// 调用外部接口查询账户余额
WkChannelNoEnum channelNo = WkChannelNoEnum.getPlatChannelNo(v.getChannelNo());
Money balance = wkPayManager.balance(v.getActNo(), channelNo);
if(balance!=null) {
bankBal.addTo(balance);
}
LogUtil.info(LOGGER, "{0}[{1}]查询账户余额: {2}", plan.getPlanType().getDesc(), plan.getPlanNo(), bankBal.getAmount());
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "[{0}]-ChannelNo[{1}]-ActNo[{2}]调用五矿查询账户余额异常",
plan.getPlanNo(), v.getChannelNo(), v.getActNo());
return;
}
accountAttributeEnumMoneyMap.put(v.getActAttr(),bankBal);
});
return accountAttributeEnumMoneyMap;
}
private String buildReportMessage(Map<String,Map<AccountAttributeEnum, Money>> buildMessageMap,Date currDate){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTimeStr = sdf.format(currDate);
StringBuilder sb=new StringBuilder();
sb.append("截止到"+currentTimeStr+"\n");
buildMessageMap.forEach((planNo,moneyMap)->{
sb.append("放款池:"+planNo);
moneyMap.forEach((accountType,freeMoney)->{
switch (accountType) {
case RECV:{
sb.append("回款户余额为:"+freeMoney.getAmount());
break;
}
case PAY:{
sb.append("放款户余额为:"+freeMoney.getAmount());
break;
}
default:
throw new RuntimeException("不支持的账户类型:"+accountType);
}
sb.append("\n");
});
});
return sb.toString();
}
@Override
protected String getWatchJob() {
return null;
}
@Override
protected IEnum getBizType() {
return AbssqrNoticeTypeEnum.BalanceReport;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.keeper.node;
import com.abssqr.plat.biz.shared.scheduler.job.plan.PlanCapitalOrderJob;
import com.abssqr.plat.common.facade.enums.AbssqrNoticeTypeEnum;
import com.abssqr.plat.common.model.repo.plan.PlanCapitalOrderRepo;
import com.general.system.common.model.IEnum;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.MessageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Set;
/**
* 支付任务监控
*
* @author xiachenxiang
* @version com.abssqr.plat.biz.shared.scheduler.job.keeper.node: capitalOrderKeeper.java, v 0.1 2019-09-27 11:35 AM xiachenxiang Exp $
*/
@Component
public class CapitalOrderKeeper extends AbstractKeeperNode {
@Autowired
private PlanCapitalOrderRepo capitalOrderRepo;
@Value("${wkabs.org.zhaolian:1009}")
private String zhaolianOrgCode;
@Override
protected Void doHandle(Date date) {
LogUtil.info(LOGGER, "支付任务监控-start");
Long count = capitalOrderRepo.getFailCount(execTimes);
if (count != null && count > 0) {
String msg = MessageUtil.formatMsg("支付任务监控到有[{0}]条失败任务,请排查具体原因!", count);
LogUtil.info(LOGGER, msg);
// 获取用户
Set<String> receivers = super.getAdminReceivers();
super.sendSystemNotice("支付任务告警", zhaolianOrgCode, msg, receivers);
}
LogUtil.info(LOGGER, "支付任务监控-end");
return null;
}
@Override
protected IEnum getBizType() {
return AbssqrNoticeTypeEnum.CapitalOrder;
}
@Override
protected String getWatchJob() {
return PlanCapitalOrderJob.class.getName();
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.plan;
import cn.hutool.json.JSONUtil;
import com.abssqr.plat.biz.shared.scheduler.BaseQuartzJob;
import com.abssqr.plat.common.facade.enums.AccountAttributeEnum;
import com.abssqr.plat.common.facade.enums.AccountTypeEnum;
import com.abssqr.plat.common.facade.enums.CommonErrorCodeEnum;
import com.abssqr.plat.common.facade.enums.PlanCapitalTransTypeEnum;
import com.abssqr.plat.common.facade.enums.PlanStatusEnum;
import com.abssqr.plat.common.facade.enums.PlanTypeEnum;
import com.abssqr.plat.common.facade.enums.StageChangeTypeEnum;
import com.abssqr.plat.common.facade.model.account.Account;
import com.abssqr.plat.common.facade.model.org.OrganizationEntity;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.facade.model.plan.PlanCapitalOrder;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
import com.abssqr.plat.common.model.enums.TraderTypeEnum;
import com.abssqr.plat.common.model.exception.AbssqrBizException;
import com.abssqr.plat.common.model.repo.plan.PlanCapitalOrderRepo;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.common.model.seq.SequenceUtil;
import com.abssqr.plat.common.util.base.Day;
import com.abssqr.plat.common.util.utils.DayUtil;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.abssqr.plat.core.service.acct.AcctManager;
import com.abssqr.plat.core.service.plan.PlanAstManager;
import com.abssqr.plat.core.service.wk.pay.WkPayManager;
import com.abssqr.plat.core.share.pay.PlanCapitalCreateRequest;
import com.abssqr.plat.core.share.pay.PlanCapitalOrderManager;
import com.general.system.common.model.Money;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.VarChecker;
import com.general.system.tool.util.ToolUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.List;
import java.util.Optional;
/**
* 放款池计划 资金交易处理
* 放款截止日 次日进行 放款户向 回款户资金划账
*
* @author hanfei
* @version $Id: LenderOrgCapitalJob.java, v 0.1 2018-01-06 上午12:39 hanfei Exp $
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class LenderOrgCapitalJob extends BaseQuartzJob {
@Autowired
TransactionTemplate transactionTemplate;
@Autowired
WkPayManager wkPayManager;
@Autowired
PlanRepo planRepo;
@Autowired
AcctManager acctManager;
@Autowired
PlanAstManager planAstManager;
@Autowired
PlanCapitalOrderRepo planCapitalOrderRepo;
@Autowired
PlanCapitalOrderManager planCapitalOrderManager;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
/**
* 每天 30 15/20 * * * ?
*/
@Value("${sync.quartz.plan.orgcapital}")
private String cron;
@Override
protected String getCronExpr() {
return cron;
}
@Override
protected boolean isRequestRecovery() {
return true;
}
@Override
public void doExecute() {
// 获取转让会计日
Day curDate = orgAcctDayComponent.getTrfAcctDay();
LogUtil.info(LOGGER, "[LnderOrgCapitalJob]-[{0}]放款计划资金交易处理-start", curDate);
// 1. 查询存续中的放款池计划
List<PlanBase> planBases = planRepo.getPlansByStatus(PlanTypeEnum.SPV, PlanStatusEnum.ONGOING);
for (PlanBase planBase : planBases) {
// 当前有资金交易单未处理完毕 则不进行账户资金处理等待下一次处理
// 校验是否需有未完成支付单
if (planCapitalOrderManager.repayAcctCapital(planBase.getPlanNo())){
continue;
}
if (!(planBase instanceof OrganizationEntity)){
LogUtil.error(LOGGER, "放款计划[{0}]模型不匹配", planBase);
}
OrganizationEntity entity = (OrganizationEntity)planBase;
if (ToolUtil.isEmpty(entity.getStopPayDate())){
continue;
}
final String planNo = entity.getPlanNo();
// 计算当前日期与 放款截止日相差天数
int count = DayUtil.diffDays(curDate, new Day(entity.getStopPayDate()));
try {
if (count >= 1) {
LogUtil.info(LOGGER, "放款计划[{0}]放款截止日次日资金交易处理开始", planNo);
// 放款截止日 次日进行 放款户向 回款户资金划账
this.execRemitRepo(curDate, entity);
LogUtil.info(LOGGER, "放款计划[{0}]放款截止日次日资金交易处理结束", planNo);
} else {
// 判断放款截止日 大于当前日期 不进行资金操作
LogUtil.info(LOGGER, "放款计划[{0}]非放款截止日次日, 当前时间为[{1}]", planNo,curDate);
continue;
}
} catch (AbssqrBizException e) {
if (CommonErrorCodeEnum.NO_DATA == e.getErrCode()) {
LogUtil.warn(LOGGER, e.getMessage());
} else {
LogUtil.error(LOGGER, e, "放款计划[{0}]放款截止日次日资金交易处理异常", entity);
}
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "放款计划[{0}]放款截止日次日资金交易处理异常", entity);
}
}
LogUtil.info(LOGGER, "[LenderOrgCapitalJob]-[{0}]放款计划资金交易处理-end", curDate.getStandardDate());
}
/**
* 放款户 转 回款户
*
* @param curDate
* @param entity
*/
private void execRemitRepo(Day curDate, OrganizationEntity entity) {
// 查询放款户余额
Money bankBal = new Money();
// 过滤出 放款户的平台虚拟账户
List<Account> accounts = acctManager.getAcctByPlanNoAndType(entity.getPlanNo(),
AccountTypeEnum.PLAT_VIRTUAL,false);
VarChecker.checkNotEmpty(accounts, "未找到对应的账号信息,[{0}]", entity.getPlanNo());
Optional<Account> platAcctOpt = accounts.stream()
.filter(item -> item.getActAttr() == AccountAttributeEnum.PAY)
.findFirst();
Account planAcct = platAcctOpt.get();
try {
// 3、调用外部接口查询账户余额
WkChannelNoEnum channelNo = WkChannelNoEnum.getPlatChannelNo(planAcct.getChannelNo());
bankBal.addTo(wkPayManager.balance(planAcct.getActNo(), channelNo));
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "查询[{0}]五矿账户余额异常", entity.getPlanNo());
throw e;
}
if (bankBal.isZero()) {
LogUtil.info(LOGGER, "放款计划[{0}]放款户余额为0 不做操作", entity.getPlanNo());
return;
}
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// 记录资产水位表 创建资金交易订单
planAstManager.changePlanAst(curDate.getStandardDate(), entity.getPlanNo(), (planAst, planAstLogList) -> {
boolean existCapital = planCapitalOrderManager.repayAcctCapital(entity.getPlanNo());
VarChecker.checkArgument(!existCapital,"回款户资金划账-未完成支付单,防止并发");
LogUtil.info(LOGGER, "放款计划[{0}]放款截止日次日进行放款户向回款户资金划账", entity.getPlanNo());
PlanCapitalTransTypeEnum transType = PlanCapitalTransTypeEnum.SPV_REMIT_REPO;
// 3、 创建支付订单
PlanCapitalCreateRequest request = new PlanCapitalCreateRequest();
request.setBizNo(SequenceUtil.genSeqNo(transType.getCode()));
request.setPlanNo(entity.getPlanNo());
request.setTargetOrgCode(entity.getPlanNo());
request.setTransAmt(bankBal);
request.setPayableAmt(bankBal);
request.setAccountDate(curDate.getStandardDate());
request.setTransType(transType);
request.setMemo("-放款截止日次日进行放款户向回款户资金划账");
PlanCapitalOrder order = planCapitalOrderManager.createCapitalOrder(request);
// 放款池放款终止转回款户 需要先增加校验金额 满足后续变更水位校验
planAstManager.changeCheckCashAmt(planAst, order.getTransAmt(), transType.getFlowType());
// 更新计划资产水位表,追加在途的支出收入金额,扣减待结算支出收入金额 并登记日志
planAstLogList.add(planAstManager.itemChangeStage(order.getAccountDate(), planAst, TraderTypeEnum.INITIATOR,
StageChangeTypeEnum.ON_WAY, order.getTransAmt(), transType,
order.getBizNo(), JSONUtil.toJsonStr(order)));
});
}
});
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.plan;
import com.abssqr.plat.biz.shared.handler.PlanAstClearingOrderHandler;
import com.abssqr.plat.biz.shared.scheduler.BaseQuartzJob;
import com.abssqr.plat.common.facade.enums.CommonErrorCodeEnum;
import com.abssqr.plat.common.facade.enums.PlanStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.model.exception.AbssqrBizException;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.general.system.common.util.LogUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.Date;
import java.util.List;
/**
* 承接池受让计划 与 放款池计划
* 结算单进行支付交易处理
三 增加清算支付处理任务 PlanAstClearingOrderHandler
1、拉取待支付的 结算单 TaskStatusEnum.INIT
2、根据对手机构进行汇总支付与收入,进行轧差计算,创建支付订单,一个对手机构对应一笔支付单
PlanCapitalTransTypeEnum 交易类型增加 支付 与 收入 类型进行对应
3、修改结算单状态为 WAITING,等待支付结果
4、变更资产水位表中待结算 与 在途金额
四 修改 PlanCapitalOrderListener 交易单结果监听器
1、增加选择处理器,根据不同 PlanCapitalTransTypeEnum 类型,进行对应业务处理剥离 分配兑付与清算
2、清算类型交易单结果处理:
2.1、拉取交易单据对应交易对手的结算单,根据实际确认金额,循环每条扣减金额及更改状态为SUCCESS
2.2、对支付金额不足剩余的 结算单 更改状态为 INIT,等待下次支付
2.3、根据交易单据金额更改扣减水位表的 待结算支出 或 待结算收入 金额
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.handler: PlanAstStatHandler.java, v 0.1 2019-06-12 20:44 zhenxuan.luo Exp $
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class PlanAstClearingOrderJob extends BaseQuartzJob {
@Autowired
private PlanRepo planRepo;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private PlanAstClearingOrderHandler planAstClearingOrderHandler;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
/**
* 每天 25 2/5 * * * ?
*/
@Value("${sync.quartz.plan.clear}")
private String cron;
@Override
protected String getCronExpr() {
return cron;
}
@Override
protected boolean isRequestRecovery() {
return true;
}
@Override
public void doExecute() {
// 获取转让会计日
Date curDate = orgAcctDayComponent.getTrfAcctDay().getStandardDate();
LogUtil.info(LOGGER, "[ClearingOrderJob]-[{0}]结算单进行支付交易处理任务start", curDate);
// 1.1 查询当前 状态为 存续中 承接池计划
List<PlanBase> onGoingPlans = planRepo.getPlansByStatus(null,PlanStatusEnum.ONGOING);
LogUtil.info(LOGGER, "[ClearingOrderJob]-当前存续期计划数量[{0}]", onGoingPlans.size());
for (PlanBase entity : onGoingPlans) {
final String planNo = entity.getPlanNo();
try {
LogUtil.info(LOGGER, "{0}[{1}]结算单进行支付交易处理开始", entity.getPlanType().getDesc(), planNo);
transactionTemplate.execute(status -> {
planAstClearingOrderHandler.handle(entity);
return null;
});
LogUtil.info(LOGGER, "{0}[{1}]结算单进行支付交易处理结束", entity.getPlanType().getDesc(), planNo);
} catch (AbssqrBizException e) {
if (CommonErrorCodeEnum.NO_DATA == e.getErrCode()) {
LogUtil.warn(LOGGER, e.getMessage());
} else {
LogUtil.error(LOGGER, e, "{0}[{1}]结算单进行支付交易处理异常", entity.getPlanType().getDesc(), planNo);
}
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "{0}[{1}]结算单进行支付交易处理异常", entity.getPlanType().getDesc(), planNo);
}
}
}
}
\ No newline at end of file
/**
* abssqr.com Inc.
* Copyright (c) 2017-2018 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.plan;
import com.abssqr.plat.biz.shared.handler.PlanAstStatTaskHandler;
import com.abssqr.plat.biz.shared.scheduler.BaseQuartzJob;
import com.abssqr.plat.common.facade.enums.CommonErrorCodeEnum;
import com.abssqr.plat.common.facade.enums.PlanStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.model.exception.AbssqrBizException;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.common.util.base.Day;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.general.system.common.util.LogUtil;
import com.general.system.tool.util.ToolUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.List;
/**
* 资产清算统计业务 初始化清算汇总调度任务
*
* @author hanfei
* @version $Id: PlanAstStatJob.java, v 0.1 2018-01-06 上午12:39 hanfei Exp $
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class PlanAstStatJob extends BaseQuartzJob {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private PlanRepo planRepo;
@Autowired
private PlanAstStatTaskHandler planAstStatTaskHandler;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
/**
* 每天 5 0/5 * * * ?
*/
@Value("${sync.quartz.plan.stat}")
private String cron;
@Override
protected String getCronExpr() {
return cron;
}
@Override
public void doExecute() {
// 获取转让会计日
Day trfDate = orgAcctDayComponent.getTrfAcctDay();
LogUtil.info(LOGGER, "[PlanAstStatJob]-[{0}]资产清算统计业务start", trfDate.getDateString());
// 1.1 查询当前 状态为 存续中 承接池计划
List<PlanBase> onGoingPlans = planRepo.getPlansByStatus(null,PlanStatusEnum.ONGOING);
if (ToolUtil.isEmpty(onGoingPlans)){
return;
}
LogUtil.info(LOGGER, "[PlanAstStatJob]-当前存续期计划数量[{0}]", onGoingPlans.size());
for (PlanBase entity : onGoingPlans) {
final String planNo = entity.getPlanNo();
try {
LogUtil.info(LOGGER, "{0}[{1}]的统计任务初始化开始", entity.getPlanType().getDesc(), planNo);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
PlanBase lockedPlanBase = planRepo.lockPlanByNo(planNo);
if (lockedPlanBase.getStatus() != PlanStatusEnum.ONGOING) {
LogUtil.info(LOGGER, "计划[{0}]不在存续期,不进行统计任务", lockedPlanBase);
return;
}
planAstStatTaskHandler.handle(lockedPlanBase.getPlanNo(), trfDate);
}
});
LogUtil.info(LOGGER, "{0}[{1}]的统计任务初始化结束", entity.getPlanType().getDesc(), planNo);
} catch (AbssqrBizException e) {
if (CommonErrorCodeEnum.NO_DATA == e.getErrCode()) {
LogUtil.warn(LOGGER, e.getMessage());
} else {
LogUtil.error(LOGGER, e, "{0}[{1}]的统计任务初始化异常", entity.getPlanType().getDesc(), planNo);
}
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "{0}[{1}]的统计任务初始化异常", entity.getPlanType().getDesc(), planNo);
}
}
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.plan;
import com.abssqr.plat.biz.shared.scheduler.BaseQuartzJob;
import com.abssqr.plat.common.dal.mysql.auto.dataobject.PlanCapitalOrderDO;
import com.abssqr.plat.common.dal.mysql.auto.paging.PlanCapitalOrderPage;
import com.abssqr.plat.common.facade.enums.CommonErrorCodeEnum;
import com.abssqr.plat.common.facade.enums.TaskStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanCapitalOrder;
import com.abssqr.plat.common.model.domain.job.JobControl;
import com.abssqr.plat.common.model.exception.AbssqrBizException;
import com.abssqr.plat.common.model.repo.plan.PlanCapitalOrderRepo;
import com.abssqr.plat.core.share.pay.PlanCapitalOrderManager;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.SystemDateUtil;
import com.general.system.common.util.ThreadUtil;
import com.general.system.tool.util.ToolUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
/**
* 计划资金支付交易单发起处理
*
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.scheduler.job.plan: PlanCapitalOrderJob.java, v 0.1 2019-06-18 21:19 zhenxuan
* .luo Exp $
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class PlanCapitalOrderJob extends BaseQuartzJob {
@Autowired
private PlanCapitalOrderManager planCapitalOrderManager;
@Autowired
private PlanCapitalOrderRepo planCapitalOrderRepo;
@Autowired
private TransactionTemplate transactionTemplate;
/**
* 每天 30 3/5 * * * ?
*/
@Value("${sync.quartz.plan.capital}")
private String cron;
/**
* 每天 30 3/5 * * * ?
*/
@Value("${sync.space.capital:3000}")
private Long capital;
@Override
protected String getCronExpr() {
return cron;
}
@Override
protected boolean isRequestRecovery() {
return true;
}
@Override
public void doExecute() {
Date curExecTime = SystemDateUtil.getSystemDate();
// 获取 交易单据 改为查询 所有 init 状态的支付交易单 进行执行 使用分页查询减小外部并发
PlanCapitalOrderPage page = new PlanCapitalOrderPage();
page.setStatus(TaskStatusEnum.INIT.getCode());
page.setNextExecTime(curExecTime);
AtomicLong minId = new AtomicLong(0L);
do {
page.setId(minId.get());
// 1、查询资金单据
planCapitalOrderRepo.getCapitalOrderByStatus(page);
if (ToolUtil.isEmpty(page.getDatas())) {
LogUtil.info(LOGGER, "[CapitalOrderJob]-[{0}]资金支付交易单没有可执行数据", curExecTime);
return;
}
LogUtil.info(LOGGER, "[CapitalOrderJob]-[{0}]资金支付交易单发起处理任务start", curExecTime);
for (PlanCapitalOrderDO order : page.getDatas()) {
// 循环查询条件 设置最小id
minId.set( minId.get()<order.getId() ? order.getId() : minId.get());
try {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
// 交易单 加锁
PlanCapitalOrder lockOrdr = planCapitalOrderRepo.lockBySeqNo(order.getSeqNo());
// 执行时间判断
if (curExecTime.compareTo(lockOrdr.getProcTime()) >= 0) {
JobControl jobControl = jobControlRepository.selectByJobName(getJobName());
if (!jobControl.getIsEff().isYes()) {
LogUtil.warn(LOGGER, "计划资金单[{0}]终止,任务控制生效标记为[{1}]", getJobName(), jobControl.getIsEff());
return;
}
planCapitalOrderManager.processCapitalOrder(lockOrdr, SystemDateUtil.getSystemDate());
}
}
});
} catch (AbssqrBizException e) {
if (CommonErrorCodeEnum.NO_DATA == e.getErrCode()) {
LogUtil.warn(LOGGER, e.getMessage());
} else {
LogUtil.error(LOGGER, e, "计划资金单[{0}]发起交易异常:[{1}]", order.getSeqNo(), e.getMessage());
}
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "计划资金单[{0}]发起交易异常:[{1}]", order.getSeqNo(), e.getMessage());
}finally {
ThreadUtil.sleep(capital,LOGGER);
}
}
} while (page.hasNextPage());
LogUtil.info(LOGGER, "[CapitalOrderJob]-[{0}]资金支付交易单发起处理任务end:[{1}]", curExecTime, minId);
}
}
\ No newline at end of file
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.plan;
import com.abssqr.plat.biz.shared.scheduler.BaseQuartzJob;
import com.abssqr.plat.common.dal.mysql.auto.dataobject.PlanCapitalOrderDO;
import com.abssqr.plat.common.dal.mysql.auto.paging.PlanCapitalOrderPage;
import com.abssqr.plat.common.facade.enums.TaskStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanCapitalOrder;
import com.abssqr.plat.common.integration.wk.domain.qry.response.trade.TradeResult;
import com.abssqr.plat.common.integration.wk.domain.qry.response.trade.TradeResultItem;
import com.abssqr.plat.common.model.convertor.PlanCapitalOrderConvertor;
import com.abssqr.plat.common.model.repo.plan.PlanCapitalOrderRepo;
import com.abssqr.plat.core.service.wk.pay.WkPayManager;
import com.abssqr.plat.core.share.pay.PlanCapitalFinishRequest;
import com.abssqr.plat.core.share.pay.PlanCapitalOrderManager;
import com.general.system.common.model.Money;
import com.general.system.common.util.LogUtil;
import com.general.system.common.util.SystemDateUtil;
import com.general.system.tool.util.ToolUtil;
import com.google.common.collect.Maps;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
/**
* 计划资金支付交易单结果查询
*
* @author zhenxuan.luo
* @version com.abssqr.plat.biz.shared.scheduler.job.plan: PlanCapitalOrderJob.java, v 0.1 2019-06-18 21:19 zhenxuan
* .luo Exp $
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class PlanCapitalOrderResJob extends BaseQuartzJob {
@Autowired
private PlanCapitalOrderManager planCapitalOrderManager;
@Autowired
private PlanCapitalOrderRepo planCapitalOrderRepo;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private WkPayManager wkPayManager;
/**
* 每天 30 4/5 * * * ?
*/
@Value("${sync.quartz.plan.query}")
private String cron;
@Override
protected String getCronExpr() {
return cron;
}
@Override
protected boolean isRequestRecovery() {
return true;
}
/**
* 支付结果查询
* 1、查询资金单据 状态为 {@link TaskStatusEnum WAITING}
* 2、以 planCapitalOrder.getOutAcptNo() 对应 tradeNo 查询五矿订单结果接口
* 3、更新 资金单据 支付结果
*
* @throws JobExecutionException
*/
@Override
public void doExecute() {
Date curExecTime = SystemDateUtil.getSystemDate();
AtomicInteger count = new AtomicInteger();
PlanCapitalOrderPage page = new PlanCapitalOrderPage();
page.setNextExecTime(curExecTime);
page.setStatus(TaskStatusEnum.WAITING.getCode());
AtomicLong minId = new AtomicLong(0L);
do {
page.setId(minId.get());
// 1、查询资金单据
planCapitalOrderRepo.getCapitalOrderByStatus(page);
if (ToolUtil.isEmpty(page.getDatas())) {
LogUtil.info(LOGGER, "[CapitalOrderResJob]-[{0}]资金支付交易单没有可执行数据", curExecTime);
return;
}
LogUtil.info(LOGGER, "[CapitalOrderResJob]-[{0}]资金支付交易单结果查询任务start", curExecTime);
List<String> entryNos = new ArrayList<>(page.getDatas().size());
Map<String, PlanCapitalOrder> tradeMap = page.getDatas().stream().map(one -> {
entryNos.add(one.getOutAcptNo());
minId.set(minId.get()<one.getId()?one.getId():minId.get());
return one;
}).collect(Collectors
.toMap(PlanCapitalOrderDO::getOutAcptNo,
item -> PlanCapitalOrderConvertor.convert2Domain(item)));
LogUtil.info(LOGGER, "[CapitalOrderResJob]-[{0}]资金支付交易单结果查询任务-minId={1}", curExecTime, minId.get());
try {
// 2、查询五矿订单结果接口
TradeResult result = wkPayManager.tradeRstQry(entryNos);
final Map<String, TradeResultItem> enNoTradeMap = Maps.newHashMap();
if (ToolUtil.isNotEmpty(result.getPayInfoList())) {
enNoTradeMap.putAll(result.getPayInfoList().stream().collect(
Collectors.toMap(TradeResultItem::getEntryNo, tradeResultItem -> tradeResultItem)));
}
tradeMap.forEach((entryNo, order) -> {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
TradeResultItem item = enNoTradeMap.get(entryNo);
if (item == null) {
LogUtil.warn(LOGGER,"资金支付交易单结果查询-未查到条目号对应的结果,等待下次查询:{0}", entryNo);
} else {
PlanCapitalFinishRequest finishRequest = new PlanCapitalFinishRequest();
finishRequest.setSeqNo(order.getSeqNo());
finishRequest.setOutTransNo(item.getEntryNo());
finishRequest.setCfrmAmt(Money.createWithCent(item.getPayMoney()));
boolean isOver = false;
// 判断查询结果状态
switch (item.getStatus()) {
case 成功:
finishRequest.setRes(TaskStatusEnum.SUCCESS);
finishRequest.setMemo(item.getStatus().getDesc());
isOver = true;
break;
case 处理中:
// 处理中不做操作继续查询
break;
case 支付平台异常:
//什么都不做,发告警 fixme 发站内信,运营人员通知支付平台排查问题。
LogUtil.error(LOGGER,"支付平台异常-[{0}]",entryNo);
break;
default:
finishRequest.setRes(TaskStatusEnum.FAILURE);
finishRequest.setMemo(item.getStatus().getDesc());
isOver = true;
}
if (isOver) {
// 3、更新 资金单据 支付结果
planCapitalOrderManager.finishCapitalOrder(finishRequest);
}
}
count.getAndIncrement();
}
});
});
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "查询五矿订单结果接口异常:{0}", e.getMessage());
}
} while (page.hasNextPage());
LogUtil.info(LOGGER, "[CapitalOrderResJob]-[{0}]资金支付交易单结果查询任务end,exec[{1}]", curExecTime, count.get());
}
}
\ No newline at end of file
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.biz.shared.scheduler.job.plan;
import com.abssqr.plat.biz.shared.handler.PlanFundHandler;
import com.abssqr.plat.biz.shared.scheduler.BaseQuartzJob;
import com.abssqr.plat.common.facade.enums.PlanStatusEnum;
import com.abssqr.plat.common.facade.model.plan.PlanBase;
import com.abssqr.plat.common.model.repo.plan.PlanRepo;
import com.abssqr.plat.common.util.base.Day;
import com.abssqr.plat.core.service.accounting.OrgAcctDayComponent;
import com.general.system.common.util.LogUtil;
import com.general.system.tool.util.ToolUtil;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 资金到账情况查询
*
* @author bangis.wangdf
* @version com.abssqr.plat.biz.shared.scheduler.job.plan: PlanFundJob.java, v 0.1 2019-06-16 16:08 bangis.wangdf Exp $
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class PlanFundJob extends BaseQuartzJob {
@Autowired
private PlanFundHandler planFundHandler;
@Autowired
private PlanRepo planRepo;
@Autowired
private OrgAcctDayComponent orgAcctDayComponent;
/**
* 每天 45 11/20 * * * ?
*/
@Value("${sync.quartz.plan.fund}")
private String cron;
@Override
protected String getCronExpr() {
return cron;
}
@Override
protected boolean isRequestRecovery() {
return true;
}
/**
* 计划银行账户余额查询
* 1、放款池回款户
* 2、受让池业务户
*
* @throws JobExecutionException
*/
@Override
public void doExecute() {
// 获取转让会计日
Day curDate = orgAcctDayComponent.getTrfAcctDay();
LogUtil.info(LOGGER, "[FundJob]-[{0}]余额查询任务start", curDate);
// 1.1 查询当前 状态为 存续中 承接池计划
List<PlanBase> onGoingPlans = planRepo.getPlansByStatus(null,PlanStatusEnum.ONGOING);
if (ToolUtil.isEmpty(onGoingPlans)){
return;
}
for (PlanBase entity : onGoingPlans) {
try {
// 执行余额查询
planFundHandler.executeQueryBalance(entity, curDate);
} catch (Throwable e) {
LogUtil.error(LOGGER, e, "[FundJob]计划[{0}]余额修正任务异常", entity);
}
}
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.Result;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
import com.abssqr.plat.common.integration.wk.domain.opr.OprRstHeader;
import com.abssqr.plat.common.integration.wk.domain.opr.request.acct.WkAccount;
import com.abssqr.plat.common.integration.wk.domain.opr.request.trade.TradeList;
import com.abssqr.plat.common.integration.wk.domain.opr.response.AccountListResult;
import com.abssqr.plat.common.integration.wk.domain.opr.response.ProjectResult;
import com.abssqr.plat.common.integration.wk.domain.qry.QryRstHeader;
import com.abssqr.plat.common.integration.wk.domain.qry.response.BalanceResult;
import com.abssqr.plat.common.integration.wk.domain.qry.response.trade.TradeResult;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
/**
* 五矿支付平台接口
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk: WkPayIntegration.java, v 0.1 2019-06-19 11:10 bangis.wangdf Exp $
*/
public interface WkPayIntegration {
/**
* 租户签约与维护
*
* @param seqNo 业务流水号,五矿使用UUID
* @return
*/
Result<OprRstHeader, ProjectResult> project(String seqNo,String projNo,String projName);
/**
* 账户信息维护
*
* @param seqNo
* @param accountList
* @return
*/
Result<OprRstHeader, AccountListResult> account(String seqNo, List<WkAccount> accountList);
/**
* 账户余额查询 B100002
* 最多50条
*
* @param seqNo
* @param no
* @return
*/
Result<QryRstHeader, BalanceResult> balance(String seqNo, String no, WkChannelNoEnum channelNo);
/**
* 代理交易
*
* @param seqNo
* @param tradeList
* @return
*/
Result<OprRstHeader, WkBody> trade(String seqNo, TradeList tradeList);
/**
* 代理交易结果查询
*
* @param seqNo
* @param entryNos
* @return
*/
Result<QryRstHeader, TradeResult> tradeRstQry(String seqNo, List<String> entryNos);
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: Request.java, v 0.1 2019-06-18 14:46 bangis.wangdf Exp $
*/
@XmlRootElement(name = "Package")
public class Request<H extends WkHeader, B extends WkBody> extends WkObject {
private H header;
private B body;
public H getHeader() {
return header;
}
public void setHeader(H header) {
this.header = header;
}
public B getBody() {
return body;
}
public void setBody(B body) {
this.body = body;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: Request.java, v 0.1 2019-06-18 14:46 bangis.wangdf Exp $
*/
public class Result<H extends WkHeader, B extends WkBody> extends WkObject {
private Class<H> headerClazz;
private Class<B> bodyClazz;
public Result(Class<H> headerClazz, Class<B> bodyClazz) {
this.headerClazz = headerClazz;
this.bodyClazz = bodyClazz;
}
private H header;
private B body;
public H getHeader() {
return header;
}
public void setHeader(H header) {
this.header = header;
}
public B getBody() {
return body;
}
public void setBody(B body) {
this.body = body;
}
public Class<H> getHeaderClazz() {
return headerClazz;
}
public Class<B> getBodyClazz() {
return bodyClazz;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain;
/**
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: WkBody.java, v 0.1 2019-06-18 14:51 bangis.wangdf Exp $
*/
public class WkBody extends WkObject{
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain;
import java.util.Date;
import com.abssqr.plat.common.integration.wk.enums.WkAsynEnum;
import com.abssqr.plat.common.integration.wk.enums.ComIdEnum;
import com.abssqr.plat.common.integration.wk.enums.RequestTypeEnum;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: WkHeader.java, v 0.1 2019-06-18 14:47 bangis.wangdf Exp $
*/
public abstract class WkHeader extends WkObject {
/**
* 交易请求码
*/
private RequestTypeEnum RequestType;
/**
* 唯一编码
*/
private String UUID;
/**
* 业务系统标号
*/
private ComIdEnum comId;
/**
* 白名单ip地址
*/
private String comIP;
/**
* 请求发送时间
*/
private Date sendTime;
/**
* 是否异步接口
*/
private WkAsynEnum asyn;
/**
* 回调Url
*/
private String returnUrl;
/**
* 签名串
*/
private String signed;
/**
* 客户端 枚举 10 N
*/
private String clientType;
public RequestTypeEnum getRequestType() {
return RequestType;
}
public void setRequestType(RequestTypeEnum requestType) {
RequestType = requestType;
}
public String getUUID() {
return UUID;
}
public void setUUID(String UUID) {
this.UUID = UUID;
}
public ComIdEnum getComId() {
return comId;
}
public void setComId(ComIdEnum comId) {
this.comId = comId;
}
public String getComIP() {
return comIP;
}
public void setComIP(String comIP) {
this.comIP = comIP;
}
public Date getSendTime() {
return sendTime;
}
public void setSendTime(Date sendTime) {
this.sendTime = sendTime;
}
public WkAsynEnum getAsyn() {
return asyn;
}
public void setAsyn(WkAsynEnum asyn) {
this.asyn = asyn;
}
public String getReturnUrl() {
return returnUrl;
}
public void setReturnUrl(String returnUrl) {
this.returnUrl = returnUrl;
}
public String getSigned() {
return signed;
}
public void setSigned(String signed) {
this.signed = signed;
}
public String getClientType() {
return clientType;
}
public void setClientType(String clientType) {
this.clientType = clientType;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: WkObject.java, v 0.1 2019-06-18 17:41 bangis.wangdf Exp $
*/
public abstract class WkObject {
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
/**
* @see java.lang.Object#clone()
*/
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: WkPayConfig.java, v 0.1 2019-06-19 19:00 bangis.wangdf Exp $
*/
@Component
@ConfigurationProperties(prefix = "wkabs.pay")
public class WkPayConfig {
/**
* 项目编号
*/
private String projNo;
/**
* 项目名称
*/
private String projName;
/**
* 余额类型(
* 本地("0", "本地"),
* 渠道余额("1", "渠道余额"),)
*/
private String balanceType;
/**
* 交易代理结果回调
*/
private String tradeCallBackUrl;
/**
* 五矿支付wsdl地址
*/
private String host;
public String getProjNo() {
return projNo;
}
public void setProjNo(String projNo) {
this.projNo = projNo;
}
public String getProjName() {
return projName;
}
public void setProjName(String projName) {
this.projName = projName;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getTradeCallBackUrl() {
return tradeCallBackUrl;
}
public void setTradeCallBackUrl(String tradeCallBackUrl) {
this.tradeCallBackUrl = tradeCallBackUrl;
}
public String getBalanceType() {
return balanceType;
}
public void setBalanceType(String balanceType) {
this.balanceType = balanceType;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.config;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.IoUtil;
import com.abssqr.gateway.util.SftpUtil;
import com.abssqr.plat.common.facade.enums.CommonErrorCodeEnum;
import com.abssqr.plat.common.model.exception.AbssqrBizException;
import com.abssqr.plat.common.model.utils.SftpFileUtil;
import com.jcraft.jsch.ChannelSftp;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.InputStream;
/**
* sftp 配置
* @author hanfei
* @version $Id: WkSftpConfig.java, v 0.1 2019-09-19 4:23 PM hanfei Exp $
*/
@Component
@ConfigurationProperties(prefix = "wkabs.upload")
public class WkSftpConfig {
private static ThreadLocal<SftpFileUtil> selfChannelSftpThreadLocal = new ThreadLocal<>();
/**
* sftp 下载
*/
public FastByteArrayOutputStream downloadSftp(String fileSrc){
try {
InputStream stream = SftpUtil.getInputStream(fileSrc, this.selfChannelSftp());
return IoUtil.read(stream);
} catch (Exception e) {
throw new AbssqrBizException("下载文件异常", CommonErrorCodeEnum.SFTP_ERROR, e);
} finally {
close();
}
}
/**
* sftp 上传
*/
public boolean uploadSftp(InputStream stream, String fileName, String filePath){
try {
boolean result = SftpUtil.uploadFile(filePath, fileName, stream, this.selfChannelSftp());
if (!result){
throw new AbssqrBizException("上传文件失败", CommonErrorCodeEnum.SFTP_ERROR);
}
return result;
} catch (Exception e) {
throw new AbssqrBizException("上传文件异常", CommonErrorCodeEnum.SFTP_ERROR, e);
} finally {
close();
}
}
/**
* 获取sftp 连接通道
* @return
*/
public ChannelSftp selfChannelSftp() {
if (selfChannelSftpThreadLocal.get() == null) {
SftpFileUtil _sftpFileUtil = new SftpFileUtil(
this.getHost(),
this.getPort(),
this.getUsername(),
this.getPassword());
selfChannelSftpThreadLocal.set(_sftpFileUtil);
}
return selfChannelSftpThreadLocal.get().getChannel();
}
/**
* 关闭连接通道
*/
public static void close() {
if (selfChannelSftpThreadLocal.get() != null) {
selfChannelSftpThreadLocal.get().close();
selfChannelSftpThreadLocal.set(null);
}
}
/**
* 上传方式
*/
private String type;
/**
* 地址
*/
private String host;
/**
* 端口
*/
private Integer port;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 超时时间
*/
private String timeout;
/**
* 上传路径
*/
private String path;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTimeout() {
return timeout;
}
public void setTimeout(String timeout) {
this.timeout = timeout;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr;
import com.abssqr.plat.common.integration.wk.domain.WkHeader;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.ws: OprHeader.java, v 0.1 2019-06-18 14:02 bangis.wangdf Exp $
*/
public class OprHeader extends WkHeader {
/**
* 交易数量
*/
private int tradeCount;
public int getTradeCount() {
return tradeCount;
}
public void setTradeCount(int tradeCount) {
this.tradeCount = tradeCount;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr;
import com.abssqr.plat.common.integration.wk.domain.WkHeader;
import com.abssqr.plat.common.integration.wk.enums.ComIdEnum;
import com.abssqr.plat.common.integration.wk.enums.PlatResultCodeEnum;
import com.abssqr.plat.common.integration.wk.enums.RequestTypeEnum;
import java.util.Date;
/**
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.ws: OprRstHeader.java, v 0.1 2019-06-18 14:24 bangis.wangdf Exp $
*/
public class OprRstHeader extends WkHeader {
/**
* 返回状态 10000 成功 90000 支付平台异常
*/
private PlatResultCodeEnum resultCode;
/**
* 返回信息描述
*/
private String resultMsg;
public PlatResultCodeEnum getResultCode() {
return resultCode;
}
public void setResultCode(PlatResultCodeEnum resultCode) {
this.resultCode = resultCode;
}
public String getResultMsg() {
return resultMsg;
}
public void setResultMsg(String resultMsg) {
this.resultMsg = resultMsg;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
import com.abssqr.plat.common.integration.wk.enums.ProjStateEnum;
/**
* 3.2.13租户信息维护
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request: Project.java, v 0.1 2019-06-19 10:54 bangis
* .wangdf Exp $
*/
@XmlRootElement(name = "ProjectCreate")
public class Project extends WkBody {
/**
* 租户号
*/
private String projNo;
/**
* 租户名称
*/
private String projName;
/**
* 租户状态 字符 2 Y 01-生效,02-失效
*/
private ProjStateEnum ProjState;
/**
* 保留域
*/
private String info1;
public String getProjNo() {
return projNo;
}
public void setProjNo(String projNo) {
this.projNo = projNo;
}
public String getProjName() {
return projName;
}
public void setProjName(String projName) {
this.projName = projName;
}
public ProjStateEnum getProjState() {
return ProjState;
}
public void setProjState(ProjStateEnum projState) {
ProjState = projState;
}
public String getInfo1() {
return info1;
}
public void setInfo1(String info1) {
this.info1 = info1;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.acct;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
/**
* 账户列表
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request: AccountList.java, v 0.1 2019-06-19 18:41 bangis.wangdf Exp $
*/
public class AccountList extends WkBody {
List<WkAccount> accountList;
public List<WkAccount> getAccountList() {
return accountList;
}
public void setAccountList(List<WkAccount> accountList) {
this.accountList = accountList;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.acct;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.WkAcctKindEnum;
import com.abssqr.plat.common.integration.wk.enums.WkAcctTypeEnum;
import com.abssqr.plat.common.integration.wk.utils.WkSequenceUtil;
import com.abssqr.plat.common.integration.wk.utils.WkSequenceUtil.Account;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 账户信息
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request: WkAccount.java, v 0.1 2019-06-19 18:42 bangis
* .wangdf Exp $
*/
@XmlRootElement(name = "AccountInfo")
public class WkAccount extends WkObject {
/**
AccountNo 账户号 字符 32 Y 不能使用ufc(不区分大小写)开头,业务系统保证唯一并以业务系统编号开头,且只能由数字、字母和下划线组成
AccountName 账户名称 字符 128 N 非空时使用
TenantNo 租户编号 字符 32 Y 支付平台开通的租户编号,使用前向支付平台获取,一旦与账户绑定成功后无法修改
CustNo 客户号/用户号 字符 64 N 不能使用ufc(不区分大小写)开头,业务系统保证唯一,且只能由数字、字母和下划线组成
CustName 客户名称/用户名称 字符 128 N 非空时使用
AcctType 账户类型 字符 2 Y 1-放款账户,2-扣款账户,3-商户账户,4-费用账户,5-溢缴款账户
AcctKind 账户种类 字符 2 N 非必填,为空的情况下为 对私,指定了 账户种类 之后,按照指定的 类型进行建立。
01为对公,02为对私
*/
/**
* @see Account#genAccountNo(com.abssqr.plat.common.integration.wk.enums.TradeTypeEnum, java.lang.String, com.abssqr.plat.common.facade.enums.AccountAttributeEnum)
* 不能使用ufc(不区分大小写)开头,业务系统保证唯一并以业务系统编号开头,且只能由数字、字母和下划线组成
* 000004_TradeTypeEnum_planNo
*/
private String accountNo;
/**
* @see Account#genAccountName(com.abssqr.plat.common.integration.wk.enums.TradeTypeEnum, java.lang.String, com.abssqr.plat.common.facade.enums.AccountAttributeEnum)
* 不能使用ufc(不区分大小写)开头,业务系统保证唯一并以业务系统编号开头,且只能由数字、字母和下划线组成
* 000004_扣款/放款_planName
*/
private String accountName;
/**
* 租户编号 之前生成的租户编号
*/
private String tenantNo;
/**
* @see WkSequenceUtil.Account#genCustNo(String)
* 客户号,使用计划编号
* 000004_planNo
*/
private String custNo;
/**
* @see WkSequenceUtil.Account#genCustName(String)
* 客户名称 计划名称
*/
private String custName;
/**
* 账户类型 字符 2 Y 1-放款账户,2-扣款账户,3-商户账户,4-费用账户,5-溢缴款账户
*/
private WkAcctTypeEnum acctType;
/**
* 账户种类 字符 2 N 非必填,为空的情况下为 对私,指定了 账户种类 之后,按照指定的 类型进行建立。
* 01为对公,02为对私
*/
private WkAcctKindEnum acctKind;
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getTenantNo() {
return tenantNo;
}
public void setTenantNo(String tenantNo) {
this.tenantNo = tenantNo;
}
public String getCustNo() {
return custNo;
}
public void setCustNo(String custNo) {
this.custNo = custNo;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public WkAcctTypeEnum getAcctType() {
return acctType;
}
public void setAcctType(WkAcctTypeEnum acctType) {
this.acctType = acctType;
}
public WkAcctKindEnum getAcctKind() {
return acctKind;
}
public void setAcctKind(WkAcctKindEnum acctKind) {
this.acctKind = acctKind;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.trade;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.WkAccountTypeEnum;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request.trade: TdAccountInfo.java, v 0.1 2019-06-20 20:51
* bangis.wangdf Exp $
*/
@XmlRootElement(name = "AccountInfo")
public class TdAccountInfo extends WkObject {
/**
* 账户号 字符 32 Y 银行账户号或支付平台账户号
**/
private String accountNo;
/**
* 账户类型 枚举 2 Y 详见4.7
**/
private WkAccountTypeEnum accountType;
/**
* 账户姓名 字符 64 S 账户姓名,使用银行账户时非空
**/
private String accountName;
/**
* 支付系统渠道(银行)编号 枚举 10 S 见4.3渠道代码列表,使用客户银行账户时非空
**/
private WkChannelNoEnum channelNo;
/**
* 联行号 枚举 20 S 联行号,暂时未使用
**/
private String bankDetailNo;
/**
* 开户行名称 字符 128 S 网点/支行名称 当账户类型为企业账户时该项必填
**/
private String bankName;
/**
* 开户行所在省 字符 128 S 网点/支行所在省 当账户类型为企业账户时该项必填
**/
private String province;
/**
* 开户行所在市 字符 128 S 网点/支行所在市 当账户类型为企业账户时该项必填
**/
private String city;
/**
* 信用卡3位安全码 字符 3 S 信用卡3位安全码 账户类型为个人信用卡必填
**/
private String CVN2;
/**
* 信用卡有效期 字符 4 S 格式 YYMM 账户类型为个人信用卡必填
**/
private String VALDATE;
/**
* 手机号 字符 15 N 手机号
**/
private String phoneNo;
/**
* email 字符 20 N email
**/
private String Email;
/**
* 证件类型 字符 5 Y 见4.6目前仅支持身份证
* 0 个人 身份证
* 1 个人 户口簿
* 2 个人 护照
* 3 个人 军官证
* 4 个人 士兵证
* 5 个人 港澳居民来往内地通行证
* 6 个人 台湾同胞来往内地通行证
* 7 个人 临时身份证
* 8 个人 外国人居留证
* 9 个人 警官证
* X 个人/企业 其他证件
* A 企业 组织机构代码证号
* B 企业 营业执照号码
* C 企业 登记证书
* D 企业 国税登记证号码
* E 企业 地税登记证号码
* F 企业 开户许可证
* G 企业 事业单位编号
* I 企业 金融许可证编号
**/
private String certificateType;
/**
* 证件号 字符 20 Y 证件号
**/
private String certificateNo;
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public WkAccountTypeEnum getAccountType() {
return accountType;
}
public void setAccountType(WkAccountTypeEnum accountType) {
this.accountType = accountType;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public WkChannelNoEnum getChannelNo() {
return channelNo;
}
public void setChannelNo(WkChannelNoEnum channelNo) {
this.channelNo = channelNo;
}
public String getBankDetailNo() {
return bankDetailNo;
}
public void setBankDetailNo(String bankDetailNo) {
this.bankDetailNo = bankDetailNo;
}
public String getBankName() {
return bankName;
}
public void setBankName(String bankName) {
this.bankName = bankName;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCVN2() {
return CVN2;
}
public void setCVN2(String CVN2) {
this.CVN2 = CVN2;
}
public String getVALDATE() {
return VALDATE;
}
public void setVALDATE(String VALDATE) {
this.VALDATE = VALDATE;
}
public String getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(String phoneNo) {
this.phoneNo = phoneNo;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public String getCertificateType() {
return certificateType;
}
public void setCertificateType(String certificateType) {
this.certificateType = certificateType;
}
public String getCertificateNo() {
return certificateNo;
}
public void setCertificateNo(String certificateNo) {
this.certificateNo = certificateNo;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.trade;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
import com.abssqr.plat.common.integration.wk.enums.EnTradeTypeEnum;
import com.abssqr.plat.common.integration.wk.utils.WkSequenceUtil.Trade;
/**
* 交易详情
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request: TdEntryInfo.java, v 0.1 2019-06-20 20:19 bangis
* .wangdf Exp $
*/
@XmlRootElement(name = "EntryInfo")
public class TdEntryInfo extends WkObject {
/**
EntryNo 条目号 字符 50 Y 业务系统保证唯一,并以业务系统编号开头
EnTradeType 条目交易类型 枚举 2 Y 详见4.4
Amount 金额 金钱 10 Y 交易金额(单位:分)
EntryTypeNo 条目类型编号 数字 10 Y 最大长度10位数字
须由交易类型编号开头
统一交易内编号长度必须一致,统一交易编号补不能重复
(交易优先级按照条目类型编号,由小到大)
ChannelNo 渠道编号 字符 6 S 指定渠道,选填,如果有效则直接使用指定渠道而不路由,如果无效则直接失败。
SourceAccountList 源交易账户信息列表 列表 Y 列表内容为SourceAccountInfo,不同交易对列表数量要求不同,详见4.4 根据扣款放款转换
TargetAccountList 目标交易账户信息列表 列表 Y 列表内容为 TargetAccountInfo,不同交易对列表数量要求不同,详见4.4
Remark1 备注1 字符 128 N 备注1
Remark2 备注2 字符 128 N 备注2
Remark3 备注3 字符 128 N 备注3
*/
/**
* @see Trade#genEntryNo()
* 条目号 字符 50 Y 业务系统保证唯一,并以业务系统编号开头
*/
private String entryNo;
/**
* 条目交易类型 枚举 2 Y 详见4.4
*/
private EnTradeTypeEnum enTradeType;
/**
* 金额 金钱 10 Y 交易金额(单位:分)
*/
private long amount;
/**
* @see Trade#genEntryTypeNo(EnTradeTypeEnum, int)
* 条目类型编号 数字 10 Y 最大长度10位数字
* 须由交易类型编号开头
* 统一交易内编号长度必须一致,统一交易编号补不能重复
* (交易优先级按照条目类型编号,由小到大)
*/
private String entryTypeNo;
/**
* 渠道编号 字符 6 S 指定渠道,选填,如果有效则直接使用指定渠道而不路由,如果无效则直接失败。
*/
private WkChannelNoEnum channelNo;
/**
* 源交易账户信息列表 列表 Y 列表内容为SourceAccountInfo,不同交易对列表数量要求不同,详见4.4 根据扣款放款转换
*/
private List<TdSourceAccountInfo> sourceAccountList;
/**
* TargetAccountList 目标交易账户信息列表 列表 Y 列表内容为 TargetAccountInfo,不同交易对列表数量要求不同,详见4.4
*/
private List<TdTargetAccountInfo> targetAccountList;
private String remark1;
private String remark2;
private String remark3;
public String getEntryNo() {
return entryNo;
}
public void setEntryNo(String entryNo) {
this.entryNo = entryNo;
}
public EnTradeTypeEnum getEnTradeType() {
return enTradeType;
}
public void setEnTradeType(EnTradeTypeEnum enTradeType) {
this.enTradeType = enTradeType;
}
public long getAmount() {
return amount;
}
public void setAmount(long amount) {
this.amount = amount;
}
public String getEntryTypeNo() {
return entryTypeNo;
}
public void setEntryTypeNo(String entryTypeNo) {
this.entryTypeNo = entryTypeNo;
}
public WkChannelNoEnum getChannelNo() {
return channelNo;
}
public void setChannelNo(WkChannelNoEnum channelNo) {
this.channelNo = channelNo;
}
public List<TdSourceAccountInfo> getSourceAccountList() {
return sourceAccountList;
}
public void setSourceAccountList(List<TdSourceAccountInfo> sourceAccountList) {
this.sourceAccountList = sourceAccountList;
}
public List<TdTargetAccountInfo> getTargetAccountList() {
return targetAccountList;
}
public void setTargetAccountList(List<TdTargetAccountInfo> targetAccountList) {
this.targetAccountList = targetAccountList;
}
public String getRemark1() {
return remark1;
}
public void setRemark1(String remark1) {
this.remark1 = remark1;
}
public String getRemark2() {
return remark2;
}
public void setRemark2(String remark2) {
this.remark2 = remark2;
}
public String getRemark3() {
return remark3;
}
public void setRemark3(String remark3) {
this.remark3 = remark3;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.trade;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
/**
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request.trade: TdSourceAccountInfo.java, v 0.1 2019-06-20 20:48 bangis.wangdf Exp $
*/
@XmlRootElement(name = "SourceAccountInfo")
public class TdSourceAccountInfo extends WkObject {
/**
* 账户信息
*/
private TdAccountInfo accountInfo;
/**
* 优先级,如果有多个交易账号时需要通过优先级指定使用顺序(同一条目内不能重复),按从小到大使用,长度固定2
*/
private int level;
public TdAccountInfo getAccountInfo() {
return accountInfo;
}
public void setAccountInfo(TdAccountInfo accountInfo) {
this.accountInfo = accountInfo;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.trade;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
/**
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request.trade: TdSourceAccountInfo.java, v 0.1 2019-06-20 20:48 bangis.wangdf Exp $
*/
@XmlRootElement(name = "TargetAccountInfo")
public class TdTargetAccountInfo extends WkObject {
/**
* 账户信息
*/
private TdAccountInfo accountInfo;
/**
* 优先级,如果有多个交易账号时需要通过优先级指定使用顺序(同一条目内不能重复),按从小到大使用,长度固定2
*/
private int level;
public TdAccountInfo getAccountInfo() {
return accountInfo;
}
public void setAccountInfo(TdAccountInfo accountInfo) {
this.accountInfo = accountInfo;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.trade;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.TradeTypeEnum;
/**
* 交易信息
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request: TradeInfo.java, v 0.1 2019-06-20 20:15 bangis
* .wangdf Exp $
*/
public class TradeInfo extends WkObject {
/**
* TradeNo 交易号 字符 50 Y 业务系统保证唯一,并以业务系统编号开头
* TradeTypeNo 交易类型编号 数字 6 Y 最大长度6位数字 001放,002扣款
* TotalEntryNum 总条目数 字符 2 Y 最大10(同一交易最多10个条目)
* EntryList 交易详情 列表 Y 列表内容为 TdEntryInfo
*/
/**
*
* 交易号 字符 50 Y 业务系统保证唯一,并以业务系统编号开头
*/
private String tradeNo;
/**
* 交易类型编号 数字 6 Y 最大长度6位数字 001放,002扣款
*/
private TradeTypeEnum tradeTypeNo;
/**
* 总条目数 字符 2 Y 最大10(同一交易最多10个条目)
*/
private Long totalEntryNum;
/**
* 交易详情 列表 Y 列表内容为 TdEntryInfo
*/
private List<TdEntryInfo> entryList;
public String getTradeNo() {
return tradeNo;
}
public void setTradeNo(String tradeNo) {
this.tradeNo = tradeNo;
}
public TradeTypeEnum getTradeTypeNo() {
return tradeTypeNo;
}
public void setTradeTypeNo(TradeTypeEnum tradeTypeNo) {
this.tradeTypeNo = tradeTypeNo;
}
public Long getTotalEntryNum() {
if(totalEntryNum==null&&this.entryList!=null){
return Long.valueOf(this.entryList.size());
}
return totalEntryNum;
}
public void setTotalEntryNum(Long totalEntryNum) {
this.totalEntryNum = totalEntryNum;
}
public List<TdEntryInfo> getEntryList() {
return entryList;
}
public void setEntryList(List<TdEntryInfo> entryList) {
this.entryList = entryList;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.request.trade;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
/**
* 代理交易
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.request: TradeList.java, v 0.1 2019-06-20 20:12 bangis
* .wangdf Exp $
*/
public class TradeList extends WkBody {
private List<TradeInfo> tradeList;
public List<TradeInfo> getTradeList() {
return tradeList;
}
public void setTradeList(List<TradeInfo> tradeList) {
this.tradeList = tradeList;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.response;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.response: AccountListResult.java, v 0.1 2019-06-19 19:17
* bangis.wangdf Exp $
*/
public class AccountListResult extends WkBody {
List<AccountResult> accountList;
public List<AccountResult> getAccountList() {
return accountList;
}
public void setAccountList(
List<AccountResult> accountList) {
this.accountList = accountList;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.response;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.WkAcctStatusEnum;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.response: AccountResult.java, v 0.1 2019-06-19 19:17
* bangis.wangdf Exp $
*/
@XmlRootElement(name = "AccountInfo")
public class AccountResult extends WkObject {
/**
* AccountNo 账户号 字符 64 Y 不能使用ufc(不区分大小写)开头,业务系统保证唯一并以业务系统编号开头
* Status 交易状态 枚举 2 Y 见4.5
* Message 信息描述 字符 128 Y
*/
private String accountNo;
/**
* 交易状态
*/
private WkAcctStatusEnum status;
/**
* 信息描述
*/
private String message;
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public WkAcctStatusEnum getStatus() {
return status;
}
public void setStatus(WkAcctStatusEnum status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.opr.response;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
import com.abssqr.plat.common.integration.wk.enums.WkResultCodeEnum;
/**
* 3.2.13租户信息维护结果
*
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.opr.response: ProjectResult.java, v 0.1 2019-06-19 11:04
* bangis.wangdf Exp $
*/
@XmlRootElement(name = "ProjectCreateResult")
public class ProjectResult extends WkBody {
/**
* 信息维护结果
*/
private WkResultCodeEnum resultCode;
/**
* 信息维护结果描述
*/
private String resultDesc;
public WkResultCodeEnum getResultCode() {
return resultCode;
}
public void setResultCode(WkResultCodeEnum resultCode) {
this.resultCode = resultCode;
}
public String getResultDesc() {
return resultDesc;
}
public void setResultDesc(String resultDesc) {
this.resultDesc = resultDesc;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry;
import com.abssqr.plat.common.integration.wk.domain.WkHeader;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: QryHeader.java, v 0.1 2019-06-18 14:24 bangis.wangdf Exp $
*/
public class QryHeader extends WkHeader {
/**
* 每页条数
*/
private int PageSize;
/**
* 页码
*/
private int PageNo;
public int getPageSize() {
return PageSize;
}
public void setPageSize(int pageSize) {
PageSize = pageSize;
}
public int getPageNo() {
return PageNo;
}
public void setPageNo(int pageNo) {
PageNo = pageNo;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry;
import com.abssqr.plat.common.integration.wk.domain.WkHeader;
import com.abssqr.plat.common.integration.wk.domain.opr.OprRstHeader;
import com.abssqr.plat.common.integration.wk.enums.ComIdEnum;
import com.abssqr.plat.common.integration.wk.enums.PlatResultCodeEnum;
import com.abssqr.plat.common.integration.wk.enums.RequestTypeEnum;
import javax.xml.crypto.Data;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain: QryRstHeader.java, v 0.1 2019-06-18 14:25 bangis.wangdf Exp $
*/
public class QryRstHeader extends OprRstHeader {
/**
* 最大页码
*/
private int maxPage;
public int getMaxPage() {
return maxPage;
}
public void setMaxPage(int maxPage) {
this.maxPage = maxPage;
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry;
/**
*
* @author yangcheng
* @version TradeItem.java, v0.12019-06-1816:43 yangchengExp$
*/
public class QueryInfo {
/**
* 查询条件 编号
*/
private String no;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.request;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
import com.abssqr.plat.common.integration.wk.enums.LocalOrChannelEnum;
/**
*账户余额查询接口请求
*
* @author yangcheng
* @version AccountBalanceParam.java, v0.12019-06-1815:52 yangchengExp$
*/
public class AccountBalanceParam extends WkBody {
/**
* 账户号
*/
private String no;
/*
* 渠道代码
*/
private WkChannelNoEnum channelNo;
/**
* 本地或渠道余额 0-本地,1-渠道余额
*/
private LocalOrChannelEnum localOrChannel;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public WkChannelNoEnum getChannelNo() {
return channelNo;
}
public void setChannelNo(WkChannelNoEnum channelNo) {
this.channelNo = channelNo;
}
public LocalOrChannelEnum getLocalOrChannel() {
return localOrChannel;
}
public void setLocalOrChannel(LocalOrChannelEnum localOrChannel) {
this.localOrChannel = localOrChannel;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.request.trade;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.qry.request.trade: TradeItem.java, v 0.1 2019-06-21 21:29
* bangis.wangdf Exp $
*/
@XmlRootElement(name = "QueryInfo")
public class TradeItem extends WkObject {
/**
* 查询条件 编号
*/
private String no;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.request.trade;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
import com.abssqr.plat.common.integration.wk.enums.TradeQueryTypeEnum;
/**
* 交易结果查询
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.qry.request.trade: TradeQuery.java, v 0.1 2019-06-21 21:23
* bangis.wangdf Exp $
*/
public class TradeQuery extends WkBody {
/**
QueryType 查询类型 字符 2 Y 1 按日期区间查询
2 按接口流水号查询
3按交易交易号查询
4按交易条目号查询
StartDate 开始日期 枚举 10 S “查询类型”为1时必传
格式:yyyy-MM-dd
EndDate 结束日期 枚举 10 S “查询类型”为1时必传
格式:yyyy-MM-dd
QueryList 查询条件 列表 S “查询类型”为2、3、4时必传,列表内容为 TradeItem,
一次请求最多50个查询条件
*/
/**
* 查询类型
*/
private TradeQueryTypeEnum queryType;
private String startDate;
private String endDate;
private List<TradeItem> queryList;
public TradeQueryTypeEnum getQueryType() {
return queryType;
}
public void setQueryType(TradeQueryTypeEnum queryType) {
this.queryType = queryType;
}
public String getStartDate() {
return startDate;
}
public void setStartDate(String startDate) {
this.startDate = startDate;
}
public String getEndDate() {
return endDate;
}
public void setEndDate(String endDate) {
this.endDate = endDate;
}
public List<TradeItem> getQueryList() {
return queryList;
}
public void setQueryList(List<TradeItem> queryList) {
this.queryList = queryList;
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.response;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
/**
*账户余额明细响应
* @author yangcheng
* @version BalanceInfo.java, v0.12019-06-1816:20 yangchengExp$
*/
public class BalanceInfo extends WkObject {
/**
* 账户号
*/
private String accountNo;
/**
* 渠道编号
*/
private WkChannelNoEnum channelNo;
/**
* 余额
*/
private long balance;
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
public WkChannelNoEnum getChannelNo() {
return channelNo;
}
public void setChannelNo(WkChannelNoEnum channelNo) {
this.channelNo = channelNo;
}
public long getBalance() {
return balance;
}
public void setBalance(long balance) {
this.balance = balance;
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.response;
import java.util.List;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
/**
* @author yangcheng
* @version BalanceResult.java, v0.12019-06-1816:26 yangchengExp$
*/
public class BalanceResult extends WkBody {
private List<BalanceInfo> balanceList;
public List<BalanceInfo> getBalanceList() {
return balanceList;
}
public void setBalanceList(List<BalanceInfo> balanceList) {
this.balanceList = balanceList;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.response.trade;
import com.abssqr.plat.common.facade.model.plan.PlanCapitalOrder;
import com.abssqr.plat.common.integration.wk.domain.WkBody;
import com.abssqr.plat.common.integration.wk.enums.WkTradeStatusEnum;
import com.general.system.tool.util.ToolUtil;
import java.util.ArrayList;
import java.util.List;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.qry.response.trade: TradeResult.java, v 0.1 2019-06-21 21:36
* bangis.wangdf Exp $
*/
public class TradeResult extends WkBody {
List<TradeResultItem> payInfoList;
public List<TradeResultItem> getPayInfoList() {
return payInfoList;
}
public void setPayInfoList(
List<TradeResultItem> payInfoList) {
this.payInfoList = payInfoList;
}
public static List<TradeResultItem> mockDate(List<PlanCapitalOrder> orders){
List<TradeResultItem> list = new ArrayList<>();
if (ToolUtil.isEmpty(orders)){
return list;
}
orders.forEach(one -> {
TradeResultItem item = new TradeResultItem();
item.setEntryNo(one.getOutAcptNo());
item.setPayMoney(one.getTransAmt().getCent());
item.setStatus(WkTradeStatusEnum.成功);
list.add(item);
});
return list;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.domain.qry.response.trade;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
import com.abssqr.plat.common.integration.wk.domain.WkObject;
import com.abssqr.plat.common.integration.wk.enums.WkChannelNoEnum;
import com.abssqr.plat.common.integration.wk.enums.EnTradeTypeEnum;
import com.abssqr.plat.common.integration.wk.enums.WkTradeStatusEnum;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.domain.qry.response.trade: TradeResultItem.java, v 0.1 2019-06-21
* 21:37 bangis.wangdf Exp $
*/
@XmlRootElement(name = "PayInfo")
public class TradeResultItem extends WkObject {
/**
FlowNo 接口流水号 枚举 32 Y 头报文UUID
TradeNo 交易号 字符 32 Y
TradeTypeNo 交易业务类型 字符 10 Y
TradeChannel 交易渠道 枚举 8 Y 4.3渠道代码表
EntryNo 条目号 字符 32 Y
EntryTypeNo 条目业务类型 金额 10 Y
RpayMoney 请求支付金额 字符 10 Y (单位分)
PayMoney 实际支付金额 字符 10 Y (单位分)
EnTradeType 条目交易类型 枚举 2 Y 见4.4
PayTime 交易时间 字符 20 Y yyyy-MM-dd HH:mm:ss
Status 交易状态 字符 2 Y 见4.5
Message 交易信息反馈 字符 128 Y
*/
/**
* 接口流水号 枚举 32 Y 头报文UUID
*/
private String flowNo;
/**
* 交易号 字符 32 Y
*/
private String tradeNo;
/**
* 交易业务类型 字符 10 Y
*/
private String tradeTypeNo;
/**
* 交易渠道 枚举 8 Y 4.3渠道代码表
*/
private WkChannelNoEnum tradeChannel;
/**
* 条目号 字符 50 Y 业务系统保证唯一,并以业务系统编号开头
*/
private String entryNo;
/**
* 请求支付金额 Y 交易金额(单位:分)
*/
private long rpayMoney;
/**
* 实际支付金额
*/
private long payMoney;
/**
* 条目交易类型 枚举 2 Y 详见4.4
*/
private EnTradeTypeEnum enTradeType;
/**
* 交易时间 字符 20 Y yyyy-MM-dd HH:mm:ss
*/
private Date payTime;
/**
* 交易状态 字符 2 Y 见4.5
*/
private WkTradeStatusEnum status;
/**
* 交易信息反馈
*/
private String message;
public String getFlowNo() {
return flowNo;
}
public void setFlowNo(String flowNo) {
this.flowNo = flowNo;
}
public String getTradeNo() {
return tradeNo;
}
public void setTradeNo(String tradeNo) {
this.tradeNo = tradeNo;
}
public String getTradeTypeNo() {
return tradeTypeNo;
}
public void setTradeTypeNo(String tradeTypeNo) {
this.tradeTypeNo = tradeTypeNo;
}
public WkChannelNoEnum getTradeChannel() {
return tradeChannel;
}
public void setTradeChannel(WkChannelNoEnum tradeChannel) {
this.tradeChannel = tradeChannel;
}
public String getEntryNo() {
return entryNo;
}
public void setEntryNo(String entryNo) {
this.entryNo = entryNo;
}
public long getRpayMoney() {
return rpayMoney;
}
public void setRpayMoney(long rpayMoney) {
this.rpayMoney = rpayMoney;
}
public long getPayMoney() {
return payMoney;
}
public void setPayMoney(long payMoney) {
this.payMoney = payMoney;
}
public EnTradeTypeEnum getEnTradeType() {
return enTradeType;
}
public void setEnTradeType(EnTradeTypeEnum enTradeType) {
this.enTradeType = enTradeType;
}
public Date getPayTime() {
return payTime;
}
public void setPayTime(Date payTime) {
this.payTime = payTime;
}
public WkTradeStatusEnum getStatus() {
return status;
}
public void setStatus(WkTradeStatusEnum status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
* 表示平台所在业务类别
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.enums: RequestTypeEnum.java, v 0.1 2019-06-18 14:04 bangis.wangdf Exp $
*/
public enum ComIdEnum implements WkEnum {
/**
ufc0000 支付平台
000003 小微信贷系统
**/
支付平台("ufc0000", "支付平台"),
小微信贷系统("000003", "小微信贷系统"),
资产转让("000004", "资产转让"),
;
private static final Map<String, ComIdEnum>
codeMap = new HashMap<String, ComIdEnum>();
static {
for (ComIdEnum item : ComIdEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private ComIdEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static ComIdEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public ComIdEnum getByWkCode(String code) {
return getByCode(code);
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author yangcheng
* @version EnTradeTypeEnum.java, v0.12019-06-1817:03 yangchengExp$
*/
public enum EnTradeTypeEnum implements WkEnum {
/**
01 放款
02 扣款
03 充值
04 提现
05 挂账充值
06 挂账提现
**/
放款("01", "放款"),
扣款("02", "扣款"),
充值("03", "充值"),
提现("04", "提现"),
挂账充值("05", "挂账充值"),
挂账提现("06", "挂账提现"),
;
private static final Map<String, EnTradeTypeEnum>
codeMap = new HashMap<String, EnTradeTypeEnum>();
static {
for (EnTradeTypeEnum item : EnTradeTypeEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private EnTradeTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static EnTradeTypeEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public EnTradeTypeEnum getByWkCode(String code) {
return getByCode(code);
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author yangcheng
* @version LocalOrChannelEnum.java, v0.12019-06-1815:56 yangchengExp$
*/
public enum LocalOrChannelEnum implements WkEnum {
/**
0 本地
1 渠道余额
**/
本地("0", "本地"),
渠道余额("1", "渠道余额"),
;
private static final Map<String, LocalOrChannelEnum>
codeMap = new HashMap<String, LocalOrChannelEnum>();
static {
for (LocalOrChannelEnum item : LocalOrChannelEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private LocalOrChannelEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static LocalOrChannelEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public LocalOrChannelEnum getByWkCode(String code) {
return getByCode(code);
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
* @author yangcheng
* @version PlatResultCodeEnum.java, v0.12019-06-1814:48 yangchengExp$
*/
public enum PlatResultCodeEnum implements WkEnum {
/**
* 10000 成功
* 90000 支付平台异常
**/
成功("10000", "成功"),
支付平台异常("90000", "支付平台异常"),
服务异常("99999", "服务异常"),
异常("9", "异常"),
未知("xxxx", "未知"),
;
private static final Map<String, PlatResultCodeEnum>
codeMap = new HashMap<String, PlatResultCodeEnum>();
static {
for (PlatResultCodeEnum item : PlatResultCodeEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private PlatResultCodeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static PlatResultCodeEnum getByCode(String code) {
PlatResultCodeEnum result = codeMap.get(code);
if (result == null) {
if (code.startsWith(异常.code)) {
result = 异常;
} else {
return 未知;
}
}
return result;
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public PlatResultCodeEnum getByWkCode(String code) {
return getByCode(code);
}
}
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.enums: ProjStateEnum.java, v 0.1 2019-06-19 10:56 bangis.wangdf Exp $
*/
public enum ProjStateEnum implements WkEnum {
生效("01", "生效"),
失效("02", "失效"),
;
private static final Map<String, ProjStateEnum>
codeMap = new HashMap<String, ProjStateEnum>();
static {
for (ProjStateEnum item : ProjStateEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private ProjStateEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static ProjStateEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public ProjStateEnum getByWkCode(String code) {
return getByCode(code);
}
}
\ No newline at end of file
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author yangcheng
* @version QueryTypeEnum.java, v0.12019-06-1816:31 yangchengExp$
*/
public enum QueryTypeEnum implements WkEnum{
/**
1 按日期区间查询
2 按接口流水号查询
3 按交易交易号查询
4 按交易条目号查询
**/
QT_1("1", "按日期区间查询"),
QT_2("2", "按接口流水号查询"),
QT_3("3", "按交易交易号查询"),
QT_4("4", "按交易条目号查询"),
;
private static final Map<String, QueryTypeEnum>
codeMap = new HashMap<String, QueryTypeEnum>();
static {
for (QueryTypeEnum item : QueryTypeEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private QueryTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static QueryTypeEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public QueryTypeEnum getByWkCode(String code) {
return getByCode(code);
}
}
\ No newline at end of file
/**
* abssqr.com Inc.
* Copyright (c) 2017-2019 All Rights Reserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
* @author bangis.wangdf
* @version com.abssqr.plat.common.integration.wk.enums: RequestTypeEnum.java, v 0.1 2019-06-18 14:04 bangis.wangdf
* Exp $
*/
public enum RequestTypeEnum implements WkEnum {
/**
* 账户信息维护 A100002 1 同步
* 账户状态维护 A100003 1 同步
* 交易代理 P100001 1-50 异步
* 账户余额查询 B100002 1 同步
* 交易结果查询 B100007 1 同步
* 个人要素验证 B100006 1 同步
* A100011 租户信息维护接口 同步
**/
A100002("A100002", "账户信息维护", WkAsynEnum.),
// A100003("A100003", "账户状态维护", WkAsynEnum.是),
A100011("A100011", "租户信息维护", WkAsynEnum.),
P100001("P100001", "交易代理", WkAsynEnum.),
B100002("B100002", "账户余额查询", WkAsynEnum.),
B100007("B100007", "交易结果查询", WkAsynEnum.),
;
private static final Map<String, RequestTypeEnum>
codeMap = new HashMap<String, RequestTypeEnum>();
static {
for (RequestTypeEnum item : RequestTypeEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private WkAsynEnum asyn;
private String code;
private String desc;
private RequestTypeEnum(String code, String desc, WkAsynEnum asyn) {
this.code = code;
this.desc = desc;
this.asyn = asyn;
}
public static RequestTypeEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
public WkAsynEnum getAsyn() {
return asyn;
}
@Override
public RequestTypeEnum getByWkCode(String code) {
return getByCode(code);
}
}
/**
* abssqr.comInc.
* Copyright(c)2019-2019AllRightsReserved.
*/
package com.abssqr.plat.common.integration.wk.enums;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author yangcheng
* @version SettleTypeEnum.java, v0.12019-06-1815:33 yangchengExp$
*/
public enum SettleTypeEnum implements WkEnum {
/**
01 实时结算
02 定时自动结算
**/
实时结算("01", "实时结算"),
定时自动结算("02", "定时自动结算"),
;
private static final Map<String, SettleTypeEnum>
codeMap = new HashMap<String, SettleTypeEnum>();
static {
for (SettleTypeEnum item : SettleTypeEnum.values()) {
codeMap.put(item.getCode(), item);
}
}
private String code;
private String desc;
private SettleTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public static SettleTypeEnum getByCode(String code) {
return codeMap.get(code);
}
@Override
public String getCode() {
return code;
}
@Override
public String getDesc() {
return desc;
}
@Override
public SettleTypeEnum getByWkCode(String code) {
return getByCode(code);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment