訪客SDK接入文件
在 App 內打開訪客聊天頁面。宿主傳入 HTTPS 地址後,SDK 使用系統 WebView / WKWebView 加載,並處理導航、權限、下載回傳與站點數據清理。
不使用 SDK、App 自建 WebView 打開訪客頁,見 訪客端 WebView 自行接入。
當前版本:0.0.1
| 平臺 | 要求 | 集成 |
|---|---|---|
| Android | minSdk 23 | Maven Central:io.github.twt-chat:visitor-sdk:0.0.1 |
| iOS | iOS 15+ | SPM:https://github.com/TWT-Chat/twt-visitor-ios.git(tag 0.0.1,產品 TwtVisitorSDK) |
| Flutter | Flutter ≥ 3.44,Dart ^3.12.2 | Git: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 即可。
快速開始
接入方只需搞清三件事:
url(必填):控制台設定的 URL 地址,必須 HTTPS。- 設定項:SDK 認識的欄位(
isApp/language/theme/title/directChatId/newMessageSoundMode)。都有預設值,可不傳。 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 |
isApp | false | true 時寫 is_app=1 | App 內打開,訪客頁顯示關閉按鈕。false 不寫 is_app=0 |
language | zh-cn | 每次都寫 lang | en / zh-cn / zh-tw / ja / ko / de / fr / pt / ru / es / vi / th / id / ms / tl |
theme | system | 每次都寫 theme | light / dark / system。執行時 setTheme 只接受 light / dark |
title | null | 否 | 原生標題欄文案;空則使用網頁標題 |
directChatId | null | 有值時寫 direct=1&chatid= | 直達會話,並去掉 chat_id |
newMessageSoundMode | web | 一般否 | 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
| 能力 | Android | iOS | Flutter |
|---|---|---|---|
| 打開獨立頁 | TwtVisitorSdk.start | TwtVisitorSDK.present | VisitorFlutter.present |
| 嵌入 | — | makeEmbeddedController + register | VisitorView |
| 切換主題 | handle.setTheme | handle.setTheme | VisitorFlutter.setTheme / handle.setTheme |
| 下載回傳 | handle.reportDownloadStatus | 同左 | VisitorFlutter.reportDownloadStatus |
| 關閉 | handle.close() | handle.close() | 獨立頁走系統返回;嵌入頁由宿主 pop |
| 清理站點數據 | TwtVisitorSdk.clearSiteData | TwtVisitorSDK.clearSiteData | VisitorFlutter.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:開始下載,完成後reportDownloadStatusonNewMessage:新訊息onBack():返回鍵。true表示宿主已處理onPermissionResult:權限結果
iOS VisitorBridgeDelegate(弱引用)
visitorDownloadRequested(...)visitorNewMessage()(可能重複)visitorBack() -> BoolvisitorPermissionResult(...)
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 都能使用。