本文說明如何開始使用 iOS 專用的無頭行動版 SDK。
透過 iOS 版無頭行動 SDK,您可以直接在內建的 iOS 體驗中加入 CCAI 平台支援,不必使用預先建構的 CCAI 平台 UI。
您不必顯示 CCAI 平台品牌的 Widget,而是:
將 CCAI iOS SDK 整合至應用程式。
自行建構畫面、導覽和視覺設計。
使用 SDK 執行下列操作:
開始及管理即時通訊和語音工作階段。
提供電子郵件、預約通話和轉移選項。
支援智慧動作、附件和會後流程 (客戶滿意度調查、問卷調查、虛擬服務專員)。
CCAI 平台會處理客服中心邏輯 (路徑、佇列、管道、設定、報表)。您擁有完整的應用程式體驗 (使用者介面、流程和品牌)。
如果您偏好使用預先建構的可設定 UI,而非自行建構,請使用標準行動 SDK。
需求條件
以下是整合 iOS 專用無頭行動 SDK 的必要條件。
iOS 平台需求條件
最低 iOS 版本:iOS 16.6 以上版本
語言:Swift
IDE:應用程式支援的最新穩定版 Xcode
架構:目前 Xcode 工具鍊支援的標準 iOS 架構。
應用程式權限
由於內建應用程式會處理智慧動作的 UI (拍攝相片、錄製影片或驗證身分),因此您必須聲明 Apple 的強制性隱私權。
在 Info.plist 中新增下列鍵,並說明應用程式如何使用資料:
NSCameraUsageDescription:使用者必須具備這項權限,才能拍攝及傳送相片/影片,或執行服務專員要求的智慧動作。NSMicrophoneUsageDescription:即時語音通話和錄製有聲影片時必須使用。NSPhotoLibraryUsageDescription:使用者必須取得這項權限,才能上傳現有的相片或影片。NSFaceIDUsageDescription:如果您支援生物辨識驗證智慧動作,則必須提供這項資訊。
CCAI 平台執行個體需求條件
您必須存取 CCAI 平台執行個體的「開發人員設定」,才能取得下列詳細資料:
公司金鑰
公司密碼
主機網址 - CCAI 平台的主機名稱 (例如
your_subdomain.ccaiplatform.com)
這些值可用於:
公司金鑰 + 主機網址:在 iOS 應用程式中初始化 SDK。
公司密碼:在後端簽署用於驗證使用者的 JSON Web Token (JWT)。
推播通知
如要撥打電話及使用特定智慧動作,您需要:
設定 Apple 推播通知服務 (APNs),以便傳送標準推播通知。
VoIP 服務憑證,可支援來電和特定通話相關通知。
您將學會以下內容:
在 Apple 開發人員入口網站中設定 APNs 和 VoIP 憑證。
在 CCAI Platform 管理員入口網站中,依序前往「設定」>「開發人員設定」>「行動應用程式」,上傳轉換後的憑證。
在應用程式中註冊遠端通知和 VoIP 推送通知。
將適當的裝置權杖轉送至 SDK。
在「目標」>「簽署和功能」中,啟用下列項目:
推播通知功能。
背景模式功能,並勾選下列項目:
網際網路通訊協定語音 - 這是 VoIP 推播通知 (來電、使用 PSTN 的智慧動作) 的必要項目。
音訊、AirPlay 和子母畫面 - 應用程式在背景執行時,必須使用這項功能才能繼續進行語音通話。
遠端通知 - 這是標準 APNs 推播傳送功能的必要條件。
無頭 iOS SDK 如何整合至應用程式
iOS 專用的無頭行動裝置 SDK 可視為三層:
CCAI 平台和 SDK
SDK 會與 CCAI Platform 平台安全地互動,並提供下列功能:
使用 JSON Web Token (JWT) 進行驗證。
佇列和管道路徑中繼資料 (即時通訊、語音、預約通話、電子郵件、外部轉移連結)。
即時管理工作階段狀態。
智慧動作、檔案附件和螢幕分享的安全傳輸管道。
轉移邏輯和工作階段後階層評估。
您的 iOS 應用程式 (UI 和邏輯由您處理)
你可以全面掌控視覺和導覽體驗:
進入點:例如「說明」分頁或「與我們聯絡」按鈕。
選單:顯示佇列的方式 (例如「帳單」、「技術支援」)。
通話期間的 UI:自訂即時通訊泡泡、通話畫面和控制項。
應用程式的用途:呼叫 SDK API 來啟動及結束工作階段、監聽 SDK 事件,以及驅動檢視畫面控制器導覽。
設定 CCAI 平台管理員入口網站
CCAI Platform 管理員會設定參與規則 (營業時間、可用管道、等待時間門檻和問卷調查)。SDK 會讀取這項設定,並以原始資料和事件的形式向應用程式公開。您決定如何在畫面上繪製該設定。
擷取公司憑證
整合 SDK 前,請先從 CCAI Platform 執行個體取得憑證:
使用管理員帳戶登入 CCAI Platform 管理員入口。
依序前往「設定」>「開發人員設定」。
在「公司金鑰和密碼」下方,複製:
公司金鑰
公司密碼
記下主機網址:CCAI 平台的主機名稱 (例如
your_subdomain.ccaiplatform.com)。
您將使用:
在 iOS 應用程式中:公司金鑰 + 主機網址。
在後端伺服器中:用於簽署 JWT 的公司密碼:
驗證使用者身分。
CCAI Platform 使用的選用自訂資料或內容。
在 iOS 應用程式中新增 SDK
無頭 SDK 採用模組化架構建構而成,您會與應用程式所需的特定功能模組 (例如 CCAIChat 或 CCAIScreenShare) 一併安裝核心 CCAIKit。
如要在應用程式中整合 iOS SDK,請按照下列步驟操作。
選項 A:Swift Package Manager (建議)
請將以下內容新增到您的
Package.swift檔案中:dependencies: [ .package(url: "https://github.com/UJET/ccai-ios-sdk.git", from: "3.3.1") ], targets: [ .target( name: "YourTargetName", dependencies: [ .product(name: "CCAIKit", package: "CCAIKit") ] ) ]在
AppDelegate檔案中匯入CCAIKit:import CCAIKit如果專案是 SwiftUI,請在
App結構體中宣告@UIApplicationDelegateAdaptor:@main struct YourAppName: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate // ... }
初始化無頭 SDK
在應用程式啟動期間初始化 SDK。由於 SDK 採用模組化架構,您必須先初始化核心 CCAI 系統,然後註冊特定服務模組 (例如即時通訊或螢幕分享)。
基本初始化
SDK 會使用 InitOptions 結構體,將所有必要設定綁在一起:
import CCAIKit
import CCAIChat // If using Chat
import CCAIScreenShare // If using Screen Share
class AppDelegate: NSObject, UIApplicationDelegate, CCAIDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// 1. Configure initialization options
let options = InitOptions(
key: "YOUR_COMPANY_KEY",
urlHost: "your_subdomain.ccaiplatform.com",
delegate: self,
languageCode: "en", // ISO 639 code (defaults to "en")
cacheAuthToken: true // Whether to cache the auth token (defaults to true)
)
// 2. Initialize the core SDK
do {
try CCAI.shared.initialize(options: options)
} catch {
print("Failed to initialize CCAI: \(error.localizedDescription)")
return true
}
// 3. Initialize feature modules
// Chat minimal (no options required)
CCAI.shared.initializeChat()
// Chat with optional configuration
// let chatOptions = ChatOptions(
// delegate: webFormDelegate, // Implement to intercept and render custom web forms within your own UI
// downloadTranscriptVisibility: .hideInPostChat, // Hide the post-chat download affordance
// greeting: "Hello! How can I help you?"
// )
// CCAI.shared.initializeChat(chatOptions)
// Screen Share (optional)
// let screenShareOptions = ScreenShareOptions(
// key: "YOUR_SCREEN_SHARE_KEY",
// domain: "your_domain.com"
// )
// CCAI.shared.initializeScreenShare(screenShareOptions)
return true
}
// ... CCAIDelegate methods (Authentication) go here ...
}
InitOptions 設定參考資料
public struct InitOptions {
/// The company key used for authentication
public let key: String
/// The host URL for CCAI platform (for example, "my-unique-instance.uc1.ccaiplatform.com")
public let urlHost: String
/// The preferred language code for localization (defaults to "en")
public var languageCode: String
/// The delegate that receives SDK events and callbacks
public weak var delegate: CCAIDelegate?
/// Whether to cache the authentication token (defaults to true)
public let cacheAuthToken: Bool
}
可用的 SDK 服務
初始化後,您就可以透過 CCAI.shared 單例存取各種服務:
let authService = CCAI.shared.authService
let companyService = CCAI.shared.companyService
let queueMenuService = CCAI.shared.queueMenuService
let optionsService = CCAI.shared.optionsService
let languageService = CCAI.shared.languageService
let pushNotificationService = CCAI.shared.pushNotificationService
let endUserService = CCAI.shared.endUserService
let chatService = CCAI.shared.chatService // Only available after initializeChat()
let screenShareService = CCAI.shared.screenShareService // Only available after initializeScreenShare()
let rateService = CCAI.shared.rateService // For CSAT ratings and survey submission
let smartActionService = CCAI.shared.smartActionService // Dedicated service for smart action lifecycle
擷取公司設定
初始化後,請使用 companyService 擷取公司層級的設定。這項功能有助於填入語言選擇器、顯示公司名稱,或在使用者進入佇列前讀取支援聯絡資訊。
do {
let company = try await CCAI.shared.companyService?.get()
print("Company: \(company?.displayName ?? "Unknown")")
} catch {
print("Failed to get company info: \(error)")
}
驗證使用者身分
Headless Mobile SDK 會使用 JSON Web Token (JWT) 驗證使用者,並安全地將情境資訊傳遞至服務專員的顧客關係管理系統。
運作方式
SDK 會使用簡化的兩步驟非同步驗證流程:
SDK 判斷需要驗證使用者。
它會呼叫您的
CCAIDelegate方法 (ccaiShouldAuthenticate()),這是非同步函式。應用程式會使用公司密碼,在後端伺服器上遠端簽署 JWT。
接著,應用程式會將簽署的 JWT 傳遞至
CCAI.shared.authService?.authenticate(jwt),以交換驗證權杖。系統會將驗證權杖傳回 SDK,完成連線。
實作 CCAIDelegate 進行驗證
應用程式必須實作 CCAIDelegate 協定。SDK 需要驗證時,會呼叫單一非同步委派方法。
CCAIDelegate 通訊協定
public protocol CCAIDelegate: AnyObject {
/// Authenticates the end user and returns an auth token
func ccaiShouldAuthenticate() async -> String?
}
導入範例 (Swift)
class AppDelegate: CCAIDelegate {
func ccaiShouldAuthenticate() async -> String? {
// 1. Sign JWT remotely on your backend server
guard let jwt = await signJWTRemotely() else { return nil }
// 2. Authenticate JWT using authService to get an auth token
return try? await CCAI.shared.authService?.authenticate(jwt)
}
}
完整範例,包含 JWT 簽署,可供參考和測試
class AuthController: CCAIDelegate {
func ccaiShouldAuthenticate() async -> String? {
var jwt = JWT(claims: claims)
// First, sign JWT with company secret (do this on your backend in production)
guard let secret = self.companySecret,
let key = secret.data(using: .utf8) else { return nil }
let signer = JWTSigner.hs384(key: key)
guard let encodedJWT = try? jwt.sign(using: signer) else { return nil }
// Then authenticate JWT using authService to get an auth token
return try? await CCAI.shared.authService?.authenticate(encodedJWT)
}
}
將自訂資料傳遞至 CRM
如要將情境資料傳遞給代理程式 (例如使用者的目前裝置 OS、位置或帳戶層級),後端必須先將 custom_data 物件插入 JWT 酬載,再進行簽署。
每筆自訂資料都必須格式化為 JSON 物件,內含 label (代理程式看到的內容)、value 和 type。
支援的資料類型
string:標準文字 (例如「iPhone 14 Pro」)。number:整數或浮點數 (例如 1234 或 99.99)。date:13 位數的 UTC Unix 時間戳記,包含毫秒 (例如 1537399655992)。url:標準 HTTP/HTTPS 網址格式。boolean:標準的 true 或 false 值。
保留的 CRM 金鑰
CCAI Platform 支援特定保留鍵,可觸發平台內建行為,例如將使用者標示為 VIP,或向服務專員發出惡意行為人警告。這些值必須格式化為布林類型,且只有在酬載是使用安全的 JWT 方法簽署時,系統才會接受。
reserved_verified_customer:指出客戶是否已通過內部系統驗證。reserved_bad_actor:向服務專員回報使用者可能是垃圾內容或詐欺帳戶。reserved_repeat_customer:指出這位顧客最近是否經常聯絡支援團隊。
含有保留鍵的酬載範例
{
"iat": 1537399656,
"exp": 1537400256,
"custom_data": {
"reserved_verified_customer": {
"label": "Verified Customer",
"value": true,
"type": "boolean"
},
"reserved_bad_actor": {
"label": "Bad Actor",
"value": false,
"type": "boolean"
},
"reserved_repeat_customer": {
"label": "Repeat Customer",
"value": false,
"type": "boolean"
}
}
}
管理驗證權杖
SDK 也提供手動更新或清除快取驗證權杖的方法:
// Set a new auth token
CCAI.shared.authService?.updateAuthToken("new_auth_token")
// Clear the current token (for example, on user logout)
CCAI.shared.authService?.updateAuthToken(nil)
自訂資料 JWT 酬載結構定義
後端建構最終簽署酬載時,必須嚴格遵守這個結構定義。請注意強制性 iat (發行時間) 和 exp (到期時間) 時間戳記。
{
"iat": 1537399656,
"exp": 1537400256,
"custom_data": {
"os_version": {
"label": "OS Version",
"value": "16.4",
"type": "string"
},
"membership_tier": {
"label": "Membership Tier",
"value": "Platinum",
"type": "string"
},
"ssn_last_four": {
"label": "SSN",
"value": "1234",
"type": "string",
"invisible_to_agent": true
},
"reserved_verified_customer": {
"label": "Verified Customer",
"value": true,
"type": "boolean"
}
}
}
啟用推播通知
SDK 會使用推播通知執行下列操作:
來電。
特定智慧操作和通話相關事件。
在應用程式於背景執行時維持狀態。
設定憑證
CCAI 平台需要兩種不同類型的 Apple 推送憑證,才能儲存在 CCAI 平台管理員入口網站:
Apple 推播通知服務 (APNs) SSL 憑證 - 用於標準遠端推播通知。
VoIP 服務憑證 - 用於來電通知和特定通話相關智慧動作。
這兩項憑證都是在 Apple 開發人員入口網站中建立,並轉換為 PEM 格式,然後上傳至 CCAI 平台管理員入口網站。
建立 APNs SSL 憑證
請按照 Apple 官方「建立與 APNs 的憑證型連線」指南中的後續步驟,建立 APNs SSL 憑證。
登入 developer.apple.com,然後前往「Certificates, Identifiers & Profiles」。
選取「+」按鈕,建立新憑證。
在「服務」下方,選取「Apple 推播通知服務 SSL (Sandbox 和 Production)」。
選擇與應用程式套件 ID 相符的應用程式 ID,然後選取「繼續」。
上傳從 Mac 上的「鑰匙圈存取」產生的憑證簽署要求 (CSR):
依序開啟「鑰匙圈存取」>「憑證輔助程式」>「向憑證授權單位要求憑證…」
輸入電子郵件地址,將 CA 電子郵件地址留空,選取「儲存到磁碟」,然後選取「繼續」。
選取「繼續」,然後「下載」生成的
.cer檔案。按兩下
.cer檔案,將其安裝到「鑰匙圈存取」。在「鑰匙圈存取」中找到已安裝的憑證,按一下滑鼠右鍵,然後選取「匯出…」,將憑證儲存為
.p12檔案。系統會提示你設定匯出密碼。使用
openssl將.p12檔案轉換為 PEM 格式:# Extract the certificate openssl pkcs12 -in apns_certificate.p12 -out apns_cert.pem -clcerts -nokeys # Extract the private key openssl pkcs12 -in apns_certificate.p12 -out apns_key.pem -nocerts -nodes # (Optional) Combine into a single PEM file cat apns_cert.pem apns_key.pem > apns_combined.pem
建立 VoIP 服務憑證
透過 VoIP 服務憑證,應用程式就能透過 Apple 的 PushKit 架構接收高優先順序推播通知,從而從終止狀態喚醒應用程式,處理來電。如需最新官方步驟,請參閱 Apple 開發人員說明文件中的「建立 VoIP 服務憑證」。
登入 developer.apple.com,然後前往「Certificates, Identifiers & Profiles」。
選取「+」按鈕,建立新憑證。
在「服務」下方,選取「VoIP 服務憑證」。
選擇與應用程式套件 ID 相符的應用程式 ID,然後選取「繼續」。
上傳您為 APNs SSL 憑證產生的憑證簽署要求 (CSR) (或建立新的 CSR)。
選取「繼續」,然後「下載」生成的
.cer檔案。按兩下
.cer檔案,將其安裝到「鑰匙圈存取」。在「鑰匙圈存取」中找出已安裝的 VoIP 服務憑證,按一下滑鼠右鍵,然後選取「匯出…」,將憑證儲存為
.p12檔案。使用
openssl將.p12檔案轉換為 PEM 格式:# Extract the certificate openssl pkcs12 -in voip_certificate.p12 -out voip_cert.pem -clcerts -nokeys # Extract the private key openssl pkcs12 -in voip_certificate.p12 -out voip_key.pem -nocerts -nodes # (Optional) Combine into a single PEM file cat voip_cert.pem voip_key.pem > voip_combined.pem
將憑證上傳至 CCAI 平台管理員入口網站
登入 CCAI Platform 管理員入口網站。
依序前往「設定」>「開發人員設定」>「行動應用程式」。
上傳 APNs PEM 憑證。
上傳 VoIP PEM 憑證。
要求推播通知權限
SDK 提供便利方法,可要求推送通知授權 (僅限 iOS):
let options: UNAuthorizationOptions = [.alert, .sound]
try await CCAI.shared.pushNotificationService?.registerForPushNotifications(
options: options
) { granted in
if granted {
print("Push notifications granted")
} else {
print("Push notifications denied")
}
}
註冊遠端通知
在 AppDelegate 中實作推播通知委派。SDK 提供 pushNotificationService,可轉送權杖:
import CCAIKit
class AppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
CCAI.shared.pushNotificationService?.updatePushToken(
data: deviceToken,
type: .apns
)
}
func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
CCAI.shared.pushNotificationService?.updatePushToken(
data: nil,
type: .apns
)
}
}
請務必在 Xcode 的「Target」>「Signing & capabilities」分頁中,啟用「Capabilities」>「Push notifications」和「Background modes」,以便接收遠端通知。
處理傳入的推播通知
收到推送有效負載時,請轉送至 SDK 進行處理:
func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
// Let the SDK determine if this push relates to an incoming call,
// session update, or another internal event
CCAI.shared.pushNotificationService?.handlePushNotification(userInfo)
completionHandler(.newData)
}
SDK 會判斷推送通知是否與來電、工作階段更新或其他內部事件相關,並據此處理。
註冊 VoIP 推播通知
對於來電和某些以 PSTN 為基礎的智慧動作,除了標準 APNs 權杖,SDK 也需要 VoIP 推送權杖。VoIP 推播通知的優先順序較高,可從終止狀態喚醒應用程式。
在 AppDelegate 的 didFinishLaunchingWithOptions 中匯入 PushKit 並建立 PKPushRegistry
import PushKit
class AppDelegate: NSObject, UIApplicationDelegate, PKPushRegistryDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// ... SDK initialization ...
// Register for VoIP push notifications
let voipRegistry = PKPushRegistry(queue: DispatchQueue.main)
voipRegistry.delegate = self
voipRegistry.desiredPushTypes = [.voIP]
return true
}
}
導入 PKPushRegistryDelegate 方法,將 VoIP 權杖和酬載轉送至 SDK
// MARK: - PKPushRegistryDelegate
func pushRegistry(
_ registry: PKPushRegistry,
didUpdate credentials: PKPushCredentials,
for type: PKPushType
) {
// Forward the VoIP token to the SDK
CCAI.shared.pushNotificationService?.updatePushToken(
data: credentials.token,
type: .voip
)
}
func pushRegistry(
_ registry: PKPushRegistry,
didInvalidatePushTokenFor type: PKPushType
) {
// Clear the VoIP token
CCAI.shared.pushNotificationService?.updatePushToken(
data: nil,
type: .voip
)
}
func pushRegistry(
_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping () -> Void
) {
guard type == .voIP else {
completion()
return
}
// Forward the VoIP payload to the SDK using the `handleVoIPPush`
// extension on `CCAI` (defined in the `CCAICall` module). The SDK
// takes ownership of the call lifecycle; invoke PushKit's completion
// handler in the trailing closure after the SDK has accepted the
// payload.
CCAI.shared.handleVoIPPush(payload: payload.dictionaryPayload) { completion() }
}