How to use template + factory design mode intelligently to realize asynchronous callback in aggregate payment platform

Keywords: Spring Lombok

Asynchronous callback process

  1. Parsing message (verification signature)
  2. Log collection (same)
  3. 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

Published 19 original articles, won praise 5, visited 10000+
Private letter follow

Posted by jassh on Tue, 14 Jan 2020 19:01:44 -0800