字数:32672
基本分析
下列是一套伪代码,用于向银行发起退款。之前的入账流水有的是模拟的,有的是真实的,处理逻辑上基本上是一致的,但是中间的细致过程有不同,比如:真实的退款是要调用招行的接口,虚拟的还是接着虚构一个结果。
过程如下:
定时任务开始
查询待退流水
判断,无,则结束
循环,发起退款
如果是,模拟的,走模拟退款过程(1)
如果是,真实的,走真实退款过程(2)
统计,两者各自成功与失败的数量
过程(1)模拟退款
判断,状态非待退,结束
查现是否有退款记录
判断,无,则走创建退款过程(1.2),带个实质为无的标识对象
判断,有
读状态
判断,状态为退款成功,更新入账流水的状态为已退,结束
判断,状态为退款失败,则走创建退款过程(1.2),带个实质为有的标识对象
判断,状态为已申请
**模拟读结果,随机生成结果真或假(这可以作为具体的策略)**
判断,如果真,更新退款记录状态,新增退款成功日志,更新入账流水状态为已退
判断,如果假,更新退款记录状态,新增退款成功日志,更新入账流水状态为已退(这儿有一些重复代码了)
过程(1.2)创建模拟退款
**模拟依赖结果,随机生成真或假(这可以作为具体的策略)**
判断,如果真(1.2.1)
判断,如果存在退款记录,直接用原记录
判断,如果不存在退款记录,创建对象,并给相关属性赋值
更新退款记录的状态(相对于过程1差异是要多更新回执编号和尝试次数),新增退款已申请日志,新增入账流水日志为已申请退款
(代码与过程1有部分重复)
判断,如果假(1.2.2),直接返回了(这个地方还漏了未做创建申请失败的日志)
过程(2)真实退款,流程与过程(1)非常相似,特别的一点是这个过程(2)还作为服务的业务实现被外部调用
判断,状态非待退,结束
查现是否有退款记录
判断,无,则走创建退款过程(2.2),带个实质为无的标识对象
判断,有
读状态
判断,状态为退款成功,更新入账流水的状态为已退,结束
判断,状态为退款失败,则走创建退款过程(2.2),带个实质为有的标识对象
判断,状态为已申请
**读银行结果(这可以作为具体的策略)**
结果有银行业务数据,执行状态和执行结果两者均成功,则更新退款记录状态,新增退款成功日志,更新入账流水状态为已退
结果无银行业务数据,或以上的其它种情况,更新退款记录状态,新增退款失败日志,更新入账流水状态为失败
过程(2.2)创建真实退款
**打包数据,发给招商,收到反馈(这可以作为具体的策略)**
判断,如果真(2.2.1)
判断,如果存在退款记录,直接用原记录
判断,如果不存在退款记录,创建对象,并给相关属性赋值
更新退款记录的状态(相对于过程2差异是要多更新回执编号和尝试次数),新增退款已申请日志,新增入账流水日志为已申请退款
(代码与过程2有部分重复)
判断,如果假(2.2.2),直接返回了(这个地方还漏了未做创建申请失败的日志)
综上,流程有一些重复的实现,细节代码有的重复,有的还有点小差异:
(1)不好改,改一个地方,另一个相仿的地方照着改,看能不能把流程做成同一个
(2)细节不好改,细节一不小心改了一个地方没改另一个地方
(3)小地方的改动,往往比较隐蔽地影响其它。
这些都是导致事件可控难度升级。考虑用策略模式重构,模拟和真实的业务相当于两套不同的策略实现,可以同时载到上下文中被调度。
代码差异
直接看代码的差异,重构前:
2.1定时任务开始
public void execTaskCreateBankRefunds() {
log.info("定时任务-退款:开始执行");
//获取待退还的流水
//(1)(2)平台出账记录中不存在出账成功(或在途的)的关联流水的,待退入账,视为有效待退
List<BankPayment> ps = getBankPaymentsNeedRefund();
if (ps == null || ps.isEmpty()) return;
int amount_simu_succ = 0;
int amount_simu_failed = 0;
int amount_real_succ = 0;
int amount_real_failed = 0;
//(3)发起退款申请
for (BankPayment p : ps) {
if (CommConst.TRUE == p.getIs_simulate()) { //模拟退款
if (simulateRepay(p)) {
amount_simu_succ++;
} else {
amount_simu_failed++;
}
} else { //真实退款
if (transfer.createRepay(p)) {
amount_real_succ++;
} else {
amount_real_failed++;
}
}
}
log.info("定时任务-退款:\n{}条待退,(1)处理模拟退款,成功{}条,失败{}条;(2)处理真实退款,成功{}条,失败{}条。\n统计依据:(1)成功指:1退款请求已经存在且成功,2之前失败重新发起成功,3退款请求已经存在查结果为成功(2)失败指:1发起退款申请失败,2查询退款申请请求失败,3查询退款申请的结果为失败"
, new Object[]{ps.size(), amount_simu_succ, amount_simu_failed, amount_real_succ, amount_real_failed});
}
2.2模拟退款
//模拟退款经办
@Deprecated
public boolean simulateRepay(BankPayment p) {
//非待退状态的流水不处理
if (p.getState_payment() != CoreCommConst.STATE_DEPOSIT_WAIT_REFUND) {
return false;
}
//先查有没有退款记录
BankRefund r = getLatestBankRefundByPayId(p.getId_payment());
if (r == null) {
return simulateExecRepay(p, r);
} else {// r != null
//查状态
switch (r.getState_refund()) {
case CoreCommConst.STATE_REFUND_SUCC: //1.之前已经成功过(未有效同步状态字),更新平台入账流水的状态
changePaymentState(p, EnumMoneyLogPack.REFUND_SUCC);
return true;
case CoreCommConst.STATE_REFUND_FAILED: //2.之前失败了,再次发起退款申请
return simulateExecRepay(p, r);
case CoreCommConst.STATE_REFUND_APPLYED: //3.之前申请了,查询一下银行处理结果
boolean succ = generateTrueOrFalse(); //取随机结果
long curr = System.currentTimeMillis();
EnumMoneyLogPack pack;
if (succ) {
pack = EnumMoneyLogPack.REFUND_SUCC;
String comment = getSpecialRefundComment(pack);
r.setComment_state(comment);
r.setState_refund(CoreCommConst.STATE_REFUND_SUCC);
r.setLtm_refund_update(curr);
createOrUpdateBankRefund(r); //更新退款请求的状态为成功
//写退款成功日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(r.getCmb_req_nbr());
rl.setComment_state(comment);
rl.setId_ref(0);
rl.setId_refund(r.getId_refund());
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(curr);
rl.setTimes_create_req(r.getTry_times());
createOrUpdateRefundLog(rl);
changePaymentState(p, pack); //更新平台入账流水状态为成功
return true;
}
pack = EnumMoneyLogPack.REPAY_BANK_FAILED;
String comment = getSpecialRefundComment(pack);
r.setState_refund(CoreCommConst.STATE_REFUND_FAILED);
r.setLtm_refund_update(curr);
r.setComment_state(comment);
createOrUpdateBankRefund(r); //更新退款请求的状态为失败
//写退款失败日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(r.getCmb_req_nbr());
rl.setComment_state(comment);
rl.setId_ref(0);
rl.setId_refund(r.getId_refund());
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(curr);
rl.setTimes_create_req(r.getTry_times());
createOrUpdateRefundLog(rl);
changePaymentState(p, pack); //更新平台入账日志
return false;
default:
break;
}// switch
return false;
}
}
2.3执行模拟退款
@Deprecated
public boolean simulateExecRepay(BankPayment p, BankRefund r) {
boolean succ = generateTrueOrFalse(); //取随机结果
if (succ) {
long curr = System.currentTimeMillis();
int try_times = 1;
long id_ref_refund = 0; //平台入账关联的退款流水
long cmb_req_nbr = 0;//请求的编号
if (r != null) {//已经存在申请记录
try_times = r.getTry_times() + 1;
}
EnumMoneyLogPack pack = EnumMoneyLogPack.REPAY_REFUND_COMMIT;
String comment = String.format("第%d次请求,%s", try_times, pack.getCommentRefund());
if (pack.isNeedAddFlag() //需要加模拟两字
//&& prop.isOpen_simulate_payment() //打开了模拟 ,为模拟数据必然是打开了这个开关
&& CommConst.TRUE == p.getIs_simulate()) { //为模拟数据
comment = "模拟," + comment;
}
if (r != null) {//已经存在申请记录
id_ref_refund = r.getId_refund();
} else {
//创建或更新出账记录
r = new BankRefund();
id_ref_refund = idGenerator.nextId();
r.setLtm_refund_create(curr);
r.setMoney(p.getMoney());
r.setType_refund(CoreCommConst.TYPE_REFUND_NORMAL);//此为正常退款业务
r.setState_refund(CoreCommConst.STATE_REFUND_APPLYED);
r.setId_bank_member(p.getId_bank_member());
r.setId_payment_related(p.getId_payment());
r.setId_refund(id_ref_refund);
}
r.setComment_state(comment);
r.setLtm_refund_update(curr);
cmb_req_nbr = Long.parseLong(StringUtils.getIDStarsWithLetter(0, 3, false));
r.setCmb_req_nbr(cmb_req_nbr);
r.setTry_times(try_times);
//提交成功
createOrUpdateBankRefund(r);
//写退款日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(cmb_req_nbr);
rl.setComment_state(comment);
rl.setId_ref(try_times == 1 ? p.getId_payment() : 0); //仅第一次退款关联上入账流水ID
rl.setId_refund(id_ref_refund);
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(curr);
rl.setTimes_create_req(try_times);
createOrUpdateRefundLog(rl);
//写流水处理日志和保证金(如果关联上了)日志
changePaymentState(p, pack, try_times == 1 ? id_ref_refund : 0);
}
return succ;
}
2.4真实退款
/**
* 退款,根据平台的入账流水,制造(查询)出账结果
* @param p
* @return
*/
@Deprecated
public boolean createRepay(BankPayment p) {
//非待退状态的流水不处理
//if (p.getState_payment() != CoreCommConst.STATE_DEPOSIT_WAIT_REFUND) {
// return false;
//}
//先查有没有退款记录
BankRefund r = bankService.getLatestBankRefundByPayId(p.getId_payment());
if (r == null) {
return execRepay(p, r);
} else {// r != null
//查状态
switch (r.getState_refund()) {
case CoreCommConst.STATE_REFUND_SUCC: //1.之前已经成功过(未有效同步状态字),更新平台入账流水的状态
bankService.changePaymentState(p, EnumMoneyLogPack.REFUND_SUCC);
return true;
case CoreCommConst.STATE_REFUND_FAILED: //2.之前失败了,再次发起退款申请
return execRepay(p, r);
case CoreCommConst.STATE_REFUND_APPLYED: //3.之前申请了,查询一下银行处理结果
com.test.xml.NTDUMINF.CMBSDKPGK elm = new com.test.xml.NTDUMINF.CMBSDKPGK();
try {
elm.fromXmlFile(TransferService.class.getResource("/xml_template/").getPath() + "NTDUMINF.xml");
elm.getINFO().setLGNNAM(CoreCommConst.LGNNAME);
elm.getNTDUMINFX1().setREQNBR(r.getCmb_req_nbr());
String xml = elm.toXml();
xml = xml.replace("UTF-8", "GBK");
log.info("发送[查询]请求:\n{}", xml);
//发送给招商了
String retNet = NetUtil.httpPost(xml);
//解释结果
com.test.xml.NTDUMINF_RET.CMBSDKPGK elm_ret = new com.test.xml.NTDUMINF_RET.CMBSDKPGK();
elm_ret.fromXmlStream(retNet.getBytes("UTF-16"));
log.info("接收[查询]反馈:\n{}", elm_ret.toXml());
long curr = System.currentTimeMillis();
String errDetails = "";
if (com.test.xml.NTDUMINF_RET.INFO_RETCOD.n0
!= elm_ret.getINFO().getRETCOD()) { //查询请求调用成功
errDetails = elm_ret.getINFO().getERRMSG();
} else {//成功,进一步获取子结果
if ((com.test.xml.NTDUMINF_RET.NTDUMINFZ1_REQSTA.FIN
== elm_ret.getNTDUMINFZ1().getREQSTA())//银行完成
&& (com.test.xml.NTDUMINF_RET.NTDUMINFZ1_RTNFLG.S
== elm_ret.getNTDUMINFZ1().getRTNFLG())//且成功
){
EnumMoneyLogPack pack = EnumMoneyLogPack.REFUND_SUCC;
String comment = pack.getCommentRefund();
r.setComment_state(comment);
r.setState_refund(CoreCommConst.STATE_REFUND_SUCC);
r.setLtm_refund_update(curr);
bankService.createOrUpdateBankRefund(r); //更新退款请求的状态为成功
//写退款成功日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(r.getCmb_req_nbr());
rl.setComment_state(comment);
rl.setId_ref(0);
rl.setId_refund(r.getId_refund());
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(curr);
rl.setTimes_create_req(r.getTry_times());
bankService.createOrUpdateRefundLog(rl);
bankService.changePaymentState(p, EnumMoneyLogPack.REFUND_SUCC); //更新平台入账流水状态为成功
return true;
}
errDetails = String.format("银行执行状态字[%s],结果字[%s]"
, elm_ret.getNTDUMINFZ1().getREQSTA().toString()
, elm_ret.getNTDUMINFZ1().getRTNFLG().toString());
}
EnumMoneyLogPack pack = EnumMoneyLogPack.REPAY_BANK_FAILED;
String comment = pack.getCommentRefund() + ",详情为:" + errDetails;
//结果不成功,下一个周期再重新发起新请求
r.setState_refund(CoreCommConst.STATE_REFUND_FAILED);
r.setLtm_refund_update(curr);
r.setComment_state(comment);
bankService.createOrUpdateBankRefund(r); //更新退款请求的状态为失败
//写退款失败日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(r.getCmb_req_nbr());
rl.setComment_state(comment);
rl.setId_ref(0);
rl.setId_refund(r.getId_refund());
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(curr);
rl.setTimes_create_req(r.getTry_times());
bankService.createOrUpdateRefundLog(rl);
bankService.changePaymentState(p, EnumMoneyLogPack.REPAY_BANK_FAILED); //更新平台入账流水状态为失败
return false;
} catch (LtException | IOException e) {
//请求异常,忽略流水状态的维护
e.printStackTrace();
}
break;
default:
break;
}// switch
return false;
}
}
2.5执行真实退款
//退款经办
@Deprecated
private boolean execRepay(BankPayment p, BankRefund r) {
com.test.xml.NTOPRDMR.CMBSDKPGK elm = new com.test.xml.NTOPRDMR.CMBSDKPGK();
try {
elm.fromXmlFile(TransferService.class.getResource("/xml_template/").getPath() + "NTOPRDMR.xml");
elm.getINFO().setLGNNAM(CoreCommConst.LGNNAME);
elm.getNTOPRDMRX1().setSETNBR(p.getSetnbr());//套号
elm.getNTOPRDMRX1().setTRXNBR(p.getTrxnbr());//流水号
elm.getNTOPRDMRX1().setTRSAMT(p.getMoney());
elm.getNTOPRDMRX1().setDUMNBR(String.format("%010d", p.getId_bank_member()));
elm.getNTOPRDMRX1().setEPTDAT(StringUtils.formatCurrDate(StringUtils.getDateFormat(CoreCommConst.FORMAT_DATE_YMD)));
elm.getNTOPRDMRX1().setRPYACC(p.getPay_acc_no());
elm.getNTOPRDMRX1().setRPYNAM(p.getPay_acc_name());
elm.getNTOPRDMRX1().setINTFLG("N");//是否退息,固定为N
long id_ref_post = idGenerator.nextId();
elm.getNTOPRDMRX1().setYURREF(id_ref_post);
String xml = elm.toXml();
xml = xml.replace("UTF-8", "GBK");
log.info("发送[退款]请求:\n{}", xml);
//发送给招商了
String retNet = NetUtil.httpPost(xml);
//解释结果
com.test.xml.NTOPRDMR_RET.CMBSDKPGK elm_ret = new com.test.xml.NTOPRDMR_RET.CMBSDKPGK ();
elm_ret.fromXmlStream(retNet.getBytes("UTF-16"));
log.info("接收[退款]反馈:\n{}", elm_ret.toXml());
int ret_code = elm_ret.getINFO().getRETCOD();
if (ret_code != 0) {
return false;
} else {//成功,增加请求的记录
long curr = System.currentTimeMillis();
int try_times = 1;
long id_ref_refund = 0; //平台入账关联的退款流水
long cmb_req_nbr = 0;//请求的编号
if (r != null) {//已经存在申请记录
try_times = r.getTry_times() + 1;
}
EnumMoneyLogPack pack = EnumMoneyLogPack.REPAY_REFUND_COMMIT;
String comment = String.format("第%d次请求,%s", try_times, pack.getCommentRefund());
if (r != null) {//已经存在申请记录
id_ref_refund = r.getId_refund();
} else {
//创建或更新出账记录
r = new BankRefund();
id_ref_refund = idGenerator.nextId();
r.setLtm_refund_create(curr);
r.setMoney(p.getMoney());
r.setType_refund(CoreCommConst.TYPE_REFUND_NORMAL);//此为正常退款业务
r.setState_refund(CoreCommConst.STATE_REFUND_APPLYED);
}
r.setComment_state(comment);
r.setId_bank_member(p.getId_bank_member());
r.setId_payment_related(p.getId_payment());
r.setId_refund(id_ref_refund);
r.setLtm_refund_update(curr);
cmb_req_nbr = elm_ret.getNTOPRRTNZ().getREQNBR();
r.setCmb_req_nbr(cmb_req_nbr);
r.setTry_times(try_times);
//提交成功
bankService.createOrUpdateBankRefund(r);
//写退款日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(cmb_req_nbr);
rl.setComment_state(comment);
rl.setId_ref(try_times == 1 ? p.getId_payment() : 0); //仅第一次退款关联上入账流水ID
rl.setId_refund(id_ref_refund);
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(curr);
rl.setTimes_create_req(try_times);
bankService.createOrUpdateRefundLog(rl);
//写流水处理日志和保证金(如果关联上了)日志
bankService.changePaymentState(p, pack, id_ref_refund);
return true;
}
} catch (LtException | IOException e) {
e.printStackTrace();
}
return false;
}
可见,有重复的流程造成了一定的代码重复,重构后如下:
public void execTaskCreateBankRefunds() {
log.info("定时任务-退款:开始执行");
//获取待退还的流水
//(1)(2)平台出账记录中不存在出账成功(或在途的)的关联流水的,待退入账,视为有效待退
List<BankPayment> ps = getBankPaymentsNeedRefund();
if (ps == null || ps.isEmpty()) return;
int amount_simu_succ = 0;
int amount_simu_failed = 0;
int amount_real_succ = 0;
int amount_real_failed = 0;
AbstractRefundStategy simulateExector = new SimulateRepay(this, idGenerator);
AbstractRefundStategy actualExector = new ActualRepay(this, idGenerator);
//(3)发起退款申请
for (BankPayment p : ps) {
if (CommConst.TRUE == p.getIs_simulate()) { //模拟退款
if (simulateExector.createRefund(p)) {
amount_simu_succ++;
} else {
amount_simu_failed++;
}
} else { //真实退款
if (actualExector.createRefund(p)) {
amount_real_succ++;
} else {
amount_real_failed++;
}
}
}
log.info("定时任务-退款:\n{}条待退,(1)处理模拟退款,成功{}条,失败{}条;(2)处理真实退款,成功{}条,失败{}条。\n统计依据:(1)成功指:1退款请求已经存在且成功,2之前失败重新发起成功,3退款请求已经存在查结果为成功(2)失败指:1发起退款申请失败,2查询退款申请请求失败,3查询退款申请的结果为失败"
, new Object[]{ps.size(), amount_simu_succ, amount_simu_failed, amount_real_succ, amount_real_failed});
}
public abstract class AbstractRefundStategy {
private final Logger log = LoggerFactory.getLogger(AbstractRefundStategy.class);
protected SnowflakeIdWorker idGenerator;
protected BankService bankService;
protected TransferService transfer;
protected EnumMoneyLogPack pack;
AbstractRefundStategy(BankService bankService, SnowflakeIdWorker idGenerator){
this.bankService = bankService;
this.idGenerator = idGenerator;
}
public EnumMoneyLogPack getPack() {
return pack;
}
protected void setPack(EnumMoneyLogPack pack) {
this.pack = pack;
}
private BankRefund initBreforeCreateRefund(BankRefund r, BankPayment p){
long curr = System.currentTimeMillis();
int try_times = 1;
if (r != null) {
try_times = r.getTry_times() + 1;
} else {
r = new BankRefund();
r.setId_refund(idGenerator.nextId());
r.setLtm_refund_create(curr);
r.setType_refund(CoreCommConst.TYPE_REFUND_NORMAL);//此为正常退款业务
r.setState_refund(CoreCommConst.STATE_REFUND_APPLYED);
r.setMoney(p.getMoney());
r.setId_bank_member(p.getId_bank_member());
r.setId_payment_related(p.getId_payment());
}
r.setLtm_refund_update(curr);
r.setTry_times(try_times);
return r;
}
public boolean createRefund(BankPayment p){
//非待退状态的流水不处理
if (CoreCommConst.STATE_DEPOSIT_WAIT_REFUND != p.getState_payment() //非待退
&& CoreCommConst.STATE_DEPOSIT_LOSE != p.getState_payment() //非罚没 TODO 暂时能后台处理
) {
return false;
}
//先查有没有退款记录
BankRefund r = bankService.getLatestBankRefundByPayId(p.getId_payment());
long id_ref_payment = 0;
if (r == null) {
r = execCreateRefund(initBreforeCreateRefund(r, p), p);
} else {// r != null
id_ref_payment = r.getId_payment_related();
//查状态
switch (r.getState_refund()) {
case CoreCommConst.STATE_REFUND_SUCC: //1.之前已经成功过(未有效同步状态字),更新平台入账流水的状态,这种情况不太可能出现
bankService.changePaymentState(p, EnumMoneyLogPack.REFUND_SUCC);
return true;
case CoreCommConst.STATE_REFUND_FAILED: //2.之前失败了,再次发起退款申请
if (r.getTry_times() >= CoreCommConst.TIMES_TRY) { //10次为限,放弃退款
log.info("放弃退款,尝试次数达到10次,退款流水号{}", r.getId_refund());
setPack(EnumMoneyLogPack.REFUND_GIVEUP);
r.setComment_state(pack.getCommentRefund());
} else {
r = execCreateRefund(initBreforeCreateRefund(r, p), p);
}
break;
case CoreCommConst.STATE_REFUND_APPLYED: //3.之前申请了,查询一下银行处理结果
r = refreshRefund(r);
break;
default:
r = null;
break;
}
}
if (r != null && pack != null) {
//创建或更新退款
bankService.createOrUpdateBankRefund(r);
//创建退款日志
RefundLog rl = new RefundLog();
rl.setCmb_req_nbr(r.getCmb_req_nbr());
rl.setComment_state(r.getComment_state());
rl.setId_ref(id_ref_payment == 0 ? p.getId_payment() : 0); //仅第一次时有值
rl.setId_refund(r.getId_refund());
rl.setId_refund_log(idGenerator.nextId());
rl.setLtm_state_update(r.getLtm_refund_update());
rl.setTimes_create_req(r.getTry_times());
bankService.createOrUpdateRefundLog(rl);
//更新入账银行流水日志
bankService.changePaymentState(p, getPack()
, id_ref_payment == 0 ? r.getId_refund() : 0); //仅在初次创建时,关联ID
return CoreCommConst.STATE_REFUND_SUCC == r.getState_refund();
}
return false;
}
/**
* 已申请的退款最新情况刷新,相当于读
* @return
*/
abstract BankRefund refreshRefund(BankRefund exists);
/**
* 执行要创建的对象的生成
* @param exists
* @return
*/
abstract BankRefund execCreateRefund(BankRefund exists, BankPayment p);
}
/**
* 真实退款
* @author ta
*
*/
public class ActualRepay extends AbstractRefundStategy {
private final Logger log = LoggerFactory.getLogger(ActualRepay.class);
public ActualRepay(BankService bankService, SnowflakeIdWorker idGenerator) {
super(bankService, idGenerator);
}
@Override
BankRefund refreshRefund(BankRefund r) {
long ltm_update = System.currentTimeMillis();
int state = r.getState_refund();
String errDetails = null;
com.test.xml.NTDUMINF.CMBSDKPGK elm = new com.test.xml.NTDUMINF.CMBSDKPGK();
try {
elm.fromXmlFile(TransferService.class.getResource("/xml_template/").getPath() + "NTDUMINF.xml");
elm.getINFO().setLGNNAM(CoreCommConst.LGNNAME);
elm.getNTDUMINFX1().setREQNBR(r.getCmb_req_nbr());
String xml = elm.toXml();
xml = xml.replace("UTF-8", "GBK");
log.info("发送[查询退款结果]请求:\n{}", xml);
//发送给招商了
String retNet = NetUtil.httpPost(xml);
//解释结果
com.test.xml.NTDUMINF_RET.CMBSDKPGK elm_ret = new com.test.xml.NTDUMINF_RET.CMBSDKPGK();
elm_ret.fromXmlStream(retNet.getBytes("UTF-16"));
log.info("接收[查询退款结果]反馈:\n{}", elm_ret.toXml());
if (com.test.xml.NTDUMINF_RET.INFO_RETCOD.n0
!= elm_ret.getINFO().getRETCOD()) { //查询请求调用返回为不成功
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
state = CoreCommConst.STATE_REFUND_FAILED;
errDetails = elm_ret.getINFO().getERRMSG();
} else {//成功,进一步获取子结果
if ((com.test.xml.NTDUMINF_RET.NTDUMINFZ1_REQSTA.FIN
== elm_ret.getNTDUMINFZ1().getREQSTA())//银行完成
&& (com.test.xml.NTDUMINF_RET.NTDUMINFZ1_RTNFLG.S
== elm_ret.getNTDUMINFZ1().getRTNFLG())//且成功
){//查询成功
setPack(EnumMoneyLogPack.REFUND_SUCC);
state = CoreCommConst.STATE_REFUND_SUCC;
} else {//结果为不成功
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
state = CoreCommConst.STATE_REFUND_FAILED;
errDetails = String.format("银行执行状态字[%s],结果字[%s]"
, elm_ret.getNTDUMINFZ1().getREQSTA().toString()
, elm_ret.getNTDUMINFZ1().getRTNFLG().toString());
}
}
} catch (LtException | IOException e) {
//啥也不干
//setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
//state = CoreCommConst.STATE_REFUND_FAILED;
//errDetails = "请求银行查询退款结果时异常";
e.printStackTrace();
}
String comment = pack.getCommentRefund()
+ (errDetails == null? "" : ",详情为:" + errDetails);
r.setComment_state(comment);
r.setState_refund(state);
r.setLtm_refund_update(ltm_update);
return r;
}
@Override
BankRefund execCreateRefund(BankRefund r, BankPayment p) {
String errDetails = null;
com.test.xml.NTOPRDMR.CMBSDKPGK elm = new com.test.xml.NTOPRDMR.CMBSDKPGK();
try {
elm.fromXmlFile(TransferService.class.getResource("/xml_template/").getPath() + "NTOPRDMR.xml");
elm.getINFO().setLGNNAM(CoreCommConst.LGNNAME);
elm.getNTOPRDMRX1().setSETNBR(p.getSetnbr());//套号
elm.getNTOPRDMRX1().setTRXNBR(p.getTrxnbr());//流水号
elm.getNTOPRDMRX1().setTRSAMT(p.getMoney());
elm.getNTOPRDMRX1().setDUMNBR(String.format("%010d", p.getId_bank_member()));
elm.getNTOPRDMRX1().setEPTDAT(StringUtils.formatCurrDate(StringUtils.getDateFormat(CoreCommConst.FORMAT_DATE_YMD)));
elm.getNTOPRDMRX1().setRPYACC(p.getPay_acc_no());
elm.getNTOPRDMRX1().setRPYNAM(p.getPay_acc_name());
elm.getNTOPRDMRX1().setINTFLG("N");//是否退息,固定为N
elm.getNTOPRDMRX1().setYURREF(idGenerator.nextId()); //这个地方的业务参考号到底有没有什么影响
String xml = elm.toXml();
xml = xml.replace("UTF-8", "GBK");
log.info("发送[退款]请求:\n{}", xml);
//发送给招商了
String retNet = NetUtil.httpPost(xml);
//解释结果
com.test.xml.NTOPRDMR_RET.CMBSDKPGK elm_ret = new com.test.xml.NTOPRDMR_RET.CMBSDKPGK ();
elm_ret.fromXmlStream(retNet.getBytes("UTF-16"));
log.info("接收[退款]反馈:\n{}", elm_ret.toXml());
int ret_code = elm_ret.getINFO().getRETCOD();
if (ret_code != 0) {
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
r.setState_refund(CoreCommConst.STATE_REFUND_FAILED);
errDetails = elm_ret.getINFO().getERRMSG();
} else {//成功,增加请求的记录
setPack(EnumMoneyLogPack.REPAY_REFUND_COMMIT);
r.setCmb_req_nbr(elm_ret.getNTOPRRTNZ().getREQNBR());
}
} catch (LtException | IOException e) {
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
r.setState_refund(CoreCommConst.STATE_REFUND_FAILED);
errDetails = "请求银行发起退款时异常";
e.printStackTrace();
}
String comment = String.format("第%d次退款请求,%s", r.getTry_times(), pack.getCommentRefund())
+ (errDetails == null? "" : ",详情为:" + errDetails);
r.setComment_state(comment);
return r;
}
}
public class SimulateRepay extends AbstractRefundStategy {
public SimulateRepay(BankService bankService, SnowflakeIdWorker idGenerator) {
super(bankService, idGenerator);
}
@Override
BankRefund refreshRefund(BankRefund r) {
boolean succ = bankService.generateTrueOrFalse(); //取随机结果
long ltm_update = System.currentTimeMillis();
int state = 0;
if (succ) { //假定读到的情况是退款成功
setPack(EnumMoneyLogPack.REFUND_SUCC);
state = CoreCommConst.STATE_REFUND_SUCC;
} else {//假定读到的情况是退款失败
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
state = CoreCommConst.STATE_REFUND_FAILED;
}
String comment = bankService.getSpecialRefundComment(getPack());
r.setComment_state(comment);
r.setState_refund(state);
r.setLtm_refund_update(ltm_update);
return r;
}
@Override
BankRefund execCreateRefund(BankRefund r, BankPayment p) {
String errDetails = null;
boolean succ_query = bankService.generateTrueOrFalse(); //取随机结果
if (succ_query) {//模拟请求银行,成功
boolean succ_result = bankService.generateTrueOrFalse(); //取随机结果
if (succ_result) {
setPack(EnumMoneyLogPack.REPAY_REFUND_COMMIT);
r.setCmb_req_nbr(Long.parseLong(StringUtils.getIDStarsWithLetter(0, 3, false)));
} else {
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
r.setState_refund(CoreCommConst.STATE_REFUND_FAILED);
errDetails = "[这里是银行业务处理结果为非正常的描述]";
}
} else { //模拟请求银行,失败
setPack(EnumMoneyLogPack.REPAY_BANK_FAILED);
r.setState_refund(CoreCommConst.STATE_REFUND_FAILED);
errDetails = "请求银行发起退款时异常";
}
String comment = String.format("第%d次退款请求,%s", r.getTry_times(), pack.getCommentRefund())
+ (errDetails == null? "" : ",详情为:" + errDetails);
r.setComment_state(comment);
return r;
}
}
代码量对比:
(1)重构前374行,重构后332行
(2)重构前16426字,重构后14272字
从量上看,相差并不是很大,从代码的结构来看,重构后清晰不少,而且解决了一些细节问题,整合后较好维护。