企业微信-审批控件中的外部选项的应用全流程

前言

  • 安卓端可以使用,苹果和PC端使用不了,这是个困扰了我很久的问题,在全网查找的时候发现,这个15年就有人陆续提出了这个问题,但是一直没有解决方案,企业微信侧也没有给出明确的解释,直到我在腾讯拉了企微的开发过来,才发现就是个10年都没去优化的陷阱。。。
  • 解决方案见下方步骤四

背景

  • 企业微信审批和dcops工单平台的互联
  • 在企业微信的审批应用的一些审批模版里添加一个控件,这个控件可以获取到dcops的工单号

实现方案

查阅文档和页面

  • 在企微审批应用后台模版里添加一个 多选或者单选的控件,这个控件的"选项来源"选择"关联外部选项",就会出现一个填外部选项页面地址的输入框
    在这里插入图片描述

    • 我们需要获取到用户身份,用该用户身份登录和划定可选工单号的范围,就需要完成 带登录态跳转移动端页面
    • 根据文档 构造网页授权链接
      • 注意必须使用urlencode对链接进行处理 然后再赋值给redirect_uri,urlencode是指对URL 中的某些字符,如空格、问号、等号等,转换为特定编码格式
        在这里插入图片描述
  • 查看 审批控件中的外部选项接口文档 发现调用该接口需要先完成两件事情

    • 先调用 wx,agentConfig配置
    • 获取到这个控件添加到url里的key,下面调用接口时会用到
      在这里插入图片描述

配置实现

一、引入js

<!-- <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> -->
 <script src="https://res.wx.qq.com/wwopen/js/jsapi/jweixin-1.0.0.js"></script>
 <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>

二、通过config接口注入权限验证配置

  window.wx.config({
          beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
          debug: true, // 在测试没问题之后,关闭debug模式,防止弹窗
          appId: 'xxxx', // 必填,企业微信的corpID
          timestamp: this.timestamp, // 必填,生成签名的时间戳
          nonceStr: 'xxxx', // 必填,生成签名的随机串
          signature: this.signatrue, // 必填,签名,见 附录-JS-SDK使用权限签名算法
          jsApiList: ['agentConfig','saveApprovalSelectedItems','getApprovalSelectedItems'], // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
        });
        wx.error((e) => {
          e && alert(JSON.stringify(e));
        });
!!#ff0000 FAQ!!
生成签名
  • 完成wx.config之前,需要先去生成签名signature。文档JS-SDK使用权限签名算法

  • 必需的noncestr、timestamp必须和上一步wx.config里填写的nonceStr、timestamp一模一样。

  • url不包含#之后的部分,可使用window.location.href.split('#')[0]处理

  • 拼接好之后必须用sha1加密
    在这里插入图片描述

  • 完成生成签名signature之前,需要先去生成临时票据,获取企业的jsapi_ticket

    • jsapi_ticket的有效期为7200秒,api调用次数也非常有限,需做缓存处理

三、通过agentConfig接口注入应用(审批应用)权限验证配置

window.wx.ready((e) => {
          window.wx.agentConfig({
                        beta: true,
                        corpid: 'xxx', // 必填,企业微信的corpid,必须与当前登录的企业一致
                        agentid: 'xxx', // 必填,企业微信的应用id
                        timestamp: this.timestamp, // 必填,生成签名的时间戳
                        nonceStr: 'xxx', // 必填,生成签名的随机串
                        signature: this.appsignature,// 必填,签名,见附录1
                        jsApiList: ['selectExternalContact', 'saveApprovalSelectedItems','getApprovalSelectedItems'], //必填
                        success: function(res) {
                          console.log('应用权限获取成功', res);
                        },
                        fail: function(res) {
                          console.log('应用权限获取失败', res);
                        }
                  });
        });
!!#ff0000 FAQ!!
调用失败wx.agentConfig is not a function
  • 按照企业微信官方文档 引入JS文件 引入的http://res.wx.qq.com/open/js/jweixin-1.2.0.js,在调用wx.agentConfig时,会报错Uncaught TypeError: wx.agentConfig is not a function
  • 所以 第一步 的引用链接改为https://res.wx.qq.com/wwopen/js/jsapi/jweixin-1.0.0.js,即可调用所有jssdk接口
签名无效invalid signature
  • agentConfig与config的签名算法完全一样,但是jsapi_ticket的获取方法不一样,需要单独获取
  • 并且获取access_token的也需要用对应应用的secret,参考官方文档
    在这里插入图片描述
提示需使用应用可信域名
  • “审批应用“这种基础应用是不能配置可信域名的,需要使用第三方自建应用,在网页授权及JS-SDK里配置上redirect_uri的域名或ip,否则会报错permission denied
    在这里插入图片描述

  • 并且在审批应用的“可调用接口的应用”里添加上该第三方自建应用,即可正确调用

  • 在这里插入图片描述

四、通过wx.invoke接口保存和查询选中的数据

window.wx.invoke('saveApprovalSelectedItems', {
                            "key": mykey, // 字符串,从 URL 中获取到的 key
                            "selectedData": selectedData,// 字符串,选中的选项格式化为 JSON 字符串,格式见
                          },(res) => {
                                if (res.err_msg === 'saveApprovalSelectedItems:ok') {
                                    console.log('保存结果成功', res);
                                    console.log('保存请求参数', {
                                      "key": mykey,
                                      "selectedData": selectedData,
                                    });
                                } else {
                                  console.log('保存结果失败', res);
                                }
                          });
!!#ff0000 FAQ!!
"确定"按钮不亮,这里应该是企微端控制的
  • 确保selectedData 必须是字符串,否则 按钮是灰色的
    在这里插入图片描述
选中一次数据之后,再次进入选择别的数据,该控件的数据不能被替换掉?
  • 两次的key不相同,这里先写一个固定的key测试即可
  • 使用固定的key就可以替换了,说明key是和控件绑定的
苹果/iphone端和PC端的“确定”按钮怎么都不会亮,安卓的可以正常使用
  • 企微对安卓端的调用没有那么严格,key正确与否、与企微携带过来的key是否相同,都不影响安卓端正常使用

  • 苹果/iphone端和PC端的限制比较严格,key必须要填写,而且是企微跳转动态添加过来的。
    在这里插入图片描述

  • 那么问题就来了,如果我用这种https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE&agentid=AGENTID#wechat_redirect,带身份验证跳转的形式来构造网页授权链接,审批应用添加的两个参数key和selectorType,应该是添加到了末尾,必然会丢失。

  • 这就意味着 身份授权和key不能同时获取到。这是企微一直没有优化的地方,从15年开始就有人提出这个问题了。有以下两种解决方案

    • 方案一:不使用企微提供的构造网页授权链接,直接跳转第三方页面。如果第三方网站可以开放直接跳转进入,或者设置白名单,并且不需要使用审批提单人来区分数据(比如我希望提加班审批单的人只能看到他自己的第三方数据,我就需要获取到当前提单人/操作人)。显然不是很好的方案
    • 方案二:经测试key必须添加到redirect_uri里,并且urlencode,才能正确跳转和获取到key。
      • 那么我们就可以先直接跳转到第三方页面(比如:https:xxx/test),

      • key和selectorType会被添加到url末尾。拦截页面获取到key之后,添加到redirect_uri
        在这里插入图片描述

      • 再通过"构造网页授权链接"获取身份验证,来完成既获取身份授权又获取到key,相当于跳转了三次。至此PC端和苹果端可以正常使用了。
        实现代码如下,XXX根据实际情况填写:

	// 拦截企微跳转链接,先获取到key再重新跳转
    if (this.$route.query.path === 'test') {
      try {
	// 拦截没有身份授权code的
        if (!this.$route.query.code) {
          const origin = 'http://XXXX.com'
	  // 从URL里获取到key
          let url = `${origin}/loading?path=test&key=${this.$route.query.key}`;
	  // 构造网页授权链接并跳转
          window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=XXX&redirect_uri=${encodeURIComponent(
            url
          )}&response_type=code&scope=snsapi_base&state=XXX&agentid=XXX#wechat_redirect`;
          return;
        }
      } catch (error) {
        console.log(error);
      }
    }

五、既然key是控件id,而且是动态添加的,那么用接口拉取企微的审批模版数据,是不是就不能用固定控件id解析数据?

在这里插入图片描述

  • 经多单测试,虽然key确实是控件id,而且是动态添加的,但是审批模版的控件id没有变化,用接口拉取企微的审批模版数据,可以用固定控件id解析数据。

其他尝试

WECOM-JSSDK

  • **WECOM-JSSDK**提供了Typescript类型支持、npm引入等新能力
    • 也是先权限注入再调用接口。
    ww.register({   
    	   corpId: '',       // 必填,当前用户企业所属企业ID   
        agentId: '',                  // 必填,当前应用的AgentID   
        jsApiList: ['getExternalContact'], // 必填,需要使用的JSAPI列表   
        getConfigSignature,                // 必填,根据url生成企业签名的回调函数   
        getAgentConfigSignature            // 必填,根据url生成应用签名的回调函数 })  
        
    async function getConfigSignature(url) {   
    // 根据 url 生成企业签名   
    // 生成方法参考 https://developer.work.weixin.qq.com/document/14924   	
    return { timestamp, nonceStr, signature } }  
    
    async function getAgentConfigSignature(url) {   
    // 根据 url 生成应用签名,生成方法同上,但需要使用应用的 jsapi_ticket   
    	return { timestamp, nonceStr, signature } }
    
FAQ
wx.invoke用不了
  • 需要使用ww.invoke,但是并没有官方文档说明,应该和wx的用法一样
本地调试可以使用ww.getSignature,传入JSAPI_TICKET即可,虽然会报错,但是不影响使用
  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值