跳至主要内容

訪客SDK接入文件

在 App 內打開訪客聊天頁面。宿主傳入 HTTPS 地址後,SDK 使用系統 WebView / WKWebView 加載,並處理導航、權限、下載回傳與站點數據清理。

不使用 SDK、App 自建 WebView 打開訪客頁,見 訪客端 WebView 自行接入。

當前版本:0.0.1

平臺要求集成
AndroidminSdk 23Maven Central:io.github.twt-chat:visitor-sdk:0.0.1
iOSiOS 15+SPM:https://github.com/TWT-Chat/twt-visitor-ios.git(tag 0.0.1,產品 TwtVisitorSDK)
FlutterFlutter ≥ 3.44,Dart ^3.12.2Git:https://github.com/TWT-Chat/visitor_flutter.git(ref 0.0.1)

集成​

Android​

dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}

dependencies {
implementation("io.github.twt-chat:visitor-sdk:0.0.1")
}

SDK 已合併 INTERNET、RECORD_AUDIO、CAMERA(required=false)。Android 9 及以下若下載到公共 Downloads,請自行添加 WRITE_EXTERNAL_STORAGE。

iOS​

Xcode → File → Add Package Dependencies,填入:

https://github.com/TWT-Chat/twt-visitor-ios.git

Dependency Rule 選擇 Exact Version 0.0.1,產品勾選 TwtVisitorSDK。Deployment Target ≥ iOS 15。

在 Info.plist 中聲明:

<key>NSMicrophoneUsageDescription</key>
<string>用於發送語音訊息</string>
<key>NSCameraUsageDescription</key>
<string>用於拍攝並傳送照片或影片</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>用於儲存會話圖片</string>
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>

請保持 App Transport Security 預設設置。公開 API 須在主線程調用。

Flutter​

dependencies:
visitor_flutter:
git:
url: https://github.com/TWT-Chat/visitor_flutter.git
ref: 0.0.1
flutter pub get

Android 端需設定 mavenCentral()(見上方 Android 集成)。若使用 RepositoriesMode.PREFER_SETTINGS,還須保留 Flutter Engine 倉庫 https://storage.googleapis.com/download.flutter.io。iOS 端無需再添加 SPM,按 iOS 一節設定 Info.plist 即可。


快速開始​

接入方只需搞清三件事:

  1. url(必填):控制台設定的 URL 地址,必須 HTTPS。
  2. 設定項:SDK 認識的欄位(isApp / language / theme / title / directChatId / newMessageSoundMode)。都有預設值,可不傳。
  3. query:給訪客頁的業務參數。SDK 不解釋 key,只負責 UTF-8 編碼拼進 URL。匿名訪客可以不傳。

不要自己拼 ?a=1&b=2。不要把密碼、Cookie、AppSecret 或長期 token 放進 URL。

最少打開(只傳 url)時 SDK 拼出:

控制台設定的 URL 地址?lang=zh-cn&theme=system

lang=zh-cn、theme=system 由預設設定寫入。App 內若要顯示關閉按鈕,再設 isApp = true。

Android​

val handle = TwtVisitorSdk.start(
this,
VisitorConfig(url = "控制台設定的 URL 地址"),
)

start 打開 VisitorActivity 並返回 VisitorHandle。傳入非 Activity Context 時會自動加上 FLAG_ACTIVITY_NEW_TASK。下載、新訊息等回呼見「回呼與事件」。

iOS​

import TwtVisitorSDK

let config = VisitorConfiguration(
url: URL(string: "控制台設定的 URL 地址")!
)
let handle = try TwtVisitorSDK.present(from: self, configuration: config, delegate: self)

由宿主 dismiss 頁面;dismiss 之後 handle 失效。

Flutter​

嵌入當前頁面:

import 'package:visitor_flutter/visitor_flutter.dart';

final config = VisitorConfiguration(
url: '控制台設定的 URL 地址',
);

Expanded(child: VisitorView(configuration: config))

VisitorView 必須放在有確定尺寸的父佈局中(如 Expanded、SizedBox)。

打開獨立原生頁:

final handle = await VisitorFlutter.present(configuration: config);

獨立頁沒有 close,由系統返回或頁面內關閉按鈕結束。


設定項​

三端欄位相同。SDK 會把部分設定寫成 URL query,並覆蓋 query 裏的同名 key。

欄位預設進 URL?說明
url空(必填)基址控制台設定的 URL 地址,僅 HTTPS。HTTP、file、javascript、自定義 scheme、帶 user:pass 的地址會被拒絕
query空 Map原樣拼接業務參數,見下一節。不要手拼 ?a=1
isAppfalsetrue 時寫 is_app=1App 內打開,訪客頁顯示關閉按鈕。false 不寫 is_app=0
languagezh-cn每次都寫 langen / zh-cn / zh-tw / ja / ko / de / fr / pt / ru / es / vi / th / id / ms / tl
themesystem每次都寫 themelight / dark / system。執行時 setTheme 只接受 light / dark
titlenull否原生標題欄文案;空則使用網頁標題
directChatIdnull有值時寫 direct=1&chatid=直達會話,並去掉 chat_id
newMessageSoundModeweb一般否web:頁面播放;native:宿主在新訊息回呼中播放。走 JS 橋,不靠 URL(Flutter Android present() 會額外帶 new_message_sound_mode)

寫入順序:url 自帶 query → config.query → is_app / lang / theme / direct+chatid。後者覆蓋前者。

query 業務參數​

query 是透明 Map,SDK 只編碼拼接,不解釋 key。匿名訪客可以整份不傳。is_app / lang / theme / direct / chatid 用設定項,不要再寫進 query。

綁定業務使用者時:

query = mapOf(
"sbs" to "user-123",
"sbs_mm" to signature,
"ranstr" to randomStr,
"name" to "張三",
)
參數必填?含義
sbs綁使用者時必填業務系統中的使用者唯一 ID,訪客頁用它識別已登入客戶
sbs_mm有 sbs 就要sbs 的簽名
ranstr有簽名就要參與簽名的隨機串
name可選訪客姓名,進入客服工作臺展示
nickname可選訪客暱稱
email可選訪客郵箱
phone可選訪客手機號
customer_remark可選客戶備註,隨登入提交給客服側
ext_fk_id可選已有訪客 ID,用來續上該訪客的歷史會話
referer可選來源頁 URL(也認 referer_url),客服側顯示爲來源鏈接
source_title可選來源頁標題

不要傳 visitor_id、source=android / ios / flutter:訪客頁不讀。App 標識用設定項 isApp=true。


會話 API​

能力AndroidiOSFlutter
打開獨立頁TwtVisitorSdk.startTwtVisitorSDK.presentVisitorFlutter.present
嵌入—makeEmbeddedController + registerVisitorView
切換主題handle.setThemehandle.setThemeVisitorFlutter.setTheme / handle.setTheme
下載回傳handle.reportDownloadStatus同左VisitorFlutter.reportDownloadStatus
關閉handle.close()handle.close()獨立頁走系統返回;嵌入頁由宿主 pop
清理站點數據TwtVisitorSdk.clearSiteDataTwtVisitorSDK.clearSiteDataVisitorFlutter.clearSiteData

下載狀態:started / completed / failed / cancelled。requestId 必須與請求一致。可選欄位:path / progress / sourceUrl / mimeType / bytes / errorCode / message。iOS 相冊完成路徑爲 photos://localIdentifier。

清理結果:SUCCESS / INVALID_URL / UNSUPPORTED / IN_USE / FAILED(Flutter 爲小寫駝峯)。IN_USE 表示仍有會話佔用該 host。

切換帳號:關閉頁面 → 等待銷毀完成 → clearSiteData 成功 → 再打開下一個帳號。


回呼與事件​

回呼在主線程。請按 requestId / messageId 去重;頁面銷毀時把未完成的下載標爲 failed。

Android VisitorBridgeListener

  • onDownloadRequested:開始下載,完成後 reportDownloadStatus
  • onNewMessage:新訊息
  • onBack():返回鍵。true 表示宿主已處理
  • onPermissionResult:權限結果

iOS VisitorBridgeDelegate(弱引用)

  • visitorDownloadRequested(...)
  • visitorNewMessage()(可能重複)
  • visitorBack() -> Bool
  • visitorPermissionResult(...)

Flutter VisitorFlutter.events

無監聽時不緩存事件,進入頁面即 listen,離開時 cancel。

late final StreamSubscription<VisitorBridgeEvent> sub;

@override
void initState() {
super.initState();
sub = VisitorFlutter.events.listen((e) {
switch (e.type) {
case 'downloadRequested':
break;
case 'webReady':
case 'webLoadFailed':
case 'close':
case 'new_message':
break;
}
});
}

@override
void dispose() {
sub.cancel();
super.dispose();
}

事件名:downloadRequested、webReady、webLoadFailed、close、new_message、theme。

嵌入式頁面處理返回:

PopScope(
canPop: false,
onPopInvokedWithResult: (_, __) async {
if (!await VisitorFlutter.handleBack()) {
if (context.mounted) Navigator.of(context).pop();
}
},
child: VisitorView(configuration: config),
)

handleBack() == true 表示頁面已消費返回(例如從會話詳情回到列表)。首次加載失敗可調用 VisitorFlutter.reload()。


行爲說明​

導航 同域 HTTPS 留在容器內;跨域 HTTPS 使用系統瀏覽器;其他 scheme 攔截。

存儲 Cookie、LocalStorage、IndexedDB 預設持久化。第三方 Cookie 與混合內容關閉。

權限 僅同域 HTTPS 的麥克風 / 相機採集會進入系統授權,跨域一律拒絕。 例外:Flutter 在 Android 上的嵌入頁只允許麥克風,相機會被拒絕。需要拍攝時請使用獨立頁或原生 SDK。

檔案選擇 走系統 / WebKit 檔案選擇器,支援單選與多選。

下載 WebView 下載與頁面內下載都會回呼給宿主,由宿主執行後再回傳狀態。

返回 先交給頁面(約 300ms,用於關閉預覽等)。頁面不處理再詢問宿主;宿主也不處理才關閉容器。


常見問題​

爲什麼打開失敗? 檢查地址是否爲 HTTPS,以及 query 的 key 是否合法。iOS 還會校驗 directChatId。

爲什麼清不掉站點數據? 會話仍在會返回 IN_USE。先關閉全部相關頁面,等銷毀完成後再清理。iOS 按 host 匹配 WebKit 記錄,同一記錄下的兄弟子域可能一併清除,但不會做全局清空。

嵌入的 Flutter 頁面高度爲 0? 給 VisitorView 明確高度,例如包在 Expanded 裏。

如何直達某個會話? 設置 directChatId。

如何綁定已登入使用者? 在 query 裏傳 sbs、sbs_mm、ranstr。不要傳 visitor_id。

如何在 App 內顯示關閉按鈕? isApp = true。

主題如何跟隨系統? 初始使用 theme = system。執行中只能切到 light 或 dark。

弱網、後臺、鎖屏、WebSocket? 請在真機上驗證。SDK 不額外封裝網路層。

是否支援截圖橋、圖片剪貼簿? 不提供截圖橋。圖片剪貼簿不保證所有系統 WebView 都能使用。