====== REST API渠道集成 ====== 开通REST API渠道并配置服务器信息后,客服向客户回复的消息,将被环信转发到服务器的回调地址中。该功能可用于环信客服云与第三方服务器之间的消息传递。 注:REST API渠道为旗舰版功能。 ===== 创建REST关联 ===== REST API渠道支持创建多个REST关联,每个REST关联均可作为环信与您的服务器之间收发消息的通道。 创建REST关联: - 进入“管理员模式 > 渠道管理 > REST API”页面; - 点击“添加REST关联”按钮,填写关联名称、回调地址,并保存。 系统自动为您生成Client ID、Client Secret、发送消息API。Client ID和Client Secret用于向环信发送消息时的身份认证;“发送消息API”为您向环信发送消息时使用的REST API接口,方法为POST。 {{:cs:300visitoraccess:admin-channel-restapi.png?nolink|REST API渠道}} ===== 身份认证 ===== 当您的服务器使用REST关联中的“发送消息API”向环信客服云发送消息时,需要通过环信的身份认证。环信使用HMAC(Hashed Message Authentication Code,散列消息身份认证码)进行身份认证。 ==== 请求头 ==== 在发送消息的API中添加如下请求头: X-Auth-Expires: 1234567 Content-Type: application/json; utf-8 Authorization: hmac {Client ID}:{signature} X-Auth-Expires 为签名过期时间,必须使用时间戳,单位毫秒;比如当前时间为 'Tue Mar 14 19:20:54 2017',时间戳为 1489490454142,如果想让签名在1分钟后过期,则 X-Auth-Expires: 1489490514142。如果时间戳为非正值,则表示不过期。 Authorization 中 signature 使用 Client Secret 通过 hmac-SHA256 算法生成。 ==== Signature生成规则 ==== Signature生成规则如下: base64(hmac-sha256(Client_SECRET, HTTP-Verb + "\n" + RESOURCE_PATH + "\n" + X-Auth-Expires + "\n" + md5(CONTENT) )) ==== Signature计算示例 ==== 例如下面这个请求: * Client ID: 283e8488-06d6-43d4-b8a8-d8f0a300f4ce * Client Secret: 02a0693ba5a57560df1f26a991204cb0 POST /api/tenants/5950/rest/channels/20/messages HTTP/1.1 Content-Type: application/json; utf-8 X-Auth-Expires: 1489490514142 {"bodies":[{"msg":"testmsg2","type":"txt"}],"ext":{"queue_id":"","queue_name":"","agent_username":"","visitor":{"user_nickname":"userNickname","true_name":"userTrueName","qq":"999999999","email":"test@test.test","phone":"18888888888","company_name":"companyName","description":"description"}},"msg_id":"14332423141234234","origin_type":"rest","from":"test_weichat_visitor05","timestamp":1468832767680} === 第 1 步:计算md5(CONTENT) === CONTENT为Request body的内容(JSON格式,没有空格和换行)。 上述示例的计算结果为: 705bfbd388d2bf852813fc90e655b5ed;所以待加密字符串为: POST\n/api/tenants/5950/rest/channels/20/messages\n1489490514142\n705bfbd388d2bf852813fc90e655b5ed === 第 2 步:根据Client Secret与待加密字符串计算signature === 使用hmac-sha256加密,然后对其返回的原始二进制数据进行base64编码。 上述示例的计算结果为: yLgHjb8GckRpZ2uW8kb0qipODRkaFCIBNQsnZ2vhGMo= Java 代码示例: String secret = "02a0693ba5a57560df1f26a991204cb0"; String message = "POST\n/api/tenants/5950/rest/channels/20/messages\n1489490514142\n705bfbd388d2bf852813fc90e655b5ed"; final SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA256"); final Mac mac = Mac.getInstance("HmacSHA256"); mac.init(keySpec); final byte[] result = mac.doFinal(message.getBytes()); Base64.getEncoder().encodeToString(result); 其他代码示例:[[https://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/|Examples of creating base64 hashes using HMAC SHA256 in different languages]] === 第 3 步:添加 Authorization 请求头 === 完整请求如下: POST /api/tenants/5950/rest/channels/20/messages HTTP/1.1 Content-Type: application/json; utf-8 Authorization: hmac 283e8488-06d6-43d4-b8a8-d8f0a300f4ce:yLgHjb8GckRpZ2uW8kb0qipODRkaFCIBNQsnZ2vhGMo= X-Auth-Expires: 1489490514142 {"bodies":[{"msg":"testmsg2","type":"txt"}],"ext":{"queue_id":"","queue_name":"","agent_username":"","visitor":{"user_nickname":"userNickname","true_name":"userTrueName","qq":"999999999","email":"test@test.test","phone":"18888888888","company_name":"companyName","description":"description"}},"msg_id":"14332423141234234","origin_type":"rest","from":"test_weichat_visitor05","timestamp":1468832767680} ===== 投递客户消息到环信 ===== 支持投递文本、图片、语音、视频消息到环信客服云。并且,可以在消息中增加ext扩展字段,以实现更多个性化功能。 ==== 消息示例 ==== **注意:** 以下消息格式仅为JSON示例,计算signature和投递消息时请删除所有空格、换行、注释。 === 文本消息 === 发送文本消息的Request body格式: { "bodies": [ { "msg": "testmsg2", // 消息内容 "type": "txt" // 消息类型,支持文本(txt)、图片(img)、语音(audio)、视频(video)消息 } ], "ext": { "queue_id": "", // 可选,技能组ID,用于指定技能组 "queue_name": "", // 可选,技能组名称,用于指定技能组 "agent_username": "", // 可选,客服登录邮箱,用于指定客服 "visitor": { // 客户信息 "user_nickname": "userNickname", // 客户昵称 "true_name": "userTrueName", // 客户的真实姓名 "qq": "999999999", // 客户的QQ号码 "email": "test@test.test", // 客户的电子邮件地址 "phone": "18888888888", // 客户的电话号码 "company_name": "companyName", // 客户的公司名称 "description": "description", // 客户的描述 "tags":["vip1", "vip2"] // 可选,用于VIP客户在待接入中插队 } }, // 可选,消息ID,环信根据msg_id对消息进行去重,每条消息需要有唯一的msg_id "msg_id": "14332423141234234", // 渠道类型,固定值为rest "origin_type": "rest", // 客户ID,显示在“资料”页签,如果客户为微信公众号的粉丝,建议填写“原始ID+openid” "from": "test_weichat_visitor05", // 消息发送的时间 "timestamp": 1468832767680 } === 图片消息 === 发送图片消息的Request body格式: { "bodies": [ { "type": "img", // 消息类型,图片消息 "url": "https://172.17.2.154:9090/images/entry/logo.png", // 图片的下载地址 "filename": "logo.png", // 图片名称 "size": { "width": 480, // 可选,图片宽度,单位:px "height": 720 // 可选,图片高度,单位:px } } ], "ext": { "queue_id": "", "queue_name": "", "agent_username": "", "visitor": { "user_nickname": "userNickname", "true_name": "userTrueName", "qq": "999999999", "email": "test@test.test", "phone": "18888888888", "company_name": "companyName", "description": "description" } }, "msg_id": "14332423141234234", "origin_type": "rest", "from": "test_weichat_visitor05", "timestamp": 1468832767680 } === 语音消息 === 发送语音消息的Request body格式: { "bodies": [ { "type": "audio", // 消息类型,语音消息 "url": "https://172.17.2.154:9090/media/msg.mp3", // 语音文件的下载地址 "filename": "msg.mp3", // 语音文件名称 "length": 1 // 可选,语音消息的时长,单位:秒 } ], "ext": { "queue_id": "", "queue_name": "", "agent_username": "", "visitor": { "user_nickname": "userNickname", "true_name": "userTrueName", "qq": "999999999", "email": "test@test.test", "phone": "18888888888", "company_name": "companyName", "description": "description" } }, "msg_id": "14332423141234234", "origin_type": "rest", "from": "test_weichat_visitor05", "timestamp": 1468832767680 } === 视频消息 === 发送视频消息的Request body格式: { "bodies": [ { "type": "video", // 消息类型,视频消息 "url": "https: //a1.easemob.com/easemob-demo/chatdemoui/chatfiles/671dfe30-7f69-11e4-ba67-8fef0d502f46", // 视频文件的下载地址 "filename": "1418105136313.mp4", // 视频文件名称 "length": 10 // 可选,视频消息的时长,单位:秒 } ], "ext": { "queue_id": "", "queue_name": "", "agent_username": "", "visitor": { "user_nickname": "userNickname", "true_name": "userTrueName", "qq": "999999999", "email": "test@test.test", "phone": "18888888888", "company_name": "companyName", "description": "description" } }, "msg_id": "14332423141234234", "origin_type": "rest", "from": "test_weichat_visitor05", "timestamp": 1468832767680 } ==== 扩展功能 ==== 在客户消息中增加ext扩展字段,可以实现更多个性化功能,包括:显示客户信息、指定技能组、指定客服、VIP客户插队、发送订单消息、发送轨迹消息,等等。 === 显示客户信息 === 通过在''visitor''字段中指定客户信息,可以将这些客户信息显示在客服云中会话页面的“资料”页签。 "ext": { "visitor": { // 客户信息 "user_nickname": "userNickname", // 客户昵称 "true_name": "userTrueName", // 客户的真实姓名 "qq": "999999999", // 客户的QQ号码 "email": "test@test.test", // 客户的电子邮件地址 "phone": "18888888888", // 客户的电话号码 "company_name": "companyName", // 客户的公司名称 "description": "description", // 客户的描述 } }, === 指定技能组 === 通过在''ext''字段中指定技能组ID或技能组名称,可以指定会话分配的技能组。推荐使用技能组名称指定技能组,技能组名称需与客服云“管理员模式 > 成员管理 > 技能组”页面设置的技能组名称一致,中英文均可。 在扩展字段中指定技能组的方式,对应于客服云“管理员模式 > 设置 > 会话分配规则”页面的“入口指定”。 "ext": { "queue_id": "", // 可选,技能组ID,用于指定技能组 "queue_name": "", // 可选,技能组名称,用于指定技能组 }, === 指定客服 === 通过在''ext''字段中指定客服登录邮箱,可以指定会话分配的客服。如果指定了客服,会话将直接分配给对应的客服,进入客服的“进行中”会话列表。 注:客服离线时,可能无法及时接待会话。 "ext": { "agent_username": "", // 可选,客服登录邮箱,用于指定客服 }, === VIP客户插队 === 通过设置''tags''字段,可以实现VIP客户插队的功能。当客服全忙时,VIP客户可插队到“待接入”队列的队首,有空闲客服出现时,优先接入。 客户发起会话时,凡是”tags”字段非空的客户都会直接排在待接入队列的最前面。当有多个客户包含非空的”tags”字段时,这些客户单独按会话发起时间排队。 "ext": { "visitor": { // 客户信息 "tags":["vip1", "vip2"] // 可选,用于VIP客户在待接入中插队 } }, === 发送订单消息 === 通过在''ext''字段中指定订单标题、金额、描述、图片、路径等信息,可以把订单消息发给访客。 "ext": { "msgtype": { "order": { "title":"我的订单", //订单标题 "order_title":"订单号:1513256", //订单编号 "price":"¥: 555.00", //订单金额 "desc":"潮流背包", //订单描述 "img_url":"http://o8ugkv090.bkt.clouddn.com/hd_two.png", //商品图片 "item_url":"https://yourdomain.com/item/a.html" //商品路径 } } }, === 发送轨迹消息 === 通过在''ext''字段中指定标题、价格、描述、图片、路径等信息,可以把轨迹消息发给访客。 "ext": { "msgtype": { "track": { "title":"我正在看:", //商品标题 "price":"¥: 235.00", //商品价格 "desc":"潮流女鞋", //商品描述 "img_url":"http://o8ugkv090.bkt.clouddn.com/hd_three.png", //商品图片 "item_url":"https://yourdomain.com/item/a.html" //商品路径 } } }, ===== 接收客服回复的消息 ===== 环信将客服回复的消息(文本、图片、语音、文件消息)投递到REST关联的服务器回调地址。收到客服消息后,需要对消息进行解析,并转发给对应的客户(to字段指定的客户ID)。 ==== 消息示例 ==== 客服消息的消息体bodies内容与投递消息到环信的格式一致。 图片消息示例: { "bodies": [ { "type": "img", // 消息类型,支持文本(txt)、图片(img)、语音(audio)、文件(file)消息 "url": "https://kefu.sh.easemob.com/v1/Tenant/11784/MediaFiles/8350c049-c36d-4b63-8d02-e535ec9de2865L2T6aqM5YWz6IGU77yIZ2F0ZXdhee-8iS5wbmc=", "filename": "testImg.png", "size": { "width": 602, "height": 439 } } ], "ext": { "msg_id": "cff22371-6eed-42ee-81ad-5923993fd8e8", "visitor": { "user_nickname": "userNickname", "true_name": "userTrueName", "qq": "999999999", "email": "test@test.test", "phone": "18888888888", "company_name": "companyName", "description": "description", "weixin": null, "tags": null, "callback_user": "test_weichat_visitor06" // 客户ID,与to字段的值一致 }, "agent": { "avatar": null, // 客服头像 "user_nickname": "客服昵称" // 客服昵称 }, "queue_id": null, "queue_name": "", "agent_username": "" }, "to": "test_weichat_visitor06", // 接收消息的客户ID,根据该ID判断将消息投递给哪位客户 "channel_type": "rest", // 关联类型,固定值为rest "tenant_id": 11784, // 租户ID "origin_type": "rest", // 渠道类型,固定值为rest "channel_id": 1 // REST关联的ID,与发送消息API URL中的ID一致 }