准确来说应该是微信接口的BUG,但可能会在一定条件下瞬间刷爆access_token。
简要描述
长链接转短链接接口中的 long_url 如果带有名为 access_token 的参数,会直接导致接口返回 40001,如果项目的 autoRefreshToken 也正好是 true ,会直接导致 java.lang.StackOverflowError 并刷爆服务号的 access_token
模块版本情况
- WxJava 模块名: weixin-java-mp
- WxJava 版本号:3.3.0
期待结果 和 实际情况
先说说微信的BUG
使用官方例子调用长链接转短链接( long_url 添加 access_token 参数):
curl -d "{\"action\":\"long2short\",\"long_url\":\"http://wap.koudaitong.com/v2/showcase/goods?alias=128wi9shh&spm=h56083&redirect_count=1&access_token={random_str}\"}" "https://api.weixin.qq.com/cgi-bin/shorturl?access_token={access_token}"
- {random_str} : 随机字符串,网址中的参数名正好被命名成了access_token
- {access_token} : 正常可用的微信access_token
返回值
{"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [1l1fVa08158619!]"}
修改上面long_url中 access_token 的参数名,或者去掉 access_token 这个参数(这里改成了 bccess_token)
curl -d "{\"action\":\"long2short\",\"long_url\":\"http://wap.koudaitong.com/v2/showcase/goods?alias=128wi9shh&spm=h56083&redirect_count=1&bccess_token={random_str}\"}" "https://api.weixin.qq.com/cgi-bin/shorturl?access_token={access_token}"
- {random_str} : 同上
- {access_token} : 同上
返回值
{"errcode":0,"errmsg":"ok","short_url":"https:\/\/w.url.cn\/s\/AdCvL5R"}
再看看项目中的代码
me.chanjar.weixin.mp.api.impl.BaseWxMpServiceImpl
...
public <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
...
if (error.getErrorCode() == 42001 || error.getErrorCode() == 40001 || error.getErrorCode() == 40014) {
this.getWxMpConfigStorage().expireAccessToken();
if (this.getWxMpConfigStorage().autoRefreshToken()) {
return this.execute(executor, uri, data);
}
}
...
代码中判断到 40001 会让当前 access_token 失效,并且判断到 autoRefreshToken 会继续调用 this.execute()方法
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException {
...
try {
return this.executeInternal(executor, uri, data);
} catch (WxErrorException e) {
...
也就是回到上一个方法,但同样会返回 40001,开始死循环。
日志
Handler dispatch failed; nested exception is java.lang.StackOverflowError
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Caused by: java.lang.StackOverflowError: null
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.read(InputRecord.java:503)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:930)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at okio.Okio$2.read(Okio.java:139)
准确来说应该是微信接口的BUG,但可能会在一定条件下瞬间刷爆access_token。
简要描述
长链接转短链接接口中的
long_url如果带有名为access_token的参数,会直接导致接口返回40001,如果项目的autoRefreshToken也正好是true,会直接导致java.lang.StackOverflowError并刷爆服务号的access_token模块版本情况
期待结果 和 实际情况
先说说微信的BUG
使用官方例子调用长链接转短链接(
long_url添加access_token参数):返回值
{"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [1l1fVa08158619!]"}修改上面long_url中
access_token的参数名,或者去掉access_token这个参数(这里改成了bccess_token)返回值
{"errcode":0,"errmsg":"ok","short_url":"https:\/\/w.url.cn\/s\/AdCvL5R"}再看看项目中的代码
me.chanjar.weixin.mp.api.impl.BaseWxMpServiceImpl
代码中判断到
40001会让当前access_token失效,并且判断到autoRefreshToken会继续调用this.execute()方法也就是回到上一个方法,但同样会返回
40001,开始死循环。日志