通讯录展示组件
1. 背景介绍
企业通讯录是企业的重要敏感数据,第三方将不再直接获取到授权企业的通讯录数据(接口将不再返回人名与部门名)。第三方页面若需要展示用户的通讯录信息,可使用如下的 open-data 组件,以提供更加安全良好的体验。
2. 浏览器方案
2.1 环境要求
- 企业微信APP需 2.8.10 及以上版本
2.2 使用方法
1. 通过企业微信登录应用管理后台
在非微信、企业微信内置浏览器中使用 open-data 时,需要通过企业微信管理端跳转或第三方登录授权进行登录。
需要注意,通过上述方法登录跳转的目标域名要和使用 open-data 的页面域名保持一致。
在开发过程中,我们可以在 open-data 调试页面中查看当前浏览器登录的应用信息。
2. 引入 open-data SDK
在页面上引入以下SDK:
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js" referrerpolicy="origin"></script>
<script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js" referrerpolicy="origin"></script>
- sdk 内容是动态返回的,请严格按照上面的方式引入,不要保存到项目本地后打包引入
- referrerpolicy 声明为 origin 是为了让 sdk 能够顺利识别关键域名,不能去掉
3. 进行 agentConfig
无论是微信、企业微信的内置浏览器还是第三方浏览器,都需要通过wx.agentConfig登记第三方应用的身份信息。
需要注意,在第三方浏览器中调用 wx.agentConfig 前不需要进行 wx.config。
注意:在企业微信客户端的页面上,进行 agentConfig 的调用,必须要等 wx.config 完成后才调用(即 wx.config 的成功回调)
4. 绑定 open-data 元素
上述步骤完成后,我们就可以通过 WWOpenData.bind 方法对页面上的元素进行绑定,完成后 SDK 将在绑定的元素上渲染出对应的开放数据:
<!-- 注意:这里的 openid 是 userid 和 departmentid 的统称 -->
<ww-open-data type="userName" openid="{{openid}}"></ww-open-data>
<script>
WWOpenData.bind(document.querySelector('ww-open-data'))
</script>
open-data 元素上的属性请参考[2.5 元素属性](#17172/2.5 元素属性)章节。
在支持 custom elements 的浏览器中,SDK 会自动对 元素进行绑定。
2.3 API 列表
WWOpenData.bind(el: Element)
绑定 open-data 元素,在获取数据后,SDK 将在元素内渲染出对应的开放数据。
WWOpenData.bindAll(nodeList: NodeList | Array)
批量绑定 open-data 元素,参考 WWOpenData.bind。
注意:为了保证在所有环境下表现正常,一旦 open-data 元素的内容发生了变化,必须调用 WWOpenData.bind 接口重新绑定一次
WWOpenData.on(event: string, callback: Function)
为兼容旧版本终端,使用前需要判断函数是否存在
添加事件监听函数,事件列表参考[2.4 事件列表](#17172/2.4 事件列表)。
WWOpenData.off(event: string, callback: Function)
为兼容旧版本终端,使用前需要判断函数是否存在
移除事件监听函数。
WWOpenData.checkSession(params: CheckSessionParams)
为兼容旧版本终端,使用前需要判断函数是否存在
检查登录态信息。
if (WWOpenData.checkSession) {
WWOpenData.checkSession({
success() {
console.log('有登录态')
},
fail() {
console.error('登录态过期')
}
})
}
WWOpenData.initCanvas()
启动 canvas 支持功能
WWOpenData.prefetch(params: PrefetchParams)
预加载通讯录数据
if (WWOpenData.prefetch) {
WWOpenData.prefetch({ items }, (err, data) => {
if (err) {
// 错误处理
}
// 数据处理
})
}
注意:出于安全设计和浏览器策略,prefetch 接口必须在 https 的网页下调用,否则会报运行错误
2.4 事件列表
error
当 SDK 获取数据失败时触发。
update
当 open-data 元素渲染内容发生变更时触发。
2.5 元素属性
页面通过 open-data 元素上的属性控制需要渲染的内容:
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
type | string | 是 | 开放数据类型 |
openid | string | 是 | 数据ID,根据type取值而定 |
corpid | string | 否 | 企业ID,用户所属的企业 corpid |
假设有“上下游”或“教育局校互联”企业 A 和 B, 开发者需要在页面同时渲染 A和B的通讯录数据,这时可以通过填入特定企业的 corpid,去指定要渲染的企业数据
type 的合法值
值 | 说明 |
---|---|
userName | 用户名称 |
userAlias | 用户别名 |
departmentName | 部门名称 |
若 type=userName,此时 openid 对应 userid
若 type=userAlias,此时 openid 对应 userid。如果用户没有别名,将返回传入的openid
若 type=departmentName,此时 openid 对应 departmentid
每 20ms 最多绑定 1000 个 open-data 元素,超出的部分将被忽略
如果用户或部门不合法,将返回传入的openid
2.6 前端框架适配
若页面使用了 vue、react 等前端框架,可在框架提供的钩子函数中调用 WWOpenData.bind 进行绑定:
Vue
<template>
<ww-open-data :type="type" :openid="openid" />
</template>
<script>
export default {
props: ['type', 'openid'],
mounted() {
WWOpenData.bind(this.$el)
}
}
</script>
React
import React, { useRef, useLayoutEffect } from 'react'
export default function WWOpenDataCom({ type, openid }) {
const ref = useRef(null)
useLayoutEffect(() => {
WWOpenData.bind(ref.current)
})
return <ww-open-data ref={ref} type={type} openid={openid} />
}
2.7 示例代码
<html>
<body>
<ww-open-data type="userName" openid="{{openid}}"></ww-open-data>
<script src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script src="//open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
<script>
(async () => {
if (/MicroMessenger/i.test(navigator.userAgent)) {
await config(configParams)
}
await agentConfig(agentConfigParams)
// 注意: 在企业微信平台下,只有 agentConfig 成功回调后,WWOpenData 才会注入到 window 对象上面
WWOpenData.bindAll(document.querySelectorAll('ww-open-data'))
})()
function config(config) {
return new Promise((resolve, reject) => {
wx.config(config)
wx.ready(resolve)
wx.error(reject)
})
}
function agentConfig(config) {
return new Promise((success, fail) => {
wx.agentConfig({ ...config, success, fail })
})
}
</script>
</body>
</html>
更加完整的示例程序,可以参考 open-data 控件 demo。
3. 小程序方案
3.1 环境要求
- 企业微信APP需 2.8.9 及以上版本
- 微信上小程序基础库版本需 1.9.6 及以上版本
- 开发者工具中不要在企业微信小程序模式下运行插件
注意:当前小程序通讯录展示插件不支持显示头像
3.2 使用方法
(1) 开发者在小程序管理后台申请使用插件,添加路径:设置 ->第三方服务 -> 插件管理 -> 添加插件,搜索并添加插件ID: wx5917c8c26f85c588,无需审核确认。
(2) 开发者在小程序app.json 文件中添加对插件的引用
"plugins": {
"contactPlugin": {
"version": "2.1.0",
"provider": "wx5917c8c26f85c588"
}
}
(3) 开发者在具体引用插件的页面文件json文件中,添加对组件的引用,例如:
"usingComponents": {
"ww-open-data":"plugin://contactPlugin/ww-open-data"
}
(4) 在 wxml 中调用 ww-open-data
组件展示用户信息:
<ww-open-data
type="{{type}}"
corpid="{{corpid}}"
openid="{{openid}}"
bindupdate="onDataUpdate"
/>
参数说明:
属性 | 类型 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|
type | string | 是 | 开放数据类型 | 1.0.0 |
corpid | string | 是 | 用户所属的企业corpid | 1.0.0 |
openid | string | 是 | 数据ID,根据type取值而定 | 1.0.0 |
bindupdate | eventhandle | 否 | 当组件展示的数据发生变更时触发,event.detail = { type, corpid, openid, hasData } | 2.1.0 |
type 与 openid 属性参考[2.5 元素属性](#17172/2.4 元素属性)
假设有上下游企业 A 和 B, 开发者需要在页面同时渲染 A和B的通讯录数据,这时可以通过填入特定企业的 corpid,去指定要渲染的企业数据
3.3 开发调试
在开发者工具开发调试,需要用企业微信扫码运行时,需要在“添加编译模式”里的启动参数添加如下参数:debug_extinfo=true&debug_plugin=true,才能正常调起授权登录。添加方法请参考下图:
3.4 示例程序
开发者可参考 open-data 小程序 demo。
4. canvas 支持方案
4.1 作用
- 支持三方应用在 canvas 中安全渲染通讯录数据
- 支持 echarts、antv g2 等第三方图形库,在 canvas 渲染模式下,正确渲染通讯录数据
4.2 使用方式
1 . 在完成了 WWOpenData 的初始化后,调用 initCanvas
方法
if (WWOpenData.initCanvas) {
WWOpenData.initCanvas()
}
2 . 调用 WWOpenData 的 prefetch
方法,将需要在图形显示的名称,进行预获取。可以参考以下代码
const result = await new Promise((resolve, reject) => {
WWOpenData.prefetch({ items }, (err, data) => {
if (err) {
return reject(err)
}
resolve(data)
})
})
其中,items
和 result
的格式分别是:
items: [
{
type: string, // userType
id: string, // openid
corpid: string, // corpid (非必须)
}
]
result: [
{
type: string,
id: string,
data: string, // 重要,这里的数据需要传入到 canvas 图形库中
}
]
3 . 到了这一步,已经完备了 canvas 展示通讯录数据的将, result
返回的 data,开发者可以理解成是 加密过的通讯录数据,接下来,开发者只需要把这些加密过的通讯录数据,当成正常的数据,放到 canvas 的接口 或者 第三方图形库的接口上,进行渲染即可。
4 . 一般情况下,为了避免页面受到 xss 攻击时,泄漏图片数据,默认情况下,渲染过通讯录信息的 canvas,是禁止使用 toDataUrl 导出图片的。如果确实有这样的需求,服务商可以在渲染 canvas 前,调用 WWOpenData.enableCanvasSharing 这个 api,调用后,渲染出来的 canvas 就能通过 toDataUrl 导出图片。与之相对,WWOpenData.disableCanvasSharing 这个 api 可以重新禁止 canvas 导出图片。
5. 发送应用消息支持id转译
应用在下发消息时,可以在内容中以模板参数语法包含id,企业微信在下发时会将其替换为成员名或部门名,目前支持文本/文本卡片/图文/图文(mpnews)这四种消息类型,参数使用说明具体参见“发送应用消息”,注意需要在原接口参数上添加 enable_id_trans 字段且置为1,才能开启转译.
6. 人名或部门名搜索方案
通过通讯录搜索接口,可以根据名字或拼音搜索出对应的userid或部门id。
7. 包含人名部门名的文件导出方案
先将文件通过“上传需要转译的文件”接口上传到企业微信服务端,接着调用“异步通讯录id转译”接口提交转译任务,然后通过“获取异步任务结果”获取最终下载文件的url,注意该url仅能在有用户登录态的浏览器打开以下载文件,详情参见“通讯录ID转译”。
8. 通讯录用户排序方案
通过通讯录userid排序,可以根据姓名拼音升序或者降序排列。
FAQ
-
页面使用了 iframe,iframe 内找不到 WWOpenData
解决方法:针对应用页面使用了 iframe 的情况,可以通过 window.parent 的方式往最外层的 webview 访问 WWOpenData 对象。 -
agentConfig 签名一直报错
注意点:agentConfig 的签名参数 和 wx.config 是不一样的,参考文档 -
第三方浏览器,其他浏览器工作正常,safari 工作不正常
解答:由于 Safari 浏览器对 cors 策略的处理和其他浏览器不一样,在第三方浏览器上,请务必按照文档完成 wx.agentConfig 的处理 -
关于 jWeixin sdk 版本的处理,请注意:在企业微信上,必须引入的是 1.2.0 版本的 jWeixin sdk,在微信 或者 其他第三方浏览器,可以引入其他版本的 jWeixin sdk
-
单页面应用,在 windows 客户端可以渲染,但是在 iOS 客户端不能渲染
解答:由于目前 windows 客户端 和 iOS 存在差异,为了保证各个端运行正确,请严格保证如下标准:如果单页面应用使用了 browser history 作为路由,请保证每次 url 变更后,都正常完成 wx.config 和 wx.agentConfig 初始化。 -
页面在浏览器,在 iOS,Mac,Android 上面的企业微信都表现正常,但是在 windows 企业微信下,会偶发不能渲染通讯录控件内容
解答:由于 企业微信的 windows 客户端浏览器内核不支持 customElements,每次更新了 open-data 元素后,需要用 bind 或者 bindAll 接口对目标元素进行一次更新,这样才能保证 open-data 元素实时渲染正确的数据。遇到上面的情况,请检查一下页面代码,看看有没有可能出现时序问题:先执行了 bind,然后才渲染出对应的 open-data 元素 -
如何自定义显示内容,比如表单需要显示“提交人+提交日期+业务类型”?
将需要替换通讯录名称的文本替换为ww-open-data标签引用,其它保留不变。比如,
<ww-open-data type="userName" openid="{{openid}}"></ww-open-data>+提交日期+业务类型
-
通讯录展示组件,是否可以一次性显示多个名称?
组件的每个ww-open-data标签引用对应到一个通讯录名称,显示多个名称,则引用多个ww-open-data。比如,显示完整的部门路径,只需要将路径的部门id依次引用即可。 -
第三方管理端,如何实现成员搜索?
调用接口:通讯录搜索,传入搜索的关键词,获取搜索结果的userid/departmentid。
再调用通讯录展示组件,显示出搜索的成员名称/部门名称。 -
如何实现搜索后的结果按拼音排序?
调用接口:通讯录userid排序,支持指定的用户列表按拼音升序/降序,返回的结果为排序后的列表。 -
第三方管理端,导入业务数据文件(如打卡记录),包括了通讯录名称,如何识别?
如果业务数据文件中记录中有唯一字段标识,则可以直接对应关联;
如果通过通讯录名称关联用户,调用 通讯录搜索 接口,获取搜索结果的userid/departmentid,对应关联到用户 -
第三方管理端,支持导出业务数据文件(如打卡列表),需要包含通讯录名称,如何实现?
解决方案参考:通讯录ID转译。以模板参数填入数据文件中,并上传至企业微信后台,数据文件中的模板参数就会替换为通讯录名称,并获取到一个文件访问地址。
该文件访问地址,需要用户通过企业微信登录至第三方管理端,才可下载。 -
页面请求数据报错403
通常是由于用户未登录至第三方业务页面导致,可以访问 open-data 调试页面 查看登录信息。
注意,在单点登录的场景(包括有扫码登录,应用安装完成跳转,以及从企业微信Web管理端业务跳转),在指定的redirect_uri的域名,才会有登录用户身份。
比如,扫码登录后跳转到域名A,在域名B下使用组件,是会报错403的。 -
已删除的成员或部门,是否能通过通讯录组件展示名字
可以。对于同一个userid或部门ID,企业微信仅展示最后一个删除的成员或部门的名字;删除之后再重新添加相同的userid或部门ID,则只展示新成员或新部门的名字。(注:部门名仅支持展示2021年10月1号之后删除的部门)