异常交易定时处理
文章目录
一 异常交易的描述
1.1 异常的产生
当交易的处理需要通过其他渠道完成,但是由于网络异常、服务拥塞、渠道系统异常等未知情况导致渠道并没有返回处理结果,此时的交易就是我们需要手动处理的"异常交易"。
注意:只要是渠道返回了信息,无论是"系统异常"、"交易失败"或其他任何提示,都表示该笔交易的状态是已知的,不能当做异常来处理
1.2 渠道的异常处理方式
渠道提供的处理方式主要有两种:
- 渠道提供交易查询接口。当交易未知时提供查询
- 渠道提供红冲退款接口。针对涉及金额类的交易,红冲的含义类似于不管这笔交易成功还是失败,中台是不知道的,渠道按照撤销处理给冲掉即可。
二 中台的异常处理思路
2.1 银行类系统中常见的处理方式
在传统的POS、收银机等系统中,主要是将异常的交易信息存放到终端,在机具签到或做其他准备交易时,提前选择其中的一些(一般是按序取前三笔)发起查询/冲正。
若这些查询/冲正交易是否成功,在异常栈中去除,若依然未知则继续保留。
2.2 中台处理异常的方式
中台亦可以借鉴终端的处理方式,每次处理优先级高的几笔。
但是由于中台的处理能力和灵活性比终端强,可以采用定时任务的方式,每天定时处理所有的异常交易。通常资金一类的交易会有订单号、交易号、请求号等,为了避免冲突,查询最好使用调用方的唯一标记号(渠道的标记号在异常时可能是不会返回的)
三 具体实现(红冲为例)
3.1 抛出渠道红冲异常
try {
return doPost(...);
} catch (IOException e) {
e.printStackTrace();
if (e instanceof SocketTimeoutException) {
logger.error("数据接收超时");
// 1.若本就是红冲,则抛超时标记
// 2.若非红冲交易但需要检测红冲时,抛红冲标记
if (!isRedRushTrade && isRedRushNeeded) {
throw new xxxException(ErrorCodes.SYS_TRANS_NEED_RED_RUSH);
}
throw new xxxException(ErrorCodes.SYS_DATA_RECEIVE_TIMEOUT);
} else if (e instanceof ConnectTimeoutException) {
logger.error("渠道连接超时");
throw new xxxException(ErrorCodes.SYS_NET_CONNECT_TIMEOUT);
} else if (e instanceof ConnectException) {
logger.error("渠道连接失败");
throw new xxxException(ErrorCodes.SYS_NET_CONNECT_ERROR);
} else {
logger.error("其他系统错误");
throw new xxxException(ErrorCodes.SYS_SYSTEM_ERROR);
}
}
3.2 交易状态记为:UNKNOWN
在数据库中将该笔交易记为UNKNOWN。
3.3 spring定时脚本处理
@org.springframework.scheduling.annotation.Scheduled(cron = "0 50 23 * * ?")
public void dataBaseMigrate(){
...
}
在每天23:50:00的时候定时处理异常交易。