注意: 本文只對在線服務接入訪客名片功能進行詳細敘述。
1. 在線服務訪客名片接入流程
注意:本文只對在線服務接入訪客名片功能進行詳細敘述。
接入在線服務的租戶通常會有這么一個需求,就是希望客服在工作臺界面能夠看到來咨詢問題的訪客的個人信息,以便提供更好的服務。出于為客戶的數據安全考慮,云客服不會獲取接入方的客戶信息,這就需要接入方提供一個頁面或接口(即“訪客名片”)來供云客服系統實時展示,而這樣的一個頁面或接口需要查詢參數,比如類似userId這樣的能確定客戶身份的信息。接入方如何將這些查詢參數傳遞給云客服,以便云客服系統在調用接入方的“訪客名片”時將查詢參數透傳給接入方系統,這就是本文檔要解決的問題。
在線服務接入訪客名片的工作有兩個,分別為 :
訪客端聊天窗數據埋點。
客服端工作臺訪客信息展示。
訪客名片詳細工程(Java語言) JavaDemo(PhP語言)phpdemo(C#語言)C#Demo
上述demo可以直接本地執行Application.java中的main函數。
其他開發語言目前沒有代碼demo,請用戶參考Java語言進行開發。
注意:該文檔所需公鑰,需要收集租戶id(提供聊天窗url),和當前文檔鏈接,提工單給我們的同學生成。
2. 訪客端聊天窗數據埋點
埋點主要是構造帶有用戶信息的加密鏈接。
2.1 在線服務埋點鏈接
訪問 https://robot-ccs.aliyun.com/scenemng.htm#/scenemng頁面,選擇要構造加密信息的聊天窗 URL,以移動端的鏈接為例,以下就是一個標準的云客服在線服務聊天窗 URL:https://cschat-ccs.aliyun.com/index.htm?tntInstId=_0GBRgxU&scene=SCE00000023。 如果以這個埋點鏈接直接連入在線客戶,客服在工作臺端看到的只能是匿名訪客。我們需要對這個鏈接加些參數,才能讓其變為一個帶實名訪客信息的聊天窗鏈接。
2.2 需要加哪些參數?
只需要加上兩個 URL 參數,即可使一個匿名鏈接變為實名鏈接:
cinfo:將要傳給訪客名片的查詢參數被加密后的內容。
key:非對稱加密算法加密后的對稱加密密鑰。
最終的聊天窗 URL 需變成這樣:https://cschat-ccs.aliyun.com/index.htm?tntInstId=_0GBRgxU&scene=SCE00000023&cinfo=xxxxx&key=yyyyy可以看到,這兩個參數提到最多的詞就是“加密”。處于安全考慮,這些必須以密文形式傳遞,否則將會給惡意攻擊者可趁之機。接入方對加密技術不了解也沒關系,后面會有示例代碼。
2.3 cinfo里是什么內容?
cinfo 里明文的內容構造示例:
{
"extInfo":{" uid ":"11111"," customerInfo ":"11111"},
"userId":"12345",
"uname":"Tom",
"browser":"chrome",
"network":"4G",
"appVersion":"1.0.0",
"os":"iOS",
"device":"iphone6 plus",
"resolution":"1920*1280",
"timestamp":當前時間的UNIX時間戳
}
最重要的 3 個字段:extInfo、userId、timestamp。請詳細閱讀下表中這 3 個字段的說明。
字段代碼 | 字段名稱 | 字段說明 |
extInfo | 業務擴展信息 | 該字段是一個JSON對象,內容由接入方確定。用于存放接入方訪客名片需要用到的查詢參數,云客服系統會負責將這些查詢參數透傳給接入方的訪客名片地址,格式形如:”extInfo”:{“key1”:”val1”,” “key2”:”val2” },其中的key-value均由接入方自己指定。云客服平臺不關注其中的內容,只會透傳給接入方的訪客名片。該字段必須設置。 |
userId | 用戶id | 訪客在接入方系統中的標識。該字段必須設置。 |
timestamp | 時間戳 | 當前時間的UNIX時間戳,增加該字段可以控制埋點鏈接的有效時間,提升安全性,(單位:毫秒)。在線工作臺配置管理中可增加一個配置編碼為ENTRY_URL_EXPIRE_TIME的配置項(單位:秒),當云客服系統接收到請求的時間減去該字段的值得到的時間跨度超過了配置的有效時間,則認為該加密鏈接已失效,云客服系統將拒絕此次訪問。該字段雖為可選字段,但出于安全考慮,建議設置。 |
uname | 用戶名稱 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
browser | 瀏覽器 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
network | 網絡 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
appVersion | 應用端版本 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
os | 操作系統 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
device | 設備 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
resolution | 分辨率 | 用于在線工作臺的環境信息tab中展示,可不傳;不傳則不展示。 |
2.4 如何生成最終的cinfo和key?
接下來將明文進行加密,以得到最終要拼接到聊天窗 URL 中的 cinfo 和 key 參數。
代碼示例
publicclassTest{
//注意:該公鑰僅供demo示范使用,用戶公鑰請參考文檔第四部分,收集信息,聯系開發同學獲取。
privatestaticString pub_key ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp5khaVZIP+x+n+ari3c1dcYRuNG7BUL0VVt1X2+KDcOpTHtfdHUQIzrHdbikZSyaCKyHLbAuLsU24gulCKmMGtjFGS6OiavUFFikVnVnOyEzcnhSPBiJNdlUo5TNYOVN1SUCutJUxvibQ1za6IcnHf4okgPTgcrXVHyG5ntCbE9ippKLe7q0z0TUIkRxesbKZiQPBDOgBukJUiFMk95zqCdESCe6kCSp2GdIojyVAelU11JIcAm/4OjCCFMz6Jcnse7rdScxRsoMHU89tDmXG9mo3PhUXyfQJzyESlotKek99eHPkSr7EW/SBj3xMc+ysrBZd+4tFOZJIRIlFf/eSQID****";
//還原出RSA公鑰對象
privatestaticPublicKey getPubKey()throwsException{
X509EncodedKeySpec keySpec =new X509EncodedKeySpec(Base64Util.decode(pub_key));
KeyFactory keyFactory;
keyFactory =KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
return key;
}
publicstaticvoid main(String[] args)throwsException{
JSONObject extInfo =newJSONObject();
extInfo.put("userId","123456");
extInfo.put("userName","Tom");
JSONObject cinfo =newJSONObject();
cinfo.put("userId","123456");
cinfo.put("extInfo", extInfo);
PublicKey publicKey = getPubKey();
Map<String,String> map =CustomerInfoCryptoUtil.encryptByPublicKey(cinfo.toString(), publicKey);
String uri ="&key="+ map.get("key")+"&cinfo="+ map.get("text");
}
}
目前加密方法只支持 Java 語言,加密所需的密鑰請聯系云客服的技術人員獲取,加密所需的工具類 jar 包可以下載導入。
2.5 生成最終的帶實名訪客信息的聊天窗URL
通過上一步得到了加密后的cinfo和key,將這兩個參數拼接到原聊天窗 URL 中,即可得到最終的 URL(如 2.2 描述)。可以在
進行測試。3. 客服端工作臺訪客信息展示
在工作臺對訪客信息展示一共有兩種方案:
頁面嵌入
外部接口調用
這兩種方案不可以同時使用, 請選擇一種。
3.1 頁面嵌入方案
該方案需要租戶自己提供一個訪客名片的展示頁面, 以iframe的形式嵌入到在線工作臺右側。工作流程如下:
提供訪客名片頁面的URL。
對該頁面的URL中的params進行解密(params由云客服系統構造)。
頁面對params的內容進行展示。
利用postMessage函數方法, 回傳userId和userName。
3.1.1 提供訪客名片URL
編寫一個簡單的頁面用于展示客戶信息。并把URL填寫到
的輸入框中。3.1.2 params進行解密
客服工作臺在加載租戶提供的URL的時候, 會在URL中拼接三個參數:params, key, iframeKey
。
https://www.example.com/customerinfo.htm?params=***&key=***&iframeKey=***
params : AES對稱性加密后的JSON字符串 key : RSA非對稱性加密后的AES密鑰 iframeKey : 服務記錄TAB-ID(不用關心該字段含義)。
解密params方法請參考本文:第四節解密。
解密后的結果是一個JSON數據, 該數據內容的參數含義如下:
名稱 | 類型 | 可空 | 字段限制 | 描述 |
extInfo | String | 是 | 2048 | 業務個性化信息,來源于聊天窗埋點的鏈接,示例:”extInfo”:{“key1”:”value1”,” key2”:”value2” },其中key值接入組件可自行定義。 |
sourceType | String | 否 | 32 | 在線頁面嵌入時需要根據此參數判斷展示類型,在線為縱向展示。 |
contactId | String | 是 | 64 | 服務記錄ID,供接入方處理個性化業務與服務記錄之間的關聯關系, 例如:業務自有工單需要與云客服平臺服務記錄做關聯的場景中。 |
timestamp | String | 否 | 32 | 生成事件Unix時間戳。 |
3.1.3 頁面對params的內容進行展示
拿到解密后的params內容后,在iframe頁面上渲染其內容信息, 展示給客服。
3.1.4 利用postMessage函數方法回傳userId和userName
請將下面代碼放到頁面中。
function sendMessage(type, data){
constparams={};
params.type = type;
params.data = data;
params.resource ='csbridge';
params.iframeKey ='1';// 從url參數獲取,示例假設值為1
window.parent.postMessage(JSON.stringify(params),'*');
}
然后在步驟 3.1.2 的params解密后, 調用:
sendMessage('updateUserInfo',{"userId":"TESTID123456789","userName":"Tom"});
3.1.5 更新嵌入的頁面高度
本小節是為了樣式調整, 不是必須的. 使用方法同上一節類似。
示例 sendMessage('updateHeight', 300); //300是需要設定的高度。
以上是接入訪客名片的所有流程。
3.2 外部接口調用
使用這種方案的時候,不需要租戶提供任何前端頁面, 只需要提供一個接口,云客服會通過Post的方式調用這個接口來查詢訪客信息。
注意:該接口必須支持跨域請求. 跨域解決方案可自行搜索CORS獲取。 接口協議必須是HTTPS。 響應頭中 Content-Type 為 application/json; charset=utf-8。
客戶需要做的流程為:
提供客戶查詢接口URL。
對該URL收到的POST請求中,取得params和key參數并解密。
通過解密后的內容,查詢該訪客的詳細信息返回。
3.2.1 提供客戶查詢接口URL
提供該URL,并配置到云客服工作臺的組件配置>訪客名片URL。用下面的方式選擇外部請求。
3.2.2 取得params和key參數并解密
云客服會對該接口發送POST請求(跨域)。其中兩個參數params和key會拼接在上一步配置的URL后面。 例如:
https://www.example.com/customerinfo.json?params=***&key=***
在取得這兩個參數后,需要進行解密。
解密params方法請參考本文: 第四節解密
解密之后的內容是一個JSON字符串, 各個字段意義如下(各個字段并不一定有,可以為空):
名稱 | 類型 | 可空 | 字段限制 | 描述 |
tel | String | 是 | 32 | 電話號碼 |
extInfo | String | 是 | 2048 | 聊天窗埋點信息 |
userId | String | 是 | 64 | 租戶CRM中的用戶ID |
cardId | String | 是 | 32 | 用戶證件號碼 |
timestamp | String | 否 | 32 | Unix時間戳 |
3.2.3 通過解密后的內容查詢用戶信息并返回.
解密后的內容含有用戶的關鍵信息,通過這個信息客戶自行查詢到相信信息, 并按照嚴格的格式返回。
返回的JSON數據中,userId為必填字段。云客服平臺會以此數據作為客戶的唯一標識,并保存在云客服平臺服務記錄中。該字段不用再schema中做字段信息的描述。
樣例:
{
"message":"查詢成功",//成功的消息
"success":true,//表示查詢成功
"result":{//下面是自定義用戶信息內容.
"telePhone":"13*******000",
"customerName":"某銀行某分行",
"userName":"test",
"email":"w***@example.com",
"userId":"0CE0540B-E351-4B83-B47F-72A2E8D2479E",//這個必須有!
"customerNo":"77777",
"account":"77777",
"mobile":"",
"schema":{//會按照schema的結構來展示用戶信息
"properties":{
"customerName":{
"name":"客戶名",
"type":"text"
},
"account":{
"name":"客戶賬號",
"type":"text"
},
"userName":{
"name":"聯系人",
"type":"text"
},
"telePhone":{
"name":"電話",
"type":"text"
},
"email":{
"name":"郵箱",
"type":"text"
}
}
}
}
}
4. 解密
4.1 解密步驟
從HTTPS請求URL中獲取對應參數,分別是params, key。
將用戶公鑰還原成PublicKey類型。
調用CustomerInfoCryptoUtil.decryptByPublicKey(params, key, publicKey)方法進行解密。
4.2 maven依賴
<repository>
<id>central</id>
<url>http://mvn.cloud.alipay.com/nexus/content/groups/public</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<dependency>
<groupId>com.alipay.fc.csplatform</groupId>
<artifactId>fccsplatform-common-crypto</artifactId>
<version>1.0.0.20161108</version>
</dependency>
4.3 Java-Demo
publicclassTest{
//注意:該公鑰僅供demo示范使用,用戶公鑰請聯系技術支持獲取。
privatestaticString pub_key ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp5khaVZIP+x+n+ari3c1dcYRuNG7BUL0VVt1X2+KDcOpTHtfdHUQIzrHdbikZSyaCKyHLbAuLsU24gulCKmMGtjFGS6OiavUFFikVnVnOyEzcnhSPBiJNdlUo5TNYOVN1SUCutJUxvibQ1za6IcnHf4okgPTgcrXVHyG5ntCbE9ippKLe7q0z0TUIkRxesbKZiQPBDOgBukJUiFMk95zqCdESCe6kCSp2GdIojyVAelU11JIcAm/4OjCCFMz6Jcnse7rdScxRsoMHU89tDmXG9mo3PhUXyfQJzyESlotKek99eHPkSr7EW/SBj3xMc+ysrBZd+4tFOZJIRIlFf/eSQID****";
//還原出RSA公鑰對象
privatestaticPublicKey getPubKey()throwsException{
X509EncodedKeySpec keySpec =new X509EncodedKeySpec(Base64Util.decode(pub_key));
KeyFactory keyFactory;
keyFactory =KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
return key;
}
publicstaticvoid main(String[] args)throwsException{
Stringparams= request.getParameter("params");
String key = request.getParameter("key");
PublicKey publicKey = getPubKey();
String cinfo =CustomerInfoCryptoUtil.decryptByPublicKey(params, key, publicKey);
JSONObject dataJsonObject = JSON.parseObject(cinfo);
//加驗時間戳
Date requestDate =newDate(dataJsonObject.getLong("timestamp"));
Date now =newDate();
//...
//TODO 業務處理
}
}
5 常見問題
data must start with zero
解決方式:使用URLEncode解密params參數和key參數。
CustomerInfoCryptoUtil.decryptByPublicKey(URLEncoder.encode(params,"UTF-8"),URLEncoder.encode(key,"UTF-8"), publicKey);
如果在按照文檔對接成功,但是工作臺無法顯示,需要提供租戶id,工作臺客戶接入時的控制臺network中調用填寫接口的response信息,然后提工單給我們。