1. 详解nodejs 开发企业微信第三方应用入门教程

     更新时间:2019年03月12日 14:32:16   作者:Worktile   我要评论

    这篇文章主要介绍了详解nodejs 开发企业微信第三方应用入门教程,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    最近公司要开发企业微信端的 Worktile,以前做的是企业微信内部应用,所以只适用于私有部署客户,而对于公?#24615;?#23458;户就无法使用,所有就准备开发企业微信的第三方应用,本文主要介绍在调研阶段遇到的山珍海味。

    开发之前你需要前注册为第三方服务商,然后用第三方服务商的账号创建应用,创建之后只需要管理员授权应用,第三方服务商即可为用户提供服务。

    一、注册第三发服务商

    登陆 服务商官网 ,注册成为服务商,并登陆服务商管理后台。

    二、配置开发信息

    在创建应用之前,首先要配置好通用开发参数

    在填写系统事件接收 url 时,要正确响应企业微信验证 url 的请求。这个可以参考企业微信后台,自建应用的接收消息的 api 设置。

    在企业的管理端后台,进入需要设?#23186;?#25910;消息的目标应用,点击“接收消息”的?#21543;?#32622;API接收”按钮,进入配置页面。

    要求填写应用的 URL、Token、EncodingAESKey 三个参数

    • URL 是企业后台接收企业微信推送请求的访问协议和地址,支持 http 或 https 协议(为了提高安全性,建议使用 https)。
    • Token 可由企业?#25105;?#22635;写,用于生成签名。
    • EncodingAESKey 用于消息体的?#29992;埽?#26159; AES 密钥的 Base64 编码。

     2.1 验证 url 有效性

    当点击保存的时候,企业微信会发生一条 get 请求?#25945;?#20889;的 url

    比如 url 设置的是 https://api.worktile.com , 企业微信将发送如下验证请求:

    请求地址: https://api.worktile.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS×tamp=13500001234&nonce=123412323&echostr=ENCRYPT_STR

    参数 ?#24471;?/th>
    msg_signature 企业微信?#29992;?#31614;名,msg_signature 结合了企业填写的 token、请求中的 timestamp、nonce 参数、?#29992;?#30340;消息体
    timestamp 时间戳
    nonce 随机数
    echostr ?#29992;?#30340;字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid 四个字段,其中 msg 即为消息内容明文

    2.1.1 通过参数 msg_signature 对请求进行校验

    首先要把刚才配置时随机生成的 token, timestamp, nonce, msg_encrypt 进行 sha1 ?#29992;埽?#36825;里我们可以直接使用 npm 模块 sha1 进行?#29992;埽?#28982;后判断得到的 str 是否和 msg_signature 相等。

    function sha1(str) {
     const md5sum = crypto.createHash('sha1');
     md5sum.update(str);
     const ciphertext = md5sum.digest('hex');
     return ciphertext;
    }
    function checkSignature(req, res, encrypt) {
     const query = req.query;
     console.log('Request URL: ', req.url);
     const signature = query.msg_signature;
     const timestamp = query.timestamp;
     const nonce = query.nonce;
     let echostr;
     console.log('encrypt', encrypt);
     if (!encrypt) {
      echostr = query.echostr;
     } else {
      echostr = encrypt;
     }
     console.log('timestamp: ', timestamp);
     console.log('nonce: ', nonce);
     console.log('signature: ', signature);
     // 将 token/timestamp/nonce 三个参数进行字典序?#21028;?
     const tmpArr = [token, timestamp, nonce, echostr];
     const tmpStr = sha1(tmpArr.sort().join(''));
     console.log('Sha1 String: ', tmpStr);
     // 验证?#21028;?#24182;?#29992;?#21518;的字符串与 signature 是否相等
     if (tmpStr === signature) {
      // 原样返回echostr参数内容
      const result = _decode(echostr);
      console.log('last', result);
      console.log('Check Success');
      return result;
     } else {
      console.log('Check Failed');
      return 'failed';
     }
    }

    2.1.2 解密 echostr 得到 msg 并返回

    密文解密过程:

    对刚才生成的 AESKey 进行 base64 解码

    const EncodingAESKey = '21IpFqj8qolJbaqPqe1rVTAK5sgkaQ3GQmUKiUQLwRe';
    let aesKey = Buffer.from(EncodingAESKey + '=', 'base64');

    对 AESKey 进行 aes-256-cbc 解密

    function _decode(data) {
     let aesKey = Buffer.from('21IpFqj8qolJbaqPqe1rVTAK5sgkaQ3GQmUKiUQLwRe' + '=', 'base64');
     let aesCipher = crypto.createDecipheriv("aes-256-cbc", aesKey, aesKey.slice(0, 16));
     aesCipher.setAutoPadding(false);
     let decipheredBuff = Buffer.concat([aesCipher.update(data, 'base64'), aesCipher.final()]);
     decipheredBuff = PKCS7Decoder(decipheredBuff);
     let len_netOrder_corpid = decipheredBuff.slice(16);
     let msg_len = len_netOrder_corpid.slice(0, 4).readUInt32BE(0);
     const result = len_netOrder_corpid.slice(4, msg_len + 4).toString();
     return result; // 返回一个解密后的明文-
    }
    function PKCS7Decoder (buff) {
     var pad = buff[buff.length - 1];
     if (pad < 1 || pad > 32) {
      pad = 0;
     }
     return buff.slice(0, buff.length - pad);
    }

    然后返回 result 即可

    res.end(result);

    2.2 回调 url 验证失败问题

    验证 URL 时,经常会碰到 URL 验证失败的问题,解决思路是借助微信企业号 接口调试工具

    三、创建应用

    四、测试应用

    应用创建成功后,服务商可以授权 10 个测试企业

    从企业微信应用市场发起授权时,企业微信给刚才应用设置的 指令回调 url 发送一个 post 请求,比如:

    https://api.worktile.com/worktile?msg_signature=b99605616153ffbfbe6ebbb500bd211e67ed714d×tamp=1551076894&nonce=1551709703 ,直接返回成功即可。

    各个事件的回调,服务商在收到推送后都必须直接返回字符串 “success?#20445;?#33509;返回值不是 “success?#20445;?#20225;业微信会把返回内容当作错误信息。

    app.post('/worktile', function (req, res) {
     console.log('req.body', req.body);
     res.send('success');
    });

    测试应用注意事项

    1. 用于安?#23433;?#35797;的企业微信帐号需服务商自行注册,每个应用支持同时添加 10 个测试企业微信账号
    2. 安?#23433;?#35797;的企业微信帐号使用的是当前的应用配置信息,后续的修改不会进行同步;如需更新应用信息请重新授权安装
    3. 同一企业微信帐号,不支持同时安?#23433;?#35797;应用和正式发布的应用

    五、应用上线

    已?#29616;?#20225;业微信的服务商,?#23665;?#20837;应用管理—点击提交上线—勾选应用—提交上线。

    六、用户网页授权登录

    6.1 构造第三方应用网页授权链接

    如果第三方应用需要在打开的网页里面携带用户的身份信息,第一步需要构造如下的链接来获取 code:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

    参数 必须 ?#24471;?/th>
    appid 第三方应用 id(即 ww 或 wx 开头的 suite_id)。注意与企业的网页授权登录不同
    redirect_uri 授权后重定向的回调链接地址,请使用 urlencode 对链接进?#20889;?#29702; ,注意域名需要设置为第三方应用的可信域名
    response_type 返回类型,此时固定为:code
    scope 应用授权作用域。snsapi_base:静默授权,可获取成员的基础信息(UserId与DeviceId);snsapi_userinfo:静默授权,可获取成员的详细信息,但不包含手机、邮箱等敏感信息;snsapi_privateinfo:手动授权,可获取成员的详细信息,包含手机、邮箱等敏感信息。
    state 重定向后会带上 state 参数,企业可以填写 a-zA-Z0-9 的参数值,长度不可超过 128 个字节
    #wechat_redirect 终端使用此参数判断是否需要带上身份信息

    企业员工点击后,页面将跳转至 redirect_uri?code=CODE&state=STATE,第三方应用可根据 code 参数获得企业员工的 corpid 与 userid。code 长度最大为 512 字节。

    6.2 获取访问用户身份

    请求方式:GET(HTTPS)

    请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/getuserinfo3rd?access_token=SUITE_ACCESS_TOKEN&code=CODE

    参数 必须 ?#24471;?/th>
    access_token 第三方应用的 suite_access_token,参见“获取第三方应用凭证”
    code 通过成员授权获取到的 code,最大为 512 字节。?#30475;?#25104;员授权带上的 code 将不一样,code 只能使用一次,5 分钟未被使用自动过期。

     6.2.1 获取第三方应用的 suite_access_token

    请求方式:POST(HTTPS)

    请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token

    参数 是否必须 ?#24471;?/th>
    suite_id 以 ww 或 wx 开头应用 id(对应于旧的以 tj 开头的套件 id)
    suite_secret 应用 secret
    suite_ticket 企业微信后台推送的 ticket

    由于第三方服务商可能托管了大量的企业,其安全问题造成的影响会更加?#29616;兀?#25925; API 中除了合法来源 IP 校验之外,还额外增加了 suite_ticket 作为安全凭证。

    获取 suite_access_token 时,需要 suite_ticket 参数。suite_ticket 由企业微信后台定时推送给“指令回调 URL?#20445;?#27599;十分钟更新一次,见推送 suite_ticket

    suite_ticket ?#23548;?#26377;效期为 30 分钟,可以容错连续两?#20301;?#21462; suite_ticket 失败的情况,但是请永远使用最新接收到的 suite_ticket。

    通过本接口获取的 suite_access_token 有效期为 2 小时,开发者需要进行缓存,不可频繁获取。

    6.2.2 获取推送 suite_ticket

    企业微信服务器会定时(每十分钟)推送 ticket。ticket 会实时变更,并用于后续接口的调用。

    请求方式:POST(HTTPS)

    请求地址: https://api.ninesix.cc/worktile?msg_signature=87276aaf15a13e1eb2ebb6d93732ca668c3ddef8×tamp=1551850300&nonce=1551051655

    在发生授权、通讯录变更、ticket 变化等事件时,企业微信服务器会向应用的“指令回调 URL”推送相应的事件消息,nodejs 接收到的是 xml,解析后拿到 encrypt 字段,然后使用上面配置通用开发参数的 url 时用的解密方式,就可以得到 suite_ticket。

    6.3 获取用户敏感信息

    请求方式:POST(HTTPS)

    请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/getuserdetail3rd?access_token=SUITE_ACCESS_TOKEN

    {
      "user_ticket": "USER_TICKET"
    }

    参数 必须 ?#24471;?/th>
    access_token 第三方应用的 suite_access_token,参见“获取第三方应用凭证”
    user_ticket 成员?#26412;?/td>

    返回结果:

    {
      "errcode": 0,
      "errmsg": "ok",
      "corpid": "wwxxxxxxyyyyy",
      "userid": "lisi",
      "name": "李四",
      "mobile": "15913215421",
      "gender": "1",
      "email": "[email protected]",
      "avatar": "http://shp.qpic.cn/bizmp/xxxxxxxxxxx/0",
      "qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=vcfc13b01dfs78e981c"
    }

    七、用户授权成功

    首页

    详情页

    八、给用户发消息

    我们可以给推送文本、?#35745;?#35270;频、文件、图文等类型。

    请求方式:POST(HTTPS)

    请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN

    推送的时候需要 access_token 和 应用的 agentId,第三方服务商,可通过接口 获取企业授权信息 获取该参数值,其实可以直接通过获取企业永久授权码 直接取到这两个值。

    在我们测试安装应用成功之后,企业微信会 post 一条请求给指令回调 URL,通过上面的解密方式,可以解析到 xml 中的 auth_code

    然后通过 https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKENauth_code 可以获取到 access_token 和 agentId,返回的 agent 是一个数组,但仅旧的多应用套件授权时会返回多个agent,对新的单应用授权,永远只返回一个 agent。

    再通过 access_token 和 agentId 就可以愉快的给用户发送消息了。

    当点击链接时,可以跳到指定任务或者日程等,只不过返回时还是在企业微信的消息模块,并不能自动打开第三方应用,客服回复不支持这么做。

    九、注意事项

    api 可能有时效性,如有差异,以官方 api 为准。

    完整 demo

    以上就是本文的全部内容,希望对大?#19994;?#23398;习有所帮助,也希望大家多多支持脚本之家。

    相关文章

  2. 使用Node搭建reactSSR服务端渲染架构

    使用Node搭建reactSSR服务端渲染架构

    这篇文章主要介绍了使用Node搭建reactSSR服务端渲染架构,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  3. NodeJS制作爬虫全过程

    NodeJS制作爬虫全过程

    这篇文章主要介绍了NodeJS制作爬虫的全过程,包括项目建立,目标网站分析、使用superagent获取源数据、使用cheerio解析、使用eventproxy来并发抓取每个主题的内容等方面,有需要的小伙伴参考下吧。
    2014-12-12
  4. 详解Node.js:events事件模块

    详解Node.js:events事件模块

    由于nodejs是单线程运行的,所以nodejs需要借助事件轮询,本篇文章主要介绍了Node.js:events事件模块,有兴趣的可以了解一下。
    2016-11-11
  5. Node.js中环境变量process.env的一些事详解

    Node.js中环境变量process.env的一些事详解

    这篇文章主要给大家介绍了关于Node.js中环境变量process.env的一些事,文中通过示例代码介绍的非常详细,对大家学习或者使用node.js具有一定的参考学习价值,需要的朋友们下面随着小编来一起学?#25226;?#20064;吧。
    2017-10-10
  6. 使用node.js对音视频文件?#29992;?#30340;实例代码

    使用node.js对音视频文件?#29992;?#30340;实例代码

    本文通过实例代码给大家介绍了使用node.js对音视频文件?#29992;?#30340;方法,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-08-08
  7. 最新评论

    常用在线小工具

    山东群英会开奖查询