场景,接手项目负责维护,交接中未明确提及项目是否跑通过微信支付成功回调。
后台能正常接受到微信的传参:
#微信官方回调参数
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