【微信支付回调】踩过坑

场景,接手项目负责维护,交接中未明确提及项目是否跑通过微信支付成功回调。
后台能正常接受到微信的传参:

#微信官方回调参数

  
  
  
  
  
  
  
  
  
  
  
  
  
  1
  
  
  
  
  
  

那么就只要模拟微信回调不就可以了嘛,网上找到以下方法...
通过POSTMAN请求命中自己的回调接口
POST http://127.0.0.1:8888/wx/payNotify
上诉微信返回数据放于Body的raw中。

命中断点后直接报错
java.io.IOException: Stream closed
代码打到了有错误的第5行:

1            InputStream inStream = request.getInputStream();
2            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
3            byte[] buffer = new byte[1024];
4            int len = 0;
5            while ((len = inStream.read(buffer)) != -1) {
6                outSteam.write(buffer, 0, len);
7            }

来回捣鼓最初想法是:
1.微信能够回调,且APP能够正常支付,客户端是没有问题的。
2.支付回调给我的参数是对的,所有只有解析的时候是有问题的。

所以和同事打算从新找一遍排查问题:重新弄的下单流程,梳理逻辑为:传参,传参生成签名,一起传那预支付订单,及再次签名传APP,支付成功,得到微信回调。这逻辑没毛病...

开始找为什么输入流报IO错误:【Stream closed】
于是开始排查是不是传参的时候把stream处理过,导致后面就一直失败,这时候感觉方向又迷茫又清晰。

看别人代码整个头大了...
他们的自定义拦截器写了4个拦截配置,我该从哪里入手?

    /**
     * 添加拦截器链配置
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(AInterceptor)
                .addPathPatterns(AInclude)
                .excludePathPatterns(AExclude);

        registry.addInterceptor(BInterceptor)
                .addPathPatterns(BInclude)
                .excludePathPatterns(BExclude);

        registry.addInterceptor(CInterceptor)
                .addPathPatterns(CInclude)
                .excludePathPatterns(CExclude);

        registry.addInterceptor(DInterceptor)
                .addPathPatterns(DInclude)
                .excludePathPatterns(DExclude);
    }

啊这?拦截我难道要每个改过去?难道我不是就只要我的body中的值不丢不就可以了么?
那我反着把这个body的值能正常获取吧...

那我反手把代码又加了一下

package com.interceptor;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;

/**
 * @author lvlvlv
 * @Description:
 * @Date:2021/1/8
 */
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
    public byte[] body;

    public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = toByteArray(request.getInputStream());
        if (ToolUtil.isEmpty(request.getInputStream())) {
            String sessionStream = getBodyString(request);
            body = sessionStream.getBytes(Charset.forName("UTF-8"));
        }
    }

    /**
     * 获取请求Body
     *
     * @param request
     * @return
     */
    public String getBodyString(final ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = cloneInputStream(request.getInputStream());
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }

    /**
     * Description: 复制输入流
* * @param inputStream * @return
*/ public InputStream cloneInputStream(ServletInputStream inputStream) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; try { while ((len = inputStream.read(buffer)) > -1) { byteArrayOutputStream.write(buffer, 0, len); } byteArrayOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); return byteArrayInputStream; } private byte[] toByteArray(InputStream in) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); byte[] buffer = new byte[1024 * 4]; int n = 0; while ((n = in.read(buffer)) != -1) { out.write(buffer, 0, n); } return out.toByteArray(); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return bais.read(); } }; } }

在加一个corsFilter

package com.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author bobo
 * @description:
 * @date 2019-05-26
 */
@Component
@WebFilter(urlPatterns = "/*", filterName = "CorsFilter")
public class CorsFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(CorsFilter.class);

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws 
IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest reqs = (HttpServletRequest) req;
        String curOrigin = reqs.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", curOrigin == null ? "true" : curOrigin);
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Expose-Headers", "*");
        String a = reqs.getRequestURI();
        ServletRequest requestWrapper = null;
        if (req instanceof HttpServletRequest) {
            requestWrapper = new MyHttpServletRequestWrapper((HttpServletRequest) req);
        }
        if (requestWrapper == null) {
            chain.doFilter(req, res);
            return;
        } else {
            chain.doFilter(requestWrapper, res);
            return;
        }
    }

    @Override
    public void init(FilterConfig filterConfig) {
        logger.info("========================Cors Filter Apply===============================");
    }

    @Override
    public void destroy() {
    }
}

啊!!!!成功了,body的值获取正常了...
之前技术看来是从来没有接收到过微信回调的数据啊...
眼泪要下来了...我的头发感觉都少了几根...

再次走正常流程下单...回调成功了!!!!
交接时候我让对方写了是否有已知事项未处理...
什么都未告知!!!!讲道理浪费时间了...

谨记。
2021年3月12日18:27:32

你可能感兴趣的:(【微信支付回调】踩过坑)