功能简介#

RTM(real time message)系统,用来提供用户与待客系统之间实时通信的服务,使用websocket协议。

通信过程#

创建会话

客户端需要先调用获得工单聊天入口API发起一次请求,得到响应后,根据返回结果中提供的endpoint向聊天服务器发起websocket连接,此过程必须在30秒内完成,如果超时,需要重新申请。

保持心跳

可以通过由客户端主动对服务器发起ping/pong消息来保持连接以及检查连接存活性。

通信

在完成创建会话的步骤后,服务器与客户端之间将通过websocket交换事件,一般为一来一回的调用形式。

事件的排序

每个事件都有一个timestamp字段,该字段为一个UTC的时间戳,以字符串形式展现,由于这个字符串的特殊性(完全由数字组成,并在200年内都不会改变长度),所以所有的事件都应该以timestamp进行排序,较小的排在时间线的前面。

事件的发送

由于websocket是异步的,客户端在向服务器发送消息时,必须在每条消息中都携带一个正数的id,并且在一次连接中不要重复,服务器在收到消息并妥善处理后,会将这个事件返回,并携带reply_to字段,用来表示已经处理好一个idreply_to的消息,客户端可以用这个来作为消息是否发送成功的标志。

需要注意的是,只有客户端的事件需要使用此机制,服务器的通知不需要客户端做任何确认,也不会做任何重发,如果客户端需要矫正自己的数据,使用Web API来获取完整的事件列表。

对于服务器无法识别的类型,服务器将不予理会,如果客户端总是发送无意义的内容,服务器会主动断开连接。

结束会话

客户端可以随时关闭连接,服务器则只在有错误的时候关闭。

事件类型#

事件由type字段来标识具体类型,对于有扩展的事件,可以使用subtype来表示子类型。

一般事件:

事件 类型
hello事件 hello
ping/pong事件 ping/pong
消息事件 message
附件消息事件 attachment
工单状态改变事件 change_status

扩展事件:

事件 类型 子类型 描述
自动回复 message auto_reply_message 系统自动回复的消息
插入 FAQ message faq_message 回复插入FAQ

hello事件#

在客户端连接上服务器以后,为了验证双方已经正确的建立连接,客户端应发送hello给服务器,如在30秒后客户端都没有收到服务器的hello,则应该断开,通过调用获得工单聊天入口API重新获取endpoint重连。

// client
{
  "id": 1,
  "type": "hello"
}
// server
{
  "reply_to": 1,
  "type": "hello"
}

ping/pong事件#

为了保持连接,客户端可以跟服务器交换ping/pong信息,客户端发送:

{
  "id": 239,
  "type": "ping",
  "timestamp": "1462480013.164"
}

服务器会返回:

{
  "reply_to": 239,
  "type": "pong",
  "timestamp": "1462480013.787"
}

在客户端时间准确的情况下,可以利用此处的timestamp判断与服务器之间的延时。

同时服务器支持websocket native ping/pong,支持该协议的客户端可以选择任意选择一种ping/pong使用

消息事件#

message是双方主要通信的事件,格式如下:

{
  "type": "message",
  "timestamp": "1462480013.164",
  "ticket_id": "VwKXD5P8",
  "user_id": "MPrx7MNK", // optional
  "staff_id": "4NkZjApm",
  "text": "this is a message from santa, hohoho"
}
name description
subtype 可选,表示特殊的 message,比如对于自动回复,其值为auto_reply_message
timestamp 时间戳,尽管客户端可以发送一个自己的,服务器会在reply的时候覆盖成服务器上的时间
ticket_id 工单的id
user_id\ staff_id
text 消息正文

subtype的取值范围:

value description
auto_reply_message 该消息是一条自动回复消息
faq_message 该消息是一条FAQ

FAQ消息事件#

当消息中包含faq文章时,消息的subtype应为faq_message,同时,还应包含一个articles字段,用来描述消息中FAQ的具体信息,格式如下:

{
  "type": "message",
  "text": "please refs to https://faq/id"
  ...
  "subtype": "faq_message",
  "articles": [
    {
      "id": faq.id,
      "title": faq.title,
      "url": faq.url, // 这个url应该在text中出现过,如上面的https://faq/id,并且可以直接在浏览器中打开该FAQ
    },
    ...
  ]
}

附件消息事件#

此消息只会从服务器下发,用于收到包含附件的信息,客户端需要使用附件上传API来上传附件。格式如下:

{
  "type": "attachment",
  "timestamp": "1462480013.164",
  "attachment_id": "JPoyykkN",
  "ticket_id": "VwKXD5P8",
  "user_id": "MPrx7MNK",
  "staff_id": "4NkZjApm",  // optional
  "content_type": "image/jpg",
  "filename": "3222fe17-6302-4e94-acb3-d1debe510bc1.jpg",
  "size": 153984,
  "url": "https://cdn.daikeapp.com/uploads/attachment/file/17/3222fe17-6302-4e94-acb3-d1debe510bc1.jpg",
  "thumb_url": "https://cdn.daikeapp.com/uploads/attachment/file/17/thumb_3222fe17-6302-4e94-acb3-d1debe510bc1.jpg",
  "mediumthumb_url": "https://cdn.daikeapp.com/uploads/attachment/file/17/medium_thumb_3222fe17-6302-4e94-acb3-d1debe510bc1.jpg"
}
name description
attachment_id 附件id
timestamp 时间戳,服务器上的UTC时间
ticket_id 工单的id
user_id\ staff_id
url 附件的url
content_type 附件的mime type
filename 附件文件名
size 附件大小
thumb_url 附件缩略图的url,只有在上传图片时才出现
medium_thumb_url 附件中等缩略图的url,只有在上传图片时才出现

工单状态改变事件#

工单状态发生改变时(客服关闭工单;用户确认关闭工单;用户重新打开工单)产生该事件。 客户端收到status为closed的消息后,客户端应提示用户确认,如果用户确认关闭,则发送confirmed给服务器端,否则发送waiting_for_user给服务器。

{
  "type": "change_status",
  "status": "closed",
  "ticket_id": "VwKXD5P8",
  "timestamp": "1462480013.164",
  "staff_id": "4NkZjApm",
  "user_id": "MPrx7MNK"
}
name description
ticket_id 工单的id
timestamp 时间戳,尽管客户端可以发送一个自己的,服务器会在reply的时候覆盖成服务器上的时间
user_id\ staff_id
status 取值为closedconfirmedwaiting_for_user,对应的情况分别是客服关闭工单,用户确认关闭工单,用户重新打开工单