Este documento explica como começar a usar o SDK Headless Mobile para iOS.
O SDK Headless Mobile para iOS permite adicionar suporte da plataforma CCAI diretamente à sua experiência integrada do iOS sem usar uma interface pré-criada da plataforma CCAI.
Em vez de apresentar um widget com a marca da plataforma CCAI, você:
Integre o SDK do CCAI para iOS ao seu app.
Crie suas próprias telas, navegação e design visual.
Use o SDK para:
Iniciar e gerenciar sessões de chat e de voz.
Ofereça opções de e-mail, ligações programadas e redirecionamento.
Suporte a ações inteligentes, anexos e fluxos pós-sessão (CSAT, pesquisas, agente virtual).
A CCAI Platform processa a lógica da central de atendimento (roteamento, filas, canais, configuração, relatórios). Você é o proprietário da experiência completa do app (UI, fluxos e branding).
Se você preferir uma interface configurável pré-criada em vez de criar a sua própria, use o SDK para dispositivos móveis padrão.
Requisitos
Estes são os requisitos para integrar o SDK headless para dispositivos móveis para iOS.
Requisitos da plataforma iOS
Versão mínima do iOS: iOS 16.6 ou mais recente
Linguagem: Swift
IDE: versão estável mais recente do Xcode compatível com seu app
Arquiteturas: arquiteturas padrão do iOS compatíveis com sua cadeia de ferramentas atual do Xcode.
Permissões do app
Como o app integrado processa a UI das ações inteligentes (captura de fotos, gravação de vídeos ou verificação de identidade), você precisa declarar as permissões de privacidade obrigatórias da Apple.
Adicione as seguintes chaves ao Info.plist com uma descrição de como o app
usa os dados:
NSCameraUsageDescription: necessário para que os usuários tirem e enviem fotos/vídeos ou para ações inteligentes solicitadas pelo agente.NSMicrophoneUsageDescription: necessário para chamadas de voz instantâneas e para gravar vídeos com som.NSPhotoLibraryUsageDescription: necessário para que os usuários façam upload de fotos ou vídeos do rolo da câmera.NSFaceIDUsageDescription: obrigatório se você oferecer suporte a ações inteligentes de verificação biométrica.
Requisitos da instância da plataforma CCAI
Você precisa acessar as Configurações do desenvolvedor da instância da plataforma CCAI para obter os seguintes detalhes:
Chave da empresa
Código secreto da empresa
URL do host: o nome do host da plataforma CCAI (por exemplo,
your_subdomain.ccaiplatform.com)
Esses valores são usados para:
Chave da empresa + URL do host: no seu app iOS para inicializar o SDK.
Código secreto da empresa: no seu back-end para assinar JSON Web Tokens (JWT) usados para autenticar usuários.
Notificações push
Para fazer ligações e usar algumas ações inteligentes, você precisa do seguinte:
Configuração do serviço de notificação push da Apple (APNs) para notificações push padrão.
Um certificado de serviços de VoIP para oferecer suporte a chamadas recebidas e notificações específicas relacionadas a chamadas.
Você vai:
Configure as credenciais do APNs e do VoIP no portal do desenvolvedor da Apple.
Faça upload dos certificados convertidos no portal do administrador da plataforma CCAI em Configurações > Configurações do desenvolvedor > App móvel.
Registre seu app para receber notificações remotas e pushs de VoIP.
Encaminhe os tokens de dispositivo adequados para o SDK.
Em Target > Signing & capabilities, ative o seguinte:
Recurso de notificações push.
Recurso Modos em segundo plano com estes itens marcados:
Voz sobre IP: necessário para notificações push de VoIP (chamadas recebidas, ações inteligentes usando PSTN).
Áudio, AirPlay e picture-in-picture: necessários para que o áudio da ligação continue quando o app estiver em segundo plano.
Notificações remotas: necessárias para a entrega push padrão do APNs.
Como o SDK headless do iOS se encaixa no seu app
O SDK Headless Mobile para iOS pode ser visto como três camadas:
Plataforma e SDK da CCAI Platform
O SDK interage com segurança com a plataforma CCAI Platform e oferece:
Autenticação com JSON Web Tokens (JWT).
Metadados de roteamento de fila e canal (chat, voz, ligação programada, e-mail, links de redirecionamento externo).
Gerenciamento de estado de sessão em tempo real.
O pipeline de transporte seguro para ações inteligentes, anexos de arquivos e compartilhamento de tela.
Lógica de evasão e avaliação de hierarquia pós-sessão.
Seu app iOS (UI e a lógica são processadas por você)
Você controla toda a experiência visual e de navegação:
Pontos de entrada: por exemplo, uma guia Ajuda ou um botão Entre em contato.
Menus: como você mostra as filas (por exemplo, Faturamento, Suporte técnico).
Interface na sessão: balões de chat, telas de chamada e controles personalizados.
O que o app faz: chama APIs do SDK para iniciar e encerrar sessões, ouve eventos do SDK e direciona a navegação do controlador de visualização.
Configuração do portal do administrador da plataforma CCAI
Os administradores da Plataforma CCAI configuram as regras de engajamento (horário de funcionamento, canais disponíveis, limites de tempo de espera e pesquisas). O SDK lê essa configuração e a expõe ao app como dados e eventos brutos. Você decide como desenhar essa configuração na tela.
Recuperar credenciais da empresa
Antes de integrar o SDK, extraia as credenciais da sua instância da plataforma CCAI:
Faça login no portal de administradores da plataforma CCAI com uma conta de administrador.
Acesse Configurações > Configurações do desenvolvedor.
Em Chave da empresa e código secreto, copie:
Chave da empresa
Código secreto da empresa
Anote o URL do host:o nome do host da plataforma CCAI (por exemplo,
your_subdomain.ccaiplatform.com).
Você usará:
No seu app iOS: chave da empresa + URL do host.
No seu servidor de back-end: código secreto da empresa para assinar JWTs para:
Autenticação de usuário final.
Dados ou contexto personalizados opcionais usados pela plataforma CCAI.
Adicionar o SDK ao app iOS
O SDK Headless é criado usando uma arquitetura modular. Você instala o
CCAIKit principal junto com os módulos de recursos específicos que o app exige (por exemplo,
CCAIChat ou CCAIScreenShare).
Para integrar o SDK do iOS no seu app, siga a próxima sequência de etapas.
Opção A: Gerenciador de pacotes do Swift (recomendado)
Adicione a instrução a seguir ao seu arquivo
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") ] ) ]Importe
CCAIKitno arquivoAppDelegate:import CCAIKitSe o projeto for SwiftUI, declare
@UIApplicationDelegateAdaptorno structApp:@main struct YourAppName: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate // ... }
Inicializar o SDK sem interface gráfica
Inicialize o SDK durante a inicialização do app. Devido à arquitetura modular do SDK, é necessário inicializar primeiro o sistema principal da CCAI e depois registrar os módulos de serviço específicos (como chat ou compartilhamento de tela).
Inicialização básica
O SDK usa uma struct InitOptions que agrupa toda a configuração necessária:
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 ...
}
Referência de configuração do 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
}
Serviços de SDK disponíveis
Depois da inicialização, você pode acessar vários serviços pelo singleton 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
Buscar configuração da empresa
Após a inicialização, busque a configuração no nível da empresa usando
companyService. Isso é útil para preencher seletores de idioma, mostrar o nome da empresa ou ler os detalhes de contato do suporte antes que o usuário entre em uma fila.
do {
let company = try await CCAI.shared.companyService?.get()
print("Company: \(company?.displayName ?? "Unknown")")
} catch {
print("Failed to get company info: \(error)")
}
Autenticar usuários finais
O SDK Headless Mobile usa JSON Web Tokens (JWT) para autenticar usuários e transmitir informações contextuais com segurança para o CRM do agente.
Como funciona
O SDK usa um fluxo de autenticação assíncrona simplificado em duas etapas:
O SDK determina que precisa autenticar o usuário.
Ele chama o método
CCAIDelegate,ccaiShouldAuthenticate(), que é uma função assíncrona.Seu app assina um JWT remotamente no servidor de back-end usando o código secreto da empresa.
Em seguida, o app transmite o JWT assinado para
CCAI.shared.authService?.authenticate(jwt)e o troca por um token de autenticação.O token de autenticação é retornado ao SDK para concluir a conexão.
Implementar o CCAIDelegate para autenticação
O app precisa implementar o protocolo CCAIDelegate. O SDK chama o único método delegado
assíncrono quando precisa de autenticação.
Protocolo CCAIDelegate
public protocol CCAIDelegate: AnyObject {
/// Authenticates the end user and returns an auth token
func ccaiShouldAuthenticate() async -> String?
}
Exemplo de implementação (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)
}
}
Exemplo completo com assinatura JWT para referência e teste
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)
}
}
Transmitir dados personalizados ao CRM
Se você quiser transmitir dados contextuais ao agente (por exemplo, o SO do dispositivo atual do usuário, a localização ou o nível da conta), seu back-end precisará injetar um objeto custom_data no payload do JWT antes de assiná-lo.
Cada parte de dados personalizados precisa ser formatada como um objeto JSON que contenha um
label (o que o agente vê), um value e um type.
Tipos de dados compatíveis
string: texto padrão (por exemplo, "iPhone 14 Pro").number: números inteiros ou de ponto flutuante (por exemplo, 1234 ou 99,99).date: um carimbo de data/hora Unix UTC de 13 dígitos, incluindo milissegundos (por exemplo, 1537399655992).url: formato padrão de URL HTTP/HTTPS.boolean: valor padrão verdadeiro ou falso.
Chaves de CRM reservadas
A plataforma CCAI é compatível com chaves reservadas específicas que acionam comportamentos integrados na plataforma, como sinalizar um usuário como VIP ou avisar um agente sobre um usuário de má-fé. Eles precisam ser formatados como tipos booleanos e só serão aceitos se o payload for assinado usando o método JWT seguro.
reserved_verified_customer: indica se um cliente foi autenticado com sucesso pelos seus sistemas internos.reserved_bad_actor: sinaliza o usuário para o agente como um possível spammer ou conta fraudulenta.reserved_repeat_customer: indica se o cliente entrou em contato com o suporte com frequência recentemente.
Exemplo de payload com chaves reservadas
{
"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"
}
}
}
Gerenciar tokens de autenticação
O SDK também oferece métodos para atualizar ou limpar manualmente o token de autenticação em cache:
// 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)
Esquema de payload JWT de dados personalizados
Quando o back-end cria o payload final para ser assinado com o código secreto da empresa, ele precisa seguir estritamente este esquema. Observe os carimbos de data/hora obrigatórios iat (emitido em) e exp (validade).
{
"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"
}
}
}
Ativar notificações push
O SDK usa notificações push para:
Ligações recebidas.
Algumas ações inteligentes e eventos relacionados a chamadas.
Manter o estado quando o app está em segundo plano.
Configurar certificados
A plataforma CCAI exige que dois tipos diferentes de certificados push da Apple sejam salvos no portal do administrador da plataforma CCAI:
Um certificado SSL do serviço de notificação push da Apple (APNs), usado para notificações push remotas padrão.
Um certificado de serviços de VoIP, usado para notificações de chamadas recebidas e algumas ações inteligentes relacionadas a chamadas.
Os dois certificados são criados no portal Apple Developer, convertidos para o formato PEM e enviados ao portal do administrador da CCAI Platform.
Criar um certificado SSL do APNs
Siga estas etapas, com base no guia oficial da Apple Como estabelecer uma conexão baseada em certificado com APNs, para criar um certificado SSL do APNs.
Faça login em developer.apple.com e navegue até Certificates, Identifiers & Profiles.
Selecione o botão + para criar um certificado.
Em "Serviços", selecione SSL do serviço de notificação push da Apple (sandbox e Production).
Escolha o ID do app que corresponde ao identificador do pacote do aplicativo e selecione Continuar.
Faça upload de uma solicitação de assinatura de certificado (CSR) gerada pelo Acesso às Chaves no Mac:
Abra Acesso às Chaves > Assistente de Certificados > Solicitar um certificado de uma autoridade certificadora…
Digite seu endereço de e-mail, deixe o campo "Endereço de e-mail da CA" vazio, selecione Salvo em disco e clique em Continuar.
Selecione Continuar e Baixar o arquivo
.cergerado.Clique duas vezes no arquivo
.cerpara instalá-lo no Keychain.No Keychain Access, localize o certificado instalado, clique com o botão direito do mouse nele e selecione Exportar… para salvar como um arquivo
.p12. Você vai receber uma solicitação para definir uma senha de exportação.Converta o arquivo
.p12para o formato PEM usandoopenssl:# 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
Criar um certificado de serviços de VoIP
Os certificados de serviços VoIP permitem que seu app receba notificações push de alta prioridade pelo framework PushKit da Apple, que pode ativar o app de um estado encerrado para atender chamadas recebidas. Para conferir as etapas oficiais mais recentes, consulte Criar certificados de serviços VoIP na documentação para desenvolvedores da Apple.
Faça login em developer.apple.com e navegue até Certificates, Identifiers & Profiles.
Selecione o botão + para criar um certificado.
Em "Serviços", selecione Certificado de serviços de VoIP.
Escolha o ID do app que corresponde ao identificador do pacote do aplicativo e selecione Continuar.
Faça upload da mesma solicitação de assinatura de certificado (CSR) gerada para seu certificado SSL do APNs ou crie uma nova.
Selecione Continuar e Baixar o arquivo
.cergerado.Clique duas vezes no arquivo
.cerpara instalá-lo no Keychain.No Keychain Access, localize o certificado de serviços VoIP instalados, clique com o botão direito do mouse nele e selecione Exportar… para salvar como um arquivo
.p12.Converta o arquivo
.p12para o formato PEM usandoopenssl:# 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
Fazer upload de certificados para o portal do administrador da plataforma CCAI
Faça login no portal do administrador da Plataforma CCAI.
Acesse Configurações > Configurações do desenvolvedor > App móvel.
Faça upload do certificado PEM das APNs.
Faça upload do certificado PEM de VoIP.
Solicitar permissões de notificações push
O SDK oferece um método conveniente para solicitar autorização de notificação push (somente 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")
}
}
Registrar o app para receber notificações remotas
Implemente os delegados de notificação push no seu AppDelegate. O SDK
fornece pushNotificationService para encaminhar tokens:
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
)
}
}
Não se esqueça de ativar Capabilities > Push notifications e Background modes para notificações remotas na guia Target > Signing & capabilities no Xcode.
Gerenciar notificações push recebidas
Quando você receber um payload de push, encaminhe-o ao SDK para processamento:
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)
}
O SDK determina se o push está relacionado a uma chamada recebida, uma atualização de sessão ou outro evento interno e o processa de acordo.
Registrar para receber notificações push de VoIP
Para chamadas recebidas e determinadas ações inteligentes baseadas em PSTN, o SDK exige um token de push VoIP além do token APNs padrão. As notificações push de VoIP são entregues com alta prioridade e podem despertar o app de um estado encerrado.
Importe PushKit e crie um PKPushRegistry no didFinishLaunchingWithOptions do AppDelegate
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
}
}
Implemente os métodos PKPushRegistryDelegate para encaminhar tokens e payloads de VoIP ao 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() }
}