上一篇文章:nodejs微信公众号开发——6.自定义菜单,实现了简单自定义菜单的功能,里面每个菜单的类型都是
click
的,当然它支持更多类型,如view
,scancode_waitmsg
,scancode_push
,pic_sysphoto
,location_select
等,根据实际需求配置。本节主要介绍用户管理的内容 (项目github地:https://github.com/Panfen/wem... )
1. 用户管理介绍
公众号里面的用户可能来自四面八方,拥有这不同的职业、兴趣等类别,可以通过对用户有效的管理,实现精准服务、精准营销。用户管理的内容包含:
- 用户分组管理
- 设置用户备注名
- 获取用户基本信息(UnionID机制)
- 获取用户列表
- 获取用户地理位置
- 网页授权获取用户基本信息
2. 用户分组
使用这个接口,对公众平台的分组进行查询、创建、修改、删除等操作,也可以使用接口在需要时移动用户到某个分组。接口提供的功能包括:
- 创建分组
- 查询所有分组
- 查询用户所在分组
- 修改分组名
- 移动用户分组
- 批量移动用户分组
- 删除分组
2.1 在api中定义url
var api = {
...
groups:{
create:prefix+'groups/create?', //access_token=ACCESS_TOKEN 创建分组,POST请求
get:prefix+'groups/get?', //access_token=ACCESS_TOKE 查询所有分组,GET请求
getId:prefix+'groups/getid?', //access_token=ACCESS_TOKEN 查询用户所在分组,POST请求
update:prefix+'groups/update?', //access_token=ACCESS_TOKEN 修改分组名,POST请求
membersUpdate:prefix+'groups/members/update?', //access_token=ACCESS_TOKEN 移动用户分组,POST请求
membersBatchupdate:prefix+'groups/members/batchupdate?', //access_token=ACCESS_TOKEN 批量移动用户分组,POST请求
delete:prefix+'groups/delete?' //access_token=ACCESS_TOKEN 删除分组,POST请求
}
}
2.2 创建分组:createGroup
写到现在,应该对这种api的代码实现非常熟悉了,都是在Wechat
的原型上增加方法:
Wechat.prototype.createGroup = function(name){
var that = this;
return new Promise(function(resolve,reject){
that.fetchAccessToken().then(function(data){
var url = api.groups.create + 'access_token=' + data.access_token;
var opts = {
group:{
name:name
}
};
request({method:'POST',url:url,body:opts,json:true}).then(function(response){
var _data = response.body;
if(_data.group){
resolve(_data.group);
}else{
throw new Error('create group failed: ' + _data.errmsg);
}
}).catch(function(err){
reject(err);
});
});
});
}
2.3 获取所有分组:getGroups
同样是简单的增加原型方法:
Wechat.prototype.getGroups = function(name){
var that = this;
return new Promise(function(resolve,reject){
that.fetchAccessToken().then(function(data){
var url = api.groups.get + 'access_token=' + data.access_token;
request({url:url,json:true}).then(function(response){
...
});
});
});
}
注:
"
是"
的十进制表示,因为是测试,我就不改了
2.4 删除分组:deleteGroups
接口提供功能是,发起一次请求根据一个ID删除一个分组,即一次删除一个分组。有些时候我们希望一次删除多个分组,我们可以自己封装支持批量删除的操作:
Wechat.prototype.deleteGroups = function(idArr){
var that = this;
that.fetchAccessToken().then(function(data){
var queue = [];
for(var i = 0; i < idArr.length; i++){
queue.push(_deleteGroup(data.access_token,idArr[i]));
}
Promise.all(queue).then(function(data){
console.log('data:' + data);
}).catch(function(err){
console.log(err)
})
});
}
这里的参数idArr
是id
的数组,里面有一个或多个id
值,通过Promise.all()的方法,来处理Promise的集合,_deleteGroup
函数实现了为每一个id
构建一个Promise:
var _deleteGroup = function(access_token,id){
var url = api.groups.delete + 'access_token=' + access_token;
var opts = {
group:{
id:id
}
};
return new Promise(function(resolve,reject){
request({method:'POST',url:url,body:opts,json:true}).then(function(response){
...
});
});
}
注:
这里已经实现了批量删除分组的功能,但是后台报了一个错:TypeError: You may only yield a function, promise, generator, array, or object, but the following object was passed: "undefined"
由于不影响程序运行,主要暂时不知道怎么解决,先mark着。明白原因的大神请不吝赐教,不胜感激!
2.5 移动用户分组
鉴于移动用户分组和批量移动用户分组功能的相似性,将其实现在一个函数moveUsersToGroup
里面:
Wechat.prototype.moveUsersToGroup = function(openid,to_groupid){
var that = this;
return new Promise(function(resolve,reject){
that.fetchAccessToken().then(function(data){
var url = '';
var form = {}
if(openid && !Array.isArray(openid)) { //单个用户分组
url = api.groups.membersUpdate + 'access_token=' + data.access_token;
form = {
openid:openid,
to_groupid:to_groupid
};
}else if(Array.isArray(openid)){ //批量用户分组
url = api.groups.membersBatchupdate + 'access_token=' + data.access_token;
form = {
openid_list:openid,
to_groupid:to_groupid
};
}
request({method:'POST',url:url,body:form,json:true}).then(function(response){
...
)}
});
});
}
测试代码:
将当前用户移动到分组号为114
的分组,
else if(content === '6'){
var msg = yield wechatApi.moveUsersToGroup(message.FromUserName,114);
var groups = yield wechatApi.getGroups();
console.log('获取到如下分组:\n'+ JSON.stringify(groups));
}
可以看到,该分组的count
值变成1
。
3. 设置用户备注名
毫无技术难度的代码:
Wechat.prototype.updateUserRemark = function(openid,remark){
var that = this;
return new Promise(function(resolve,reject){
that.fetchAccessToken().then(function(data){
var url = api.user.updateUserRemark + 'access_token=' + data.access_token;
var form = {
openid:openid,
remark:remark
};
request({method:'POST',url:url,body:form,json:true}).then(function(response){
...
});
});
});
}
4.获取用户基本信息
在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称
、头像
、性别
、所在城市
、语言
和关注时间
。
获取用户信息的接口分为获取单个用户信息和批量获取用户信息,这个接口请求的地址,请求方式都不同。我们将两者实现在一个函数里面:
//获取单个或一批用户信息
Wechat.prototype.fetchUserInfo = function(open_id,lang){
var that = this;
var lang = lang || 'zh_CN';
var url = '';
var opts = {}
return new Promise(function(resolve,reject){
that.fetchAccessToken().then(function(data){
if(open_id && !Array.isArray(open_id)){ //单个获取
url = api.user.getUserInfo + 'access_token=' + data.access_token +'&openid='+ open_id +'&lang=' +lang;
opts = {
url:url,
json:true
}
}else if(open_id && Array.isArray(open_id)){
url = api.user.batchGetUserInfo + 'access_token=' + data.access_token;
var user_list = [];
for(var i=0;i<open_id.length;i++){
user_list.push({
openid:open_id[i],
lang:lang
});
}
opts = {
method:'POST',
url:url,
body:{
user_list:user_list
},
json:true
}
}
request(opts).then(function(response){
...
});
});
});
}
测试获取单个用户信息和批量获取信息(模拟):
else if(content === '8'){
var data1 = yield wechatApi.fetchUserInfo(message.FromUserName);
console.log(JSON.stringify(data1));
var data2 = yield wechatApi.fetchUserInfo([message.FromUserName]);
console.log(JSON.stringify(data2))
}
5.获取用户列表
公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成。一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
Wechat.prototype.getUserOpenIds = function(next_openid){
var that = this;
return new Promise(function(resolve,reject){
that.fetchAccessToken().then(function(data){
var url = api.user.getUserOpenIds + 'access_token=' + data.access_token;
if(next_openid) url += '&next_openid=' + next_openid;
request({url:url,json:true}).then(function(response){
...
});
});
});
}
测试一下吧:
var data1 = yield wechatApi.getUserOpenIds();
console.log(JSON.stringify(data1));
var data2 = yield wechatApi.getUserOpenIds(message.FromUserName);
console.log(JSON.stringify(data2));
看到这里的结果是不是有点奇怪?按照文档说明,当next_openid
不填写的时候,是从头开始拉取用户数据;填写next_openid
时,时第一个拉取的OPENID。从结果看出,填写next_openid
时,数据是从next_openid
开始算起的。
其他函数不在这里继续介绍(都是重复性的代码T_T),可以在github上看到完成代码。
6. 参考资料
列举了参考的几份很有价值的资料,主要是加深都promise
和koa框架
的理解。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。