Fellow Travellers

小程序实现微信与多企业微信联动通知管理

张泉
字数统计: 3.3k阅读时长: 12 min
2019/09/16 Share

简介

小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。


它是在微信的生态基础上衍生出来的轻应用,有着当前移动发展的前沿理念,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。开发者可以便携的使用微信生态中提供的资源,但是在企业微信的来临之际,去企业相关的小程序则需要第一时间去思考与构建wechat-wxWork环境关联与交互响应,从而对于服务企业的小程序提供有更好的应用场景。


在本文中,首先会着重说明一个小程序对于一个微信+N个企业微信的生态环境下的联动交互问题,以及简单介绍下企业微信下与微信环境的差异。对于微信服务号推送相关为之前功能点,这里就不详细解说了。

环境差异

1.角色主体标识差异


首先是微信,微信的生态环境中,角色使用OpenId与UnionId进行角色标识以及不同应用中的角色管理,以及小程序的登陆与服务号的推送等。


而在企业微信环境中,角色使用UserId进行角色标识,与外界应用交互使用OpenId,OpenId可与Userid 通过Token进行相互转换,但是这个OpenId与微信的OpenId是没有丝毫关系的。


2.接口差异


企业微信专有接口是指企业微信在微信小程序基础库的基础上进行的二次能力扩展,主要在逻辑层扩展,渲染层与微信小程序基本保持一致。


扩展的接口可以让小程序在企业微信环境运行时获得更多和企业微信相关的能力,比如微信小程序提供了wx.login接口用于获取用户在微信环境中的用户openid信息,企业微信提供了wx.qy.login接口用于获取Code,这样使得一个小程序在企业微信与微信消息互通的场景中,可以根据运行环境获得两种身份态。


小程序在微信环境中运行时,不支持调用企业微信专有接口,需要进行对应的兼容处理。


企业微信API点这里


企业微信专有接口点这里





## 重要思考点
  1. 差异化环境捕获
  1. 企业环境下无直接获取企业Id的多企业判断问题
  1. code只能消费一次情况下,多Token验证问题
  1. 微信验证模式(权限解析)不是锁钥匹配下Code被消费问题
  1. 微信角色、企业微信角色、第三方平台角色匹配问题
  1. 企业微信推送小程序消息

问题点解决

1.获取企业微信环境


这里操作主要是为了兼容微信环境下没有企业微信环境下的接口,避免错误调用不存在的接口导致出错。


首先调用
wx.getSystemInfo()
返回结果中,企业微信会额外有Environment参数。值为wxwork。


2.获取Token


企业微信环境下,所需要的一切去企业微信资源有关的接口都需要该企业微信的Token。注意事项见最后其他内容。

查看官方文档

 请求方式 GET(HTTPS)
 请求地址: 
https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
参数 必须 说明
corpid 企业ID,获取方式参考:术语说明-corpid
corpsecret 应用的凭证密钥,获取方式参考:术语说明-secret


3.获取UserId


企业微信环境下,调用
wx.qy.login()
获取到Code。然后与Token一起获取UserId。

查看官方文档

  请求方式 GET(HTTPS)
  请求地址: 
https://qyapi.weixin.qq.com/cgi-bin/miniprogram/jscode2session?access_token=ACCESS_TOKEN&js_code=CODE&grant_type=authorization_code

请求示例:

{
"access_token":"YeAz*********6_JdDKYMyOv_RJRA",
"js_code":"DdAomHsyxKZ***************O01iI"
"grant_type":"authorization_code"
}

返回:

{
     "userid": "zha*********n",//所需要的userId
     "session_key": "ioQ*****0HqsdIhGYawg==",
     "corpid": "wwcef6*****388445f",//验证是否与获取token的企业id是否相同
     "deviceid": "",
     "errcode": 0,
     "errmsg": "ok"
}
参数 必须 说明
access_token 调用接口凭证
js_code 通过wx.qy.login获取的code
grant_type 这里固定是authorization_code


4.企业微信推送


根据企业微信官方API文档,我们可以通过调用其API发送一个消息,消息类型为miniprogram_notice,即小程序通知消息,其大致概况内容如下:

小程序通知消息只允许小程序应用发送,之前,消息会通过统一的会话【小程序通知】发送给用户。



从2019年6月28日起,用户收到的小程序通知会出现在各个独立的小程序应用中。
小程序应用仅支持发送小程序通知消息,暂不支持文本、图片、语音、视频、图文等其他类型的消息。
不支持@all全员发送
请求方式 POST(HTTPS)
请求地址:https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN

请求示例:

{
"touser" : "zhangsan|lisi",不必需/说明:成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)userId,不是openId
"toparty": "1|2",不必需/说明:部门ID列表,多个接收者用‘|’分隔,最多支持100个。
"totag": "1|2",不必需/说明:标签ID列表,多个接收者用‘|’分隔,最多支持100个。
"msgtype" : "miniprogram_notice",必需/说明:消息类型,此时固定为:miniprogram_notice
"miniprogram_notice" : {
        "appid": "wx123123123123123",必需/说明:小程序appid,必须是与当前小程序应用关联的小程序(与服务号模板推送一致)
        "page": "pages/index?userid=zhangsan&orderid=123123123",
不必需/说明:点击消息卡片后的小程序页面,仅限本小程序内的页面。该字段不填则消息点击后不跳转。(与服务号模板推送一致)
        "title": "会议室预订成功通知",
必需/说明:消息标题,长度限制4-12个汉字
        "description": "4月27日 16:16",
不必需/说明:消息描述,长度限制4-12个汉字
        "emphasis_first_item": true,
不必需/说明:是否放大第一个content_item
        "content_item": [不必需/说明:消息内容键值对,最多允许10个item

            {
                "key": "会议室",必需/说明:长度10个汉字以内
                "value": "402"必需/说明:长度30个汉字以内
            },
            {
                "key": "会议地点",
                "value": "广州TIT-402会议室"
            },
            {
                "key": "会议时间",
                "value": "2018年8月1日 09:00-09:30"
            },
            {
                "key": "参与人员",
                "value": "周剑轩"
            }
        ]
    }
}
截止到这里,一个简单的企业微信推送流程就算完成了。以下更多是为满足业务需求所需要解决的一些问题。


5.无法直接获取企业微信Id问题


由于特殊的小程序应用场景,当前小程序应用了一个微信和N个企业微信环境,但是微信并没有考虑这种场景,官方默认的为开发者是直接知道当前该企业微信的Id与Secret,也就是一对一,一个应用的企业Id与secret只会用在一个后台,那对于多个企业微信你的的场景,我怎么知道我当前登陆的是哪个企业微信呢?




为了后台需额外一张表(或者之前与租户有关的表)来记录每个租户对应的企业Id与secret,然后通过传入租户信息,来匹配企业取出企业Id与secret,获取token之后去解析code,拿到企业Id与传入租户的企业Id进行比对判定。获取流程如下:




wxworkAppRunnuable





6.多企业微信下Token验证问题


由于多个企业微信会具有多个企业Id与secret,也就是有不同的Token,前端传入一个code只能被消费一次,万一不是当前code,是不是要来回通讯遍历所有的租户信息来看是不是对应的企业微信?




这里有两种解决方法:


首先是传入一个code,通过任意一个企业微信信息获取的token来解析,拿到企业Id,再去查询所有的企业Id表,找到匹配的租户与企业微信名称来确定,并返回前端当前是哪个企业微信登入的。


另一种就是让用户自己去选择租户,每次操作后,后台会返回给他当前操作的租户与企业微信是否匹配以获取推送相关的参数。也就是当用户自己决定要打开的时候再去获取他的数据参数并返回他是否匹配正确并且打开成功了。




7.微信验证模式问题


这个在我初次看来以为是和手机号以及手机验证码一样的机制,也就是我一个手机发出的验证码仅能匹配到当前手机使用且只能被当前手机验证消费掉,但是经过测试发现,并不是这样。




企业微信的code并不是验证码,企业微信id与secret也并不是个手机号,他的验证模式更像是权限解析问题,即我code中本身就存在一些信息,也就是我验证成功之后所得到的信息并不是通过企业微信的基本信息中获取的,而是从code中解析出来的,而企业微信id与secret获取的Token更像是一个门禁卡,即你有没有权限去操作解析code的机器,至于是不是自己企业的code,无关紧要。这也就意味着,一个企业微信登陆获取的code可以被任何一个企业id和secret换取的Token解析之后消费掉。也就是我有任意一个合法token就可以解析任意一个Code。由此也就产生了上一个问题中,code被无效消费的问题。




8.微信角色 企业微信角色 平台角色匹配问题


这个问题看起来是不是很像是数据库3张表之间的关联关系问题,实际上也就是这个问题。微信角色的唯一标识为OpenId,企业微信角色的唯一标识为UserId,平台角色有自己的UserCode,我们只需要把这些关系理一下。



wxworkAppRunnuable


首先是微信角色,我们使用手机号与微信号一一对应,然后所有的租户(企业)都可以通过手机号匹配到该微信。微信:租户 = 1:n


然后是租户如企业,租户只有一个企业微信,我们可以通过租户域来和企业Id一一匹配上,租户里的角色和企业微信里的角色也是一一匹配。企业微信:租户 = 1:1


最后是微信与企业微信,通过上面两层我们就可以拿到一个微信角色怎么匹配多个企业微信角色了,一个微信可以通过自己唯一的手机号可以匹配到所以租户中这个手机号的角色对应的企业微信角色,或者加上租户域就能匹配到一个企业微信角色。微信:企业微信 = 1:n




9.微信服务号推送 企业推送管理


其实将问题8的逻辑理出来之后,根据相应关系梳理出来每个角色所具备的所有模板推送即可,例如一个角色拥有1个微信服务号中的5个模板推送,以及3个企业微信的各5个推送,那我进行这1x5+3x5=20个推送的管理即可。将推送相需要的参数根据对应关系存下来,便可以进行这些类型的推送管理,如果模板推送的类型相同,则可以通过一些字段(wx,qyId)+模板类型,快捷的找到指定的推送设置进行下一步操作。



其他


企业微信绑定小程序


登陆企业微信后台,选择绑定公众平台,使用小程序管理员微信进行扫描验证,选择要绑定的小程序,进行授权,企业微信后台获取到小程序Secret,以供使用。


Token权限问题


获取Token需要两个参数。企业微信管理端会有两个参数(企业Id与secret)。(这里注意:企业微信的secret有好几种,分别是应用secret,通讯录secret,外部用户secret,不同的secret获取的权限是不同的。这里要使用的是小程序里面的那个secret。在企业微信后台对应小程序展开位置可以查看。权限查看地址请点击这里


CATALOG
  1. 1. 简介
  2. 2. 环境差异
    1. 2.1. 1.角色主体标识差异
    2. 2.2. 2.接口差异
  3. 3. 问题点解决
  4. 4. 其他
    1. 4.1. 企业微信绑定小程序
    2. 4.2. Token权限问题