开始使用聊天对话API
重要的:自2022年1月1日起,聊天对话API处于维护模式,将不会接收新功能。Bug和安全修复将在需要时继续进行。短信客户可以购买阳光对话许可证并利用这个平台进行添加第三方或自定义机器人到他们的工作流程作为替代选项。
聊天对话API允许您的应用程序充当Zendesk聊天代理,并与您的网站访问者进行交互。亚博
该API使用GraphQL数据查询语言为您提供了更大的灵活性。GraphQL让你:
- 精确定义应用程序所需的数据
- 尽量减少请求的数量
- 使用GraphQL类型系统验证查询
有关GraphQL的更多信息,请参见GraphQL资亚博电脑端源在下面。
你可以通过以下两种方式之一调用对话API:
- 发出HTTP请求
https://chat-api.zopim.com/graphql/request
- 发送请求到已验证的WebSocket地址(
wss: / / chat-api.zopim.com/stream/0.1/graphql/ {session_id}: {client_id}
).
HTTP请求主要用于身份验证.所有其他请求都应该通过WebSocket连接进行。
本文涉及的主题:
限制
对话API有以下限制:
- 不支持角色和权限.会话由对话API创建的代理不符合其帐户的角色和权限设置。
- 不完全支持分配聊天路由.只有当使用对话API的代理是部门中唯一的代理时,分配的聊天路由才会工作。
- 仅与来自Zendesk Web Widget (亚博本地的或定制移动SDK)或Zendesk亚博聊天小部件(本地的或定制移动SDK/Web SDK).
GraphQL模式文档
对话API的GraphQL模式文档可在以下站点获得https://亚博zendesk.github.io/conversations-api/.该模式包含对话API支持的所有操作的完整细节。
提示:您可以使用ChromiQL谷歌Chrome扩展或GraphQL IDE帮助您构造具有自动补全和错误检测的GraphQL查询。只需将端点设置为https://chat-api.zopim.com/graphql/request
.请注意,您不能使用它们来发出实际的请求,因为它们没有您的身份验证信息。
关键概念
术语
游客-某人访问您的网站与嵌入式聊天小部件。
小部件-嵌入式Zendesk聊天界亚博面。
代理-服务访客聊天的人。
通道—访问者和座席通过通道交换聊天消息。
GraphQL操作
对话API支持3个主要的GraphQL操作:
- 突变—突变操作可以修改数据。
- 查询—查询操作可以查询您感兴趣的数据。
- 订阅-订阅操作,您可以订阅主题,从中获得实时更新。
请注意对话API使用Relay连接模型来提供对结果集进行切片和分页的标准机制。看到继电器游标连接规范更多信息请访问Facebook Github网站。
API查询流程
要开始查询API,必须首先使用startAgentSession
的HTTP请求https://chat-api.zopim.com/graphql/request
.端点响应一个会话ID、一个客户端ID和一个WebSocket URL,您可以使用它来建立WebSocket连接。
#样本WebSocket连接url
#格式:wss://闲谈,聊天-api.zopim.com/流/0.1/graphql/{session_id}:{client_id}
wss://闲谈,聊天-api.zopim.com/流/0.1/graphql/8b40lm:9012841289
一旦建立了WebSocket连接,就可以通过该连接继续查询API。
在某些情况下,您的会话可能无效。您将收到服务结束(EOS
)信号。看到服务结束信号.
开始
本节描述如何开始使用对话API。本节中描述的应用程序的完整源代码可在网上获得。看到示例应用程序代码.
本节涵盖的主题:
启动代理会话
要使用OAuth身份验证启动代理会话,首先要生成一个OAuth访问令牌与读
,写
,闲谈,聊天
作用域如在OAuth身份验证在Zendes亚博k开发者门户网站上。生成访问令牌之后,调用startAgentSession
的HTTP请求中的令牌https://chat-api.zopim.com/graphql/request
.
Const request = require('超级代理');
const CHAT_API_URL = 'https://chat-api.zopim.com/graphql/request';
Const查询= '突变{
startAgentSession(access_token: "my_oauth_access_token") {
websocket_url
session_id
client_id
}
}';
请求
. post (CHAT_API_URL)
这里({
“内容类型”:“application / json”
})
.send({query});
该示例使用搞
库用于创建HTTP请求。您还可以使用首选的HTTP请求库。
在成功启动代理会话后,如果凭据有效,您应该得到如下响应:
{
“数据”:{
“startAgentSession”:{
“websocket_url”:“wss: / / chat-api.zopim.com/stream/0.1/graphql/8b40lm: 9012841289”,
“session_id”:“8 b40lm”,
“client_id”:“9012841289”
}
}
}
的值建立WebSocket连接websocket_url从响应中。
const WebSocket = require('ws');
const webSocket = new webSocket (
“wss: / / chat-api.zopim.com/stream/0.1/graphql/8b40lm: 9012841289”
);
webSocket。On ('open', () => {
//做某事
});
该示例使用ws
库用于客户端连接。你可以使用你喜欢的websocket客户端库。
订阅收到的消息
订阅传入消息允许您侦听来自未服务的访问者或由您服务的频道的任何聊天消息。
const messageSubscriptionQuery = {
有效载荷:{
查询:'订阅{
消息{
节点{
id
内容
{频道
id
}
从{
__typename
display_name
}
}
}
} '
},
类型:“请求”,
id: REQUEST_ID。MESSAGE_SUBSCRIPTION
};
webSocket.send (JSON.stringify (messageSubscriptionQuery));
的messageSubscriptionQuery变量包含对Message类型的特定数据(id、内容、通道、from)的请求。看到消息在参考文档中查询可以查询的字段。
唯一请求ID (REQUEST_ID。MESSAGE_SUBSCRIPTION)还提供了用于标识此请求的响应。让我们来听听这个ID。
webSocket。On ('message',函数(message) {
const data = JSON.parse(message);
让messageSubscriptionId;
//监听成功的消息订阅请求
如果(数据)。id=== REQUEST_ID.MESSAGE_SUBSCRIPTION) {
messageSubscriptionId = data.payload.data.subscription_id;
}
});
如果订阅成功,你会得到如下回复:
{
“有效载荷”:{
“数据”:{
“subscription_id”:“a1gf13bjz13”
}
},
“id”:456
}
的subscription_id属性标识订阅。
webSocket。On ('message',函数(message) {
const data = JSON.parse(message);
让messageSubscriptionId;
//监听成功的消息订阅请求
如果(数据)。id=== REQUEST_ID.MESSAGE_SUBSCRIPTION) {
messageSubscriptionId = data.payload.data.subscription_id;
}
//监听访问者的聊天信息
如果(
DATA .sig === 'DATA' &&
数据。subscription_id === messageSubscriptionId &&
data.payload.data
) {
const chatMessage = data.payload.data.message.node;
const sender = chatMessage.from;
如果发送者。__typename=== TYPE.VISITOR) {
console.log (
' [message]收到:'${chatMessage. '内容}从:'${
sender.display_name
} ' '
);
}
}
});
特殊字段信号数据标识任何订阅数据消息。您的应用程序应该检查这个字段并监听它subscription_id当你通过WebSocket连接接收消息时。
更新座席状态
让我们确保代理处于在线状态,以便访问者可以查看小部件。
const updateAgentStatusQuery = {
有效载荷:{
查询:'突变{
updateAgentStatus(状态:ONLINE) {
节点{
id
}
}
} '
},
类型:“请求”,
id: REQUEST_ID。UPDATE_AGENT_STATUS
};
webSocket.send (JSON.stringify (updateAgentStatusQuery));
从访客那里发送信息
转到Zendesk聊天小部件嵌入的网页。亚博类型”嗨开始聊天。您的应用程序应该能够接收和打印聊天消息。
[消息]收到了:“嗨”从:“访客12345678”
向访问者发送消息
您也可以向访问者发送消息。让我们在每次接收到来自访问者的消息时回显访问者发送的内容。
webSocket。On ('message',函数(message) {
const data = JSON.parse(message);
让messageSubscriptionId;
//监听成功的消息订阅请求
如果(数据)。id=== REQUEST_ID.MESSAGE_SUBSCRIPTION) {
messageSubscriptionId = data.payload.data.subscription_id;
}
//监听访问者的聊天信息
如果(
DATA .sig === 'DATA' &&
数据。subscription_id === messageSubscriptionId &&
data.payload.data
) {
const chatMessage = data.payload.data.message.node;
const sender = chatMessage.from;
如果发送者。__typename=== TYPE.VISITOR) {
console.log (
' [message]收到:'${chatMessage. '内容}从:'${
sender.display_name
} ' '
);
const sendMessageQuery = {
有效载荷:{
查询:'突变{
sendMessage (channel_id:“$ {chatMessage.channel。Id}", msg: "${
chatMessage.content
}”){
成功
}
} '
},
类型:“请求”,
id: REQUEST_ID。的SEND_MESSAGE
};
webSocket.send (JSON.stringify (sendMessageQuery));
}
}
});
回到网站,输入“Hello!”你应该得到一个'你好!他回答道。
向访问者发送结构化消息
您还可以向访问者发送结构化消息。一个例子是发送快速回复,为访问者提供回复建议。
const sendQuickRepliesQuery = {
有效载荷:{
查询:'突变{
sendQuickReplies (
channel_id:“$ {chatMessage.channel.id}”,
msg:“我们有以下选项。你最喜欢哪一个?
quick_replies:(
{
行动:{
价值:“我最喜欢的是巧克力”
},
文本:“巧克力”
},
{
行动:{
价值:“我最喜欢香草味的”
},
文本:“香草”
},
{
行动:{
价值:“我最喜欢的是饼干和奶油”
},
文本:“饼干和奶油”
},
{
行动:{
价值:“我最喜欢的是椰子”
},
文本:“椰子”
},
{
行动:{
价值:“我最喜欢的是咸味焦糖”
},
文字:“咸焦糖”
}
),
回退:{
msg:“我们有以下选项。你最喜欢哪一个?”
选择:[
“巧克力”,
“香草”,
“饼干和奶油”,
“椰子”,
“咸焦糖”
]
}
) {
成功
}
} '
},
类型:“请求”,
id: REQUEST_ID。SEND_QUICK_REPLIES
};
webSocket.send (JSON.stringify (sendQuickRepliesQuery));
在上面的例子中,quick_replies参数表示将发送给访问者的快速回复。当访问者单击其中一个快速回复时,访问者将发送所选的自定义价值给代理人。
注意回退参数可用于为不支持结构化消息的情况提供回退体验。有关更多信息,请参见在Zendesk聊天中使用结构化消息亚博在聊天帮助中心。
转部门
您也可以将对话转移到部门。首先,你需要知道你想要转到的部门的ID是什么。
注:部门ID检索自Zendesk聊天亚博REST API不会起作用。
const getDepartmentsQuery = {
有效载荷:{
查询:'查询{
部门{
{边缘
节点{
id
名字
状态
}
}
}
} '
},
类型:“请求”,
id: REQUEST_ID。GET_DEPARTMENTS
};
webSocket.send (JSON.stringify (getDepartmentsQuery));
然后将该通道转移到在线的部门。
const allDepartments = data.payload.data.department .edges;
const onlineDepartments = alldepartment .filter(
department.node.status === 'ONLINE'
);
如果(onlineDepartments。长度> 0){
const pickRandomDepartment = Math.floor(
Math.random() * onlinedepartment .length
);
const onlineDepartment = onlineDepartment [pickRandomDepartment].node;
const transferToDepartmentQuery = {
有效载荷:{
查询:'突变{
transferToDepartment (
channel_id:“$ {channelToBeTransferred}”,
department_id:“$ {onlineDepartment.id}”
) {
成功
}
} '
},
类型:“请求”,
id: REQUEST_ID。TRANSFER_TO_DEPARTMENT
};
webSocket.send (JSON.stringify (transferToDepartmentQuery));
}
有关对话API支持的所有操作的完整文档,请参阅GraphQL模式文档.
示例应用程序代码
去亚博Zendesk聊天对话API示例应用程序codesandbox。IO获取本文中描述的完整源代码。代码托管在一个基于云的Node.js沙箱中,你可以自己分叉和使用。查看示例应用程序顶部的评论部分以获得更多说明。
WebSocket请求和响应体结构
本节将介绍在使用WebSocket协议时,不同GraphQL操作所需的不同主体结构。
本节涵盖的主题:
查询和突变
请求
{
“有效载荷”:graphQLRequest,
“类型”:“请求”,
“id”:数量
}
场 | 类型 | 要求 | 描述 |
---|---|---|---|
id | 数字|字符串 | 是的 | 客户端生成的id。在响应中返回此id,以将响应与请求匹配 |
类型 | 字符串 | 是的 | 请求类型。它应该是一个值为的字符串“请求” |
有效载荷 | JSON | 是的 | 请求负载。看到请求负载 |
成功响应
{
“有效载荷”:graphQLResponse,
“id”:数量
}
场 | 类型 | 非空 | 描述 |
---|---|---|---|
id | 数字|字符串 | 是的 | 回显请求id |
有效载荷 | JSON | 是的 | 响应负载。看到响应负载 |
开始订阅
请求
{
“有效载荷”:graphQLRequest,
“类型”:“请求”,
“id”:数量
}
成功响应
{
“有效载荷”:{
“数据”:{
“subscription_id”:字符串
},
},
“id”:数量
}
使用subscription_id将后续订阅数据与订阅请求匹配并停止订阅。
停止订阅
请求
{
“有效载荷”:{
“subscription_id”:字符串
},
“类型”:“stop_subscription”,
“id”:数量
}
成功响应
{
“有效载荷”:{“数据”:{“成功”:真正的}},
“id”:数量
}
订阅数据
成功响应
{
“有效载荷”:graphqlResponse,
“团体”:“数据”,
“subscription_id”:字符串
}
的数据Sig表示响应是订阅数据。
错误响应
{
“error_code”:httpStatusCode,
“有效载荷”:graphQLErrorPayload|protocolErrorPayload,
“团体”:“数据”,
“subscription_id”:字符串
}
请求负载
{
“查询”:`突变updateVisitor {
updateVisitorInfo(display_name: "jim", visitor_id: "2.jlgwAAseGzxwEr") {
成功
}
}
($access_token: String!) {
startAgentSession(access_token: $token) {
websocket_url
session_id
client_id
}
}`,
“operationName”:“startSession”,
“变量”:{
“access_token”:“e86562f972c467f84712869bf3ccb21bdbe1e1ba2eddaa2ae6b8696e003d1d1a”
}
}
属性 | 类型 | 要求 | 描述 |
---|---|---|---|
查询 | 字符串 | 是的 | 必须符合GraphQL查询语言规范的GraphQL查询 |
变量 | 对象 | 没有 | 允许客户端传递动态查询的参数 |
operationName | 字符串 | 是的* | *如果查询包含多个命名操作,则必须。控制应执行的操作 |
响应负载
响应有效负载具有以下JSON格式,它遵循GraphQL规范.
属性 | 类型 | 要求 | 描述 |
---|---|---|---|
数据 | 对象 | 没有 | 所请求操作的执行结果 |
错误 | 数组 | 没有 | 在graphQL操作执行期间的非空错误列表。请参阅下面示例中的“graphQLErrorPayload” |
错误响应
除非另有指定,否则所有错误的响应体如下所示。
{
“错误代码”:httpStatusCode,
“有效载荷”:graphQLErrorPayload|protocolErrorPayload,
“id”:数量
}
错误响应可以指定以下类型的有效负载错误之一:graphQLErrorPayload而且protocolErrorPayload.
graphQLErrorPayload
GraphQL执行失败。
{
错误:[
{
名字:“GRAPHQL_EXEC_ERROR”,
消息:"解析hello字段时出现未知错误",
UUID:“f4706a5c - 5022 - 4 - dcf b113 - 2 baa0c848557”
},
...
]
}
每个错误包含以下属性:
属性 | 类型 | 描述 |
---|---|---|
名字 | 字符串 | 错误处理的错误名称/代码 |
消息 | 字符串 | 错误消息/细节 |
UUID | 字符串 | 错误的全局唯一标识符 |
对于处理错误,使用名字
属性可用于区分错误类型。以下是错误名字
S,你可以期待:
错误的名字 | 描述 | 的事情 |
---|---|---|
未经授权的 | 请求缺少有效的身份验证凭据。此错误可能是由于禁用了代理或使用了无效的访问令牌。 | 没有 |
被禁止的 | 服务器理解请求,但拒绝授权。此错误可能是由于您的帐户未处于活动状态,帐户没有API访问权限,或者您的访问令牌没有足够的范围来访问对话API。 | 没有 |
RATE_LIMITED | 你在给定的时间内发送了太多的请求。看到速度限制. | 是的 |
MAX_SUB | 你的订阅 请求被拒绝,因为当前会话超过了订阅限制。看到速度限制. |
没有 |
GRAPHQL_EXEC_ERROR | 我们的服务器收到了您的请求,但无法完全执行。此错误可能是由于无效的请求结构、无效的请求参数或内部服务器错误。 | 没有 |
GRAPHQL_SUB_START_ERROR | 启动GraphQL订阅请求失败。此错误可能是由于无效的请求结构或内部服务器错误。 | 有限公司(见下文) |
可重试意味着你可以尝试再次进行相同的操作调用,最好是指数回退。如果Retryable为No,则响应将始终给您相同的错误。例外:如果您得到一个GRAPHQL_SUB_START_ERROR,您可以在30秒内重试3到5次,并进行指数回退,但不是无限回退。
如果您觉得错误详细信息还不够,可以通过与支持人员联系来请求进一步的调试信息UUID.
protocolErrorPayload
协议错误。示例:对话API GraphQL服务器不可用。
{
“身体”:字符串
}
服务结束信号
服务结束(EOS
)信号表示当前代理会话不再有效。这个信号可能是由于:
- 并发登录(使用不同的会话ID创建多个会话API会话)。
- 试图建立WebSocket连接到未经身份验证的WebSocket URL。
- 后
stopAgentSession
请求被调用。
该信号将具有以下结构:
{
“原因”:“意外会话状态”,
“团体”:“EOS”
}
如果您希望应用程序在收到EOS
信号,发出信号startAgentSession
请求并使用新的已验证的WebSocket URL。
速度限制
对话API是有速率限制的。看到速度限制在聊天对话API参考文档中。
GraphQL资亚博电脑端源
请参阅以下资源以了解更多关于Grap亚博电脑端hQL的信息:
- GraphQL简介在graphql.org网站上
- 如何使用GraphQL网站
- GraphQL规范网站
- awesome-graphqlGithub上
常见问题解答
如果你有任何关于聊天对话API的问题,请检查亚博Zendesk api社区.如果之前没有人问过,请随时提出问题。