企业微信开发指南

企业微信开发指南

本文假设你已经对企业微信有了基本认识——也就是说你知道啥是企业微信,以及为啥要做企业微信开发。

企业微信的开发主要包括以下几方面:

  • 通讯录管理
  • 应用管理
  • 消息推送
  • 素材管理
  • 身份验证
  • JS-SDK

这些方面微信官方已经提供了非常详细的文档(见参考链接),本文不再赘述,这里只选取几个比较常见的开发场景分享下我自己的经验。


通讯录

通讯录由部门+员工组成,两者关系为多对多,部门有唯一的部门ID(department_id),员工有唯一的账号(userid)。

  • userid:即通讯录里的“账号”字段,新建员工档案时由管理员填写,功能类似于公众号的openid,同一企业号下唯一;
  • department_id:部门ID(点击“通讯录/组织架构树/每个部门/右上角按钮”即可查看),在新建时由微信自动生成,同一企业号下唯一;
  • 标签:本质上是对部门和员工的一个逻辑分组。


应用

按提供方来分有三种:

  1. 基础应用:由微信提供;
  2. 第三方应用:开放体系下的第三方服务商提供;
  3. 自建应用:我们自己新建的,一般我们也都是需要自建应用进行开发。

按作用来分有两种:

  1. 主页型应用:用户点击应用后直接打开一个链接;
  2. 消息型应用:可以像公众号一样设置多个菜单,每个菜单可以配置不同的响应方式。

以下展示一个应用详情界面:

应用详情

从上图我们可以看出,一个应用主要包含以下几方面的信息:

  1. AgentId:应用ID,新建应用后由微信生成;
  2. Secret:应用的Secret,结合CorpID用来获取access_token;
  3. 可见范围:哪些人能看到这个应用(可按人、按部门或者按标签进行设定);
  4. 管理员:可对该应用进行管理的人;
  5. 可信域名:应用主页链接和菜单链接都必须是该可信域名下的地址,由域名+端口组成(80或443可省略),如http://www.example.com或test.example.com:3000,需注意域名必须已通过备案;
  6. 工作台应用主页:配置用户点击应用后跳转的链接地址,配置后该应用即为主页型应用;
  7. 自定义菜单:设置后表示应用为消息型工作台应用主页链接将失效,设置方式类似于公众号。


访问令牌

访问令牌(access_token)是我们开发的第一步,我们在调用微信接口前,往往需要先获取令牌,然后才能“为所欲为” :- )。

令牌只能通过企业ID(CorpID)+Secret来获取,CorpID的查看方式如下:

每个企业号CorpID只有一个,但Secret却有几种,不同Secret获取到的令牌它的作用范围是不同的。

Secret分类如下:

  • 应用Secret:点击“应用详情”就看到了
  • 通讯录管理Secret:查看方式是“管理工具/通讯录同步”
  • 管理组Secret:查看方式是“我的企业/权限管理/管理组”(你如果找不到也很正常,因为这是老用户才有的“待遇”,现已退出历史舞台,奸笑ing)。
应用Secret
通讯录管理Secret
曾经的管理组Secret

获取令牌的接口是:

GET https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=CORPID&corpsecret=SECRECT

返回格式如下:

{
  "errcode": 0,
  "errmsg": "",
  "access_token": "accesstoken000001",
  "expires_in": 7200
}

需要注意的是access_token具有时效性,超过7200(expires_in的值)秒后就会过期,又因为获取令牌的接口有访问频率的限制,所以你需要定时刷新access_token。

详细文档请参考:获取access_token - 企业微信


场景一:网页授权登录

参考文档:网页授权登录 - 企业微信

这是我们使用频率最高的一个场景,简单的说就是:如何在用户进入应用的时候获取到他的userid(或者更详细的信息)?

授权登录使用OAuth2.0协议,先来看看微信官方提供的接入流程图:

总结下来就是三步:

  1. 用户访问时先跳微信服务器,同时你需要告诉微信服务器一个跳转地址
  2. 微信服务器先做验证,验证通过后回跳到你提供的地址,并同时带上一个跟用户信息相关的code
  3. 你根据这个code再调用另一个接口就能获取到用户数据了

第1,2步都是为了拿到code,第3步才是获取用户信息。

假如我有一个主页型应用,基本信息如下:

那么生成的网页链接是这样的(该链接可设置为主页地址、菜单链接和推送消息的跳转链接):

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx10101&redirect_uri=https%3A%2F%2Ftest.example.com%3A3000%2Fapi%2Fmyredirect&response_type=code&scope=snsapi_base#wechat_redirect

这里有两点需要注意的地方:

  1. redirect_uri的值必须经过urlencode处理(可直接调用JS的全局函数encodeURIComponent)
  2. redirect_uri的host部分(即域名+端口)必须和可信域名配置一致
  3. 如果你将一些信息从用户点击传递到回调地址,那么可以设置state参数(只有这一种传递方式)

获取用户信息的接口是(注意code只能使用一次):

GET https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE


场景二:扫码授权登录

参考文档:扫码授权登录 - 企业微信

我们这里只讨论Web网页扫码登录的场景,移动端扫码登录请参考官方文档。

在开发扫码登录前,你需要先开启应用的网页接入功能,开启方式是点击“应用详情/企业微信授权登录/Web网页”,直接将可信域名的值复制过来设置即可。

扫码登录与场景一类似,同样是OAuth2.0协议,也是先拿code再拿用户信息,交互流程图如下:

假如我有以下基本信息:

那么生成的扫码链接是这样的:

https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=wx10101&agentid=1000000&redirect_uri=https%3A%2F%2Ftest.example.com%3A3000%2Fapi%2Fmyredirect

用户打开该链接后,就会出现一个二维码,用户使用企业微信扫码后,就会跳转到回调地址并带上授权code,通过code获取用户信息的接口为:

GET https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE


场景三:素材管理

参考文档:素材管理 - 企业微信

素材管理比较简单,直接调用微信接口即可,不过需要注意的是,目前企业微信只开放了临时素材的管理接口(今天是2018-05-04),所有通过接口上传的media_id仅三天内有效。

那么如果我需要用永久性的media_id咋整?这里分享一个“黑科技”。

比如我们要上传图片素材:

  1. 首先你打开“管理工具/素材库/图片”界面;
  2. 然后打开浏览器控制台(F12或者command+option+i或者其他快捷键);
  3. 再打开Network页签准备查看网络请求(为了查看方便,可以先清空下)
  4. 这时候点击“添加图片”进行上传,如果上传成功,那么Network页签便会出现请求的参数,里面就有你想要的media_id啦。


场景四:消息推送

参考文档:发送应用消息 - 企业微信

本质上就是调用一个接口而已。

需要注意的是,消息都是以应用为单位显示的(在发送消息的时候会指定agentid),所以你调用接口所使用的access_token必须是通过该应用的Secret获得的。

如果你希望对消息内容进行排版(用html的方式),且用户点击后,你希望跳转到一个网页地址去,我推荐你使用“文本卡片消息”。

我们之前还遇到过一个场景是,希望用户在点击消息后,跳转到其他应用去,但遗憾的是目前微信还不支持跨应用跳转。


场景五:JS-SDK

参考文档:JS-SDK - 企业微信

要用JS-SDK,客户端必须要进行SDK初始化;

要进行初始化,必须要有个签名;

要有个签名,必须要有个jsapi_ticket。

所以我们先说说jsapi_ticket。jsapi_ticket其实跟access_token类似,它也会过期,也有频率限制,所以我们也需要对jsapi_ticket进行定时刷新,获取jsapi_ticket的接口如下:

GET https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN

接下来是签名,分享一个node的签名算法供参考:

const crypto = require('crypto');
const qs = require('querystring');

/**
 * 签名生成算法
 * @param {*} query 
 */
function sign(query) {
  // 1.排序
  const obj = qs.parse(query);
  const message = Object.keys(obj).sort().map(key => `${key}=${obj[key]}`).join('&');
  // 2.加密
  const signature = crypto.createHash('sha1').update(message, 'utf8').digest('hex');
  return signature;
}

// 测试
const query = 'noncestr=Wm3WZYTPz0wzccnW&jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value';
console.log(sign(m));
// => 0f9de62fce790f9a083d5c99e95740ceb90c27ed

如果你不确定你的算法是否正确,可以去微信提供的在线签名工具进行验证。

有了签名以后,我们就可以进行SDK初始化了,初始化前需要引入js文件:

http://res.wx.qq.com/open/js/jweixin-1.2.0.js(支持https)

然后开始执行初始化:

wx.config({
  beta: true,    // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
  debug: true,   // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appId: '',     // 必填,企业微信的corpID
  timestamp: '', // 必填,生成签名的时间戳
  nonceStr: '',  // 必填,生成签名的随机串
  signature: '', // 必填,签名,见附录1
  jsApiList: []  // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
// 成功回调ready
wx.ready(function(){
    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
// 失败回调error
wx.error(function(res){
    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});

这里需要注意的是所有参数都是大小写敏感的,比如后端签名时参数是noncestr,但是前端初始化时是nonceStr。

初始化成功后,就可以尽情地浪了。使用企业微信打开以下链接即可体验官方提供的Demo页面:

work.weixin.qq.com/api/ (二维码自动识别)


最后说两句

  1. 严格按照文档中要求的去做会少栽很多坑,不要看漏任何一个细节,例如大小写;
  2. 如果你已经按照文档要求去做了,还是未达到理想效果,那你可以安装一个开发者工具,尝试下从控制台输出信息去进行调试(微信的开发者工具是可以模拟整个微信环境的);
  3. 如果还是解决不了你的问题,那你就直接找客服吧(企业微信的客服反馈还是很及时的,在企业微信客户端的客服对话框中,输入“人工”即可)。
企业微信客服入口

参考链接

开发文档 - 企业微信

编辑于 2018-05-05

文章被以下专栏收录