在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。
请注意,如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。
UnionID机制说明:
  开发者可通过OpenID来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。 
获取用户基本信息(包括UnionID机制)
开发者可通过OpenID来获取用户基本信息。请使用https协议。
接口调用请求说明
http请求方式: GET https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
参数说明
参数 是否必须 说明
access_token 调用接口凭证
openid 普通用户的标识,对当前公众号唯一
lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
 
或者是批量获取用户基本信息
批量获取用户基本信息
开发者可通过该接口来批量获取用户基本信息。最多支持一次拉取100条。
接口调用请求说明
http请求方式: POST
https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=ACCESS_TOKEN
POST数据示例
{
   "user_list": [
       {
           "openid": "otvxTs4dckWG7imySrJd6jSi0CWE",
           "lang": "zh_CN"
       },
       {
           "openid": "otvxTs_JZ6SEiP0imdhpi50fuSZg",
           "lang": "zh_CN"
       }
   ]
}
参数说明
参数 是否必须 说明
openid 用户的标识,对当前公众号唯一
lang 国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN
 
通过这2个接口,可以发现要获取用户信息必要要获取用户关注公众号的 openid,那么首先要获取对应的openid,涉及到另外一个接口:
获取用户列表
公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串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
 
这样可以获取到公众号的关注着列表. 获取到openid后即可获取用户的明细信息。
 
功能实现
分析完接口参数及调用方式,下面就来进行实现吧~
可以定义一个用户信息类,这样后续处理用户信息或存储到数据库均较方便,主要属性可按接口返回字段进行定义:
  1 /**
  2  * 微信用户信息类
  3  * @author Damon
  4  */
  5 public class UserInfo
  6 {
  7 
  8     // 用户的标识
  9     private String openId;
 10 
 11     // 关注状态(1是关注,0是未关注),未关注时获取不到其余信息
 12     private int subscribe;
 13 
 14     // 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
 15     private int subscribetime;
 16 
 17     // 昵称
 18     private String nickname;
 19 
 20     // 用户的性别(1是男性,2是女性,0是未知)
 21     private int sex;
 22 
 23     // 用户所在国家
 24     private String country;
 25 
 26     // 用户所在省份
 27     private String province;
 28 
 29     // 用户所在城市
 30     private String city;
 31 
 32     // 用户的语言,简体中文为zh_CN
 33     private String language;
 34 
 35     // 用户头像
 36     private String headimgurl;
 37 
 38     private String remark;
 39 
 40     private int groupid;
 41 
 42     public String getOpenId()
 43     {
 44         return openId;
 45     }
 46 
 47     public void setOpenId(String openId)
 48     {
 49         this.openId = openId;
 50     }
 51 
 52     public int getSubscribe()
 53     {
 54         return subscribe;
 55     }
 56 
 57     public void setSubscribe(int subscribe)
 58     {
 59         this.subscribe = subscribe;
 60     }
 61 
 62     
 63     public int getSubscribetime()
 64     {
 65         return subscribetime;
 66     }
 67 
 68     public void setSubscribetime(int subscribetime)
 69     {
 70         this.subscribetime = subscribetime;
 71     }
 72 
 73     public String getNickname()
 74     {
 75         return nickname;
 76     }
 77 
 78     public void setNickname(String nickname)
 79     {
 80         this.nickname = nickname;
 81     }
 82 
 83     public int getSex()
 84     {
 85         return sex;
 86     }
 87 
 88     public void setSex(int sex)
 89     {
 90         this.sex = sex;
 91     }
 92 
 93     public String getCountry()
 94     {
 95         return country;
 96     }
 97 
 98     public void setCountry(String country)
 99     {
100         this.country = country;
101     }
102 
103     public String getProvince()
104     {
105         return province;
106     }
107 
108     public void setProvince(String province)
109     {
110         this.province = province;
111     }
112 
113     public String getCity()
114     {
115         return city;
116     }
117 
118     public void setCity(String city)
119     {
120         this.city = city;
121     }
122 
123     public String getLanguage()
124     {
125         return language;
126     }
127 
128     public void setLanguage(String language)
129     {
130         this.language = language;
131     }
132 
133     public String getHeadimgurl()
134     {
135         return headimgurl;
136     }
137 
138     public void setHeadimgurl(String headimgurl)
139     {
140         this.headimgurl = headimgurl;
141     }
142 
143     public String getRemark()
144     {
145         return remark;
146     }
147 
148     public void setRemark(String remark)
149     {
150         this.remark = remark;
151     }
152 
153     public int getGroupid()
154     {
155         return groupid;
156     }
157 
158     public void setGroupid(int groupid)
159     {
160         this.groupid = groupid;
161     }
162 
163 
164 }
View Code

 

 然后就是具体的实现方法了,其实很简单,就是先后调用2次接口就行了:
 首先的要调用获取用户openid的列表:
 1     /**
 2      * 获取公众号关注的用户openid
 3      * @return
 4      */
 5     public List<String> getUserOpenId(String access_token, String nextOpenid)
 6     {
 7         String path = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
 8         path = path.replace("ACCESS_TOKEN", access_token).replace("NEXT_OPENID", nextOpenid);
 9         System.out.println("path:" + path);
10 
11         List<String> result = null;
12         try
13         {
14             String strResp = WeChatUtil.doHttpsGet(path, "");
15             System.out.println(strResp);
16 
17             Map map = WeChatUtil.jsonToMap(strResp);
18             Map tmapMap = (Map) map.get("data");
19 
20             result = (List<String>) tmapMap.get("openid");
21 
22             System.out.println(result.toString());
23 
24         }
25         catch (HttpException e)
26         {
27             // TODO Auto-generated catch block
28             e.printStackTrace();
29         }
30         catch (IOException e)
31         {
32             // TODO Auto-generated catch block
33             e.printStackTrace();
34         }
35 
36         return result;
37     }
View Code

获取到openi的信息后,也可以先存储起来(具体看项目需要了),或再等详细信息后才存储,

对应的调用方法如下:
 1     /**
 2      * 通过用户openid 获取用户信息
 3      * @param userOpenids
 4      * @return
 5      */
 6     public List<UserInfo> getUserInfo(List<String> userOpenids)
 7     {
 8         // 1、获取access_token
 9         // 使用测试 wx9015ccbcccf8d2f5 02e3a6877fa5fdeadd78d0f6f3048245
10         WeChatTokenService tWeChatTokenService = new WeChatTokenService();
11         String tAccess_Token = tWeChatTokenService.getToken("wx9015ccbcccf8d2f5", "02e3a6877fa5fdeadd78d0f6f3048245").getToken();
12 
13         // 2、封装请求数据
14         List user_list = new ArrayList<Map>();
15         for (int i = 0; i < userOpenids.size(); i++)
16         {
17             String openid = userOpenids.get(i);
18             Map tUserMap = new HashMap<String, String>();
19             tUserMap.put("openid", openid);
20             tUserMap.put("lang", "zh_CN");
21             user_list.add(tUserMap);
22         }
23         System.out.println(user_list.toString());
24         Map requestMap = new HashMap<String, List>();
25         requestMap.put("user_list", user_list);
26         String tUserJSON = JSONObject.fromObject(requestMap).toString();
27 
28         // 3、请求调用
29         String result = getUserInfobyHttps(tAccess_Token, tUserJSON);
30         System.out.println(result);
31 
32         // 4、解析返回将结果
33         return parseUserInfo(result);
34     }
View Code

其中详细方法实现如下:

 1     /**
 2      * 解析返回用户信息数据
 3      * @param userInfoJSON
 4      * @return
 5      */
 6     private List<UserInfo> parseUserInfo(String userInfoJSON)
 7     {
 8         List user_info_list = new ArrayList<UserInfo>();
 9 
10         Map tMapData = WeChatUtil.jsonToMap(userInfoJSON);
11 
12         List<Map> tUserMaps = (List<Map>) tMapData.get("user_info_list");
13 
14         for (int i = 0; i < tUserMaps.size(); i++)
15         {
16             UserInfo tUserInfo = new UserInfo();
17             tUserInfo.setSubscribe((Integer) tUserMaps.get(i).get("subscribe"));
18             tUserInfo.setSex((Integer) tUserMaps.get(i).get("sex"));
19             tUserInfo.setOpenId((String) tUserMaps.get(i).get("openid"));
20             tUserInfo.setNickname((String) tUserMaps.get(i).get("nickname"));
21             tUserInfo.setLanguage((String) tUserMaps.get(i).get("language"));
22             tUserInfo.setCity((String) tUserMaps.get(i).get("city"));
23             tUserInfo.setProvince((String) tUserMaps.get(i).get("province"));
24             tUserInfo.setCountry((String) tUserMaps.get(i).get("country"));
25             tUserInfo.setHeadimgurl((String) tUserMaps.get(i).get("headimgurl"));
26             tUserInfo.setSubscribetime((Integer) tUserMaps.get(i).get("subscribe_time"));
27             tUserInfo.setRemark((String) tUserMaps.get(i).get("remark"));
28             tUserInfo.setGroupid((Integer) tUserMaps.get(i).get("groupid"));
29             user_info_list.add(tUserInfo);
30         }
31 
32         return user_info_list;
33     }
34 
35     /**
36      * 调用HTTPS接口,获取用户详细信息
37      * @param access_token
38      * @param requestData
39      * @return
40      */
41     private String getUserInfobyHttps(String access_token, String requestData)
42     {
43         // 返回报文
44         String strResp = "";
45         String path = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=ACCESS_TOKEN";
46         path = path.replace("ACCESS_TOKEN", access_token);
47 
48         try
49         {
50             strResp = WeChatUtil.doHttpsPost(path, requestData);
51         }
52         catch (HttpException e)
53         {
54             // 发生致命的异常,可能是协议不对或者返回的内容有问题
55             System.out.println("Please check your provided http address!" + e);
56             e.printStackTrace();
57         }
58         catch (IOException e)
59         {
60             // 发生网络异常
61         }
62         catch (Exception e)
63         {
64             System.out.println(e);
65         }
66         finally
67         {}
68         return strResp;
69     }
View Code

测试方法如下:

1     public static void main(String[] args)
2     {
3         WeChatUserService tChatUserService = new WeChatUserService();
4         tChatUserService.getUserInfo(tChatUserService.getUserOpenId(new WeChatTokenService().getToken("appid", "appSceret").getToken(), ""));
5     }
View Code

最终获取数据结果:
 

 可用把最终过去的用户信息存到数据库,后面的就由大家去发挥啦!