如何将腾讯RTC聊天与Zendesk集成

10 分钟阅读
Feb 18, 2025

场景概述

Zendesk是客户支持、销售和其他客户沟通中最流行的SaaS产品之一。同时,根据Gartner的数据,腾讯聊天在中国市场中取得了领先地位,并且是全球通信平台即服务(CPaaS)中最具竞争力的提供商之一。自然,我们为您带来了将聊天与Zendesk集成的解决方案。

在这篇文章中,我们将讨论如何构建一个客户端-代理实时通信系统,扩展Zendesk支持团队的边界,使支持团队能够在任何平台上与客户聊天。我们已经完成了Zendesk票据栏的聊天应用程序,您所需要做的就是按照以下说明安装它并发布自己的客户端。

如果这不是您感兴趣的集成解决方案,不要急于关闭按钮。请继续阅读这篇文章,通过TUIKit构建您自己的私人Zendesk应用,这并不是您待办事项中的一项繁琐任务,而是根据您想要构建的应用复杂性,仅需几个小时或几天。

应用产品

聊天

基本集成指南

前提条件

如果您尚未注册Zendesk,请尝试 免费试用

要使用聊天的任何服务,您必须注册腾讯RTC,该服务包含许多基于云的服务。之后,在控制台 上单击创建应用程序以获取您的SDKAppID,这是启动聊天服务所需的。

Creating a Application in Tencent RTC Console

Steps to Create an Application in Tencent RTC:

1. Navigate to the Tencent RTC Console.
Guidelines for Creating an Application to Use Tencent RTC Chat Services

对于客户端构建,您还需要一个网络服务器,这在本文中不包括。

集成图

此集成解决方案的目标明确而清晰:监听代理的分配并邀请代理加入与客户的对话,以便在Zendesk外讨论票据中的问题或咨询。

以下是一般集成图:

一般工作流程如下:

1. 终端用户登录到聊天。

2. 终端用户向您的后端服务器提交票据。

3. 根据提交的信息,为Zendesk创建票据。

4. 在聊天中创建一个组,等待代理加入该组。

5. 一名代理接受票据或被分配给某名代理。

6. 指定的代理加入聊天组。

7. 现在客户和代理可以自由聊天。

客户端侧的工作流程如下:

在登录之前,客户可以选择重用上次创建的票据。为此,只需登录聊天服务器。

否则,提交新的Zendesk票据。

登录服务器并使用返回的ticket.id创建一个组。

Zendesk的聊天流程如下:

更新票据的过程如下:

场景特定实现

客户端侧构建

您需要开发一个前端项目来实现聊天功能,以及一个后端项目来调用Zendesk请求。不必惊慌,前端可以顺利完成,使用TUIKit就像搭积木一样。TUIKit是一套基于聊天SDK的TUI组件,提供独立的组件,包括会话、聊天、搜索、关系链、群组以及音视频通话。TUIKit目前覆盖iOS、Android、Web和Flutter平台,我们也在努力开发React Native。请关注频道以获取最新状态。通过应用TUIKit,您只需定义调用createTicket API的策略。

以下是构建后端项目的所有代码:

const express = require('express');
const axios = require('axios').default;
var TLSSigAPIv2 = require('tls-sig-api-v2'); // 为TIM生成UserSig
require('dotenv').config();

const app = express();
app.use(express.json());

const port = process.env.PORT || 15000;
const YOUR_SDKAPPID = process.env.YOUR_SDKAPPID || 0;
const YOUR_SECRET = process.env.YOUR_SECRET || '';
const ADMIN_USERID = process.env.ADMIN_USERID || '';

const zendeskAxioInstance = axios.create({
  baseURL: `https://${process.env.SUB_DOMAIN}.zendesk.com/api/v2/`,
  auth: {
    username: process.env.EMAIL || '',
    password: process.env.TOKEN || ''
  },
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  },
  timeout: 35000
});

app.use(express.json());

app.use(function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', '*');
  next();
});

app.post('/createticket', async (req, res) => {
  const { userId, caseInfo } = req.body;
  if (!userId) return res.status(500).send('缺少userId');

  const zendeskCase = await createTicket(caseInfo);
  if (!zendeskCase.success) return res.status(500).send('票据创建失败');

  const groupId = zendeskCase.id;
  const result = await createGroup(
    groupId,
    userId,
    caseInfo.subject || groupId
  );
  if (result.ErrorCode !== 0)
    return res.status(500).send('组创建失败');
  sendGreeting(result.GroupId);

  res.status(200).send(result);
});

const createTicket = async function (caseInfo) {
  const { subject, desc, name, email } = caseInfo;
  const data = {
    request: {
      requester: {
        name: name || '匿名客户',
        email: email
      },
      subject: subject,
      comment: {
        body: desc
      }
    }
  };
  try {
    const result = await zendeskAxioInstance({
      method: 'POST',
      url: '/requests.json',
      data: data
    });
    return {
      id: result.data.request.id,
      success: true
    };
  } catch (e) {
    return { id: undefined, success: false, error: e };
  }
};

const generateUserSig = function () {
  const expires = 600;
  const api = new TLSSigAPIv2.Api(YOUR_SDKAPPID, YOUR_SECRET);
  return api.genSig(ADMIN_USERID, expires);
};

const generateRandom = function () {
  return Math.floor(Math.random() * 4294967295);
};

const createGroup = async function (groupId, userId, groupName) {
  const sig = generateUserSig();
  const random = generateRandom();
  const data = {
    Type: 'Public',
    Name: groupName,
    GroupId: `ZENDESK#${groupId}`,
    ApplyJoinOption: 'FreeAccess',
    MemberList: [{ Member_Account: userId }]
  };
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/create_group?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`;
  try {
    const groupRes = await axios.post(url, data);
    return groupRes.data;
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e };
  }
};

const sendGreeting = async function (groupId) {
  const sig = generateUserSig();
  const random = generateRandom();
  const data = {
    GroupId: groupId,
    Content: "我们正在为您的主题指派一名代理,请稍候..."
  };
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/send_group_system_notification?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`;
  try {
    const groupRes = await axios.post(url, data);
    return groupRes.data;
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e };
  }
};

app.listen(process.env.PORT || port, () =>
  console.log(`示例应用正在监听端口 ${port}!`)
);

让我们来解析一下代码。

const port = process.env.PORT || 15000;
const YOUR_SDKAPPID = process.env.YOUR_SDKAPPID || 0;
const YOUR_SECRET = process.env.YOUR_SECRET || '';
const ADMIN_USERID = process.env.ADMIN_USERID || '';

第一部分要求您将聊天标识信息设置为环境变量。您可以在这里找到所有信息。警告:请勿将您的密钥记录在代码中,以免泄露到互联网上。

const zendeskAxioInstance = axios.create({
  baseURL: `https://${process.env.SUB_DOMAIN}.zendesk.com/api/v2/`,
  auth: {
    username: process.env.EMAIL || '',
    password: process.env.TOKEN || ''
  },
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  },
  timeout: 35000
});

其次,配置Zendesk请求

// 创建Zendesk票据
const createTicket = async function (caseInfo) {
  const { subject, desc, name, email } = caseInfo;
  const data = {
    request: {
      requester: {
        name: name || '匿名客户',
        email: email
      },
      subject: subject,
      comment: {
        body: desc
      }
    }
  };
  try {
    const result = await zendeskAxioInstance({
      method: 'POST',
      url: '/requests.json',
      data: data
    });
    return {
      id: result.data.request.id,
      success: true
    };
  } catch (e) {
    return { id: undefined, success: false, error: e };
  }
};

// 创建聊天组
const createGroup = async function (groupId, userId, groupName) {
  const sig = generateUserSig();
  const random = generateRandom();
  const data = {
    Type: 'Public',
    Name: groupName,
    GroupId: `ZENDESK#${groupId}`,
    ApplyJoinOption: 'FreeAccess',
    MemberList: [{ Member_Account: userId }]
  };
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/create_group?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`;
  try {
    const groupRes = await axios.post(url, data);
    return groupRes.data;
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e };
  }
};

最后,根据输入参数创建Zendesk票据,并使用返回的zendeskCase.id作为groupID创建聊天组,该groupID以ZENDESK#作为前缀。

测试并在线发布服务器代码以供客户端使用。

TIM for Zendesk 安装

通过在Zendesk市场中搜索“Chat for Zendesk”来安装它。

接下来,输入您的SDKAppId以完成安装。

该应用将在票据栏区域显示。

它使用代理的ID作为聊天的UserID,您需要为此UserID获取UserSig。有关如何检索的详细信息,请参阅UserSig一旦登录,聊天中的用户名将自动更新为代理的姓名,可以在个人资料页面使用其他个人资料信息进行更新。一旦登录,您将保持登录状态,直到UserSig过期或触发注销。

当代理被分配到票据时,他/她将被邀请进入聊天组,并与客户进行各种类型的消息交流。

此外,您还可以私下安装该应用,联系tencentcloud_im@tencent.com以获取最新的TIM包或源代码。按照说明这里上传私人应用。

如果提供的应用不符合您的预期,您也可以开发自己的私人应用。您可以申请TUIKit来提升UI构建,并按照说明创建自己的应用。更多Zendesk API参考文献列在这里

这就是您所需的将聊天与Zendesk集成的全部内容。到目前为止,您可能已了解集成过程及Zendesk的工作流程,并建立了自己的客户端-代理实时通信应用。如果您有任何不清楚的地方或对与Zendesk的集成有更多想法,请随时联系我们

立即订购

点击这里快速访问购买页面进行订单。