【微信开发】openId不能满足开发需求,需要获取unionId。遇上了一些坑

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/uknowzxt/article/details/80095105

最近公司需要进行微信公众号开发,要求微信用户点进公众号直接登录,在实现此功能的过程中,遇见了一些坑,写出来记在这里

具体文档信息如下两个链接,openId是获取unionId的前提

获取用户openId及unionId:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

根据openId获取用户unionId:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839


经过梳理发现,同一个公司如果拥有不同的公众号、小程序....,同一个微信用户相对于这些公众号、小程序....的openId都是不同的,此时需要我们申请一个微信开放平台账号,用这个微信开放平台账号把这些公众号、小程序....绑定起来,同一个微信用户相对于同一个开放平台下的公众号、小程序...就有着完全相同的unionId了,这样可以实现,一个公司下的多公众号..之间的用户衔接。

微信开放平台:https://open.weixin.qq.com

在贴代码之前,把遇见的坑写在前面:

    1.  使用如下链接获取unionId,在获取unionId时,报错:

            {"errcode":40001,"errmsg":"invalid credential, access_token is invalid or not latest hint: [D_K0881vr49!]"}

   官方文档如下:

    

注意这里的access_token其实是基础access_token。注意access_token需要做一下缓存,这里官方文档中有进行说明。我使用了redis进行缓存

获取基础access:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

    2.  如果使用如下链接进行unionId的获取,不要忘记,scope应为 snsapi_userInfo


    3.  因为我使用了第一种方法,所以再说说第一种里面注意要点

(1)不要忘记把公众号绑定到开放平台,不然获取不到用户信息,包括unionId

(2)如果scope为snsapi_base ,一定要微信用户关注了此微信公众号,不然也获取不到unionId

(3)如果scope为snsapi_userinfo,那么用户授权允许之后,无论是否关注此微信公众号,都可以获取到unionId

贴代码:需要前端把code给我

    public Result loginByOpenId(@RequestParam String code) {

        String access_token;//token
        String openId;//openid
        String UnionID;//UnionID
        Integer expires_in;//token 过期时间


        //校验数据的合法性,是否为空
        if (StringUtils.isBlank(code)) {
            throw new ServiceException(MemberCodeConstant.USER_EMPTY);
        }


        //调用微信接口获取
        RestTemplate restTemplate = new RestTemplate();
        //获取openId
        String httpOpenIdUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + fuwuAppid + "&secret=" + fuwuSecret + "&code=" + code + "&grant_type=authorization_code";
        ResponseEntity<String> response = restTemplate.getForEntity(httpOpenIdUrl, String.class);
        if (200 != response.getStatusCodeValue()) {
            logger.error("请求失败,获取openId失败");
            throw new ControllerException(MemberCodeConstant.ACCESS_TOKEN_GET_FAIL);
        }
        String r = response.getBody();
        JSONObject body = JSONObject.parseObject(r);
        if ((Integer) body.get("errcode") != null) {
            logger.error("请求成功,但是获取openId失败,错误码:" + body.get("errcode"));
            throw new ControllerException(MemberCodeConstant.ACCESS_TOKEN_GET_FAIL);
        }
        //网页授权token 不一定能用得上
        //access_token = (String) body.get("access_token");
        openId = (String) body.get("openid");


        //获取基础access_token
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.select(CommonConstant.REDIS_YANCODE);
            access_token = jedis.get("access_token");

            /** 不存在则重新去请求*/
            if (StringUtils.isBlank(access_token)) {

                //获取access_token
                String httpTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + fuwuAppid + "&secret=" + fuwuSecret;
                ResponseEntity<Map> response2 = restTemplate.getForEntity(httpTokenUrl, Map.class);
                if (200 != response2.getStatusCodeValue()) {
                    logger.error("请求失败,获取access_token失败");
                    throw new ControllerException(MemberCodeConstant.ACCESS_TOKEN_GET_FAIL);
                }
                Map body2 = response2.getBody();
                if ((Integer) body2.get("errcode") != null) {
                    logger.error("请求成功,但是获取access_token失败,错误码:" + body2.get("errcode"));
                    throw new ControllerException(MemberCodeConstant.ACCESS_TOKEN_GET_FAIL);
                }
                access_token = (String) body2.get("access_token");
                expires_in = (Integer) body2.get("expires_in");


                //把新的access_token放入redis缓存
                jedis.set("access_token", access_token);
                jedis.expire("access_token", expires_in);


            }
        }

        //获取unionId
        String httpUnionIDUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_token + "&openid=" + openId + "&lang=zh_CN";
        ResponseEntity<String> response1 = restTemplate.getForEntity(httpUnionIDUrl, String.class);
        if (200 != response1.getStatusCodeValue()) {
            logger.error("请求失败,获取UnionId失败");
            throw new ControllerException(MemberCodeConstant.ACCESS_TOKEN_GET_FAIL);
        }
        String s = response1.getBody();
        JSONObject body1 = JSONObject.parseObject(s);

        if ((Integer) body1.get("errcode") != null) {
            logger.error("请求成功,但是获取UnionId失败,错误码:" + body1.get("errcode"));
            throw new ControllerException(MemberCodeConstant.ACCESS_TOKEN_GET_FAIL);
        }
        UnionID = (String) body1.get("unionid");
        //返回前端数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("UnionID", UnionID);


        return ResultGenerator.genSuccessResult(map);
}

展开阅读全文

没有更多推荐了,返回首页