说明

有时候我们期望获取所有的用户关注列表。

那么,有什么方法可以获取到呢?

获取用户列表

公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的 OpenID 是唯一的)组成。

一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。

接口调用请求说明

http请求方式: GET(请使用 https 协议)
https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID
参数	是否必须	说明
access_token	是	调用接口凭证
next_openid	是	第一个拉取的OPENID,不填默认从头开始拉取

返回说明

正确时返回 JSON 数据包:

{
    "total":2,
    "count":2,
    "data":{
    "openid":["OPENID1","OPENID2"]},
    "next_openid":"NEXT_OPENID"
}
参数	说明
total	关注该公众账号的总用户数
count	拉取的 OPENID 个数,最大值为10000
data	列表数据,OPENID的列表
next_openid	拉取列表的最后一个用户的OPENID

错误时返回 JSON 数据包(示例为无效 AppID 错误):

{"errcode":40013,"errmsg":"invalid appid"}

附:关注者数量超过10000时

当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求。

具体而言,就是在调用接口时,将上一次调用得到的返回中的next_openid值,作为下一次调用中的next_openid值。

示例如下:

公众账号 A 拥有23000个关注的人,想通过拉取关注接口获取所有关注的人,那么分别请求 url 如下:https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN 返回结果:

{
  "total":23000,
  "count":10000,
  "data":{"
     openid":[
        "OPENID1",
        "OPENID2",
        ...,
        "OPENID10000"
     ]
   },
   "next_openid":"OPENID10000"
}https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID1返回结果:
{
   "total":23000,
   "count":10000,
   "data":{
     "openid":[
       "OPENID10001",
       "OPENID10002",
       ...,
       "OPENID20000"
     ]
   },
   "next_openid":"OPENID20000"
}https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID2返回结果(关注者列表已返回完时,返回next_openid为空):
{
   "total":23000,
   "count":3000,
   "data":{"
       "openid":[
         "OPENID20001",
         "OPENID20002",
         ...,
         "OPENID23000"
       ]
   },
   "next_openid":"OPENID23000"
}

开源组件

可以使用基于 wxserv

public interface WxMpUserService {
    void userUpdateRemark(String var1, String var2) throws WxErrorException;

    WxMpUser userInfo(String var1) throws WxErrorException;

    WxMpUser userInfo(String var1, String var2) throws WxErrorException;

    List<WxMpUser> userInfoList(List<String> var1) throws WxErrorException;

    List<WxMpUser> userInfoList(WxMpUserQuery var1) throws WxErrorException;

    WxMpUserList userList(String var1) throws WxErrorException;

    List<WxMpChangeOpenid> changeOpenid(String var1, List<String> var2) throws WxErrorException;
}

例子

查询所有的,实际可以分页依次处理。

WxMpUserList list = wxMpService.getUserService().userList("");

System.out.println(JSON.toJSON(list));

结果:

{"total":16,"count":16,"openids":["000Kc6VD8nnOz_RC3VPPPC-dfBGI","000Kc6bg_WOGsCy4Q8P0oWOrZmBs","000Kc6cGfPhbchLolkXqni0xMjyo","000Kc6RPORnAK94hwQAALHwzo_J8","000Kc6R6-KwnH_LDIsqyplSOAPak","000Kc6VYjK-buG_Xbkg2PF4iV6F8","000Kc6T3XA5eoobRr7PqHmBfdUpY","000Kc6UE42KA65XJiGbpnxL65ESw","000Kc6Vyyw5QU1HiTatlkq-pfzyw","000Kc6RUi_gzfUbSzxhBB3SU1W7o","000Kc6Sl76K95T0SPK3Bn2HdJX4Y","000Kc6WpaGCU6o963vENiEa5FLaw","000Kc6U9N9deUVaXciwJoqNyqk_w","000Kc6cdxX-qGcZgqngRzv1MY7Pc","000Kc6ZBsRic98LDG0gZU-rSe6Lc","000Kc6ckvXambobnkkqTMhCkxc2s"],"nextOpenid":"000Kc6ckvXambobnkkqTMhCkxc2s"}

代码实现

package com.github.houbb.wechat.server.service.task;

import cn.hutool.core.collection.CollectionUtil;
import com.github.houbb.heaven.util.util.DateUtil;
import com.github.houbb.wechat.server.dal.entity.WxUserOpenidInfo;
import com.github.houbb.wechat.server.service.extra.WxUserOpenidInfoServiceEx;
import com.github.houbb.wechat.server.service.service.WxUserOpenidInfoService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class WxUserOpenIdTask {

    @Autowired
    private WxMpService wxMpService;

    @Autowired
    private WxUserOpenidInfoService wxUserOpenidInfoService;

    @Autowired
    private WxUserOpenidInfoServiceEx wxUserOpenidInfoServiceEx;

    /**
     * 分页查询,一次 10000 个
     */
    public void saveAllWxOpenId() {
        // 查询第一次的 10000
        String lastOpenId = null;
        WxMpUserList wxMpUserList = null;

        do {
            try {
                log.info("开始查询微信--------------------------------------------");
                wxMpUserList = wxMpService.getUserService().userList(lastOpenId);
                lastOpenId = wxMpUserList.getNextOpenid();
                log.info("完成查询微信-------------------------------------------- {}", wxMpUserList.getCount());

                // 遍历处理
                List<String> idList = wxMpUserList.getOpenids();
                if(CollectionUtil.isEmpty(idList)) {
                    break;
                }

                for(String wxOpenId : idList) {
                    log.info("开始处理 wx: {}", wxOpenId);
                    boolean containsFlag = wxUserOpenidInfoServiceEx.contains(wxOpenId);
                    if(containsFlag) {
                        log.warn("已经包含标识 {}", wxOpenId);
                        continue;
                    }

                    WxUserOpenidInfo wxUserOpenidInfo = new WxUserOpenidInfo();
                    wxUserOpenidInfo.setWxOpenId(wxOpenId);
                    wxUserOpenidInfo.setAddDate(DateUtil.getCurrentDatePureStr());
                    // 不包含的时候,则插入
                    wxUserOpenidInfoService.insert(wxUserOpenidInfo);
                }
            } catch (WxErrorException e) {
                throw new RuntimeException(e);
            }
        } while (wxMpUserList.getCount() > 0);
    }

}

说明

用这个方法获取历史数据,基于事件实时获取最新的关注信息。

然后再根据 userInfo 获取用户的信息。

限制

报错

【请求地址】: https://api.weixin.qq.com/cgi-bin/user/get?access_token=66_uSMIp0R8PDGV43xgv1K4E9uNmyO2-yqIUkqjA6jRvzcATP6LHjdYZk7RDiKMcbdVjibMblF0krHK0lqMU37PwDQgFZ0SMSLnxl3gsEs7NVWT4ectS2eaXhDI6OINCEaAAAIXZ
【请求参数】:null
【错误信息】:{"errcode":48001,"errmsg":"api unauthorized rid: 64015252-74a9a21a-7e5122e8"}

java.lang.RuntimeException: me.chanjar.weixin.common.error.WxErrorException: {"errcode":48001,"errmsg":"api unauthorized rid: 64015252-74a9a21a-7e5122e8"}

接口权限

发现获取用户列表中,个人账户是没有办法通过【微信认证】

参考资料

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Getting_a_User_List.html

https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId