# 页面插件接入

需要解决的问题

  1. 登录态同步:其他应用登录后可直接使用企微中台页面
  2. 权限点同步:权限点应该由其他应用配置,把对应的权限点给到企微中台,企微中台做权限控制
  3. 页面之前通信:父页面(接入方)和 iframe(企微中台)通过 postmessage 通信,场景(父页面需要获取子页面高度)

# 域名

# PC 端

https://ewmp-bg.myscrm.cn(生产)

https://beta-ewmp-bg.myscrm.cn(预发布)

# 移动端

https://ewmp.myscrm.cn(生产)

https://beta-ewmp.myscrm.cn(预发布)

# 方案

用户登录接入方应用后使用企微中台插件的行为,可以看成是企微中台授权接入方应用使用企微中台的功能,因此可以借鉴 OAUTH 授权流程,只不过整个过程是静默进行的,整个过程实现相对简单。

# 登录过程

img

# 登出过程

img

# 父子页面通信

页面高度

当 iframe 内的子页面高度发生变化,子页面会通过 postmessage 通知父页面增加高度。从而避免滚动条嵌套。

// 加入到接入方父页面的前端代码
const message = JSON.stringify({ type: 'contentHeightChange', data: { height: 300 } }) // 高度变化
window.top?.postMessage(message, '*')

window.addEventListener(
  'message',
  (e) => {
    if (typeof e.data === 'string') {
      const pageContentInfo = JSON.parse(e.data)
      if (iframe && pageContentInfo.type === 'contentHeightChange') {
        // 全屏模式下,不改变iframe 的大小,防止页面排版错乱
        if (pageContentInfo.data.width !== window.screen.width) {
          iframe.height = pageContentInfo.data.height
        }
      }
    }
  },
  false
)

iframe 登录状态过期

当 iframe 内的子页面登录状态过期时,子页面会通过 postmessage 通知父页面重走登录过程。

// 加入到接入方父页面的前端代码
const message = JSON.stringify({ type: 'loginExpiration', data: {} }) // 登录过期
window.top?.postMessage(message, '*')

window.addEventListener(
  'message',
  (e) => {
    if (typeof e.data === 'string') {
      const pageContentInfo = JSON.parse(e.data)
      if (pageContentInfo.type === 'loginExpiration') {
        // TODO: 重新获取 ticket,设置 iframe url 登录
        // window.location.href = `${config.oldHost}${config.loginUrl}`
      }
    }
  },
  false
)

iframe 组件示例

<iframe
  width="100%"
  height="700"
  ref={ifr}
  onLoad={iframeLoad}
  seamless
  src={iframeUrl}
  frameBorder="0"
  scrolling="no"
  name="ifr"
  id="ifr"
  allowFullScreen
  sandbox="allow-same-origin allow-top-navigation allow-forms allow-scripts allow-popups allow-downloads"
/>

# 页面路由 path

# PC 端

示例:http://ewmp-bg.myscrm.cn/greeting?ticket={ticket}&orgcode={orgcode}

模块 页面名称 页面路由 页面描述
欢迎语 欢迎语 /greeting 欢迎语列表页面
渠道码 渠道码管理 /channelcode-management 渠道码管理页面
素材库 素材管理

话术推荐

素材统计
/material-center

/words_recommendation

/material-statistics
素材库列表页面

话术推荐页面

素材统计首页
企微客服 客服帐号管理

自动回复管理

接待渠道管理

客服统计数据

自助导航
/customer-service

/auto-reply-management

/receive-channels

/customer-service/quality

/reply-menu-management
客服账号管理页面

自动回复管理首页

接待渠道管理首页

客服统计数据首页

自助导航首页
群发工具 群发客户

群发客户群

群发朋友圈

历史朋友圈
/enterprise-mass

/group-chat-list

/wechat-moments

/wechat-moments-history
群发客户管理页面

群发客户群管理页面

群发朋友圈管理页面

历史朋友圈管理页
客户管理 离职继承(客户)

离职继承(员工)

在职继承
/leave-inherit-customer

/leave-inherit-employee

/on-job-inherit
离职继承(客户)首页

离职继承(员工)首页

在职继承首页
聊天管控 聊天记录

员工聊天管控

客户聊天管控首页

聊天超时提醒
/chat-record

/employee-chat-control

/customer-chat-control

/chat-timeout
聊天记录首页

员工聊天管控首页

客户聊天管控首页

聊天超时提醒首页
公费电话 公费电话 /public-phone 公费电话
客户群 客户群 /customer-group-chat 客户群列表页面
企微任务 企微任务 /mission-center 企微任务首页
成员服务 客户流失提醒 /customer-churn-statistics 客户流失提醒首页

# 移动端

示例:https://ewmp.myscrm.cn/channel-code?ticket={ticket}

模块 页面名称 页面路由 页面描述
渠道码 我的码 /channel-code 获取渠道码页面
素材库 素材中心
/material-center
素材中心首页

可选参数:share_type(分享类型)可选值:群发分享:1 、直接分享:2 (默认值)

例如:xxx?ticket={ticket}&share_type=1
话术推荐 话术推荐 /words-recommend 话术推荐首页

必要参数:ticket

例如:xxx?ticket={ticket}
企微任务 任务详情(普通成员) /mission-detail 企微详情页普通成员页

必要参数:ticket、task_id (任务 id)、template_tag(普通成员标识:member_task_detail)

例如:xxx?ticket={ticket}&task_id={taskId}&template_tag=member_task_detail
企微任务 企微任务(管理者任务首页) /mission-center 管理者查看的企微任务列表页面

必要参数ticket

例如:xxx?ticket={ticket}
企微任务 进度统计(管理者统计页) /progress-statistics 管理者查看的统计页面

必要参数:ticket、task_id (任务 id)

例如:xxx?task_id=taskId&ticket={ticket}
企微任务 任务详情(管理者我的任务页) /mission-detail 管理者自己的任务页

必要参数:ticket、task_id (任务 id)、 template_tag(管理者标识:manager_task_detail)

例如:?ticket={ticket}&task_id={taskId}&template_tag=manager_task_detail
企微任务 我的勋章 /my-medal 成员完成任务后会颁发勋章,此页面展示成员的勋章信息

# 接入 API

应用方跳转到中台页面前,应用方后端需要请求中台的接口获取 ticket,然后通过 iframe 加载中台应用,把 ticket 参数拼接在 url 参数里面,由中台完成登录。

示例:http://ewmp-bg.myscrm.cn/{path}?ticket={ticket}

# 获取 ticket(PC 端)

请求方式: POST(HTTPS

请求地址: https://nbd-api.myscrm.cn/open-bff-nbd-qw-bg/user/get_ticket

请求参数说明:

参数 必须 说明
app_id 企微中台应用 ID
user_id 接入方用户 id。
user_name 接入方成员名。
permissions.funcCode 企微中台能力编码。不传则没有权限
permissions.privileges 接入方用户所拥有的权限代码集合
permissions.dataAccess 接入方用户所拥有的数据权限集合

权限点说明:登录的时候要求传用户所有的权限。permissions 为数组,数组每一项是表示授予此用户此次会话对一个企微中台能力的权限。privileges 是所在功能的具体权限功能的集合,是一个数组,具体的值由企微中台定义。在每项企微中台能力介绍章节都会声明。

请求示例:

{
  "app_id": "39fdda6e-a341-5e67-e243-d4ec9da063b8",
  "user_id" : "7ea49153-ccbd-89d3-56a7-2137055498cb",
  "user_name": "用户名",
  "permissions": [ // 功能点权限, 不传则没有权限
      {
          "funcCode": "channnel_code", // 渠道码功能名称
          "privileges": ["00", "01", "02"],  // 功能列表,表示该用户由渠道码查看、新增、编辑权限
          "dataAccess": {
            "hideGlobalproject": true // 关联项目是否隐藏“全局”
          }
      }
    ]
}

返回示例:

{
    "errcode" : 0,
    "errmsg" : "ok",
    "data": {
        "ticket": "4b9ac71a-9d08-4c40-8269-011c6b581580",
        "client_id": "a113ddbd-a22d-402b-95f0-427bd661c841",
        "expires_in": 300
    }
}

返回参数说明:

参数 说明
errcode 返回码。0 表示成功
errmsg 对返回码的文本描述内容
data.ticket 票据。用于前端嵌入页面的单点登录
data.client_id 返回给接入方的客户端标识,有效期和会话同步,用于退出登录使用
data.expires_in 有效期,只针对 ticket,单位秒

# 获取 ticket(移动端)

请求方式: POST(HTTPS

请求地址: https://nbd-api.myscrm.cn/open-bff-nbd-qw/user/get_ticket 注意,移动端获取 ticket,参数 user_id 必须是企微成员用户 id,user_name 必须是企微成员用户名,pc 端获取 ticket 则没有要求

移动端全局项目权限配置,默认为有全局项目,如果不需要全局项目需要把 organ_code 给到企微中台开发人员进行配置

请求参数说明:

参数 必须 说明
app_id 企微中台应用 ID
user_id 企微成员用户 id
user_name 企微成员用户名

请求示例:

{
  "app_id": "39fdf97b-2bc3-010d-82cd-e12d78b15714",
  "user_id" : "wang_1",
  "user_name": "用户名",
}

返回示例:

{
    "errcode" : 0,
    "errmsg" : "ok",
    "data": {
        "ticket": "4b9ac71a-9d08-4c40-8269-011c6b581580",
        "client_id": "a113ddbd-a22d-402b-95f0-427bd661c841",
        "expires_in": 300
    }
}

# 退出登录

为了安全,当业务方主动退出后需要通知中台退出登录

请求方式:POSTHTTPS

请求地址: https://nbd-api.myscrm.cn/open-bff-nbd-qw-bg/user/logout (PC 端)

请求参数说明:

参数 必须 说明
app_id 企微中台应用 ID
user_id 接入方用户。值是成员 id
client_id 客户端标识,获取 ticket 时获取

请求示例:

{
    "appid": "39fdda6e-a341-5e67-e243-d4ec9da063b8",
    "user_id" : "7ea49153-ccbd-89d3-56a7-2137055498cb",
    "client_id": "a113ddbd-a22d-402b-95f0-427bd661c841"
}

返回示例

{
    "errcode" : 0,
    "errmsg" : "ok",
}

返回参数说明

参数 说明
errcode 返回码。0 表示成功
errmsg 对返回码的文本描述内容

# 移动端注意事项

# js-sdk 调用

由于页面使用到了微信的 js-sdk,需要配置中台域名到企微后台,示例如下(下图展示的是生产环境域名):

img

# 素材中心分享说明

素材中心支持 2 中类型的分享形式:

  1. 直接分享给客户。需要通过聊天工具栏打开页面,因为从聊天窗口打开页面能获取到外部联系人。
  2. 需要选择客户(群发、朋友圈)。无法在页面获取到外部联系人的场景使用该方式(如从应用里面跳转),此时需要在 url 后面添加参数from=ykd。示例:https://ewmp.myscrm.cn/material-center?ticket={ticket}&from=ykd。

# 页面加载优化

# 背景

由于中台 H5 需要接入方传企微的用户信息,接入方需要自己完成企微的 oauth 认证获取用户信息,调用中台 api 获取 ticket,然后带上 ticket 参数跳转中台页面。整个流程较长影响页面加载速度。

# 优化方案

中台第一次登录后,会把登录态保存在 cookie 中,后续使用缓存登录,如果登录态失效则跳转接入方(接入方 url 通过参数 auth_url 告知中台),接入方重新获取 ticket 后跳转中台,中台使用 ticket 登录成功后把 sessionid 写入 cookie 中。时序图如下:其中云客多和用户中心是接入方。

img

# 示例如下

假设接入方链接为:https://access.com,下面用变量access代替

优化前链接:https://ewmp.myscrm.cn/channel-code?ticket={ticket}

优化后链接:https://ewmp.myscrm.cn/channel-code?auth_url=encodeURIComponent(access)&app_id={app_id}

# 说明

  1. 优化后链接中加入了app_id参数,这个是接入方应用在企微中台的 id,用来判断是否切换应用,是必须的
  2. 接入方的链接 access 需要实现获取 ticket 并跳转到中台页面
  3. 优化前 url 其他参数也需要在优化后链接中配置。如:https://ewmp.myscrm.cn/channel-code?auth_url=encodeURIComponent(access)&app_id={app_id}&from=ykd&other=xxx

# 移动端渠道码页面接入

移动端渠道码页面接入方式比较特殊,需要请求获取员工的渠道码页面接口获取地址

# 其他拓展

# 界面『项目』字样变量化

接入方在 iframe 链接后加上 prolabel 字段如下例:

https://ewmp-bg.myscrm.cn/greeting?ticket=5ab94798-dcd4-4707-a07b-1fbd58cf148d&orgcode=gzminjieadmin_test&prolabel=部门

界面(含子页面)会呈现如下展示(prolabel 字段不传或者传空,将默认展示'项目'二字)

img

# 样式,主题色配置

样式由 ui 设计,企微中台提供 2 种主题色配置的方法, 优先权: 链接参数配置 > organ_code 匹配 > 默认值

  1. 可以在链接中添加主题色参数 primary_color

    例如: https://ewmp-bg.myscrm.cn?ticket={ticket}&primary_color={color}

    color: 支持常见的 css 色值,需要对色值进行 encodeURIComponent 编码

    注意:十六进制的颜色值如 #abcdef, 如果没有进行 encodeURIComponent 会导致链接中的参数丢失

  2. 联系企微中台开发,提供主题色,企微中台会根据接入方的 organ_code 来进行匹配

  3. 默认值: #f65c2c, 如果没有提供主题色,主题色使用默认值进行展示