zoukankan      html  css  js  c++  java
  • 微信开发之获取用户详细列表

    本文目录

    1. 获取access_token
    2. 获取用户id列表
    3. 获取单用户详细信息
    4. 综合获取用户详细列表
    5. 代码结构组织

    php框架:Thinkphp
    主题任务:微信公众平台开发,获取用户详细信息列表。

    获取用户详细信息列表,有人会说直接去微信开发文档找到对应的Api不就得了,还有什么东西可写?
    首先,微信没有直接提供这样的Api,所以只能将相关的接口进行组合使用。姑且做一下开发记录。


    1、 获取access_token

    微信开发文档入口:

    https://mp.weixin.qq.com/wiki?action=doc&id=mp1421140183

    我的代码:

    public function getAccessToken()
    {
        $wechat = $this->wx_user; //$this->wx_user:已从数据库中取出所需公众号信息
        if (empty($wechat)) {
            $this->setError("公众号不存在!");
            return false;
        }
    
        //判断是否过了缓存期
        $expire_time = $wechat['web_expires'];
        if($expire_time > time()){
           return $wechat['web_access_token'];
        }
    
    	//调用微信提供的接口获取数据
        $appid = $wechat['appid'];
        $appsecret = $wechat['appsecret'];
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
        $return = httpRequest($url,'GET');
        if (empty($return)) {
            $this->setError("请求失败,获取access_token失败");
            return false;
        }
    
        $return = json_decode($return, true);
        if (isset($return['errcode']) && $return['errcode'] != 0) {
            $this->setError("get_access_token 错误代码;".$return['errcode']);
            return false;
        }
    
    	//设置过期时间,保存进数据库,下次判断数据库中的时间是否过期,如上面代码所示
        $web_expires = time() + 7000; // 提前200秒过期
        M('wx_user')->where(array('id'=>$wechat['id']))->save(array('web_access_token'=>$return['access_token'],'web_expires'=>$web_expires));
        return $return['access_token'];
    }
    

    上面涉及到access_token的过期刷新方案。
    因为每次从微信服务器拉取access_token时,之前用的access_token就没用了,也不是立即没用,会有个短暂的过渡期,但这个过渡期基本可以忽略不计。所以,总不能每次都生成新的access_token吧?所以要判断过期时间,在过期之前就只用保存的access_token。

    这里面还有一个问题,就是如果很多人同时都在操作这个公众号的api,那么,在过期临界点的时候会有多次拉取新access_token的现象,导致有些先拉取access_token的操作会失败,所以,微信官方建议使用AccessToken中控服务器进行集中获取access_token,所以现在就只有中控服务器拉取access_token,没人跟它竞争,不会出现上述描述的场景,放一下官方建议的解决方案图:

    因为项目这里是后台操作,一般只是管理员在操作,上述场景的情况几乎不会出现,所以简单场景应用简单解决方案。


    2、 获取用户id列表

    微信开发文档入口:

    https://mp.weixin.qq.com/wiki?action=doc&id=mp1421140840

    我的代码:

    public function getFanIdList($next_openid='')
    {
        $access_token = $this->getAccessToken();
        if (!$access_token) {
            return false;
        }
    
    	//调用微信提供的接口获取数据
        $url ="https://api.weixin.qq.com/cgi-bin/user/get?access_token={$access_token}&next_openid={$next_openid}";//重头开始拉取,一次最多拉取10000个
        $return = httpRequest($url);
        $list = json_decode($return, true);
        if (isset($list['errcode']) && $list['errcode'] != 0) {
            $this->setError("错误代码:".$list['errcode']);
            return false;
        }
        return $list;
    }
    

    获取的数据如下:

    //上边返回的$list[]元素:
    //total	关注该公众账号的总用户数
    //count	拉取的OPENID个数,最大值为10000
    //data	列表数据,OPENID的列表
    //next_openid	拉取列表的最后一个用户的OPENID
    //样本数据:
    {"total":2,"count":2,"data":{"openid":["OPENID1","OPENID2"]},"next_openid":"NEXT_OPENID"}
    

    可以看到,这里只提供了openid,我们要用这个openid去查询相应的粉丝详细信息。
    题外话
    微信目前拉取上述用户列表,一次只能拉取10000个用户。看微信的接口约束手册中,哦,接口约束手册描述接口单日可用最大次数,可以看到,获取单用户的详细信息的最大次数是拉取用户列表的最大次数的10000倍,我想这里的10000倍不是巧合。

    约束手册入口:

    https://mp.weixin.qq.com/wiki?action=doc&id=mp1433744592


    3、 获取单用户详细信息

    微信开发文档入口:

    https://mp.weixin.qq.com/wiki?action=doc&id=mp1421140839

    我的代码:

    public function getFanInfo($openid, $access_token=null)
    {
        if (null === $access_token) {
            $access_token = $this->getAccessToken();
            if (!$access_token) {
                return false;
            }
        }
    
    	//调用微信提供的接口获取数据
        $url ="https://api.weixin.qq.com/cgi-bin/user/info?access_token={$access_token}&openid={$openid}&lang=zh_CN";
        $return = httpRequest($url);
        $wxdata = json_decode($return, true);
        if (isset($wxdata['errcode']) && $wxdata['errcode'] != 0) {
            $this->setError("错误代码;".$wxdata['errcode']);
            return false;
        }
    
        $wxdata['sex_name'] = $this->sexName($wxdata['sex']);
        return $wxdata;
    }
    
    public function sexName($sex_id)
    {
        if ($sex_id == 1) {
            return '男';
        } else if ($sex_id == 2) {
            return '女';
        }
        return '未知';
    }
    

    上面返回的数据结构如下:

    /* $wxdata[]元素:
     * subscribe	用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
     * openid	用户的标识,对当前公众号唯一
     * nickname	用户的昵称
     * sex	用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
     * city	用户所在城市
     * country	用户所在国家
     * province	用户所在省份
     * language	用户的语言,简体中文为zh_CN
     * headimgurl	用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
     * subscribe_time	用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
     * unionid	只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
     * remark	公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
     * groupid	用户所在的分组ID(兼容旧的用户分组接口)
     * tagid_list	用户被打上的标签ID列表
     */
    


    4、 综合获取用户详细列表

    我的代码:

    public function fans_list()
    {
        $wechatObj = new WechatLogic($this->wx_user);
        $access_token = $wechatObj->getAccessToken();
        if (!$access_token) {
            return $this->error($wechatObj->getError());
        }
    
        $next_openid = '';
        $p = intval(I('get.p')) ?: 1;
        for ($i = 1; $i <= $p; $i++) {
            $id_list = $wechatObj->getFanIdList($next_openid);
            if ($id_list === false) {
                return $this->error($wechatObj->getError());
            }
            $next_openid = $id_list['next_openid'];
        }
    
        $user_list = [];
        foreach ($id_list['data']['openid'] as $openid) {
            $user_list[$openid] = $wechatObj->getFanInfo($openid, $access_token);
            if ($user_list[$openid] === false) {
                return $this->error($wechatObj->getError());
            }
            $user_list[$openid]['tags'] = $wechatObj->getFanTagNames($user_list[$openid]['tagid_list']);
            if ($user_list[$openid]['tags'] === false) {
                return $this->error($wechatObj->getError());
            }
        }
    
        $page  = new Page($id_list['total'], $id_list['count']);
        $show = $page->show();
        $this->assign('pager',$page);
        $this->assign('page',$show);
        $this->assign('user_list', $user_list);
        return $this->fetch();
    }
    

    上面代码是有视图输出的,主要提供一种思路。

    里边涉及到的其他代码:
    涉及到获取公众号的用户标签,文档入口:

    https://mp.weixin.qq.com/wiki?action=doc&id=mp1421140837

    /**
     * 获取粉丝标签
     * @return type
     */
    public function getAllFanTags()
    {
        $access_token = $this->getAccessToken();
        if (!$access_token) {
            return false;
        }
    
    	//调用微信提供的接口获取数据
        $url = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token={$access_token}";
        $return = httpRequest($url);
        $wxdata = json_decode($return, true);
        if (isset($wxdata['errcode']) && $wxdata['errcode'] != 0) {
            $this->setError("错误代码;".$wxdata['errcode']);
            return false;
        }
    
        //$wxdata数据样例:{"tags":[{"id":1,"name":"每天一罐可乐星人","count":0/*此标签下粉丝数*/}, ...]}
        return $wxdata['tags'];
    }
    
    /**
     * 获取所有用户标签
     * @return array
     */
    public function getAllFanTagsMap()
    {
        if ($this->tags_map !== null) {
            return $this->tags_map;
        }
    
        $user_tags = $this->getAllFanTags();
        if ($user_tags === false) {
            return false;
        }
    
        $this->tags_map = [];
        foreach ($user_tags as $tag) {
            $this->tags_map[$tag['id']] = $this->tags_map[$tag['name']];
        }
        return $this->tags_map;
    }
    
    /**
     * 获取粉丝标签名
     * @param string $tagid_list
     * @param array $tags_map
     * @return array
     */
    public function getFanTagNames($tagid_list)
    {
        if ($this->tags_map === null) {
            $tags_map = $this->getAllFanTagsMap();
            if ($tags_map === false) {
                return false;
            }
            $this->tags_map = $tags_map;;
        }
    
        $tag_names = [];
        foreach ($tagid_list as $tag) {
            $tag_names[] = $this->tags_map[$tag];
        }
        return $tag_names;
    }
    


    5、 代码结构组织

    1. 因为调用官方接口如果出错,会有错误码和错误信息,可帮助定位问题,为了不浪费这个信息,做了setError()getError()这两个小函数记录,上面已多次使用。
    2. 除了最后的综合使用的业务函数之外,其他都是微信的常规操作,都放在一个微信的常规操作类WechatLogic里边,可以给多个业务使用。


    总结
    其实只要看看官方的手册,找到自己想要的接口,如果找不到直接的接口,就自己拼凑即可。


    主要参考文档

    微信开发入门:https://mp.weixin.qq.com/wiki?action=doc&id=mp1472017492_58YV5
    微信开发文档:https://mp.weixin.qq.com/wiki

    -end-

  • 相关阅读:
    Leetcode Array 4 Median of Two Sorted Arrays
    vscode Python Pylint(代码检测插件)
    Leetcode Array 1 twoSum
    mysql 配置 安装和 root password 更改
    vscode 编译调试c/c++的环境配置
    chm文件打不开的解决办法
    A + B Problem II
    欢天喜地七仙女——代码规范与计划
    欢天喜地七仙女——项目系统设计与数据库设计
    欢天喜地七仙女——团队Gitee实战训练
  • 原文地址:https://www.cnblogs.com/hackbee/p/6827778.html
Copyright © 2011-2022 走看看