【聚合支付平臺】如何智用【模板+工廠】設計模式來實現異步回調

異步回調流程

  1. 解析報文(驗證簽名)
  2. 日誌收集(相同)
  3. 如果解析報文成功的話,修改支付狀態爲已經成功.返回不同的支付結果

模版方法設計模式

提前定義好整體的骨架,不同的行爲讓子類實現,相同的行爲直接定義在抽象類中複用。

相同的行爲就定在抽象方案中,不同的行爲的實現子類實現

核心設計要點

AbstractClass : 抽象類,定義並實現一個模板方法。這個模板方法定義了算法的骨架,而邏輯的組成步驟在相應的抽象操作中,推遲到子類去實現。
ConcreteClass : 實現父類所定義的一個或多個抽象方法。

模版方法抽象類

/**
 *
 * @description: 使用模版方法重構異步回調代碼
 */
@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 

/**
 * @title: AliPayCallbackTemplate
 */
@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 

/**
 * @title: UnionPayCallbackTemplate
 */
@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;
    }
}

工廠模式獲取模版

/**
 * @title: TemplateFactory
 */
public class TemplateFactory {

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

SpringUtils 

@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層

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

程序入口

@SpringBootApplication
@EnableAsync
public class AppTemplate {
    public static void main(String[] args) {
        SpringApplication.run(AppTemplate.class);
    }
}

控制檯輸出結果

>>>>>第一步 解析支付寶據報文.....verifySignature()
>>>>>第二步 寫入payLog........{aliPayOrderNumber=20190511, orderDes=充值會員, price=10000, analysisCode=200, aliPayMentStatus=1}
>>>>>第三步asyncService()verifySignatureMap:{aliPayOrderNumber=20190511, orderDes=充值會員, price=10000, analysisCode=200, aliPayMentStatus=1}
>>>>orderNumber:{aliPayOrderNumber},已經支付成功 修改訂單狀態爲已經支付...


>>>>>第一步 解析銀聯數據報文.....verifySignature()
>>>>>第二步 寫入payLog........{orderNumber=20190511, orderDes=充值會員, price=10000, analysisCode=200, paymentStatus=1}
>>>>>第三步asyncService()verifySignatureMap:{orderNumber=20190511, orderDes=充值會員, price=10000, analysisCode=200, paymentStatus=1}

總結

版權@須臾之餘https://my.oschina.net/u/3995125

模版設計模式優缺點

1.優點
模板方法模式通過把不變的行爲搬移到超類,去除了子類中的重複代碼。子類實現算法的某些細節,有助於算法的擴展。通過一個父類調用子類實現的操作,通過子類擴展增加新的行爲,符合“開放-封閉原則”。
2.缺點
每個不同的實現都需要定義一個子類,這會導致類的個數的增加,設計更加抽象。
3.適用場景
在某些類的算法中,用了相同的方法,造成代碼的重複。控制子類擴展,子類必須遵守算法規則。

工廠設計模式優缺點

優點:
1.代碼結構簡單。
2.獲取產品的過程更加簡單。
3.滿足了開閉原則,即對拓展開放,對修改關閉。
缺點:
拓展較繁瑣,要拓展時,需同時改動抽象工廠和工廠實現類。
 

知識分享

本文參考:螞蟻課堂:http://www.mayikt.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章