优雅的处理微信支付异步回调
处理背景
1.由于使用的是v2版本的微信支付,微信支付响应是xml字符串,所以处理需要对此响应进行解析成java对象
1.由在业务中把微信支付进行了统一封装,如调用微信支付会在系统业务级别对操作记录进行处理,如记录业务类型,支付状态,订单号,支付结果等,导致会在支付后接收微信支付通知响应时候,需要对响应信息对微信支付操作进行回写记录等等,
初始版本的微信回调实现处理
/**
* 微信支付回调处理
*
* @param xmlData 微信回调数据
* @return 微信响应信息 xml字符串
*/
public String handleNotifyResult(String xmlData) {
log.info("微信支付回调原始信息:" + xmlData);
WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
try {
//解析xml串成java对象
wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
..
..
..
业务场景处理
//保存系统级别微信支付单记录
updatePayOrder(wxPayOrderNotifyResult);
} catch (WxPayException e) {
log.error("微信支付回调异常", e);
return WxPayNotifyResponse.fail();
}
return WxPayNotifyResponse.success();
}
此种处理回调没有问题,但是如果场景过多,如商城订单支付,会员开通支付,续费支付等等业务场景,都需复写上述操作,
把会变化之处独立出来,把不需要变化的抽离出来,各是各,分开写
由上分析可看出这是一个典型的环绕处理,而环绕操作就是不需要变化的部分,每个支付的场景就是变化之处,可以采用切面来完成,处理方式,初步考虑基于注解来处理业务处理前置操作和后置操作,但思考过后发现缺失灵活性,于是决定采用策略模式通过接口来解决此问题
改动
1.上述代码把xml字符串单独抽离出来,已类变量方式存在,定义构建方法赋值xml字符串
public class WxNotify {
/**
* 微信回调数据
*/
private String xmlData;
/**
* 构建微信支付回调 支付成功方法
*
* @param xmlData 响应xml数据
*/
public WxNotify build(String xmlData) {
this.xmlData = xmlData;
return this;
}
public String handleNotifyResult() {
log.info("微信支付回调原始信息:" + xmlData);
WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
try {
//解析xml串成java对象
wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
..
..
..
业务场景处理
//保存系统级别微信支付单记录
updatePayOrder(wxPayOrderNotifyResult);
} catch (WxPayException e) {
log.error("微信支付回调异常", e);
return WxPayNotifyResponse.fail();
}
return WxPayNotifyResponse.success();
}
}
2.定义微信回调处理接口
/**
* 微信支付回调处理
*
* @author chenyanpeng
* @Date: 2021/7/30 16:42
*/
public interface NotifyHandleResponse {
/**
* 微信支付成功
*
* @param wxPayOrderNotifyResult 解析结果
* @param bllCode 业务编码
* @return 微信服务器记录的订单回调信息
*/
String success(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
/**
* 回调支付失败
*
* @param wxPayOrderNotifyResult 解析结果
* @param bllCode 业务编码
* @return 微信服务器记录的订单回调信息
*/
String fail(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
/**
* 微信回调过程处理异常
*
* @param e 异常信息
* @param bllCode 业务编码
* @return 微信服务器记录的订单回调信息
*/
String error(Exception e,WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
}
3 定义处理处理结果接口,赋值xml同时在赋值接口信息,然后面向接口开发,不是面向实现类
@Component
public class WxNotify {
/**
* 微信回调数据
*/
private String xmlData;
/**
* 通知处理响应
*/
private NotifyHandleResponse notifyHandleResponse;
/**
* 构建微信支付回调 支付成功方法
*
* @param xmlData 响应xml数据
* @param notifyInterface 通知处理接口
*/
public WxNotify build(String xmlData, NotifyHandleResponse notifyHandleResponse) {
this.notifyHandleResponse = notifyHandleResponse;
this.xmlData = xmlData;
return this;
}
public String handleNotifyResult() {
log.debug("微信支付回调原始信息:" + xmlData);
WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
try {
//解析xml串成java对象
wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
//响应结果
String message = null;
//支付结果处理
if (isOk(wxPayOrderNotifyResult)) {
//调用支付成功方法
message = WxPayNotifyResponse.success(
notifyHandleResponse.success(wxPayOrderNotifyResult, wxPayOrderNotifyResult.getOutTradeNo())
);
//此处织入支付成功后置操作
updatePayOrder(wxPayOrderNotifyResult);
}else{
//调用支付失败方法
message = WxPayNotifyResponse.fail(
notifyHandleResponse.fail(wxPayOrderNotifyResult, wxPayOrderNotifyResult.getOutTradeNo())
)
//此处织入支付成功后置操作
·····
}
return message;
} catch (WxPayException e) {
log.error("微信支付回调异常", e);
//调用程序异常处理方法
return WxPayNotifyResponse.fail(
notifyHandleResponse.error(e,wxPayOrderNotifyResult,wxPayOrderNotifyResult.getOutTradeNo())
);
}
}
/**
* 是否支付成功
*
* @param wxPayOrderNotifyResult 微信支付结果
* @return true成功
*/
private boolean isOk(WxPayOrderNotifyResult wxPayOrderNotifyResult) {
return
"SUCCESS".equals(wxPayOrderNotifyResult.getResultCode()) && "SUCCESS".equals(wxPayOrderNotifyResult.getResultCode());
}
}
4调用
@RequestMapping("/wxPay")
public class WxNotifyContrller {
//自己实现的接口处理类,该类实现定义处理接口
@Autowired
private DefaultNotifyResponseImpl notifyHandleResponse;
/**
* 默认支付回调通知处理 demo3
*
* @param xmlData 响应数据
* @return 返回给wx服务器的数据, 会显示在查询微信订单中的信息中
*/
@GetMapping(value = "/notify/demo1")
public String handleNotify(@RequestBody(required = false) String xmlData) {
return wxNotify.build(xmlData, notifyHandleResponse).handleNotifyResponse();
}
/**
* 默认支付回调通知处理 demo2
*
* @param xmlData 响应数据
* @return 返回给wx服务器的数据, 会显示在查询微信订单中的信息中
*/
@GetMapping(value = "/notify/demo2")
public String demo2(@RequestBody(required = false) String xmlData) {
return wxNotify.build(xmlData, new NotifyHandleResponse() {
@Override
public String success(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
//业务处理
.....
return "支付成功(。。。)";
}
@Override
public String fail(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
//业务处理
.....
return "支付失败(。。。)";
}
@Override
public String error(Exception e,WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
//业务处理
.....
return "支付异常(。。。)";
}
}).handleNotifyResponse();
}
}
优点
自此完成,相对之前
系统更有弹性,
调用者只需关注调用业务本身,无需关注其他
代码整洁度提高,在后期维护也更方便