場景,接手項目負責維護,交接中未明確提及項目是否跑通過微信支付成功回調(diào)。
后臺能正常接受到微信的傳參:
#微信官方回調(diào)參數(shù)
<xml>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<attach><![CDATA[支付測試]]></attach>
<bank_type><![CDATA[CFT]]></bank_type>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
<openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
<out_trade_no><![CDATA[1409811653]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
<time_end><![CDATA[20140903131540]]></time_end>
<total_fee>1</total_fee>
<coupon_fee><![CDATA[10]]></coupon_fee>
<coupon_count><![CDATA[1]]></coupon_count>
<coupon_type><![CDATA[CASH]]></coupon_type>
<coupon_id><![CDATA[10000]]></coupon_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>
那么就只要模擬微信回調(diào)不就可以了嘛,網(wǎng)上找到以下方法...
通過POSTMAN請求命中自己的回調(diào)接口
POST http://127.0.0.1:8888/wx/payNotify
上訴微信返回數(shù)據(jù)放于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.微信能夠回調(diào),且APP能夠正常支付锋爪,客戶端是沒有問題的丙曙。
2.支付回調(diào)給我的參數(shù)是對的,所有只有解析的時候是有問題的其骄。
所以和同事打算從新找一遍排查問題:重新弄的下單流程亏镰,梳理邏輯為:傳參,傳參生成簽名拯爽,一起傳那預(yù)支付訂單索抓,及再次簽名傳APP,支付成功,得到微信回調(diào)逼肯。這邏輯沒毛病...
開始找為什么輸入流報IO錯誤:【Stream closed】
于是開始排查是不是傳參的時候把stream處理過耸黑,導(dǎo)致后面就一直失敗,這時候感覺方向又迷茫又清晰篮幢。
看別人代碼整個頭大了...
他們的自定義攔截器寫了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: 復(fù)制輸入流</br>
*
* @param inputStream
* @return</br>
*/
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() {
}
}
案承!A砘肌Eβ摇!成功了昆箕,body的值獲取正常了...
之前技術(shù)看來是從來沒有接收到過微信回調(diào)的數(shù)據(jù)啊...
眼淚要下來了...我的頭發(fā)感覺都少了幾根...
再次走正常流程下單...回調(diào)成功了Q涣小!E籼取薯嗤!
交接時候我讓對方寫了是否有已知事項未處理...
什么都未告知!O吮谩B娼恪!講道理浪費時間了...
謹記捏题。
2021年3月12日18:27:32