このドキュメントでは、iOS 向け Headless Mobile SDK の使用を開始する方法について説明します。
iOS 向け Headless Mobile SDK を使用すると、事前構築済みの CCAI プラットフォーム UI を使用せずに、CCAI プラットフォームを搭載したサポートを独自の組み込み iOS エクスペリエンスに直接追加できます。
CCAI プラットフォームのブランドのウィジェットを表示する代わりに、次の操作を行います。
CCAI iOS SDK をアプリに統合します。
独自の画面、ナビゲーション、ビジュアル デザインを構築します。
SDK を使用して次の操作を行います。
チャット セッションと音声セッションを開始して管理します。
メール、予約済みの電話、回避オプションを提供します。
スマート アクション、添付ファイル、セッション後のフロー(CSAT、アンケート、仮想エージェント)をサポートします。
CCAI プラットフォームは、コンタクト センターのロジック(ルーティング、キュー、チャネル、構成、レポート)を処理します。アプリ エクスペリエンス全体(UI、フロー、ブランディング)を所有します。
独自の UI を構築するのではなく、事前構築済みの構成可能な UI を使用する場合は、標準モバイル SDK を使用します。
要件
iOS 向け Headless Mobile SDK を統合するための要件は次のとおりです。
iOS プラットフォームの要件
iOS の最小バージョン: iOS 16.6 以降
言語: Swift
IDE: アプリでサポートされている最新の安定版の Xcode バージョン
アーキテクチャ: 現在の Xcode ツールチェーンでサポートされている標準の iOS アーキテクチャ。
アプリの権限
スマート アクション(写真の撮影、動画の録画、身元確認)の UI は組み込みアプリが処理するため、Apple の必須プライバシー権限を宣言する必要があります。
アプリがデータをどのように使用するかを説明する次のキーを Info.plist に追加します。
NSCameraUsageDescription: ユーザーが写真や動画を撮影して送信する場合、またはエージェントがリクエストしたスマート アクションを実行する場合に必要です。NSMicrophoneUsageDescription: 音声通話の即時開始と音声付き動画の録画に必要です。NSPhotoLibraryUsageDescription: ユーザーがカメラロールから既存の写真や動画をアップロードするために必要です。NSFaceIDUsageDescription: 生体認証スマート アクションをサポートする場合は必須です。
CCAI プラットフォーム インスタンスの要件
次の詳細情報を取得するには、CCAI プラットフォーム インスタンスのデベロッパー設定にアクセスする必要があります。
会社キー
会社のシークレット コード
ホスト URL - CCAI プラットフォームのホスト名(例:
your_subdomain.ccaiplatform.com)
これらの値は次の目的で使用されます。
会社キー + ホスト URL: iOS アプリで SDK を初期化します。
会社の秘密コード: ユーザーの認証に使用される JSON Web Token(JWT)に署名するバックエンド。
プッシュ通知
通話と特定のスマート アクションには、次のものが必要です。
標準プッシュ通知用の Apple プッシュ通知サービス(APNs)の構成。
着信通話と特定の通話関連の通知をサポートする VoIP サービスの証明書。
次のことを行います。
Apple デベロッパー ポータルで APNs と VoIP の認証情報を構成します。
変換した証明書を CCAI Platform 管理者ポータルの [設定] > [デベロッパー設定] > [モバイルアプリ] にアップロードします。
アプリでリモート通知と VoIP プッシュを登録します。
適切なデバイス トークンを SDK に転送します。
[Target > Signing & capabilities] で、以下を有効にします。
プッシュ通知機能。
次の項目がオンになっているバックグラウンド モード機能:
Voice-over IP - VoIP プッシュ通知(着信、PSTN を使用するスマート アクション)に必要です。
音声、AirPlay、ピクチャー イン ピクチャー - アプリがバックグラウンドに移行したときに音声通話の音声が継続されるために必要です。
リモート通知 - 標準の APNs プッシュ配信に必要です。
ヘッドレス iOS SDK がアプリにどのように適合するか
iOS 向け Headless Mobile SDK は、3 つのレイヤで構成されていると考えることができます。
CCAI Platform プラットフォームと SDK
SDK は CCAI プラットフォームと安全にやり取りし、次の機能を提供します。
JSON Web Token(JWT)を使用した認証。
キューとチャネルのルーティング メタデータ(チャット、音声、予約通話、メール、外部回避リンク)。
リアルタイムのセッション状態管理。
スマート アクション、添付ファイル、画面共有の安全な転送パイプライン。
セッション後の階層評価と回避ロジック。
iOS アプリ(UI とロジックはユーザーが処理)
視覚的なエクスペリエンスとナビゲーション エクスペリエンス全体を制御できます。
エントリ ポイント: [ヘルプ] タブや [お問い合わせ] ボタンなど。
メニュー: キューの表示方法(例: Billing、Tech Support)。
セッション中の UI: カスタムのチャット バブル、通話画面、コントロール。
アプリの動作: SDK API を呼び出してセッションを開始および終了し、SDK イベントをリッスンして、ビュー コントローラのナビゲーションを制御します。
CCAI プラットフォーム管理者ポータルの構成
CCAI プラットフォーム管理者は、エンゲージメント ルール(営業時間、利用可能なチャネル、待ち時間しきい値、アンケート)を構成します。SDK はこの構成を読み取り、未加工のデータとイベントとしてアプリに公開します。画面にその構成を描画する方法を決定します。
会社の認証情報を取得する
SDK を統合する前に、CCAI Platform インスタンスから認証情報を取得します。
管理者アカウントで CCAI Platform 管理ポータルにログインします。
[設定] > [デベロッパー向けの設定] に移動します。
[Company key & secret code] で、次のものをコピーします。
会社キー
会社のシークレット コード
ホスト URL をメモします: CCAI プラットフォームのホスト名(例:
your_subdomain.ccaiplatform.com)。
使用するサービス:
iOS アプリの場合: 会社キー + ホスト URL。
バックエンド サーバー: JWT の署名に使用する会社の秘密コード:
エンドユーザー認証。
CCAI Platform で使用されるオプションのカスタムデータまたはコンテキスト。
iOS アプリに SDK を追加する
Headless SDK は、モジュール式アーキテクチャを使用して構築されています。コア CCAIKit は、アプリに必要な特定の機能モジュール(CCAIChat や CCAIScreenShare など)とともにインストールします。
アプリに 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)を使用してユーザーを認証し、コンテキスト情報をエージェントの CRM に安全に渡します。
仕組み
SDK は、簡素化された 2 段階の非同期認証フローを使用します。
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 ペイロードに挿入してから署名する必要があります。
カスタムデータはそれぞれ、label(エージェントが認識するもの)、value、type を含む JSON オブジェクトとしてフォーマットする必要があります。
サポートされるデータタイプ
string: 標準テキスト(「iPhone 14 Pro」など)。number: 整数または浮動小数点数(1234 や 99.99 など)。date: ミリ秒を含む 13 桁の UTC Unix タイムスタンプ(例: 1537399655992)。url: 標準の HTTP/HTTPS URL 形式。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 プラットフォームでは、CCAI プラットフォーム管理者ポータルに次の 2 種類の Apple プッシュ証明書を保存する必要があります。
Apple プッシュ通知サービス(APNs)の SSL 証明書 - 標準のリモート プッシュ通知に使用されます。
VoIP サービス証明書 - 着信通知や通話関連の特定のスマート アクションに使用されます。
両方の証明書は Apple Developer ポータルで作成され、PEM 形式に変換されてから、CCAI Platform 管理者ポータルにアップロードされます。
APNs SSL 証明書を作成する
Apple の公式ガイド APNs への証明書ベースの接続の確立に沿って、次の手順で APNs SSL 証明書を作成します。
developer.apple.com にログインし、[Certificates, Identifiers & Profiles] に移動します。
[+] ボタンを選択して、新しい証明書を作成します。
[サービス] で、[Apple Push Notification service SSL (Sandbox & Production)] を選択します。
アプリのバンドル ID と一致する App ID を選択し、[続行] を選択します。
Mac のキーチェーン アクセスで生成された証明書署名リクエスト(CSR)をアップロードします。
[キーチェーン アクセス] > [証明書アシスタント] > [認証局から証明書を要求…] を開きます。
メールアドレスを入力し、[CA Email Address] は空のままにして、[Saved to disk] を選択し、[Continue] を選択します。
[続行] を選択し、生成された
.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 Developer ドキュメントの Create VoIP services certificates をご覧ください。
developer.apple.com にログインし、[Certificates, Identifiers & Profiles] に移動します。
[+] ボタンを選択して、新しい証明書を作成します。
[サービス] で [VoIP サービス証明書] を選択します。
アプリのバンドル ID と一致する App 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 ベースのスマート アクションの場合、SDK では標準の APNs トークンに加えて VoIP プッシュ トークンが必要です。VoIP プッシュは優先度が高く、終了状態のアプリを起動できます。
PushKit をインポートし、AppDelegate の didFinishLaunchingWithOptions に 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() }
}