Do you think what you think is what you think? Record a joint debugging process of peer-to-peer server notification

Keywords: Java JSON xml Spring network

Two systems of the company.

Our A system should send A business contract application to B system. After receiving the data, system B will process it asynchronously and send A notice to our system A after signing.

The interface document indicates that the asynchronous notification is sent through the post request of http protocol, and the message is a json format string.

 

Our A system defines restful http interface.

[extras] @ requestBody note: the parameters received by @ requestBody are from the requestBody, that is, the request body. For http post requests. The requester passes parameters through HttpEntity, and declares the type of data content type in the request header. Spring MVC parses the data in HttpEntity by using HttpMessageConverters configured by HandlerAdapter, and then binds it to the corresponding bean.

@RestController
@Slf4j
public class TaxNotifyController {

    @Reference
    private TaxNotifyService taxNotifyService;

    /**
     *
     * @param notifyVO
     * @return
     */
    @PostMapping("/ayncNotify")
    @UnAuthToken
    public String ayncNotify(@RequestBody NotifyVO notifyVO){
        log.info("Receive callbacks----Asynchronous callback----Asynchronous notification----callback notification:{}", JSON.toJSONString(notifyVO));
        String respText = taxNotifyService.ayncNotify(notifyVO);
        log.info("Callback----Asynchronous callback----Asynchronous notification----Callback notification update content:{}",respText);
        return respText;
    }
}

 

During the test, QA found that we could not receive the callback from the other party. There is a screenshot of the other side's log as evidence.

 

Check the log of our A system. There is no log such as "receive callback asynchronous callback asynchronous notification callback notification".

 

Is the network from system B to our system A not working? Both sides are test environments! Go to the operation and maintenance department for confirmation.

[root@localhost logs]# curl http://192.168.40.84:8802/ent-boot/ayncNotify
{"code":"ERROR","message":"Request method 'GET' not supported"}

 

curl received this error because POST was required. But at least prove that the network between these two systems is no problem.

 

Confirm our log again. Clues found:

2019-12-13 11:07:01.894 [http-nio-8802-exec-9] INFO  com.emaxcard.car.filter.CrosXssFilter:40 - 
CrosXssFilter.......orignal url:/ent-boot/ayncNotify,ParameterMap:{} 2019-12-13 11:07:01.895 [http-nio-8802-exec-9] WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver:197 -
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/xml;charset=UTF-8' not supported] 2019-12-13 11:07:01.895 [http-nio-8802-exec-9] INFO com.emaxcard.car.filter.CrosXssFilter:44 -
CrosXssFilter..........doFilter url:/ent-boot/ayncNotify,ParameterMap:{}

 

Is the content type given by the other party text/xml??

 

Find the developer of system B, and check HttpUtil in the code. Sure enough, the specified content type is text/xml. As shown in the figure below. As we know, the default format of spring MVC to receive data is json serialization. You specify it in xml format. Obviously, spring MVC will throw an exception when deserializing to NotifyVO object. Naturally, this action method will not be executed, so we do not see the log "receive callback asynchronous callback asynchronous notification callback notification".

[extras] for the message converter settings of springmvc, you can view the RestTemplate.java source code in sping-web.jar.

Line122: jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader);

 

Then, we changed the development student to application/json, and the problem was solved.

 

 

But, but, but, in the afternoon when QA was testing the callback of payment order, the same problem occurred again. We could not receive the request message. Look at the log. It's text/xml again. This payment callback of system B was developed by another student. Considering that there are already external merchants accessing the B system, they are not ready to change it.

If we don't change it, we won't change it. If we don't change system B, we have to change system A. In other words, even if they don't change now, similar problems will inevitably occur in the future when other merchants connect with joint commissioning. That's the future.

How can we change it? Then, instead of receiving the NotfiyVO object directly from the RequestBody, we will receive the String string instead. Then, in the method to do the judgment and deserialization. The changed code is:

    @PostMapping("/ayncNotify")
    @UnAuthToken
    public String ayncNotify(@RequestBody String notifyStr){
        log.info("Receive callbacks----Asynchronous callback----Asynchronous notification----callback notification:{}", notifyStr);
        if(StringUtils.isBlank(notifyStr)){
            log.info("Callback notification is empty");
            return "ERROR-Callback notification request parameter is empty";
        }
        NotifyVO notifyVO = JSON.parseObject(notifyStr,NotifyVO.class);
        log.info("Callback conversion NotifyVo:{}",notifyVO);
        String respText = taxNotifyService.ayncNotify(notifyVO);
        log.info("Callback----Asynchronous callback----Asynchronous notification----Callback notification update content:{}",respText);
        return respText;
    }

 

 

THE END.

In the afternoon, I learned that when a student was docking the payment interface and the payment interface failed to return acceptance, he changed the payment result of the payment document to failure. That's not good! Payment results must be queried through the payment query interface. If the query returns that the payment is successful, the payment will be successful; if the query returns that the payment is failed, the payment will be failed; for other results found, for the sake of conservatism, they will be regarded as being in the payment, and then they will be intervened manually. Technicians must not make their own claims, and make certain unclear results as payment failure. In case of repeated payment, it would be embarrassing. When I started to do aggregate payment in 2016, I had such a miserable experience.

Posted by powlow on Fri, 13 Dec 2019 02:44:22 -0800