如何在聚合支付平臺,巧用模板+工廠設計模式來實現非同步回撥
非同步回撥流程
解析報文(驗證簽名)
日誌收集(相同)
如果解析報文成功的話,修改支付狀態為已經成功.返回不同的支付結果
模版方法設計模式
提前定義好整體的骨架,不同的行為讓子類實現,相同的行為直接定義在抽象類中複用。
相同的行為就定在抽象方案中,不同的行為的實現子類實現
核心設計要點
AbstractClass : 抽象類,定義並實現一個模板方法。這個模板方法定義了演算法的骨架,而邏輯的組成步驟在相應的抽象操作中,推遲到子類去實現。
ConcreteClass : 實現父類所定義的一個或多個抽象方法。
模版方法抽象類
/**
* All rights Reserved,
* Designed By lqq
* Copyright (C) @2020
*
* @description:使用模版方法重構非同步回撥程式碼
* @author: [email protected] 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: [email protected] 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: [email protected] 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: [email protected] 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: [email protected] 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: [email protected] 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: [email protected] 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.滿足了開閉原則,即對拓展開放,對修改關閉。
缺點:
拓展較繁瑣,要拓展時,需同時改動抽象工廠和工廠實現類。