• 如何在聚合支付平台,巧用模板+工厂设计模式来实现异步回调


    异步回调流程

    1. 解析报文(验证签名)

    2. 日志收集(相同)

    3. 如果解析报文成功的话,修改支付状态为已经成功.返回不同的支付结果

    模版方法设计模式

    提前定义好整体的骨架,不同的行为让子类实现,相同的行为直接定义在抽象类中复用。

    相同的行为就定在抽象方案中,不同的行为的实现子类实现

    核心设计要点

    AbstractClass : 抽象类,定义并实现一个模板方法。这个模板方法定义了算法的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类去实现。
    ConcreteClass : 实现父类所定义的一个或多个抽象方法。

    模版方法抽象类

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:使用模版方法重构异步回调代码
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */
    @Slf4j
    @Component
    public abstract class AbstractPayCallbackTemplate {
    /**
    * 异步回调业务
    */
    public String asyncCallBack() {
    // 1. 支付回调验证参数
    Map<String, String> verifySignatureMap = verifySignature();
    // 2. 参数验证成功,写入日志中
    payLog(verifySignatureMap);
    String analysisCode = verifySignatureMap.get("analysisCode");
    if (!analysisCode.equals(PayConstant.RESULT_PAYCODE_200)) {
    return resultFail();
    }
    // 3. 执行回调异步相关逻辑
    return asyncService(verifySignatureMap);
    }
    /**
    * 使用多线程异步写入日志
    */
    @Async
    protected void payLog(Map<String,String> verifySignatureMap){
    log.info(">>>>>>>>>>第二步 写入payLog........{}",verifySignatureMap);
    }
    /**
    * 实现业务解析操作
    */
    protected abstract String asyncService(Map<String,String> verifySignatureMap);
    /**
    * 异步返回成功结果
    */
    protected abstract String resultSuccess();
    /**
    * 异步返回失败结果
    */
    protected abstract String resultFail();
    /**
    * 支付回调验证参数
    */
    protected abstract Map<String,String> verifySignature();

    }

    具体实现模版

    ①AliPayCallbackTemplate 

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:阿里支付具体的实现
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */

    @Component
    @Slf4j
    public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Override
    protected Map<String, String> verifySignature() {
    //>>>>支付宝回调报文伪代码>>>>
    log.info(">>>>>第一步 解析支付宝数据报文.....verifySignature()");
    Map<String, String> verifySignature = new HashMap<>();
    verifySignature.put("price", "10000");
    verifySignature.put("orderDes", "充值会员");
    // 支付状态为1表示为成功....
    verifySignature.put("aliPayMentStatus", "1");
    verifySignature.put("aliPayOrderNumber", "20190511");
    // 解析报文是否成功 200 为成功..
    verifySignature.put("analysisCode", PayConstant.RESULT_PAYCODE_200);
    return verifySignature;
    }

    @Override
    protected String asyncService(Map<String, String> verifySignatureMap) {
    log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
    String paymentStatus = verifySignatureMap.get("aliPayMentStatus");
    if (paymentStatus.equals("1")) {
    String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber");
    log.info(">>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付...");
    }
    return resultSuccess();
    }

    @Override
    protected String resultSuccess() {
    return PayConstant.ALIPAY_RESULT_SUCCESS;
    }
    @Override
    protected String resultFail() {
    return PayConstant.ALIPAY_RESULT_FAIL;
    }
    }

    ②UnionPayCallbackTemplate 

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:银联支付的具体实现
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */

    @Component
    @Slf4j
    public class UnionPayCallbackTemplate extends AbstractPayCallbackTemplate {
    @Override
    protected Map<String, String> verifySignature() {
    //>>>>银联回调报文伪代码>>>>>>>>
    log.info(">>>>>第一步 解析银联数据报文.....verifySignature()");
    Map<String, String> verifySignature = new HashMap<>();
    verifySignature.put("price", "10000");
    verifySignature.put("orderDes", "充值会员");
    // 支付状态为1表示为成功....
    verifySignature.put("paymentStatus", "1");
    verifySignature.put("orderNumber", "20190511");
    // 解析报文是否成功 200 为成功..
    verifySignature.put("analysisCode", PayConstant.RESULT_PAYCODE_200);
    return verifySignature;
    }

    @Override
    protected String asyncService(Map<String, String> verifySignatureMap) {
    log.info(">>>>>第三步asyncService()verifySignatureMap:{}", verifySignatureMap);
    String paymentStatus = verifySignatureMap.get("paymentStatus");
    if (paymentStatus.equals(PayConstant.PAY_STATUS_SUCCESS)) {
    String orderNumber = verifySignatureMap.get("orderNumber");
    log.info(">>>>orderNumber:{orderNumber},已经支付成功 修改订单状态为已经支付...");
    }
    return resultSuccess();
    }

    @Override
    protected String resultSuccess() {
    return PayConstant.UNION_RESULT_SUCCESS;
    }
    @Override
    protected String resultFail() {
    return PayConstant.UNION_RESULT_FAIL;
    }
    }

    工厂模式获取模版

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:工厂模式获取模板
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */

    public class TemplateFactory {

    public static AbstractPayCallbackTemplate getPayCallbackTemplate(String templateId) {
    AbstractPayCallbackTemplate payCallbackTemplate = (AbstractPayCallbackTemplate) SpringUtils.getBean(templateId);
    return payCallbackTemplate;
    }
    }

    SpringUtils 

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:上下文获取具体的实现
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */
    @Component
    public class SpringUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
    return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
    return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz) {
    return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name, Class<T> clazz) {
    return getApplicationContext().getBean(name, clazz);
    }

    }

    相关依赖

        <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    </parent>
    <dependencies>
    <!-- sprinboot web -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.10</version>
    </dependency>
    <dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
    </dependency>
    </dependencies>

    Controller层

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:控制层
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */

    @RestController
    public class TemplateController {
    @RequestMapping("/asyncCallBack")
    public String asyncCallBack(String templateId) {
    AbstractPayCallbackTemplate payCallbackTemplate = TemplateFactory.getPayCallbackTemplate(templateId);
    return payCallbackTemplate.asyncCallBack();
    }
    }

    程序入口

    /**
    * All rights Reserved,
    * Designed By lqq
    * Copyright (C) @2020
    *
    * @description:使用模版方法重构异步回调代码
     * @author: 963833533@qq.com lqq
    * @date: Created in 2020/10/24
    * @since: 2020
    * @version: 1.0
    */
    @SpringBootApplication
    @EnableAsync
    public class AppTemplate {
    public static void main(String[] args) {
    SpringApplication.run(AppTemplate.class);
    }
    }

    控制台输出结果

    >>>>>第一步 解析支付宝据报文.....verifySignature()
    >>>>>第二步 写入payLog........{aliPayOrderNumber=20201024, orderDes=充值会员, price=10010, analysisCode=200, aliPayMentStatus=1}
    >>>>>第三步asyncService()verifySignatureMap:{aliPayOrderNumber=20201024, orderDes=充值会员, price=10000, analysisCode=200, aliPayMentStatus=1}
    >>>>orderNumber:{aliPayOrderNumber},已经支付成功 修改订单状态为已经支付...


    >>>>>第一步 解析银联数据报文.....verifySignature()
    >>>>>第二步 写入payLog........{orderNumber=20201024, orderDes=充值会员, price=10010, analysisCode=200, paymentStatus=1}
    >>>>>第三步asyncService()verifySignatureMap:{orderNumber=20201024, orderDes=充值会员, price=10000, analysisCode=200, paymentStatus=1}

    总结

    模版设计模式优缺点

    1.优点
    模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
    2.缺点
    每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
    3.适用场景
    在某些类的算法中,用了相同的方法,造成代码的重复。控制子类扩展,子类必须遵守算法规则。

    工厂设计模式优缺点

    优点:
    1.代码结构简单。
    2.获取产品的过程更加简单。
    3.满足了开闭原则,即对拓展开放,对修改关闭。
    缺点:
    拓展较繁琐,要拓展时,需同时改动抽象工厂和工厂实现类。

  • 相关阅读:
    0920 计算器,公共控件
    0919 认识winform,简单属性
    0914 c#的遍历查询-属性扩展
    0913 完整修改,删除-实体类-数据操作类
    0912 ADO.NET 增删改查
    0911 类库,委托
    0909 多态,抽象类,接口
    0908 封装继承
    0906 面向对象思想,类的介绍
    读《你不知道的JavaScript(上卷)》后感-浅谈JavaScript作用域(一)
  • 原文地址:https://www.cnblogs.com/lq-93/p/13873460.html
Copyright © 2020-2023  润新知