前后端分离微信支付回调

最近再做微信小程序,其中用到了微信支付。项目服务端用的是rest的接口形式。

微信支付调通了,但是比较坑爹的是支付回调失败,查log发现是微信回调传过来的xml,服务端没有解析正确。使用rest接口微信端返回的xml格式如下图所示:

前后端分离微信支付回调

从图中可以清楚的看到支付成功之后回调的时候微信把签名和支付单号,appid等这些重要信息都给放到http请求中了,这点微信做的还是蛮好的。接下来就是获取微信返回的xml了我最开始获取http请求中的xml还是通过最原始的方法从request中以文件流的形式读取的,代码如下:

private Map<String, String> getParamFromInputStream(HttpServletRequest request){
        
        //获取GET过来反馈信息
        Map<String,String> paramMap = new HashMap<String,String>();
        try {
            InputStream inputStream = request.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuffer temp = new StringBuffer();
            String line = bufferedReader.readLine();
            while (line != null) {
                temp.append(line).append("\r\n");
                line = bufferedReader.readLine();
            }
            bufferedReader.close();

            Document document = DocumentHelper.parseText(temp.toString());
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
            // 获取 prepay_id
            for (Element e : elementList) {
                paramMap.put(e.getName(), e.getText());
            }
        }catch(Exception e){
            this.logger.error("支付返回结果处理失败", e);
        }
        return paramMap;
    }

结果就是在代码走到 String line = bufferedReader.readLine();这一步的时候发现获取到的line(就是微信返回过来的xml)是空,根本获取不到请求头中的xml。

出现这种情况,对于http请求知之甚少的菜鸟级别的我来说简直是种折磨,最后还是请教了项目经理,他也是在网上找了好多试了好多次最终给整好了。哈哈废话了这么多直接贴解决的办法吧:

//微信支付回调
    @Path("pay")
    @POST
    @PermitAll
    @Consumes(MediaType.TEXT_XML)
    @Produces(MediaType.APPLICATION_JSON)
    public Response payCallBack(String xml){
        Map<String,Object> map = new HashMap<String,Object>();
        Map<String,String> paramMap = parseXml(xml);
        PaymentRequest paymentRequest = new PaymentRequest();
        paymentRequest.setPlugin("WxpayMentPlugin");
        paymentRequest.setParamMap(paramMap);
        PaymentResponse paymentResponse = paymentEvent.onCallback(paymentRequest);
        if("0".equals(paymentResponse.getStatus())){
            //微信支付,返回处理结果
            String returnCode = "SUCCESS";
            String returnMsg = "";
            map.put("returnCode", returnCode);
            map.put("returnMsg", returnMsg);
            return null;
        }else{
            String returnCode = "FAIL";
            String returnMsg = "";
            map.put("returnCode", returnCode);
            map.put("returnMsg", returnMsg);
            return Response.status(Response.Status.OK).entity(new RestResponse("1013","支付回调失败信息为"+map.toString())).build();
        }
        
    }

private Map<String, String> parseXml(String xml){
        //获取GET过来反馈信息
        Map<String,String> paramMap = new HashMap<String,String>();
        try {
            Document document = DocumentHelper.parseText(xml);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
            // 获取 prepay_id
            for (Element e : elementList) {
                paramMap.put(e.getName(), e.getText());
            }
        }catch(Exception e){
            this.logger.error("支付返回结果处理失败", e);
        }
        return paramMap;
    }

直接在接口上加上注解@Consumes(MediaType.TEXT_XML)就可以获取到http请求中的xml文件了,再用dom4j解析下xml,将xml转成map集合就可以了,再然后就是解析签名判断签名是否正确,然后再写自己的逻辑就可以了。

主要问题还是前后端分离之后获取http请求中信息的方式变了,至于为什么我也不知道啦。我觉得我也应该好好研究下关于http请求的各种参数。本人目前也只干了一年的java开发,经验还不足,贴出这篇文章希望一些前辈能够多多指教,也希望再开发过程中遇到此类问题的童鞋们可以看到这篇文章,少走些弯路。嘿嘿