公众号网页授code多次回调?
发布于 5 年前 作者 ganghe 4670 次浏览 来自 官方Issues

场景:公众号(已认证)自定义页面中是接口地址,在接口中获取code(成功),并通过 code 获取accessoken(成功),再获取用户信息(成功),最后通过重定向到最终页面 responses.sendRedirect(“url” + “?userId=” + userId);(失效)

重定向前后都输出日志了,说明重定向走到了,但是没有生效,这是什么原因呢?

是因为获取 code 的时候微信回调了四次吗?还是什么原因?

还有为什么微信会回调四次呢?

2 回复

你好,麻烦提供下机型,微信版本号,复现链接和复现视频(麻烦上传至腾讯视频)


    [@GetMapping](/user/GetMapping)(value = "/spots")
    public void spotsDescAuth(HttpServletRequest request, HttpServletResponse responses) {
        synchronized (this) {
            try {
                //从 redis 获取 code 对应的 accesstoken 信息,避免微信多次回调
                Map<String, String> userIdMap = codeAndUserIdRedis.get(codeAndUser);
                String code =
                    getWxCode(request, responses);
                if (code != null) {
                    String userId;
                    if (!CollectionUtils.isEmpty(userIdMap) && userIdMap.containsKey(code)) {
                        userId = userIdMap.get(request.getParameter("code"));
                        logger.info("redis 获取的 userid-》" + userId);
                    } else {
                        userId = wxChatAuth(request, responses, code, SPOTS);
                        HashMap<String, String> stringStringHashMap = new HashMap<>();
                        stringStringHashMap.put(code,userId);
                        codeAndUserIdRedis.setEx(codeAndUser,stringStringHashMap,7200);
                        logger.info("重新获取的 userid-》" + userId);
                    }
                    responses.setHeader("REDIRECT","REDIRECT");//告诉ajax要重定向
                    responses.setHeader("PATH","SPOTS"+ "?userId=" + userId);//ip为服务器ip地址,在此用ip代指
                    responses.sendRedirect(SPOTS + "?userId=" + userId);
                    logger.info("导游导览 url" + SPOTS + "?userId=" + userId);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private String getWxCode(HttpServletRequest request, HttpServletResponse response) {
        String redirect = null;
        String code = request.getParameter("code");
        logger.info("code:---->" + code);
        if (StringUtils.isBlank(code)) {
            try {
                redirect = URLEncoder.encode(request.getRequestURL().toString(), "utf-8");
                logger.info("回调地址:-》" + redirect);
                StringBuffer str = new StringBuffer();
                str.append(authorizeUrl + "&redirect_uri=" + redirect);
                str.append("&response_type=code&scope=snsapi_userinfo&state=123#connect_redirect=1#wechat_redirect");
                response.sendRedirect(str.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return code;
    }

    private String wxChatAuth(HttpServletRequest request, HttpServletResponse response, String code, String url) {
        Map<String, User> list = redisToken.get(webAccessToken);
        logger.info(webAccessToken + ":->" + list);
        User user = new User();
        String result;
        //从 redis 获取 code 对应的 accesstoken 信息,避免微信多次回调
        Map<String, String> codeMap = this.codeAndAccessTokenRedis.get(codeAndAccessToken);
        if (!CollectionUtils.isEmpty(codeMap) && codeMap.containsKey(code)) {
            result = codeMap.get(code);
            logger.info("redis 中的 result:->" + result);
        } else {
            //获取网页授权 access_token,并组装 user
            String uri = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + AppID + "&secret=" + AppSecret + "&code=" + code + "&grant_type=authorization_code";
            logger.info("网页授权 uri:->" + uri);
            result = com.ly.goddess.tools.HttpClientUtil.doGet(uri, "utf-8");
            logger.info("微信获取的result:->" + result);
            Map<String, String> newCodeMap = new HashMap<>();
            newCodeMap.put(code, result);
            codeAndAccessTokenRedis.setEx(codeAndAccessToken, newCodeMap, 7200);
        }
        StringBuffer userInfoUrl = new StringBuffer();
        String getUserInfo = "https://api.weixin.qq.com/sns/userinfo?access_token=";
        if (result != null) {
            JSONObject object = JSON.parseObject(result);
            if (object != null && object.getString("openid") != null && object.getString("access_token") != null) {
                logger.info("第一次获取的 openid :-》" + object.getString("openid"));
                user.setOpen_id(object.getString("openid"));
                String accessToken = object.getString("access_token");
                Integer expiresIn = object.getInteger("expires_in");
                if (!StringUtils.isBlank(accessToken)) {
                    //获取 redis 中存储的 accesstoken,避免多次获取
                    if (!CollectionUtils.isEmpty(list) && list.containsKey(accessToken)) {
                        String openId = user.getOpen_id();
                        BeanUtil.copyPropertiesIgnoreNull(list.get(accessToken), user);
                        user.setOpen_id(openId);
                    } else {
                        userInfoUrl.append(getUserInfo).append(accessToken).append("&openid=").append(object.getString("openid")).append("&lang=zh_CN");
                        logger.info("获取用户信息地址:->" + userInfoUrl);
                        String userInfo = com.ly.goddess.tools.HttpClientUtil.doGet(userInfoUrl.toString(), "utf-8");
                        logger.info("用户全部信息:-<" + userInfo);
                        //。。。
                        HashMap<String, User> userHashMap = new HashMap<>();
                        userHashMap.put(accessToken, user);
                        redisToken.setEx(webAccessToken, userHashMap, expiresIn);
                    }
                }
            }
        }
        
        logger.info("userId:->" + userId);
    }

}

回到顶部