判断用户是否关注微信订阅号-服务号

网上搜索了一下,还是有很多人问这个问题。但是,好些文章只讲了大概,对刚接触微信订阅号的人,依然比较懵!刚好最近也有一个场景需在做这个判断,我把这个过程整理出来。如果你刚好也在做类似的场景需求,可以参考一下。应该看了此篇文章,基本能解决你的问题。

说一下场景,一个朋友在自己的订阅号会经常发布一些马拉松的活动,他本身会被各种马拉松组织方邀请去拍照。所以会提供一些相片,供参加马拉松的人下载(在订阅号上发布链接)。他希望只有关注他订阅号的人才能访问相片的链接。

逻辑就是,如果用户访问链接,先判断用户是不是关注订阅号了,只有关注了就跳转到链接上去;如果没有关注,提标用户先关注(弹出个二维码)。需求就是这么简单。因为我之前没有做过这个判断,以为很简单。如果要判断用户有没有关注,首先要获取用户信息。

花了些时间研究了一下,发现订阅号无法做到。因为要获取用户信息,必须授权。但订阅号无法进行授权。只有服务号才能进行授权。所以第一版本就是重新注册了服务号。

服务号判断的实现

1. 先组织授权地址(包括redirect),成功后,微信会redirect过来,将code传回来。下一步获取access_token需要使用code

/**
     * 
     * @param bizId 自己业务相关的参数,微信redirect时,再返回来
     * @return
     */
    public String authUrl(String bizId) {
        String redirect = "";
        try {
            //配置redirect的 url
            redirect = URLEncoder.encode(wechatConfig.getAuthRedirect(), "utf-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        //getApiAuth()为,微信提供的地址
        return wechatConfig.getApiAuth()
                .replace("APPID", wechatConfig.getAppid())//appId是必须的
                .replace("REDIRECT_URI", redirect)
                .replace("SCOPE", "snsapi_userinfo") //可根据需要,自行选择,参考微信官方文档
                .replace("STATE", bizId);

    }

2.获取access_token

@GetMapping("/auth")
@ResponseBody
public ApiResponse authCallBack(HttpServletRequest request) {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        if (StringUtils.isEmpty(code)) {
            return new ApiResponse().ofFailure(11, "code为空");
        }
        log.info("微信授权回调, code = {}  ,state(race id) = {}", code, state);
        try {
            //获取微信授权access_token
            final LocalAccessToken localAccessToken = weiXinService.getLocalAccessToken(code);
            if (Objects.isNull(localAccessToken)) {
                return new ApiResponse().ofFailure(11, "微信授权失败:");
            }
            log.info("微信授权access_token返回参数:{}", JSON.toJSONString(localAccessToken));
            String accessToken = localAccessToken.getAccessToken();
            String openId = localAccessToken.getOpenid();
            String unionId = localAccessToken.getUnionId();
            log.info("微信授权: " + "获取授权元数据:access token: {}, openid: {}, unionid: {}", accessToken, openId, unionId);
            //如果微信的返回access_token为空
            if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openId)) {
                return new ApiResponse().ofFailure(11, "微信授权失败");
            }
            //这里是获取token见下面的代码说明,是为了获取用户是否订阅服务号的token
            final AccessToken token = weiXinService.getUsersToken();
            if (Objects.isNull(token)) {
                log.error("#token# wrong");
                return new ApiResponse().ofFailure(11, "微信授权失败");
            }
            String userInfoStr = httpClient.userInfoExt(token.getAccessToken(), openId, "zh_CN");
            userInfoStr = new String(userInfoStr.getBytes("ISO-8859-1"), "UTF-8");
            log.info("#微信授权# 用户信息 {}", userInfoStr);
            if (userInfoStr.contains(ERR_CODE)) {
                log.info("#微信授权# 用户信息 出错 {}", userInfoStr);
                return new ApiResponse().ofFailure(11, "微信授权失败:" + userInfoStr);
            }
            WxUserInfo usr = JSON.parseObject(userInfoStr, WxUserInfo.class);
            log.info("#微信授权# 用户信息 正常解析 {}", userInfoStr);
            //为1,说明关注了;为0说明没有关注
            boolean hasSub = usr.getSubscribe().intValue() == 1;
            //下载逻辑省略
            
        } catch (Exception e) {
            log.info("#微信授权# 失败", e);
            return new ApiResponse().ofFailure(11, "微信授权失败");
        }
    }

 上面代码中“weiXinService.getUsersToken()”内部是调用此接口

/**
     * access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。
     * 开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。
     * access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
     * https://developers.weixin.qq.com/doc/offiaccount/WeChat_Invoice/Nontax_Bill/API_list.html#1.1
     * @param grantType
     * @param appid
     * @return
     */
    @RequestMapping(value = "https://api.weixin.qq.com/cgi-bin/token", method = RequestMethod.GET)
    String getToken(@RequestParam("grant_type") String grantType,
                    @RequestParam("appid") String appid, @RequestParam("secret") String secret);

经过上面的2步,就可以判断出,用户是否关注服务号了。

订阅号怎么处理呢?

订阅号的判断,必须结合服务号一起实现,只是订阅号,无法判断出用户是否关注。其原理如下:

1.将订阅号绑定到服务号上。在一个服务号的不同应用,虽然openid不同,但unionid是一样的

2.通过微信提供的接口,将订阅号的用户同步到本地,比如mysql中。同步过来的数据只有openid。

3.通过调用接口查询出所有用户的unionid

4.订阅号配置服务。如果有用户订阅,取消订阅将信息推送给你的服务

5.用户通过服务号授权,可以获取到用户的unionid,拿关这个unionid去mysql查询,是否能查到。如果能查到说明已关注过了;如果查询不到,说明没有关注。

下一篇会写详细阐述实现方法。

本文如果哪里不清楚,可以留言交流!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值