Gracefully handle wechat pay asynchronous callback

Deal with the background

1. As the V2 version of wechat Pay is used, the wechat Pay response is an XML string, so the processing needs to parse the response into Java objects

1. WeChat in the business to pay for the unified packaging, such as call WeChat will pay in the system the business level of operating records for processing, such as record business types, payment status, the order number, payment results, etc., will cause the payment after receiving WeChat payment notification response time, need to pay to the response information to WeChat operations back to written records, etc.

Initial version of wechat callback implementation processing


  /** * wechat pay callback processing **@paramXmlData wechat callback data *@returnWechat response information XML string */
    public String handleNotifyResult(String xmlData) {
        log.info("Wechat Pay callback original message:" + xmlData);
        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
        try {
            // Parse the XML string into Java objectswxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData); . . . Business Scenario Processing// Save system-level wechat payment records
            updatePayOrder(wxPayOrderNotifyResult);
        } catch (WxPayException e) {
            log.error("Abnormal wechat Pay callback", e);
            return  WxPayNotifyResponse.fail();
        }
​
        return  WxPayNotifyResponse.success();
    }
Copy the code

This processing callback has no problem, but if there are too many scenarios, such as mall order payment, member opening payment, renewal payment and other business scenarios, all need to copy the above operations,

Separate out the things that will change, separate out the things that don’t need to change, write them separately

By the analysis we can see this is a typical around the handle, and surrounding the operation is no need to change the part, the scene is change of each payment, cross section can be used to complete, handling, preliminary consideration based on annotations to processing business processing pre operation and post operation, but after thinking found that lack of flexibility, and decided to adopt the strategy mode to solve this by interface The problem

changes

1. The above code extracts the XML string separately, exists in class variable mode, and defines the build method to assign the XML string
public class WxNotify {
     /** * wechat callback data */
    private String xmlData;
​
​
    /** * Build wechat pay callback payment success method **@paramXmlData responds to XML data */
   public WxNotify build(String xmlData) {
        this.xmlData = xmlData;
        return this;
    }
    
   
    public String handleNotifyResult(a) {
        log.info("Wechat Pay callback original message:" + xmlData);
        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
        try {
            // Parse the XML string into Java objectswxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData); . . . Business Scenario Processing// Save system-level wechat payment records
            updatePayOrder(wxPayOrderNotifyResult);
        } catch (WxPayException e) {
            log.error("Abnormal wechat Pay callback", e);
            return  WxPayNotifyResponse.fail();
        }
​
        returnWxPayNotifyResponse.success(); }}Copy the code
2. Define the wechat callback processing interface
 
/** * wechat pay callback processing **@author chenyanpeng
 * @Date: 2021/7/30 * / calm
public interface NotifyHandleResponse {
    /** * wechat pay successfully **@paramWxPayOrderNotifyResult Parsing result *@paramBllCode Service code *@returnOrder callback information recorded by wechat server */
    String success(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
​
​
    /** * Callback payment failed **@paramWxPayOrderNotifyResult Parsing result *@paramBllCode Service code *@returnOrder callback information recorded by wechat server */
    String fail(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
​
​
    /** * the wechat callback process is abnormal **@paramE Abnormal information *@paramBllCode Service code *@returnOrder callback information recorded by wechat server */
    String error(Exception e,WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode);
}
​
Copy the code
3. Define the interface to process the result, assign XML to the interface information at the same time, and then develop for the interface, not for the implementation class
@Component
public class WxNotify {
    
    
     /** * wechat callback data */
    private String xmlData;
    
    
     /** * Notification processing response */
    private NotifyHandleResponse notifyHandleResponse;
​
​
    
    /** * Build wechat pay callback payment success method **@paramXmlData responds to XML data *@paramNotifyInterface Notification processing interface */
    public WxNotify build(String xmlData, NotifyHandleResponse notifyHandleResponse) {
        this.notifyHandleResponse = notifyHandleResponse;
        this.xmlData = xmlData;
        return this;
    }
    
   
    public String handleNotifyResult(a) {
        log.debug("Wechat Pay callback original message:" + xmlData);
        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
        try {
            // Parse the XML string into Java objects
            wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            // Response result
            String message = null;
            // Payment result processing
            if (isOk(wxPayOrderNotifyResult)) {
                 // Call the payment success method
                 message = WxPayNotifyResponse.success(
                     notifyHandleResponse.success(wxPayOrderNotifyResult, wxPayOrderNotifyResult.getOutTradeNo())
                 );
                // The operation is performed after the payment is successful
                updatePayOrder(wxPayOrderNotifyResult);
            }else{
                 // Call the payment failure method
                message =  WxPayNotifyResponse.fail(
                        notifyHandleResponse.fail(wxPayOrderNotifyResult, wxPayOrderNotifyResult.getOutTradeNo())
                 )
                 // The operation is performed after the payment is successful...}return message;
        } catch (WxPayException e) {
            log.error("Abnormal wechat Pay callback", e);
            // Call the program exception handler
            return  WxPayNotifyResponse.fail(
                notifyHandleResponse.error(e,wxPayOrderNotifyResult,wxPayOrderNotifyResult.getOutTradeNo())
            );   
        }
    }
    
    
    
    /** * Whether the payment is successful **@paramWxPayOrderNotifyResult wechat Payment result *@returnTrue success * /
    private boolean isOk(WxPayOrderNotifyResult wxPayOrderNotifyResult) {
        return
                "SUCCESS".equals(wxPayOrderNotifyResult.getResultCode()) && "SUCCESS".equals(wxPayOrderNotifyResult.getResultCode()); }}Copy the code
4 calls
@RequestMapping("/wxPay")
public class WxNotifyContrller {
    
    
    // A self-implemented interface handler class whose implementation defines the handler interface
    @Autowired
    private DefaultNotifyResponseImpl notifyHandleResponse;
    
    
    
    
    /** * Default payment callback notification handling demo3 **@paramXmlData Responds to data *@returnThe data returned to the WX server will be displayed in the information in the query wechat order */
    @GetMapping(value = "/notify/demo1")
    public String handleNotify(@RequestBody(required = false) String xmlData) {
        return wxNotify.build(xmlData, notifyHandleResponse).handleNotifyResponse();
    }
    
    
    
    
    
    /** * Default pay callback notification handling demo2 **@paramXmlData Responds to data *@returnThe data returned to the WX server will be displayed in the information in the query wechat order */
    @GetMapping(value = "/notify/demo2")
    public String demo2(@RequestBody(required = false) String xmlData) {
        return wxNotify.build(xmlData, new NotifyHandleResponse() {
            @Override
            public String success(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
                // Business processing.return "Successful payment (...) ";
            }
            @Override
            public String fail(WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
                // Business processing.return "Payment failure (...) ";
            }
            @Override
            public String error(Exception e,WxPayOrderNotifyResult wxPayOrderNotifyResult,String bllCode) {
                // Business processing.return "Abnormal payment (...) "; } }).handleNotifyResponse(); }}Copy the code

advantages

From here on out, relative to before

The system is more resilient,

The caller only needs to focus on the calling business itself and nothing else

Improved code cleanliness, in the later maintenance is also more convenient