异步回调流程
解析报文(验证签名)
日志收集(相同)
如果解析报文成功的话,修改支付状态为已经成功.返回不同的支付结果
模版方法设计模式
提前定义好整体的骨架,不同的行为让子类实现,相同的行为直接定义在抽象类中复用。
相同的行为就定在抽象方案中,不同的行为的实现子类实现
核心设计要点
AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。
ConcreteClass : 实现父类所定义的一个或多个抽象方法。
方法一:
模版方法抽象类
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* 使用模板方法做异步回调
*/
@Slf4j
@Component
public abstract class AbstractPayCallbackTemplate {
/**
* 异步回调业务
*
* @return
*/
public String asyncCallBack(String params) {
//1、支付回调验证参数
Map<String, String> verifySignatureMap = verifySignature(params);
//2、参数验证成功,写入日志中
payLog(verifySignatureMap);
String analysisCode = verifySignatureMap.get("analysisCode");
if (!"200".equals(analysisCode)) {
return resultFail();
}
//3、执行回调异步相关逻辑
return asyncService(verifySignatureMap);
}
/**
* 使用多线程异步写入日志
*
* @param verifySignatureMap
*/
@Async
protected void payLog(Map<String, String> verifySignatureMap) {
log.info(">>>>>>>>>第二步 写入payLog........{}", verifySignatureMap);
}
/**
* 支付回调验证参数
*
* @return
*/
protected abstract Map<String, String> verifySignature(String params);
/**
* 实现业务解析操作
*
* @param verifySignatureMap
* @return
*/
protected abstract String asyncService(Map<String, String> verifySignatureMap);
/**
* 异步返回成功结果
*
* @return
*/
protected abstract String resultSuccess();
/**
* 异步返回失败结果
*
* @return
*/
protected abstract String resultFail();
}
具体实现模版
①AliPayCallbackTemplate
**
* AliPayCallbackTemplate
*/
@Slf4j
@Component
public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected Map<String, String> verifySignature(String params) {
log.info(">>>>>第一步 解析支付宝数据报文....params:{}", params);
Map<String, String> verifySignature = new HashMap<>();
verifySignature.put("price", "10000");
verifySignature.put("orderDes", "充值会员");
verifySignature.put("aliPaymentStatus", "1");
verifySignature.put("aliPayOrderNumber", "20190511");
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
protected String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
String aliPaymentStatus = verifySignatureMap.get("aliPaymentStatus");
if ("1".equals(aliPaymentStatus)) {
String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", aliPayOrderNumber);
}
return resultSuccess();
}
@Override
protected String resultSuccess() {
return "支付宝支付成功";
}
@Override
protected String resultFail() {
return "支付宝支付失败";
}
②UnionPayCallbackTemplate
/**
* UnionPayCallbackTemplate
*/
@Slf4j
@Component
public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {
@Override
protected Map<String, String> verifySignature(String params) {
log.info(">>>>>第一步 解析银联数据报文....params:{}", params);
Map<String, String> verifySignature = new HashMap<>();
verifySignature.put("price", "10000");
verifySignature.put("orderDes", "充值会员");
verifySignature.put("unionPaymentStatus", "1");
verifySignature.put("unionPayOrderNumber", "20190511");
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
protected String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
String aliPaymentStatus = verifySignatureMap.get("unionPaymentStatus");
if ("1".equals(unionPaymentStatus)) {
String unionPayOrderNumber = verifySignatureMap.get("unionPayOrderNumber");
log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", unionPayOrderNumber);
}
return resultSuccess();
}
@Override
protected String resultSuccess() {
return "银联支付成功";
}
@Override
protected String resultFail() {
return "银联支付失败";
}
相关依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.8.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.8</version>
</dependency>
InitService
@Component
public class InitService {
private final static Map<String, AbstractPayCallbackTemplate> payCallbackTemplateMap = new HashMap();
@Resource(name = "aliPayCallbackTemplate")
private AbstractPayCallbackTemplate aliPayCallbackTemplate;
@Resource(name = "unionPayCallbackTemplate")
private AbstractPayCallbackTemplate unionPayCallbackTemplate;
@PostConstruct
public void init() {
payCallbackTemplateMap.put(PayChannelEnum.ALIPAY.getCode(), aliPayCallbackTemplate);
payCallbackTemplateMap.put(PayChannelEnum.UNIONPAY.getCode(), unionPayCallbackTemplate);
}
public AbstractPayCallbackTemplate getPayCallbackTemplate(String payChannel) {
return payCallbackTemplateMap.get(payChannel);
}
PayChannelEnum
public enum PayChannelEnum {
ALIPAY("aliPay", "支付宝"),
UNIONPAY("unionPay", "银联"),
;
private final String code;
private final String value;
PayChannelEnum(String code, String value) {
this.code = code;
this.value = value;
}
public String getCode() {
return code;
}
public String getValue() {
return value;
}
Controller层
/**
* @Description TODO
* @Date 2019/12/3 19:53
* @Created by 王弘博
*/
@RestController
public class TestController {
@Resource
private InitService initService;
@RequestMapping("/asyncCallback")
public String asyncCallback(String payChannel) {
AbstractPayCallbackTemplate payCallbackTemplate = initService.getPayCallbackTemplate(payChannel);
return payCallbackTemplate.asyncCallBack("入参");
}
}
程序入口
@EnableAsync
@SpringBootApplication
public class LoanUtilApplication {
public static void main(String[] args) {
SpringApplication.run(LoanUtilApplication.class, args);
}
}
控制台输出结果
启动项目,浏览器里访问:http://localhost:8080/asyncCallback?payChannel=aliPay
浏览器里访问:http://localhost:8080/asyncCallback?payChannel=aliPay
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
方法二:
定义接口PayCallback,把需要做的事情定义成接口
/**
* @Description TODO
* @Date 2019/12/3 20:04
* @Created by 王弘博
*/
public interface PayCallback {
/**
* 验证参数
* @param params
* @return
*/
Map<String, String> verifySignature(String params);
/**
* 使用多线程异步写入日志
* @param verifySignatureMap
*/
void payLog(Map<String, String> verifySignatureMap);
/**
* 实现业务解析操作
* @param verifySignatureMap
* @return
*/
String asyncService(Map<String, String> verifySignatureMap);
/**
* 返回成功结果
*
* @return
*/
String resultSuccess();
/**
* 返回失败结果
*
* @return
*/
String resultFail();
}
定义接口PayCallback的超类实现,超类里实现公用的方法
/**
* 业务逻辑是一样的,写在超类里,如若超类不能满足,则在子类里自己扩展
*/
@Slf4j
@Component
public abstract class AbstractPayCallback implements PayCallback {
@Override
public void payLog(Map<String, String> verifySignatureMap) {
log.info(">>>>>>>>>第二步 写入payLog........{}", verifySignatureMap);
}
}
定义子类自己独特的业务逻辑,继承超类
①AliPayCallback
/**
* AliPayCallback
*/
@Slf4j
@Component
public class AliPayCallback extends AbstractPayCallback {
@Override
public Map<String, String> verifySignature(String params) {
log.info(">>>>>第一步 解析支付宝数据报文....params:{}", params);
Map<String, String> verifySignature = new HashMap<>();
verifySignature.put("price", "10000");
verifySignature.put("orderDes", "充值会员");
verifySignature.put("aliPaymentStatus", "1");
verifySignature.put("aliPayOrderNumber", "20190511");
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
public String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
String aliPaymentStatus = verifySignatureMap.get("aliPaymentStatus");
if ("1".equals(aliPaymentStatus)) {
String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", aliPayOrderNumber);
}
return resultSuccess();
}
@Override
public String resultSuccess() {
log.info("支付宝支付成功");
return "支付宝支付成功";
}
@Override
public String resultFail() {
log.info("支付宝支付失败");
return "支付宝支付失败";
}
②UnionPayCallback
/**
* UnionPayCallback
*/
@Slf4j
@Component
public class UnionPayCallback extends AbstractPayCallback {
@Override
public Map<String, String> verifySignature(String params) {
log.info(">>>>>第一步 解析银联数据报文....params:{}", params);
Map<String, String> verifySignature = new HashMap<>();
verifySignature.put("price", "10000");
verifySignature.put("orderDes", "充值会员");
verifySignature.put("unionPaymentStatus", "1");
verifySignature.put("unionPayOrderNumber", "20190511");
verifySignature.put("analysisCode", "200");
return verifySignature;
}
@Override
public String asyncService(Map<String, String> verifySignatureMap) {
log.info(">>>>>第三步 asyncService() verifySignatureMap:{}", verifySignatureMap);
String unionPaymentStatus = verifySignatureMap.get("unionPaymentStatus");
if ("1".equals(unionPaymentStatus)) {
String unionPayOrderNumber = verifySignatureMap.get("unionPayOrderNumber");
log.info(">>>>>orderNumber:{},已经支付成功,修改订单状态为已经支付...", unionPayOrderNumber);
}
return resultSuccess();
}
@Override
public String resultSuccess() {
log.info("银联支付成功");
return "银联支付成功";
}
@Override
public String resultFail() {
log.info("银联支付失败");
return "银联支付失败";
}
定义模板接口PayServiceTemplate
public interface PayServiceTemplate {
String execute(String params, AbstractPayCallback payCallback);
}
定义模板接口实现PayServiceTemplateImpl
/**
* 定义模板
*/
@Component
public class PayServiceTemplateImpl implements PayServiceTemplate {
@Override
public String execute(String params, AbstractPayCallback payCallback) {
Map<String, String> verifySignature = null;
String result = null;
try {
verifySignature = payCallback.verifySignature(params);
payCallback.payLog(verifySignature);
result = payCallback.asyncService(verifySignature);
} catch (Exception e) {
result = "系统错误";
} finally {
//打印日志,清除线程变量等
}
return result;
}
}
Controller
/**
* @Description TODO
* @Date 2019/8/12 13:02
* @Created by 王弘博
*/
@RestController
public class TestController {
@Resource
private InitService initService;
@Resource
private PayServiceTemplate payServiceTemplate;
@RequestMapping("/asyncCallback")
public String asyncCallback(String payChannel) {
AbstractPayCallback payCallback = initService.getPayCallbackTemplate(payChannel);
return payServiceTemplate.execute("入参", new AbstractPayCallback() {
@Override
public Map<String, String> verifySignature(String params) {
return payCallback.verifySignature(params);
}
@Override
public String asyncService(Map<String, String> verifySignatureMap) {
return payCallback.asyncService(verifySignatureMap);
}
@Override
public String resultSuccess() {
return payCallback.resultSuccess();
}
@Override
public String resultFail() {
return payCallback.resultFail();
}
});
}
}
执行的时候,先走payServiceTemplate.execute这个接口,依次执行该接口里的方法,当走到
verifySignature = payCallback.verifySignature(params) 方法时,会回到controller里的
@Override
public Map<String, String> verifySignature(String params) {
return payCallback.verifySignature(params);
}
这里,然后根据payChannel走到对应的子类实现;当走到模板里的 payCallback.payLog(verifySignature)方法,就会直接执行超类里的payLog。
下面是执行结果,从结果里也可以发现,第一步解析数据不是公用的,所以走了子类;第二步是公用的方法所以走了超类...
总结
模版设计模式优缺点
1.优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
2.缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
3.适用场景
在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。