问题分析
造成这种报错的原因基于官方的解释是微信端发送了两次相同的请求用户信息时使用同一个code值导致的报错,所以且不论这种设定是否合理,我们解决问题还是得从自身的服务器或者代码找到原因来解决。我的微信公众号的业务流程是通过微信端的菜单请求https://open.weixin.qq.com/connect/oauth2/authorize
获取code值再根据配置的redirect_uri将code值传到后台
在后台用这个code值请求
https://api.weixin.qq.com/sns/oauth2/access_token
来获取当前用户的openid
我分析得出的原因是服务器在后台请求获取openId的速度过慢导致微信端迟迟收不到回应故而重新发送一条,结果用一个相同的code请求两次导致报错
解决思路
网上说的大部分是通过加connect_redirect=1来解决这个问题,但是在我这里不适用(我猜可能是微信端前些年可能有这个参数但是后来给删了因为官方文档上也没有这个参数说明),我的解决思路是在第一次请求时用code设置一个短时间的本地缓存,在第二次请求报40163时根据code去缓存中拿到数据即可。
关键代码
String code = request.getParameter("code");
String openid = "";
Object opendIdCacheObj = CacheManager.getInstance().getObj(code);
//CacheManager是我自己的缓存控制类,其实这一层判断没必要,第二次进入这个方法时缓存里大概率是没有值的,因为只有请求时间大于微信服务器的过期时间才会触发两次请求,这个时候第一次请求还尚未完成,值肯定不在缓存中
if (opendIdCacheObj == null) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+FileUtil.getCurrentPropertiesValue("APPID")+"&secret="+FileUtil.getCurrentPropertiesValue("SECRET")+"&code="
+ code +"&grant_type=authorization_code";
String result = HttpClientUtil.sentGet(url);
System.out.println(code + " " + result);
Map<String, Object> resultMap = JSON.parseObject(result, Map.class);
Object openIdObj = resultMap.get("openid");
if (openIdObj == null) {
Object errorCode = resultMap.get("errcode");
//判断40163报错从缓存中拿值
if (errorCode != null && "40163".equals(errorCode.toString())) {
//线程休眠没什么用,现在肯定有值没必要等,可以去掉
Thread.sleep(500);
opendIdCacheObj = CacheManager.getInstance().getObj(code);
if (opendIdCacheObj == null) {
//请求不到openid属于非法操作,这是我自己的一些处理
request.setAttribute("state", 2);
request.setAttribute("stateValue", "此公众号无法操作");
return Constants.ERROR;
}
openid = opendIdCacheObj.toString();
} else {
//请求不到openid属于非法操作,这是我自己的一些处理
request.setAttribute("state", 2);
request.setAttribute("stateValue", "此公众号无法操作");
return Constants.ERROR;
}
}else {
openid = openIdObj.toString();
CacheManager.getInstance().putObj(code, openIdObj.toString(), 20);
}
//线程休眠没什么用,可以去掉
Thread.sleep(500);
}else {
openid = opendIdCacheObj.toString();
}
微信网页授权时遇到40163错误,原因是微信端因请求延迟重发code导致。解决方案是通过在服务器端设置短期缓存,当第二次请求时检查缓存,避免使用已被使用的code。关键在于使用code作为缓存键,存储access_token和openid。
4049

被折叠的 条评论
为什么被折叠?



