Sendbird Desk透過即時應用程式內支援增強客戶參與度。 Desk SDK 可讓您輕鬆初始化、配置客戶支援相關功能並將其建置到 Android 應用程式中。
Sendbird Desk 是 Sendbird 聊天平台的插件,用於管理工單,所有 Desk 事件都透過 Chat SDK 處理。
每張工單都會被分配適當的代理,並將被導向到聊天群組頻道,該頻道使用 Sendbird Chat SDK 在工單上實現即時訊息傳遞。
這些是 Desk SDK 的一些主要組件。
寄件人 | 亞型 | |
---|---|---|
用戶留言 | 代理或客戶 | 豐富的消息 |
管理員留言 | 從 Desk 伺服器發送,沒有特定寄件人 | 通知訊息和系統訊息 |
注意:豐富訊息進一步分為 URL 預覽、工單關閉確認請求和回饋請求訊息。
在適用於 Android 的 Desk SDK 文件中了解有關適用於 Android 的 Sendbird Desk SDK 的更多資訊。如果您對錯誤和功能請求有任何意見或疑問,請造訪 Sendbird 社群。
本部分顯示使用適用於 Android 的 Sendbird Desk SDK 需要檢查的先決條件。
Android 5.0 (API level 21) or higher
Java 8 or higher
Support androidx only
Android Gradle plugin 4.0.1 or higher
Sendbird Chat SDK for Android 4.0.3 and later
本部分為您提供開始使用適用於 Android 的 Sendbird Desk SDK 所需的資訊。
我們的範例應用程式演示了 Sendbird Desk SDK 的核心功能。從我們的 GitHub 儲存庫下載該應用程序,了解您可以使用實際 SDK 做什麼,並開始建立自己的專案。
Sendbird 應用程式包含聊天服務所需的一切,包括使用者、訊息和頻道。創建應用程式:
無論何種平台,每個應用程式只能整合一個 Sendbird 應用程式;然而,該應用程式支援跨所有 Sendbird 提供的平台進行通信,無需任何額外的設定。
注意:所有資料僅限於單一應用程式的範圍,因此不同Sendbird應用程式中的使用者無法互相聊天。
如果您熟悉使用外部程式庫或 SDK,安裝聊天 SDK 會很簡單。首先,將以下程式碼加入根build.gradle
檔案:
allprojects {
repositories {
.. .
maven { url " https://repo.sendbird.com/public/maven " }
}
}
注意:確保上述程式碼區塊未新增到您的模組
bundle.gradle
檔案中。
然後,將依賴項新增至專案的頂級build.gradle
檔案。
dependencies {
implementation ' com.sendbird.sdk:sendbird-desk-android-sdk:1.1.4 '
}
注意:
1.0.12
年 2 月 1 日之前,Desk SDK 版本1.0.12
或更低版本可從 JCenter 下載。
或者,您可以從此儲存庫下載 Desk SDK。將 Desk SDK 複製到您的libs/
資料夾中,並確保將該庫也包含在您的build.gradle
檔案中。
安裝完成後,可以建立票證以供代理商和客戶之間的通訊。請按照以下逐步說明建立您的第一張票證。
首先,啟動客戶端應用程式時必須初始化「SendBirdDesk」執行個體。在「Application.onCreate()」上呼叫「SendbirdChat.init()」和「SendBirdDesk.init()」。 SendbirdChat.init() 應先透過儀表板中 Sendbird 應用程式的 APP_ID 進行初始化。
public class MyApplication extends Application {
@ Override
public void onCreate () {
super . onCreate ();
final InitParams initParams = new InitParams ( APP_ID , this , false );
SendbirdChat . init ( initParams , new InitResultHandler () {
@ Override
public void onMigrationStarted () {
}
@ Override
public void onInitFailed ( SendbirdException e ) {
// If initializing fails, this method is called.
}
@ Override
public void onInitSucceed () {
// If initializing is successful, this method is called and you can proceed to the next step.
// You can use all Sendbird APIs, including Connect, after init is completed in your app.
SendBirdDesk . init ();
}
});
}
}
注意:Desk 和 Chat SDK 應使用相同的
APP_ID
。如果您使用另一個App_ID
的 Sendbird 實例啟動 Sendbird Desk,用戶端應用程式中的所有現有資料都會被清除。
您可以在客戶端應用程式中僅使用聊天 SDK,也可以同時使用聊天和桌面 SDK,具體取決於您想要提供的聊天服務。
軟體開發工具包 | 用於 |
---|---|
聊天軟體開發工具包 | 應用內訊息程序,客戶可以在其中互相聊天。 |
聊天和桌面 SDK | 客戶可以與客服人員聊天的門票。 |
public class MyApplication extends Application {
@ Override
public void onCreate () {
super . onCreate ();
final InitParams initParams = new InitParams ( APP_ID , this , false );
SendbirdChat . init ( initParams , new InitResultHandler () {
@ Override
public void onMigrationStarted () {
}
@ Override
public void onInitFailed ( SendbirdException e ) {
// If initializing fails, this method is called.
}
@ Override
public void onInitSucceed () {
// If initializing is successful, this method is called and you can proceed to the next step.
// You can use all Sendbird APIs, including Connect, after init is completed in your app.
SendBirdDesk . init ();
}
});
}
}
客戶可以透過各種類型的管道請求支援:應用程式內聊天或 Facebook、Instagram 和 Twitter 等社群媒體。要使用 Desk SDK 的這些支援功能, SendBirdDesk
實例應根據請求來自哪個通道與 Sendbird 伺服器連接:
authenticate()
方法及其使用者ID 進行身份驗證。通過身份驗證後,客戶可以基於 Sendbird Chat 平台與代理商進行即時聊天。
SendbirdChat . connect ( userId , accessToken , new ConnectHandler () {
@ Override
public void onConnected ( User user , SendbirdException e ) {
if ( e != null ) { // error.
return ;
}
// Use the same user Id and access token used in the SendbirdChat.connect().
SendBirdDesk . authenticate ( userId , accessToken , new SendBirdDesk . AuthenticateHandler () {
@ Override
public void onResult ( SendbirdException e ) {
if ( e != null ) { //error.
return ;
}
// SendBirdDesk is now initialized, and the customer is authenticated.
}
});
}
});
註: Sendbird Chat 平台的客戶是指已經透過 Chat SDK 進行身份驗證的使用者。如果您同時實作 Chat SDK 和 Desk SDK,請先使用使用者 ID 和存取權杖將使用者連接到 Sendbird 伺服器。
實作Ticket.create()
方法以在客戶發出初始訊息之前或之後建立新票證。
Ticket . create ( ticketTitle , userName , new Ticket . CreateHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // error
return ;
}
// The ticket is created. Agents and customers can chat with each other by sending a message through the ticket.getChannel().sendUserMessage() or sendFileMessage().
}
});
在 Sendbird 伺服器上成功建立票證後,您可以透過伺服器的回呼在ticket.getChannel()
中存取該票證及其通道。
在客戶發送第一則訊息之前,客服人員無法在儀表板中看到工單,並且不會進行工單分配。對話開始時,工單會透過 Desk Dashboard 分配給可用的客服人員,同時透過聊天 SDK 發送和接收訊息。
建立工單時您可以使用下列參數。
注意:僅需要定義 Groupkey 和 customFields,並且只能從儀表板存取。
爭論 | 類型 | 描述 |
---|---|---|
TICKET_TITLE | 細繩 | 指定票證的標題。 |
使用者名稱 | 細繩 | 指定提交或接收票證的使用者的名稱。 |
組鍵 | 細繩 | 指定特定團隊的識別碼。 |
自訂字段 | 嵌套對象 | 指定由鍵值自訂項目組成的工單的附加資訊。只有已在儀表板的「設定」 > 「工單欄位」中註冊的自訂欄位才能用作金鑰。 |
優先事項 | 細繩 | 指定票證的優先值。數值越高代表優先順序越高。有效值為LOW 、 MEDIUM 、 HIGH和URGENT 。 |
RELATED_CHANNEL_URLS | 大批 | 指定 Sendbird Chat 平台中與此工單相關的群組頻道,由頻道 URL 和頻道名稱組成。最多可新增 3 個相關頻道。 |
Map < String , String > customFields = new HashMap <>();
customFields . put ( "product" , "desk" );
customFields . put ( "line" , "14" );
customFields . put ( "select" , "option2" );
Ticket . create ( TICKET_TITLE , USER_NAME ,
"cs-team-1" , // GROUP_KEY
customFields , // CUSTOM_FIELDS
PRIORITY ,
RELATED_CHANNEL_URLS ,
new Ticket . CreateHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// The ticket is created with parameters.
}
}
);
本部分詳細介紹了從客戶端應用程式處理和關閉票證的過程。
使用ticket.setCustomFields()
方法新增有關特定工單的附加資訊。
Map < String , String > customFields = new HashMap <>();
customFields . put ( "product" , "Desk" );
customFields . put ( "line" , String . valueOf ( 30 ));
ticket . setCustomFields ( customFields , new Ticket . SetCustomFieldHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// Custom fields for the ticket are set.
// Some fields can be ignored if their keys aren't registered in the dashboard.
}
});
注意:只有在儀表板的“桌面” > “設定” > “工單欄位”中註冊的自訂欄位才能用作密鑰。
使用「SendBirdDesk」的setCustomerCustomFields()
方法讓您的客戶添加有關他們自己的附加資訊。
注意:只有在儀表板的「桌面」 > 「設定」 > 「客戶欄位」中註冊的自訂欄位才能用作金鑰。
Map < String , String > customFields = new HashMap <>();
customFields . put ( "gender" , "female" );
customFields . put ( "age" , String . valueOf ( 30 ));
SendBirdDesk . setCustomerCustomFields ( customFields , new SendBirdDesk . SetCustomerCustomFieldsHandler () {
@ Override
public void onResult ( SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// Custom fields for the customer are set.
// Some fields can be ignored if their keys aren't registered in the dashboard.
}
});
使用SendBirdDesk
的setCustomerCustomFields()
方法讓您的客戶添加有關他們自己的附加資訊。
注意:只有在儀表板的「設定」 > 「客戶欄位」中註冊的自訂欄位才能用作按鍵。
Map < String , String > customFields = new HashMap <>();
customFields . put ( "gender" , "female" );
customFields . put ( "age" , String . valueOf ( 30 ));
SendBirdDesk . setCustomerCustomFields ( customFields , new SendBirdDesk . SetCustomerCustomFieldsHandler () {
@ Override
public void onResult ( SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// Custom fields for the customer are set.
// Some fields can be ignored if their keys aren't registered in the dashboard.
}
});
相關頻道是指Sendbird Chat平台中與工單相關的群組頻道。建立票證時,將相關群組頻道的channel_url
作為參數傳遞給Ticket.create()
方法中的relatedChannelUrls
參數。若要更新相關頻道,請改用ticket.setRelatedChannelUrls()
。回呼中的ticket.relatedChannels
屬性表示相關頻道的群組頻道對象,它包含頻道名稱及其URL。
ticket . setRelatedChannelUrls ( RELATED_CHANNEL_URLS , new Ticket . SetRelatedChannelUrlsHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// The ticket.relatedChannels property has been updated.
}
});
注意:每張票最多可新增 3 個相關頻道。
透過 URL 預覽,您的應用程式使用者可以在對話期間打開連結之前滿足他們對將要獲得的內容的期望。
若要預覽 URL,應檢查每則簡訊是否包含 URL。當包含 URL 的文字訊息成功傳送後,應使用getUrlPreview()
方法提取 URL 並將其傳遞到 Sendbird 伺服器。將從伺服器接收的解析資料設定為JSON
對象,並將該物件字串化以將其作為參數傳遞給updateUserMessage()
方法中的參數。然後,帶有 URL 預覽的更新訊息會透過通道事件處理程序的onMessageUpdated()
方法傳遞到客戶端應用程式。
ticket . getChannel (). sendUserMessage ( TEXT , new UserMessageHandler () {
@ Override
public void onResult ( UserMessage userMessage , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
List < String > urls = extractUrlsFromMessage ( userMessage . getMessage ());
if ( urls . size () > 0 ) {
String strUrlPreview = toJsonString ( getOGTagsWithUrl ( urls . get ( 0 )));
UserMessageUpdateParams updateParams = new UserMessageUpdateParams ( TEXT );
updateParams . setData ( strUrlPreview );
updateParams . setCustomType ( "SENDBIRD_DESK_RICH_MESSAGE" );
ticket . getChannel (). updateUserMessage ( userMessage . getMessageId (), updateParams , new UserMessageHandler () {
@ Override
public void onResult ( UserMessage userMessage , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
}
});
}
}
});
注意:前往Github頁面並參考範例程式碼中的
updateUserMessageWithUrl()
和UrlPreviewAsyncTask
類別。您將了解如何實作上述範例程式碼中的方法,例如extractUrlsFromMessage()
、getOGTagsWithUrl()
和toJsonString()
,它們不是實際程式碼,但旨在幫助您了解要使用的整體流程網址預覽。
在通道事件處理程序的onMessageUpdated()
方法中,您可以在message.data
屬性中找到 URL 預覽的數據,如下所示。
{
"type" : " SENDBIRD_DESK_URL_PREVIEW " ,
"body" : {
"url" : " https://sendbird.com/ " ,
"site_name" : " Sendbird " ,
"title" : " Sendbird - A Complete Chat Platform, Messaging and Chat SDK and API " ,
"description" : " Sendbird's chat, voice and video APIs and SDKs connect users through immersive, modern communication solutions that drive better user experiences and engagement. " ,
"image" : " https://6cro14eml0v2yuvyx3v5j11j-wpengine.netdna-ssl.com/wp-content/uploads/sendbird_thumbnail.png "
}
}
管理訊息是系統發送的可自訂訊息,有 2 種類型的管理訊息。通知是發送並顯示給客戶和代理商的訊息,例如歡迎訊息或延遲訊息。系統訊息是當工單發生某些變更(例如工單狀態和受託人發生變更)時發送並在工單詳細資料檢視中顯示給客服人員的訊息。
注意:您可以在儀表板中的「桌面」 > “設定” > “觸發器”中自訂通知,並在“桌面” > “設定” > “系統訊息”中自訂系統訊息。
當客戶端應用程式透過通道事件處理程序的 'onMessageReceived()' 方法接收訊息時,系統訊息與通知訊息透過message.custom_type
的值進行區分,並且它們的子類型在message.data
中指定,如下所示。
{
"message_id" : 40620745 ,
"type" : " ADMM " ,
"custom_type" : " SENDBIRD_DESK_ADMIN_MESSAGE_CUSTOM_TYPE " ,
"data" : " { " type " : " SYSTEM_MESSAGE_TICKET_ASSIGNED_BY_SYSTEM " , " ticket " : <Ticket Object>} " ,
"message" : " The ticket is automatically assigned to Cindy. "
}
注意:只有當
data
具有SYSTEM_MESSAGE_TICKET_TRANSFERRED_BY_AGENT
時才會出現transfer
。
系統訊息僅供代理顯示。請參閱以下範例程式碼以避免向您的客戶顯示它們。
public static boolean isVisible ( BaseMessage message ) {
if ( message instanceof AdminMessage ) {
String data = message . getData ();
if (! TextUtils . isEmpty ( data )) {
String customType = message . getCustomType ();
boolean isSystemMessage = ADMIN_MESSAGE_CUSTOM_TYPE . equals ( customType );
JsonObject dataObj = new JsonParser (). parse ( data ). getAsJsonObject ();
String type = dataObj . get ( "type" ). getAsString ();
return ! isSystemMessage
&& ! EVENT_TYPE_ASSIGN . equals ( type )
&& ! EVENT_TYPE_TRANSFER . equals ( type )
&& ! EVENT_TYPE_CLOSE . equals ( type );
}
}
return true ;
}
雖然管理員有權直接關閉工單,但客服人員可以像管理員一樣關閉工單,也可以詢問客戶是否關閉工單,這取決於客服人員權限設定。確認請求訊息可以有以下3種狀態。
狀態 | 描述 |
---|---|
等待 | 當代理程式發送確認請求訊息時設定。 |
確認的 | 當客戶同意關閉工單時設定。 (預設值: true ) |
拒絕 | 當客戶拒絕關閉工單時設定。 (預設值: false ) |
當客戶回覆訊息時,透過呼叫Ticket.confirmEndOfChat()
方法,回應 true(同意)或 false(拒絕)將作為CONFIRMED
或DECLINED
傳送到 Sendbird 伺服器。
ticket . confirmEndOfChat ( USER_MESSAGE , true | false , new Ticket . ConfirmEndOfChatHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// You can update the UI of the message. For example, you can hide YES and No buttons.
}
});
{
"type" : " SENDBIRD_DESK_INQUIRE_TICKET_CLOSURE " ,
"body" : {
"state" : " CONFIRMED "
}
}
您可以在關閉票證後立即向客戶發送訊息,詢問他們對透過票證提供的支援是否滿意。當儀表板中的客戶滿意度評分功能開啟時,客戶將收到一則訊息,要求評分並留下評論作為回饋。該訊息可以有以下 2 種狀態。
狀態 | 描述 |
---|---|
等待 | 設定代理發送客戶回饋請求訊息的時間。 |
確認的 | 當客戶發送回應時設定。 |
當客戶回覆訊息時,他們對工單的分數和評論將透過呼叫ticket.submitFeedback()
方法發送到 Desk 伺服器。然後,確認要求訊息的狀態變成CONFIRMED
。
ticket . submitFeedback ( USER_MESSAGE , SCORE , COMMENT , net Ticket . SubmitFeedbackHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
}
});
Sendbird Desk 伺服器透過通道事件處理程序的onMessageUpdate()
方法向客戶的客戶端應用程式通知更新。
public void onMessageUpdated ( final BaseChannel channel , final BaseMessage message ) {
Ticket . getByChannelUrl ( channel . getUrl (), new Ticket . GetByChannelUrlHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) return ;
String data = message . getData ();
if (! TextUtils . isEmpty ( data )) {
JsonObject dataObj = new JsonParser (). parse ( data ). getAsJsonObject ();
String type = dataObj . get ( "type" ). getAsString ();
boolean isFeedbackMessage = "SENDBIRD_DESK_CUSTOMER_SATISFACTION" . equals ( type );
if ( isFeedbackMessage ) {
JsonObject feedback = dataObj . get ( "body" ). getAsJsonObject ();
String state = feedback . get ( "state" ). getAsString ();
switch ( state ) {
case "CONFIRMED" :
// TODO: Implement your code for the UI when there is a response from the customer.
break ;
case "WAITING" :
// TODO: Implement your code for the UI when there is no response from the customer.
break ;
}
}
}
}
});
}
注意:您可以在通道事件處理程序的
onMessageUpdate()
方法內的message.data
屬性中找到以下字串化JSON
物件。
{
"type" : " SENDBIRD_DESK_CUSTOMER_SATISFACTION " ,
"body" : {
"state" : " CONFIRMED " ,
"customerSatisfactionScore" : 3 ,
"customerSatisfactionComment" : " It was really helpful :) "
}
}
可以使用Ticket
中的reopen()
方法重新開啟已關閉的工單。
ticket . reopen ( new Ticket . ReopenHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
}
});
您可以使用Ticket.getOpenedList()
和Ticket.getClosedList()
檢索目前客戶的開啟和關閉工單清單。
您可以為客戶設計未處理票證和已關閉票證歷史記錄的收件匣活動。零是一個很好的起始值,那麼每次呼叫將按最後一條訊息創建時間降序排列最多返回 10 個票證。
注意:每個請求只能檢索 10 個票證,依訊息建立時間降序排列。
// getOpenedList()
Ticket . getOpenedList ( OFFSET , new Ticket . GetOpenedListHandler () {
@ Override
public void onResult ( List < Ticket > tickets , boolean hasNext , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// offset += tickets.size(); for the next tickets.
// TODO: Implement your code to display the ticket list.
}
});
// getClosedList()
Ticket . getClosedList ( OFFSET , new Ticket . GetClosedListHandler () {
@ Override
public void onResult ( List < Ticket > tickets , boolean hasNext , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// offset += tickets.size(); for the next tickets.
// TODO: Implement your code to display the ticket list.
}
});
對於設定了自訂欄位的工單,您可以為getOpenList()
和getClosedList()
新增篩選器,以按自訂欄位的鍵和值對工單進行排序。
Map < String , String > customFieldFilter = new HashMap <>();
customFieldFilter . put ( "subject" , "doggy_doggy" );
Ticket . getOpenedList ( OFFSET , customFieldFilter , new Ticket . GetOpenedListHandler () {
@ Override
public void onResult ( List < Ticket > tickets , boolean hasNext , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
List < Ticket > openedTicket = tickets ;
// offset += tickets.length; for the next tickets.
// TODO: Implement your code to display the ticket list.
}
});
您可以檢索特定票證及其頻道 URL。
Ticket . getByChannelUrl ( channel . getUrl (), new Ticket . GetByChannelUrlHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
}
});
您可以使用Ticket.getOpenCount()
在用戶端應用程式上顯示未處理票證的數量。
Ticket . getOpenCount ( new Ticket . GetOpenCountHandler () {
@ Override
public void onResult ( int count , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// TODO: Implement your code with the result value.
}
});
使用ticket.close()
方法允許客戶直接在其客戶端應用程式上關閉工單,以便客服人員可以快速切換到其他客戶查詢,而無需延遲或無需客戶確認。
ticket . close ( CLOSE_COMMENT , new Ticket . CloseHandler () {
@ Override
public void onResult ( Ticket ticket , SendbirdException e ) {
if ( e != null ) { // Error.
return ;
}
// TODO: Implement your code to close a ticket.
}
});
如果 API 請求失敗,處理程序中的SendbirdException
參數將包含有關錯誤的資訊。
財產 | 描述 |
---|---|
程式碼 | SendBirdError.ERR_REQUEST_FAILED (800220) |
訊息 | 帶有特定錯誤代碼的詳細錯誤訊息(如果存在)。 |