玩不转的企业微信侧边栏

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 前言如果你不知道 企业微信侧边栏 是什么,那就可以划走这篇文章了。如果你知道这是个啥,那你一定非常苦恼要怎么开始。从去年就开始就一直有在做企业微信侧边栏的应用。说实话,开发和调试体验实在是太糟糕了,而且上手的时候跟本连怎么打开它都不知道。

image.png


前言


如果你不知道 企业微信侧边栏 是什么,那就可以划走这篇文章了。如果你知道这是个啥,那你一定非常苦恼要怎么开始。


从去年就开始就一直有在做企业微信侧边栏的应用。说实话,开发和调试体验实在是太糟糕了,而且上手的时候跟本连怎么打开它都不知道。

image.png

最难顶的是官方文档也写得不仔细,连个最简单能跑的 Demo 都没有,找开发讨论区吧,官方的客服也不太懂代码,问了等于没问,很多贴子都是网友互助的。


所以为了能帮助更多人上手侧边栏,我写了一个 教程网站,以及 前端后端 两个 Demo。

image.png

这个教程和 Demo 都放在 这个 Organization 上了,也可以关注一下。

当然本文也不是简单的水文,所以下面简单来聊聊 企业微信侧边栏 一些重要的部分吧。


是什么


企业微信侧边栏(下称企微侧栏)其实就是企业微信右边的一个侧栏(WebView)。

image.png

但是并不是所有对话(session)都能打开这个侧边栏的,只有在 外部联系人外部联系群 的对话中才能右下角打开侧栏的按钮。


外部联系人外部联系群 又是个啥?为什么只有在这种情况下才能打开呢?这就要说到侧栏到底要解决的什么问题。


为什么


侧栏真正要解决的痛点其实是 社群/客户运营和管理


可能大家微信上只有 300 左右的好友,但是有没有想过如果作为一个销售人员,他可能需要添加 1000+ 的客户,要创建 100+ 的群聊,每天可能都会收到成百上千条消息。

image.png

这些客户可能被分为:想买产品的、有意愿想买产品的、已经买产品的、普通客户、VIP、SVIP等。


群聊可能被分为:2020年11月学习群、VIP 群、粉丝群等等。

这么多的客户和群聊,对于单一个销售人员来说就非常头疼。很容易就忘记这个客户是哪个分区、哪个类别、哪种标签的。


而且销售人员主要的工作就是要精细化运营、每天都要和客户以及群聊 聊天。什么时候聊、怎么聊、聊什么都是大学问,而且一旦和这么多客户、群聊聊天更是难上加难。类比一下,时间管理大师最多也只能和 10 个人聊也已经顶天了。


所以企业微信就想:能不能在聊天会话当中有一个工具箱,销售人员就可以在这个工具箱里查看客户/群聊的业务数组,或者通过这个工具箱更好地运营。这就是侧边栏的由来。

上面的这些 “客户” 和 “群聊” 则这被称为:外部联系人外部联系群,这里的 “外部” 指的就是 不是自己企业内部员工


侧栏应用架构


侧边栏本质上也是一个 WebView,所以我们只需要写好前端,无论是普通 html 或者 SPA App 都能被放在侧边栏上。


但是普通的前端还是不够的,如果你想和 企业微信 进行一定的交互,比如发消息、立即创建群聊、打开个人信息弹窗,那就需要企业微信提供的 JS-SDK,具体文档请看这里

image.png


可是 JS-SDK 是需要先 config 才能正常使用,而 config 的参数需要从 企业微信服务端 获取 jsapi_ticket 来生成 signature 才能正常初始化 JS-SDK。

wx.agentConfig({
    corpid: '', // 必填,企业微信的corpid,必须与当前登录的企业一致
    agentid: '', // 必填,企业微信的应用id (e.g. 1000247)
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名,见附录-JS-SDK使用权限签名算法
    jsApiList: ['selectExternalContact'], //必填,传入需要使用的接口名称
    success: function(res) {
        // 回调
    },
    fail: function(res) {
        if(res.errMsg.indexOf('function not exist') > -1){
            alert('版本过低请升级')
        }
    }
});
复制代码

然后问题又来了,从 企业微信服务端 获取 jsapi_ticket 又需要 access_token 这个关键参数,而 access_token 又不能直接缓存到前端,因此,还需要另外一个后端(中间层)来缓存 access_token,并提供 企业微信服务端 API 的转发服务


所以,总得来说,侧边栏看似是前端的东西,但其实它的基础架构起码有 侧边栏业务服务端企微服务端

image.png

企微的服务端已经由企业微信提供了,那我们要实现的就是 侧边栏业务服务端 了。如果你是第一次搞侧边栏,一定会被弄得非常烦,所以建议 Fork 我的 侧边栏(前端)模板后端模板,然后在这基础上进行修改。


开发关键部分


因为这里面的细节太多了,想了解具体实现还是去看那两个模板,这里仅讲一些比较重要的点。


转发服务

首先来说这个转发服务吧,需要对 企微服务端 API 进行转发,而服务端的请求是需要 access_token 作为重要参数来转的,但是 access_token 不能一直请求获取,所以需要进行 redis 缓存。


而 redis 又需要 Docker 来启动,不得不说为了做个简单网页,连 Docker 都整上了:

version: '3'
services:
  redis:
    image: redis
    container_name: 'wecom-sidebar-redis'
    ports:
      - "6379:6379"
    restart: always
复制代码

转发服务在模板里我使用简单的 Koa 实现,redis 客户端的 NPM 包,可以使用 ioredis 来缓存。


转发就很简单了,直接使用 axios 就可以了,但是要注意 proxy 要设置为 false,不然会报错:

const axios = require('axios')
const baseURL = 'https://qyapi.weixin.qq.com/cgi-bin';
const proxy = axios.create({
  baseURL,
  proxy: false // 不指定会报错 SSL routines:ssl3_get_record:wrong version number,参考:https://github.com/guzzle/guzzle/issues/2593
})
module.exports = proxy
复制代码

具体的转发调用 API 相信大家都会怎么写就不多说了。


重定向获取 userId

这种 userId 的获取机制和微信网页开发是差不多的,需要先重定向某个 url,然后从 search 参数获取 code,再用这个 code 通过上面的转发服务向企业微信服务端换取 userId,具体实现可以看 文档这里

image.png


/**
 * 获取重定位的 OAuth 路径
 * @returns {string}
 */
const generateOAuthUrl = (config: Config) => {
  const [redirectUri] = window.location.href.split('#');
  const searchObj = {
    appid: config.corpId,
    redirect_uri: encodeURIComponent(redirectUri),
    response_type: 'code',
    scope: 'snsapi_base',
    agentid: config.agentId,
    state: 'A1',
  };
  const search = Object.entries(searchObj)
    .map(entry => {
      const [key, value] = entry;
      return `${key}=${value}`;
    })
    .join('&');
  return `https://open.weixin.qq.com/connect/oauth2/authorize?${search}#wechat_redirect`;
};
/**
 * 判断当前网页是否需要重定向
 */
const checkRedirect = async (config: Config, getUserId: GetUserId) => {
  if (isMock) return
  const userId = Cookies.get('userId')
  const unAuth = !userId || userId === 'undefined' || userId === 'null'
  const codeExist = window.location.search.includes('code');
  // 判断是否需要重定向
  if (unAuth && !codeExist) {
    window.location.replace(generateOAuthUrl(config));
  }
  // 判断是否需要重新获取 userId
  if (unAuth) {
    const code = qs.parse(window.location.search.slice(1)).code as string
    const newUserId = await getUserId(code)
    Cookies.set('userId', newUserId)
  }
};
复制代码


JS-SDK 初始化

这应该是使用客户端 API 时最重要的一个步骤了,而企微的 JS-SDK API 用起来很麻烦,所以我将它的 API 又再度封装了一下,主要做的是 promisify 的操作:

const agentConfig = (agentSetting: Omit<wx.AgentConfigParams, 'success' | 'fail'>): Promise<wx.WxFnCallbackRes> => {
  return new Promise((resolve, reject) => {
    wx.agentConfig({
      ...agentSetting,
      success: resolve,
      fail: reject,
    });
  });
};
复制代码


然后从我们的转发服务获取 signature 并调用 agentConfig(3.0.24 以上可以不调用 config),

const initSdk = async (config: Config, getSignatures: GetSignatures) => {
  const { corpId, agentId } = config;
  // 获取 ticket
  const signaturesRes = await getSignatures();
  const agentConfigRes = await jsSdk.agentConfig({
    corpid: corpId,
    agentid: agentId,
    timestamp: signaturesRes.meta.timestamp,
    nonceStr: signaturesRes.meta.nonceStr,
    signature: signaturesRes.app.signature,
    jsApiList: apis,
  }).catch(e => {
    console.error(e)
  });
  console.log('agentConfig res', agentConfigRes);
  wx.error(console.error);
};
复制代码


本地开发


本地开发应该是所有前端开发都想要的一个理想环境。但是在配置侧边栏应用的 HTML 地址时,你是不能直接填 localhost 的,必须是可信域名!网上有些教程可能会让你直接改 hosts 文件来将域名转向 localhost


我给出的解决方案是使用 Whistle 来将企业微信的流量代理到本地 localhost,这样就可以在本地进行开发了,具体操作可看这里

# 代理前端(侧边栏页面代理到本地的 3000 端口),这里要改为你自己配置H5的地址就好
//service-aj0odbig-1253834571.gz.apigw.tencentcs.com http://127.0.0.1:3000
# 代理后端(后端模板的 baseURL 写死为 backend.com,这里代理到本地的 5000 端口)
//backend.com http://127.0.0.1:5000
复制代码

不过,在企业微信侧边栏上调试我们的应用还是很麻烦,我们更希望的是可以直接在浏览器上调试程序,等开发差不多了,再去真实的侧边栏环境下调试。


考虑到这一点,我在我的前端模板里也实现 Mock 模式。具体怎么玩可以看 这里,可以直接 Mock 客户端 API 的返回值和用户身份信息。能大大提高开发效率。


总结


总的来说,个人觉得虽然侧边栏开发真是个麻烦事,还有好多 bug 和兼容问题,但是确实是客户/社群运营一个非常好用的工具。


希望这篇文章能带给大家侧边栏一些基础概念,想了解更多可以去 我的教程 深入上手。



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
小程序
微信小程序vantweapp自定义侧边栏
微信小程序vantweapp自定义侧边栏
307 0
|
3月前
|
Linux 网络安全 API
企业微信自定义应用 企业可信IP配置 企业可信ip怎么设置
企业微信自定义应用 企业可信IP配置 企业可信ip怎么设置
|
6月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp微信小程序的企业人事管理系统的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的企业人事管理系统的详细设计和实现
|
Docker 容器
gitlab推送企业微信几种方式汇总(二)
gitlab推送企业微信几种方式汇总(二)
3092 1
gitlab推送企业微信几种方式汇总(二)
|
Python
gitlab推送企业微信几种方式汇总(一)
gitlab推送企业微信几种方式汇总(一)
4572 1
gitlab推送企业微信几种方式汇总(一)
|
运维 机器人 Java
Springboot 整合 企业微信机器人助手推送消息
Springboot 整合 企业微信机器人助手推送消息
1124 0
Springboot 整合 企业微信机器人助手推送消息
|
SQL 机器学习/深度学习 JSON
钉钉/企业微信机器人:“Github触发器”与“Issue机器人”
众所周知,在Serverless领域中,触发器是FaaS必不可少的一部分;一个FaaS平台,他的触发器数量、质量以及类型,很可能会决定这个FaaS平台是否能成为“主流”平台;因为触发器不仅仅是一种功能的体现,更是解决普遍性业务诉求的一个重要途径;目前来看,各个云厂商所提供的触发器基本上都会包括API网关触发器、对象存储触发器、时间触发器等,当然也有厂商提供一定的消息触发器、日志触发器、甚至是一些SQL相关的触发器、CDN触发器等,那么在我们的实际生产生活中,这些表面上看起来“很基础”的触发器,是否可以升级成为一个有趣的“高级触发器”呢?
687 0
|
监控 Java API
JAVA实现接入企业微信报警
JAVA实现接入企业微信报警
615 0
JAVA实现接入企业微信报警
|
存储 缓存 NoSQL
利用pytest hook函数实现自动化测试结果推送企业微信
利用pytest的hook函数:pytest_runtest_makereport、pytest_terminal_summary‍、redis,实现自动收集测试结果并发送消息通知到企业微信的原理及过程
利用pytest hook函数实现自动化测试结果推送企业微信
|
API C#
C# 企业微信消息推送对接
C# 企业微信消息推送对接
977 0
C# 企业微信消息推送对接