Asynchronous callback process
- Parsing message (verification signature)
- Log collection (same)
- If the message is parsed successfully, the payment status will be changed to succeeded. Different payment results will be returned
Template method design pattern
Define the whole skeleton in advance. Different behaviors are implemented by subclasses. The same behaviors are directly defined and reused in abstract classes.
The same behavior is defined in the abstract scheme, and the implementation subclass of different behaviors is implemented
Key design points
AbstractClass: an abstract class that defines and implements a template method. This template method defines the framework of the algorithm, and the steps of logic composition are deferred to the implementation of subclasses in the corresponding abstract operations.
ConcreteClass: implements one or more abstract methods defined by the parent class.
Template method abstract class
/** * * @description: Using template method to reconstruct asynchronous callback code */ @Slf4j @Component public abstract class AbstractPayCallbackTemplate { /** * Asynchronous callback service */ public String asyncCallBack() { // 1. Payment callback validation parameters Map<String, String> verifySignatureMap = verifySignature(); // 2. The parameters are verified successfully and written to the log payLog(verifySignatureMap); String analysisCode = verifySignatureMap.get("analysisCode"); if (!analysisCode.equals(PayConstant.RESULT_PAYCODE_200)) { return resultFail(); } // 3. Execute callback asynchronous related logic return asyncService(verifySignatureMap); } /** * Write logs asynchronously using multithreading */ @Async protected void payLog(Map<String,String> verifySignatureMap){ log.info(">>>>>>>>>>Step 2 write payLog........{}",verifySignatureMap); } /** * Implement business resolution operation */ protected abstract String asyncService(Map<String,String> verifySignatureMap); /** * Asynchronous return success result */ protected abstract String resultSuccess(); /** * Asynchronous return failure result */ protected abstract String resultFail(); /** * Payment callback validation parameters */ protected abstract Map<String,String> verifySignature(); }
Specific implementation template
①AliPayCallbackTemplate
/** * @title: AliPayCallbackTemplate */ @Component @Slf4j public class AliPayCallbackTemplate extends AbstractPayCallbackTemplate { @Override protected Map<String, String> verifySignature() { //"Alipay callback message pseudo code" log.info(">>>>>The first step is to analyze Alipay data packets......verifySignature()"); Map<String, String> verifySignature = new HashMap<>(); verifySignature.put("price", "10000"); verifySignature.put("orderDes", "Recharge member"); // A payment status of 1 indicates success verifySignature.put("aliPayMentStatus", "1"); verifySignature.put("aliPayOrderNumber", "20190511"); // If the message is parsed successfully, 200 means success verifySignature.put("analysisCode", PayConstant.RESULT_PAYCODE_200); return verifySignature; } @Override protected String asyncService(Map<String, String> verifySignatureMap) { log.info(">>>>>The third step asyncService()verifySignatureMap:{}", verifySignatureMap); String paymentStatus = verifySignatureMap.get("aliPayMentStatus"); if (paymentStatus.equals("1")) { String aliPayOrderNumber = verifySignatureMap.get("aliPayOrderNumber"); log.info(">>>>orderNumber:{aliPayOrderNumber},Paid successfully modify the order status to paid..."); } 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() { //>>>>UnionPay callback message pseudo code log.info(">>>>>Step 1: analyze UnionPay data message.....verifySignature()"); Map<String, String> verifySignature = new HashMap<>(); verifySignature.put("price", "10000"); verifySignature.put("orderDes", "Recharge member"); // A payment status of 1 indicates success verifySignature.put("paymentStatus", "1"); verifySignature.put("orderNumber", "20190511"); // If the message is parsed successfully, 200 means success verifySignature.put("analysisCode", PayConstant.RESULT_PAYCODE_200); return verifySignature; } @Override protected String asyncService(Map<String, String> verifySignatureMap) { log.info(">>>>>The third step asyncService()verifySignatureMap:{}", verifySignatureMap); String paymentStatus = verifySignatureMap.get("paymentStatus"); if (paymentStatus.equals(PayConstant.PAY_STATUS_SUCCESS)) { String orderNumber = verifySignatureMap.get("orderNumber"); log.info(">>>>orderNumber:{orderNumber},Paid successfully modify the order status to paid..."); } return resultSuccess(); } @Override protected String resultSuccess() { return PayConstant.UNION_RESULT_SUCCESS; } @Override protected String resultFail() { return PayConstant.UNION_RESULT_FAIL; } }
Factory mode get template
/** * @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; } //Get applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } //Get Bean through name public static Object getBean(String name) { return getApplicationContext().getBean(name); } //Get Bean through class public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } //Return the specified Bean through name and Clazz public static <T> T getBean(String name, Class<T> clazz) { return getApplicationContext().getBean(name, clazz); } }
Dependent dependence
<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 layer
/** * @title: TemplateController */ @RestController public class TemplateController { @RequestMapping("/asyncCallBack") public String asyncCallBack(String templateId) { AbstractPayCallbackTemplate payCallbackTemplate = TemplateFactory.getPayCallbackTemplate(templateId); return payCallbackTemplate.asyncCallBack(); } }
Program entry
@SpringBootApplication @EnableAsync public class AppTemplate { public static void main(String[] args) { SpringApplication.run(AppTemplate.class); } }
Console output
The first step is to analyze Alipay according to the message.....verifySignature().
>>>>>Step 2 write payLog........{aliPayOrderNumber=20190511, orderDes = top up member, price=10000, analysisCode=200, aliPayMentStatus=1}
>>>>>Step 3: asyncService()verifySignatureMap:{aliPayOrderNumber=20190511, orderDes = top up member, price=10000, analysisCode=200, aliPayMentStatus=1}
>>>>OrderNumber: {alipayordernumber}. The order status has been modified to paid successfully
>>>>>Step 1: analyze UnionPay data message..... verifySignature()
>>>>>Step 2 write payLog........{orderNumber=20190511, orderDes = top up member, price=10000, analysisCode=200, paymentStatus=1}
>>>>>Step 3: asyncService()verifySignatureMap:{orderNumber=20190511, orderDes = top up member, price=10000, analysisCode=200, paymentStatus=1}
summary
copyright @In a momenthttps://my.oschina.net/u/3995125
Advantages and disadvantages of template design mode
1. advantages
The template method pattern removes the duplicate code in the subclass by moving the invariant behavior to the superclass. Some details of the implementation of the algorithm by subclasses are helpful for the expansion of the algorithm. Through a parent class to call the operation implemented by the child class, new behaviors are added through the extension of the child class, which conforms to the "open closed principle".
2. disadvantages
Each different implementation needs to define a subclass, which will increase the number of classes and make the design more abstract.
3. Applicable scenarios
In some kinds of algorithms, the same method is used, resulting in code duplication. To control the extension of subclass, subclass must obey the algorithm rules.
Advantages and disadvantages of factory design mode
Advantage:
1. Simple code structure.
2. The process of obtaining products is simpler.
3. It meets the principle of opening and closing, that is, opening to expansion and closing to modification.
Disadvantages:
Extension is tedious. To expand, you need to change both the abstract factory and the factory implementation class.
Knowledge sharing
Reference: ant class: http://www.mayikt.com