在关注者与公众号产生消息交互后,公众号可获得关注者的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 }

然后就是具体的实现方法了,其实很简单,就是先后调用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 }
获取到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 }
其中详细方法实现如下:

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 }
测试方法如下:

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 }
最终获取数据结果:

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