收藏
回答

公众号网页授code多次回调?

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

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

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

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

回答关注问题邀请回答
收藏

2 个回答

  • 社区技术运营专员--许涛
    社区技术运营专员--许涛
    2020-11-26

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

    2020-11-26
    有用
    回复 1
    • 浩
      发表于移动端
      2020-11-27
      已解决
      2020-11-27
      回复
  • 浩
    2020-11-26
    
    
    
    
    
        @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);
        }
    
    
    }
    
    
    
    2020-11-26
    有用
    回复
登录 后发表内容
问题标签