SDK seluler Contact Center AI Platform (CCAI Platform) untuk sistem operasi Apple iOS memberikan kemampuan untuk menyematkan pengalaman seluler CCAI Platform dalam aplikasi seluler iOS.
Persyaratan
SDK seluler iOS memiliki persyaratan berikut:
- iOS 12.0+
Mengambil kredensial perusahaan
Login ke portal Contact Center AI Platform (CCAI Platform) menggunakan kredensial Admin.
Buka Setelan > Setelan Developer.
Di bagian Company Key dan Secret Code, catat Company Key dan Company Secret Code.
Memulai
Berikut ini panduan tentang cara memulai SDK seluler iOS CCAI Platform.
Penginstalan
Untuk memulai, Anda harus menginstal iOS SDK.
Mendownload aplikasi contoh
Download Aplikasi Contoh iOS.
Buka folder dan instal dependensi menggunakan CocoaPods:
$ pod install --project-directory=ExampleAppUntuk mengonfigurasi setelan project dengan cepat, jalankan skrip shell:
$ ./setup.shAtau, Anda dapat mengedit setelan project secara manual dengan mengikuti langkah-langkah berikut:
Buka
ExampleApp.xcworkspace.Ganti nilai
UJETCompanyKeydanUJETCompanySecretdiInfo.plistdengan nilai Company Key dan Company Secret Code dari halaman Settings > Developer Settings di portal CCAI Platform.Ganti nilai
UJETSubdomaindiInfo.plistdengan subdomain di URL untuk portal CCAI Platform Anda. Subdomain langsung mendahului.ujet.comdi URL— misalnya,your-subdomaindihttps://your-subdomain.ujet.com/settings/developer-setting.
Mengintegrasikan ke project Anda
Integrasi iOS SDK dengan aplikasi Anda bergantung pada lingkungan pengembangan Anda.
Swift Package Manager
Tambahkan Paket Swift untuk iOS SDK dari GitHub.
Di setelan build, masukkan -ObjC di Other Linker Flags.
Mulai Xcode 13.2, ada masalah umum terkait penggunaan framework biner yang didistribusikan menggunakan Swift Package Manager. Solusi sementara untuk masalah ini adalah menambahkan Run Script Phase ke Build Phases project Xcode Anda. Run Script Phase ini harus muncul setelah fase build Embed Frameworks. Run Script Phase baru ini harus berisi kode berikut:
find "${CODESIGNING_FOLDER_PATH}" -name '*.framework' -print0 | while read -d $'0' framework do codesign --force --deep --sign "${EXPANDED_CODE_SIGN_IDENTITY}" --preserve-metadata=identifier,entitlements --timestamp=none "${framework}" done
CocoaPods
Tambahkan baris berikut ke Podfile:
pod 'UJET', :podspec => 'https://sdk.ujet.co/ios/x.y.z/ujet.podspec' #specific version x.y.zJalankan pod install. Jika iOS SDK telah diintegrasikan sebelumnya, jalankan pod update CCAI Platform.
Carthage
Google Cloud merekomendasikan penggunaan pengelola dependensi atau integrasi manual karena dependensi CCAI Platform tidak mendukung Carthage.
Untuk menggunakan pengelola dependensi yang berbeda, ikuti langkah-langkah berikut:
Tambahkan baris berikut:
binary "https://sdk.ujet.co/ios/UJETKit.json" binary "https://sdk.ujet.co/ios/UJETFoundationKit.json" binary "https://sdk.ujet.co/ios/UJETCallRedKit.json" binary "https://sdk.ujet.co/ios/UJETChatRedKit.json" # optional # binary "https://sdk.ujet.co/ios/UJETChatBlueKit.json" binary "https://raw.githubusercontent.com/twilio/twilio-voice-ios/Releases/twilio-voice-ios.json" # this is not supported: https://github.com/twilio/conversations-ios/issues/12 # binary "https://raw.githubusercontent.com/twilio/conversations-ios/master/twilio-convo-ios.json"Jalankan
carthage bootstrap --use-xcframeworks(ataucarthage update --use-xcframeworksjika Anda mengupdate dependensi).
Integrasi manual
Download
UJETKit.xcframework,UJETFoundationKit.xcframework,UJETChatRedKit.xcframework,UJETChatBlueKit.xcframework,UJETTwilioCallKit.xcframework, dan semua dependensiTwilioVoice.xcframeworkdanTwilioConversationsClient.xcframework.Tambahkan UJETKit.xcframework ke target Anda dengan menariknya ke bagian Frameworks, Libraries, and Embedded Content.
Ulangi Langkah 2 dan 3 pada semua dependensi dari Langkah 1.
Di Build Settings, tempatkan
-ObjCdiOther Linker Flags.Tambahkan
libc++.tbdsebagai dependensi di bagianLinked Frameworkstarget.
Jika Anda akan mem-build SDK secara manual dengan project contoh, gunakan langkah-langkah di bagian berikut.
Membangun SDK secara manual dengan project contoh
Ikuti langkah-langkah berikut secara berurutan:
Download semua framework termasuk
UJETKit.xcframeworkdan dependensi lainnya.Buat folder CCAI Platform di root project dan ekstrak semua framework.
Pilih target dan build
Objc-ManualatauSwift-Manual.
Framework impor
Bagian berikut memberikan petunjuk tentang cara mengimpor framework.
Project Objective-C
@import UJETKit;
Project Swift
swiftimport
UJETimport UJETKit
Melakukan inisialisasi SDK
Melakukan inisialisasi CCAI Platform dengan UJET_COMPANY_KEY dan UJET_SUBDOMAIN.
In application:didFinishLaunchingWithOptions: method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize CCAI Platform
[UJET.initialize:UJET_COMPANY_KEY subdomain:UJET_SUBDOMAIN delegate:self];
// YOUR CODE
return YES;
}
Anda dapat mengubah level log dari verbose menjadi error. Level log default adalah
UjetLogLevelInfo.
[UJET.setLogLevel:UjetLogLevelVerbose];
Autentikasi pengguna akhir
Akses iOS SDK melalui aplikasi iOS.
Untuk memastikan bahwa pengguna akhir diautentikasi, kami memperkenalkan mekanisme penandatanganan JWT.
SDK iOS akan meminta untuk menandatangani payload saat autentikasi diperlukan. Jika penandatanganan berhasil, aplikasi akan menukar JWT yang ditandatangani dengan token autentikasi pengguna akhir. Blok berhasil atau gagal harus dipanggil sebelum delegasi ditampilkan.
Untuk pengguna anonim (ID = nil), aplikasi akan membuat UUID untuk pengguna. Jika di lain waktu pengguna diautentikasi dengan ID, aplikasi akan mencoba menggabungkan kedua pengguna berdasarkan UUID.
Di UJETObject.h dari contoh project:
@import UJETKit;
@interface UJETObject : NSObject <UJETDelegate>
Terapkan metode delegasi signPayload: payloadType: success: failure:.
- (void)signPayload:(NSDictionary *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success failure:(void (^)(NSError *))failure {
if (payloadType == UjetPayloadAuthToken) {
[self signAuthTokenInLocal:payload success:success failure:failure];
}
}
- (void)signAuthTokenInLocal:(NSDictionary *)payload success:(void (^)(NSString *))success failure:(void (^)(NSError *))failure {
NSMutableDictionary *payloadData = [payload mutableCopy];
NSDictionary *userData = [[NSUserDefaults standardUserDefaults] objectForKey:@"user-data"];
[payloadData addEntriesFromDictionary:userData];
payloadData[@"iat"] = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]]; // required
payloadData[@"exp"] = [NSNumber numberWithDouble:([[NSDate date] timeIntervalSince1970] + 600)]; // required
NSString *signedToken = [self encodeJWT:payloadData];
if (signedToken.length > 0) {
success(signedToken);
} else {
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: @"Failed to sign token" };
NSError *error = [NSError errorWithDomain:@"ExampleApp" code:0 userInfo:userInfo];
failure(error);
}
}
- (NSString *)encodeJWT:(NSDictionary *)payload {
id<JWTAlgorithm> algorithm = [JWTAlgorithmHSBase algorithm384];
NSString *secret = NSBundle.mainBundle.infoDictionary[@"UJETCompanySecret"];
return [JWTBuilder encodePayload:payload].secret().algorithm(algorithm).encode;
}
Sebaiknya tanda tangani payload dari server aplikasi Anda, bukan di klien.
Contoh ini menggunakan penandatanganan lokal untuk tujuan pengujian. Lihat signDataInRemote:
success: failure: dalam file UJETObject.m.
Untuk mengetahui informasi selengkapnya, lihat Autentikasi pengguna akhir SDK.
Menyiapkan notifikasi push
CCAI Platform mengirimkan notifikasi push untuk meminta tindakan cerdas seperti verifikasi dan foto, serta melaporkan panggilan masuk. Jika antrean chat Anda menggunakan Check In (memerlukan iOS SDK 2.16.0 atau yang lebih baru), CCAI Platform akan mengirimkan notifikasi push yang meminta konsumen yang menunggu untuk kembali ke chat dan mengonfirmasi bahwa mereka sudah siap. Lihat Check In untuk Mobile SDK. CCAI Platform memerlukan dua jenis sertifikat yang berbeda (VoIP dan APN) untuk disimpan di Portal Admin CCAI Platform.
Mengonfigurasi sertifikat
CCAI Platform memerlukan dua jenis sertifikat push Apple yang berbeda untuk disimpan di Portal Admin CCAI Platform:
Sertifikat SSL Apple Push Notification service (APNs) — digunakan untuk notifikasi push jarak jauh standar.
Sertifikat layanan VoIP — digunakan untuk notifikasi panggilan masuk dan tindakan cerdas tertentu terkait panggilan.
Kedua sertifikat dibuat di portal developer Apple, dikonversi ke format PEM, lalu diupload ke Portal Admin CCAI Platform.
Membuat sertifikat SSL APNs
Ikuti langkah-langkah berikutnya berdasarkan panduan resmi Apple Establishing a Certificate-Based Connection to APNs untuk membuat sertifikat SSL APNs.
Login ke developer.apple.com dan buka Certificates, identifiers & profiles.
Klik tombol + untuk membuat sertifikat baru.
Di bagian Services, pilih Apple push notification service SSL (Sandbox & production).
Pilih ID Aplikasi yang cocok dengan ID paket aplikasi Anda, lalu klik Continue.
Upload permintaan penandatanganan sertifikat (CSR) yang dibuat dari akses keychain di Mac Anda:
Buka Keychain access > Certificate assistant > Request a certificate from a certificate authority.
Masukkan alamat email Anda, biarkan CA email address kosong, pilih Saved to disk, lalu klik Continue.
Klik Lanjutkan, lalu Download file
.ceryang dihasilkan.Klik dua kali file
.ceruntuk menginstalnya di keychain Anda.Di Keychain access, temukan sertifikat yang diinstal, klik kanan, dan pilih Export… untuk menyimpannya sebagai file
.p12. Anda akan diminta untuk menetapkan sandi ekspor.Konversikan file
.p12ke format PEM menggunakanopenssl:
# 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
Membuat sertifikat layanan VoIP
Sertifikat layanan VoIP memungkinkan aplikasi Anda menerima notifikasi push prioritas tinggi melalui framework PushKit Apple, yang dapat mengaktifkan aplikasi Anda dari status dihentikan untuk menangani panggilan masuk. Untuk mengetahui langkah-langkah resmi terbaru, lihat Membuat sertifikat layanan VoIP dalam dokumentasi Apple Developer.
Login ke developer.apple.com dan buka Certificates, Identifiers & Profiles.
Klik tombol + untuk membuat sertifikat baru.
Di bagian Services, pilih VoIP services certificate.
Pilih ID Aplikasi yang cocok dengan ID paket aplikasi Anda, lalu klik Continue.
Upload Permintaan Penandatanganan Sertifikat (CSR) yang sama dengan yang Anda buat di bagian sebelumnya (atau buat yang baru).
Klik Lanjutkan, lalu Download file
.ceryang dihasilkan.Klik dua kali file
.ceruntuk menginstalnya di Keychain Anda.Di Keychain access, temukan sertifikat VoIP Services yang diinstal, klik kanan, lalu pilih Export… untuk menyimpannya sebagai file
.p12.Konversikan file
.p12ke format PEM menggunakanopenssl:
# 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
Mengupload sertifikat ke Portal Admin CCAI Platform
Login ke Portal Admin CCAI Platform.
Buka Setelan > Setelan developer > Aplikasi seluler.
Upload sertifikat PEM APN.
Upload sertifikat PEM VoIP.
Aktifkan notifikasi push
Pilih target Anda dan buka tab Capabilities.
Aktifkan tombol Notifikasi push.
Menguji notifikasi push
Bagian berikut memberikan panduan tentang cara menguji notifikasi push.
Bagian debug notifikasi push
Di portal administrator, buka Settings > Developer Settings. Di halaman ini, temukan bagian berjudul Debug notifikasi push:

Salin dan tempel token perangkat di area teks yang tepat, lalu pilih Aplikasi Seluler yang tepat.
Mendapatkan token perangkat
Contoh string token perangkat terlihat seperti ini:
7db0bc0044c8a203ed87cdab86a597a2c43bf16d82dae70e8d560e88253364b7
Notifikasi push biasanya ditetapkan di class yang sesuai dengan protokol UIApplicationDelegate atau PKPushRegistryDelegate. Pada titik tertentu, token perangkat akan tersedia untuk Anda. Anda dapat mencetaknya sebelum meneruskannya ke iOS SDK. Untuk mendapatkan token perangkat, gunakan cuplikan kode.
Swift
func tokenFromData(data: Data) -> String {
return data.map { String(format: "%02x", $0) }.joined()
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("apns token: ", tokenFromData(data: deviceToken))
...
}
func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
print("voip token: ", tokenFromData(data: credentials.token))
...
}
Obj-C
- (NSString *)tokenFromData:(NSData *)data {
const char *d = data.bytes;
NSMutableString *token = [NSMutableString string];
for (NSUInteger i = 0; i < data.length; i++) {
[token appendFormat:@"%02.2hhX", d[i]];
}
return [[token copy] lowercaseString];
}
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(PKPushType)type {
NSLog(@"voip token: %@", [self tokenFromData:credentials.token]);
...
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"apns token: %@", [self tokenFromData:deviceToken]);
}
Hasil
Setelah Anda memasukkan file PEM sertifikat dan token perangkat, klik tombol.
Hasilnya akan menampilkan pesan Notifikasi push berhasil dikonfigurasi jika notifikasi push pengujian berhasil dikirim.
Notifikasi push tidak dijamin akan terkirim, bergantung pada koneksi jaringan perangkat.
Konfigurasi project
Bagian berikut menguraikan perubahan yang diperlukan untuk mengonfigurasi project.
Kemampuan
Di setelan target, aktifkan kemampuan berikut:
Notifikasi Push
Background Modes (centang item ini)
Audio dan AirPlay
Voice over IP
Info.plist
Untuk melindungi privasi pengguna, setiap aplikasi iOS yang ditautkan pada atau setelah iOS 10.0 yang mengakses mikrofon, galeri foto, dan kamera perangkat, harus menyatakan niat untuk melakukannya. Sertakan kunci berikut dengan nilai string dalam file Info.plist aplikasi Anda dan berikan string tujuan untuk kunci ini. Jika aplikasi Anda mencoba mengakses mikrofon, galeri foto, dan kamera perangkat tanpa string tujuan yang sesuai, aplikasi akan keluar.
NSMicrophoneUsageDescription: Mengizinkan akses ke mikrofon untuk menelepon dan berbicara dengan tim dukungan atau pemecahan masalah, serta untuk mengirim video dengan suara terkait pertanyaan produk.
NSCameraUsageDescription: Mengizinkan akses ke kamera agar pelanggan dapat mengambil dan mengirim foto terkait pertanyaan dukungan pelanggan mereka.
NSPhotoLibraryUsageDescription: Mengizinkan akses bagi pelanggan untuk mengirim foto yang terkait dengan pertanyaan dukungan pelanggan mereka.
NSFaceIDUsageDescription: Mengizinkan akses ke verifikasi menggunakan Face ID.
Memulai iOS SDK
Tambahkan baris berikut di tempat Anda ingin memulai iOS SDK:
[UJET startWithOptions:nil];
Anda juga dapat memulai iOS SDK dari titik tertentu di menu dengan kunci ini menggunakan Titik Akses Langsung:
UJETStartOptions *option = [[UJETStartOptions alloc] initWithMenuKey:@"MENU_KEY"];
[UJET startWithOptions:option];
menuKey dapat dibuat dengan membuat Titik Akses Langsung (DAP). Langkah-langkah berikut memberikan petunjuk tentang cara membuat DAP:
Login ke portal CCAI Platform dengan kredensial administrator.
Buka Setelan > Antrean.
Pilih antrean dari struktur menu.
Pilih Buat titik akses langsung
Masukkan kunci di formulir teks.
Klik Simpan.
Menghapus cache dari lokal jika data pengguna telah diperbarui
Kami meng-cache token autentikasi di Keychain untuk digunakan kembali dan mengurangi frekuensi permintaan untuk menandatangani payload dari aplikasi host. SDK akan menggunakannya hingga masa berlakunya habis atau dicabut melalui panggilan clearUserData. Aplikasi host bertanggung jawab untuk mencabut cache ini setiap kali data terkait pengguna berubah atau diperbarui, seperti peristiwa logout.
[UJET clearUserData];
Memeriksa sesi yang ada sebelum memulai Contact Center AI Platform
Sebelum memulai sesi, periksa apakah tidak ada sesi yang sedang berlangsung. Hal ini sangat penting saat userId telah berubah.
[UJET getStatus];
Jika ada sesi yang sudah ada, kita harus meminta pengguna untuk melanjutkan sesi atau membatalkan tindakan:
if ([UJET getStatus] != UjetStatusNone) {
// Display alert to cancel login or resume existing session
}
Sesuaikan
Ada beberapa opsi untuk tema SDK yang tercantum di UJETGlobalTheme.h.
Tetapkan tema Anda setelah [UJET initialize]—misalnya:
UJETGlobalTheme *theme = [UJETGlobalTheme new];
theme.font = [UIFont fontWithName:@"OpenSans" size: 16.0f];
theme.lightFont = [UIFont fontWithName:@"OpenSans-Light" size: 16.0f];
theme.boldFont = [UIFont fontWithName:@"OpenSans-Bold" size: 16.0f];
theme.tintColor = [UIColor colorWithRed:0.243 green:0.663 blue:0.965 alpha:1.00];
[Ujet setGlobalTheme:theme];
Nama perusahaan diambil dari Portal Admin > Setelan > Detail Pusat Dukungan > Nama Tampilan.
Anda dapat menetapkan gambar logo, bukan nama perusahaan, seperti ini:
theme.companyImage = [UIImage imageNamed:@"logo"];
Gambar akan diubah ukurannya agar pas dengan area jika terlalu besar.
String
Anda juga dapat menyesuaikan string dengan mengganti nilainya. Misalnya, tempatkan kunci - nilai ini di Localizable.strings Anda:
"ujet_greeting_title" = "Title";
"ujet_greeting_description" = "Description";
String yang dapat disesuaikan tersedia dalam file ujet.strings.
Mode gelap
Anda dapat menentukan tint warna yang diinginkan untuk mode gelap agar font lebih mudah dibaca.
@property (nonatomic, strong) UIColor \*tintColorForDarkMode;
Jika Anda tidak menetapkan properti, UJETGlobalTheme.tintColor akan digunakan untuk mode
gelap. Sebaiknya tetapkan properti ini jika aplikasi Anda mendukung mode gelap. Lihat
artikel Apple berikut tentang cara memilih warna tint yang tepat untuk mode
gelap:
Tema chat
Untuk menyesuaikan layar chat, Anda memiliki opsi untuk menggunakan string JSON atau setiap class tema.
Sebagai referensi, lihat aplikasi contoh dan hapus tanda komentar pada metode customizeChatTheme.
func customizeChatTheme() throws {
guard let file = Bundle.main.path(forResource: "chat-theme-custom", ofType: "json") else { return }
let json = try String.init(contentsOfFile: file, encoding: .utf8)
let chatTheme = UJETChatTheme.init(jsonString: json)
let quickReplyTheme = UJETChatQuickReplyButtonTheme()
quickReplyTheme.style = .individual
quickReplyTheme.alignment = .right
quickReplyTheme.backgroundColor = UJETColorRef(assetName: "white_color")
quickReplyTheme.backgroundColorForHighlightedState = UJETColorRef(assetName: "quick_reply_color")
quickReplyTheme.textColor = UJETColorRef(assetName: "quick_reply_color")
quickReplyTheme.textColorForHighlightedState = UJETColorRef(assetName: "white_color")
let fontTheme = UJETFontTheme()
fontTheme.family = "Arial Rounded MT Bold"
fontTheme.size = 14
quickReplyTheme.font = fontTheme
chatTheme?.quickReplyButtonTheme = quickReplyTheme
let globalTheme = UJETGlobalTheme()
globalTheme.chatTheme = chatTheme
globalTheme.defaultAgentImage = UIImage(named: "agent_avatar_image")
globalTheme.font = UIFont(name: "Arial Rounded MT Bold", size: 14)
UJET.setGlobalTheme(globalTheme)
}
Tema kartu konten
Anda dapat menambahkan penyesuaian untuk kartu konten bersama dengan penyesuaian chat.
Anda dapat melakukannya menggunakan file json (lihat properti content_card) atau menggunakan class UJETChatContentCardTheme.
func customizeChatTheme() throws {
guard let file = Bundle.main.path(forResource: "chat-theme-custom", ofType: "json") else { return }
let json = try String.init(contentsOfFile: file, encoding: .utf8)
let chatTheme = UJETChatTheme.init(jsonString: json)
let contentCardTheme = UJETChatContentCardTheme()
contentCardTheme.backgroundColor = UJETColorRef(assetName: "agent_message_background_color")
contentCardTheme.cornerRadius = 16
let contentCardFontTheme = UJETFontTheme()
contentCardFontTheme.family = "Arial Rounded MT Bold"
contentCardFontTheme.size = 18
contentCardTheme.font = contentCardFontTheme
let contentCardBorder = UJETBorderTheme()
contentCardBorder.width = 1
contentCardBorder.color = UJETColorRef(assetName: "agent_message_border_color")
contentCardTheme.border = contentCardBorder
let contentCardFontTheme = UJETFontTheme()
contentCardFontTheme.family = "Arial Rounded MT Bold"
contentCardFontTheme.size = 18
contentCardTheme.font = contentCardFontTheme
// The font family is inherited from the contentCardFontTheme
let subtitle = UJETFontTheme()
subtitle.size = 12
contentCardTheme.subtitle = subtitle
// The font family is inherited from the contentCardFontTheme
let bodyFont = UJETFontTheme()
bodyFont.size = 10
contentCardTheme.body = bodyFont
theme.chatTheme?.contentCard = contentCardTheme
let globalTheme = UJETGlobalTheme()
globalTheme.chatTheme = chatTheme
globalTheme.defaultAgentImage = UIImage(named: "agent_avatar_image")
globalTheme.font = UIFont(name: "Arial Rounded MT Bold", size: 14)
UJET.setGlobalTheme(globalTheme)
}
Tema kartu formulir
Anda dapat menambahkan penyesuaian untuk kartu formulir bersama dengan penyesuaian chat. Lakukan
hal ini dengan menggunakan file json (lihat form_card property) atau dengan menggunakan
class UJETChatFormCardTheme.
func customizeChatTheme() throws {
guard let file = Bundle.main.path(forResource: "chat-theme-custom", ofType: "json") else { return }
let json = try String.init(contentsOfFile: file, encoding: .utf8)
let chatTheme = UJETChatTheme.init(jsonString: json)
let formCardTheme = UJETChatFormCardTheme()
formCardTheme.backgroundColor = UJETColorRef(assetName: "agent_message_background_color")
formCardTheme.cornerRadius = 16
let formCardFontTheme = UJETFontTheme()
formCardFontTheme.family = "Arial Rounded MT Bold"
formCardFontTheme.size = 18
formCardTheme.font = formCardFontTheme
let formCardBorder = UJETBorderTheme()
formCardBorder.width = 1
formCardBorder.color = UJETColorRef(assetName: "agent_message_border_color")
formCardTheme.border = formCardBorder
let titleFontTheme = UJETFontTheme()
titleFontTheme.family = "Arial Rounded MT Bold"
titleFontTheme.size = 18
formCardTheme.title = titleFontTheme
// The font family is inherited from the formCardFontTheme
let subtitleFontTheme = UJETFontTheme()
subtitleFontTheme.size = 12
formCardTheme.subtitle = subtitleFontTheme
chatTheme?.formCard = formCardTheme
let globalTheme = UJETGlobalTheme()
globalTheme.chatTheme = chatTheme
globalTheme.defaultAgentImage = UIImage(named: "agent_avatar_image")
globalTheme.font = UIFont(name: "Arial Rounded MT Bold", size: 14)
UJET.setGlobalTheme(globalTheme)
}
Konfigurasi formulir web
Untuk mengonfigurasi kemampuan formulir web, terapkan metode ujetWebFormDidReceive
dari protokol UJETDelegate. Metode ini menerima peristiwa (kamus FormMessageReceivedEvent) sebagai parameter, yang berisi informasi terkait formulir. Kamus peristiwa (FormMessageReceivedEvent) menyertakan struktur JSON berikut:
{
"type": "form_message_received",
"smart_action_id": 1,
"external_form_id": "external_foobar"
"signature": "4868a7e1dcb5..."
}
Untuk menangani peristiwa, lakukan hal berikut:
Ekstrak informasi yang relevan dari kamus peristiwa (
smart_action_id,external_form_id, dansignature).Buat URI formulir dan tanda tangan untuk data formulir.
Teruskan data formulir ke SDK sebagai kamus
FormDataEventmenggunakancompletion closure.Jika terjadi error selama pembuatan URI/tanda tangan, panggil callback menggunakan
callback.onError()denganError.
Kamus (FormDataEvent) yang diteruskan ke SDK harus memiliki struktur berikut:
{
"type": "form_data",
"signature": "4868a7e1dcb5...",
"data": {
"smart_action_id":1,
"external_form_id": "form_id",
"uri":"foobar"
}
}
Tanda tangan (HMAC-SHA:256) harus dibuat menggunakan data, yang ditandatangani dengan
kunci rahasia bersama. Kunci objek data harus diurutkan menurut abjad sebelum
membuat tanda tangan dan data yang sama harus dikirim ke SDK.
Transfer setelah sesi
Anda dapat menambahkan penyesuaian untuk VA pasca-sesi bersama dengan penyesuaian chat.
Hal ini dapat dilakukan menggunakan file JSON (lihat properti post_session) atau menggunakan class UJETChatPostSessionVaTheme. Lebar batas hanya boleh 0 atau 1 dan jika Anda tidak ingin membedakan pengalaman agen virtual pasca-sesi, Anda dapat menetapkan containerColor putih dan batas ke 0.
func customizeChatTheme() throws {
guard let file = Bundle.main.path(forResource: "chat-theme-custom", ofType: "json") else { return }
let json = try String.init(contentsOfFile: file, encoding: .utf8)
let chatTheme = UJETChatTheme.init(jsonString: json)
let postSessionVaTheme = UJETChatPostSessionVaTheme()
postSessionVaTheme.containerColor = UJETColorRef(assetName: "white_color")
let postSessionVaBorder = UJETBorderTheme()
postSessionVaBorder.width = 0
postSessionVaBorder.color = UJETColorRef(assetName: "white_color")
containerColor.border = postSessionVaBorder
chatTheme?.postSessionVaTheme = postSessionVaTheme
let globalTheme = UJETGlobalTheme()
globalTheme.chatTheme = chatTheme
UJET.setGlobalTheme(globalTheme)
}
Menu tindakan chat
Anda dapat menambahkan penyesuaian untuk menu tindakan chat bersama dengan penyesuaian chat. Hal ini dapat dilakukan dengan menggunakan file JSON (lihat properti form_card) atau dengan menggunakan class UJETChatActionMenuTheme.
func customizeChatTheme() throws {
guard let file = Bundle.main.path(forResource: "chat-theme-custom", ofType: "json") else { return }
let json = try String.init(contentsOfFile: file, encoding: .utf8)
let chatTheme = UJETChatTheme.init(jsonString: json)
let actionMenuTheme = UJETChatActionMenuTheme()
let photoLibraryIcon = UJETChatUserInputIconTheme()
photoLibraryIcon.visible = true
photoLibraryIcon.image = UJETImageRef(assetName: "library_button_asset")
let cameraIcon = UJETChatUserInputIconTheme()
cameraIcon.visible = true
cameraIcon.image = UJETImageRef(assetName: "camera_button_asset")
let cobrowseIcon = UJETChatUserInputIconTheme()
cobrowseIcon.visible = true
cobrowseIcon.image = UJETImageRef(assetName: "cobrowse_button_asset")
actionMenuTheme.libraryIcon = photoLibraryIcon
actionMenuTheme.cameraIcon = cameraIcon
actionMenuTheme.cobrowseIcon = cobrowseIcon
chatTheme?.actionMenu = actionMenuTheme
let globalTheme = UJETGlobalTheme()
globalTheme.chatTheme = chatTheme
UJET.setGlobalTheme(globalTheme)
}
Penampilan lainnya
Anda dapat menyesuaikan tampilan lainnya seperti ukuran font dan warna latar belakang.
theme.supportTitleLabelFontSize = 30;
theme.supportDescriptionLabelFontSize = 20;
theme.supportPickerViewFontSize = 30;
theme.staticFontSizeInSupportPickerView = YES;
theme.backgroundColor = UIColor.darkGrayColor;
theme.backgroundColorForDarkMode = UIColor.lightGrayColor;
CallKit
Di iOS 10.0 dan yang lebih baru, CallKit diaktifkan untuk semua panggilan.
Dengan CallKit, panggilan dalam aplikasi akan ditampilkan dengan layar panggilan dan menampilkan panggilan di histori panggilan telepon.
Untuk memulai sesi dukungan CCAI Platform baru dari histori panggilan, tambahkan blok berikut ke AppDelegate.m Anda:
AppDelegate.m:
- (BOOL)application:(UIApplication *)app continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * _Nullable))restorationHandler {
if ([userActivity.activityType isEqualToString:@"INStartAudioCallIntent"]) {
// Open app from Call history
[UJET startWithOptions:nil];
}
return YES;
}
CallKit memungkinkan ikon 40x40 ditampilkan di layar kunci saat menerima panggilan saat perangkat terkunci. Tempatkan gambar di Xcassets Anda dengan nama 'icon-call-kit'.
Mengonfigurasi SDK
Anda dapat menetapkan beberapa opsi sebelum memulai SDK.
Lihat class UJETGlobalOptions untuk mengetahui detailnya.
UJETGlobalOptions *options = [UJETGlobalOptions new];
options.fallbackPhoneNumber = @"+18001112222";
options.preferredLanguage = @"en";
[UJET setGlobalOptions:options];
Menampilkan atau menyembunyikan tombol download transkrip
Anda dapat mengonfigurasi SDK untuk menampilkan atau menyembunyikan tombol download transkrip di menu opsi chat dan di layar pasca-chat.
Kode berikut menunjukkan cara mengonfigurasi tombol download transkrip:
typedef NS_OPTIONS(NSUInteger, UJETChatDownloadTranscriptVisibilityOptions) {
UJETChatDownloadTranscriptVisibilityOptionsShowAll = 0,
UJETChatDownloadTranscriptVisibilityOptionsHideFromOptionsMenu = 1 << 0,
UJETChatDownloadTranscriptVisibilityOptionsHideFromPostChatScreen = 1 << 1,
UJETChatDownloadTranscriptVisibilityOptionsHideAll = UJETChatDownloadTranscriptVisibilityOptionsHideFromOptionsMenu | UJETChatDownloadTranscriptVisibilityOptionsHideFromPostChatScreen
};
@property (nonatomic, assign) UJETChatDownloadTranscriptVisibilityOptions transcriptVisibilityOptions;
Penggantian PSTN
Kami menyediakan penggantian PSTN untuk beberapa situasi:
Jaringan seluler sedang offline.
Backend aplikasi tidak dapat dijangkau.
VoIP tidak tersedia
Kondisi jaringan tidak cukup baik untuk terhubung. Lihat properti UJETGlobalOptions.pstnFallbackSensitivity untuk mengetahui detailnya.
Terjadi kegagalan selama koneksi karena masalah konfigurasi firewall atau penyedia.
Sebaiknya tetapkan nomor IVR perusahaan Anda di UJETGlobalOptions.fallbackPhoneNumber. Format yang direkomendasikan adalah + diikuti dengan kode negara dan nomor telepon. misalnya, +18001112222.
Sensitivitas Penggantian PSTN
Anda dapat menyesuaikan tingkat sensitivitas pemeriksaan kondisi jaringan ke penggantian PSTN.
@property (nonatomic, assign) float pstnFallbackSensitivity;
Nilai harus dalam rentang 0,0 hingga 1,0. Jika disetel ke 1, panggilan akan selalu terhubung melalui PSTN, bukan VoIP. Latensi maksimum dan nilai minimum bandwidth minimum masing-masing adalah 10.000 md dan 10 KB/dtk untuk nilai 0. Misalnya, nilai 0, 5 berarti latensi dan bandwidth minimum masing-masing adalah 5.000 md dan 15 KB/dtk.
Nilai ini dapat dikonfigurasi dengan mengikuti langkah-langkah berikut:
Login ke portal CCAI Platform sebagai administrator.
Buka Setelan > Setelan Developer > Aplikasi Seluler.
Temukan bagian Batas nomor telepon pengganti. Nilai defaultnya adalah 0,85.
Tentukan nilai minimum baru.
Klik Save.
Menonaktifkan notifikasi push di tingkat global
Anda dapat menonaktifkan notifikasi push di tingkat global. Menetapkan properti berikut ke false akan mengabaikan semua dependensi notifikasi push dan mencegah notifikasi push menjangkau pengguna akhir:
@property (nonatomic, assign) BOOL allowsPushNotifications;
Abaikan mode gelap
Anda dapat mengabaikan mode gelap di CCAI Platform SDK, khususnya dengan properti ini:
@property (nonatomic, assign) BOOL ignoreDarkMode;
Sembunyikan Status Bar
Anda dapat mengontrol visibilitas status bar dengan properti ini:
@property (nonatomic, assign) BOOL hideStatusBar;
Secara default, hideStatusBar ditetapkan ke false dan visible.
Melewati survei CSAT
Anda dapat menambahkan tombol yang memungkinkan pengguna melewati survei CSAT. Contoh kode berikut menunjukkan cara menambahkan tombol:
let options = UJETGlobalOptions()
options.skipCsat = true
Menyesuaikan indikator aktivitas
Anda dapat menambahkan animasi loader Anda sendiri (di dalam UIView) ke SDK dan
mengganti UIActivityIndicatorView default. Terapkan metode
ujet_activityIndicator dari UJETDelegate dan tampilkan
tampilan yang disesuaikan.
public func ujet_activityIndicator() -> UIView! {
let loader = UIView.init()
let animation = CABasicAnimation()
loader.backgroundColor = .blue
loader.layer.cornerRadius = 15
animation.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeOut)
animation.keyPath = "transform.scale"
animation.duration = 1.0
animation.fromValue = 0.0
animation.toValue = 1.0
animation.repeatCount = Float.infinity
animation.isRemovedOnCompletion = false
loader.layer.add(animation, forKey: "Load")
return loader
}
Jika Anda telah menetapkan UIUserInterfaceStyle sebagai Light di Info.plist aplikasi untuk memilih tidak menggunakan mode gelap sepenuhnya, Anda dapat mengabaikan properti ini.
Bahasa pilihan
CCAI Platform SDK akan menggunakan urutan prioritas berikut untuk menentukan bahasa pilihan.
Bahasa yang dipilih dari layar pembuka dalam aplikasi.
Bahasa default dipilih dari
UJETGlobalOptions. Anda dapat menetapkan bahasa default dengan propertipreferredLanguage. Kode bahasa yang didukung dapat ditemukan di fileUJETGlobalOptions.h.Bahasa perangkat yang dipilih di perangkat (dari Setelan > Umum > Bahasa & Wilayah) akan digunakan, jika didukung oleh aplikasi.
Dialek terdekat dari bahasa perangkat akan digunakan jika aplikasi tidak mendukung bahasa perangkat, tetapi mendukung dialek induk terdekatnya. Misalnya, jika pengguna memilih bahasa Spanyol Kuba sebagai bahasa di perangkat dan aplikasi tidak mendukung bahasa Spanyol Kuba, tetapi mendukung dialek induk bahasa Spanyol, bahasa Spanyol akan digunakan.
Bahasa Inggris akan digunakan jika bahasa perangkat tidak didukung oleh aplikasi.
Mengonfigurasi ikon link pengalihan eksternal
Anda dapat menyesuaikan ikon di saluran link pengalihan eksternal dengan mengupload ikon ke katalog aset aplikasi Anda dan pastikan untuk menggunakan nama ikon yang sama saat membuat link pengalihan eksternal di Setelan > Chat > Link Pengalihan Eksternal > Lihat link > Tambahkan Link Pengalihan di Portal Admin. Jika nama ikon di Portal Admin tidak cocok dengan ikon yang diupload ke aplikasi, SDK akan menggunakan ikon default. Anda dapat melihat link ini untuk mengetahui cara menambahkan gambar di katalog aset.



Mengirim data kustom ke CRM Anda
Anda dapat mengirim data kustom ke tiket CRM.
Ada dua metode untuk mengirim data kustom:
Metode aman: penandatanganan data yang telah ditentukan dengan JWT.
Metode tidak aman: data yang telah ditentukan dengan JSON biasa (Tidak direkomendasikan).
Menggunakan metode aman untuk mengirim data kustom
Anda harus menerapkan metode penandatanganan. Pertama, Anda dapat menempatkan data kustom di sisi klien, dan mengirimkannya ke server untuk ditandatangani. Di server, Anda dapat menambahkan data tambahan berdasarkan formulir yang ditentukan dan menandatanganinya dengan company.secret, lalu menampilkannya dengan JWT.
- (void)signPayload:(NSDictionary *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success failure:(void (^)(NSError *))failure
{
if (payloadType == UjetPayloadCustomData) {
// sign custom data using UJET_COMPANY_SECRET on your server.
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] init];
mutableRequest.URL = [NSURL URLWithString:@"https://your.company.com/api/ujet/sign/custom_data"];
mutableRequest.HTTPMethod = @"POST";
NSError *error;
// Make client's custom data
UJETCustomData *customData = [[UJETCustomData alloc] init];
[customData set:@"name" label:@"Name" stringValue:@"USER_NAME"];
[customData set:@"os_version" label:@"OS Version" stringValue:[[UIDevice currentDevice] systemVersion]];
[customData set:@"model" label:@"Model number" numberValue:[NSNumber numberWithInteger:1234]];
[customData set:@"temperature" label:@"Temperature" numberValue:[NSNumber numberWithFloat:70.5]];
[customData set:@"purchase_date" label:@"Purchase Date" dateValue:[NSDate date]];
[customData set:@"dashboard_url" label:@"Dashboard" urlValue:[NSURL URLWithString:@"http://internal.dashboard.com/1234"]];
NSDictionary *data = @{@"custom_data": [customData getData]};
mutableRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:data options:0 error:&error];
NSURLSessionDataTask *task = [session dataTaskWithRequest:mutableRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error) {
failure(error);
}
else {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
success(json[@"jwt"]);
}
}];
[task resume];
}
}
Menggunakan metode yang tidak aman untuk mengirim data kustom
Metode ini tidak direkomendasikan karena menciptakan potensi kerentanan yang
dapat membuat aplikasi Anda rentan terhadap serangan man in the middle. Jika Anda memilih untuk menggunakan
metode ini, kami tidak bertanggung jawab atas eksposur keamanan dan potensi
kerusakan yang mungkin terjadi. Sebaiknya gunakan metode aman yang telah dijelaskan sebelumnya untuk mengirim data kustom di aplikasi Anda. Atau, Anda dapat memulai iOS SDK dengan instance UJETCustomData. Dalam hal ini, delegasi signPayload untuk
UJETPayloadCustomData cukup memanggil success(nil);.
- (void)signPayload:(NSDictionary *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success failure:(void (^)(NSError *))failure {
if (payloadType == UjetPayloadCustomData) {
success(nil);
}
}
UJETStartOptions *options = [UJETStartOptions new];
options.unsignedCustomData = customData;
[UJET startWithOptions:options];
Menggunakan data kustom yang tidak ditandatangani untuk mengirim transkrip chat eksternal
Anda dapat mengirim transkrip chat ke SDK saat dimulai dengan data kustom yang tidak ditandatangani dengan memanggil metode setExternalChatTransfer: atau setExternalChatTransferWithDictionary: untuk menetapkan data JSON dengan NSString atau NSDictionary.
UJETCustomData *customData = [UJETCustomData new];
[customData setExternalChatTransfer:jsonString];
UJETStartOptions *options = [UJETStartOptions new];
options.unsignedCustomData = customData;
[UJET startWithOptions:options];
Format JSON:
greeting_override: stringagent: kamusname: stringavatar: string [URL avatar agen, opsional]
transcript: arraysender: string [end_useratauagent]timestamp: string [misalnya,2021-03-15 12:00:00Z]content: arraytype: string [salah satu daritext,media]text: string [wajib ada untuk jenis teks]media: kamus [wajib untuk jenis media]type: string [salah satu dari image, video]url: string [URL publik yang mengarah ke file media]
Contoh JSON:
{
"greeting_override": "Please hold while we connect you with a human agent.",
"agent": {
"name": "Name",
"avatar": "avatar url"
},
"transcript": [
{
"sender": "agent",
"timestamp": "2021-03-15 12:00:15Z",
"content": [
{
"type": "text",
"text": "**Suggestions shown:**\n\n* Help with batch or delivery\n* Help with metrics or order feedback\n* Help with Instant Cashout"
}
]
},
{
"sender": "end_user",
"timestamp": "2021-03-15 12:00:16Z",
"content": [
{
"type": "text",
"text": "Help with batch or delivery"
}
]
}
]
}
Anda dapat menggunakan Markdown pada jenis teks. Sintaksis yang didukung mencakup miring, tebal,
daftar berbutir, hyperlink, dan garis bawah (--text--).
Contoh data kustom
Bagian ini menunjukkan contoh data kustom.
JSON dienkode ke JWT
File JSON harus memvalidasi JWT. Dan objek data kustom adalah nilai kunci custom_data.
{
"iat" : 1537399656,
"exp" : 1537400256,
"custom_data" : {
"location" : {
"label" : "Location",
"value" : "1000 Stockton St, San Francisco, CA, United States",
"type" : "string"
},
"dashboard_url" : {
"label" : "Dashboard URL",
"value" : "http://(company_name)/dashboard/device_user_ID",
"type" : "url"
},
"contact_date" : {
"label" : "Contact Date",
"value" : 1537399655992,
"type" : "date"
},
"membership_number" : {
"label" : "Membership Number",
"value" : 62303,
"type" : "number"
},
"model" : {
"label" : "Model",
"value" : "iPhone",
"type" : "string"
},
"os_version" : {
"label" : "OS Version",
"value" : "12.0",
"type" : "string"
},
"last_transaction_id" : {
"label" : "Last Transaction ID",
"value" : "243324DE-01A1-4F71-BABC-3572B77AC487",
"type" : "string"
},
"battery" : {
"label" : "Battery",
"value" : "-100%",
"type" : "string"
},
"bluetooth" : {
"label" : "Bluetooth",
"value" : "Bluetooth not supported",
"type" : "string"
},
"wifi" : {
"label" : "Wi-Fi",
"value" : "Wi-Fi not connected",
"type" : "string"
},
"ssn" : {
"invisible_to_agent" : true,
"label" : "Social Security Number",
"value" : "102-186-1837",
"type" : "string"
}
}
}
Setiap data mirip dengan format objek JSON dan harus berisi kunci, nilai, jenis, dan label.
Kunci adalah ID unik untuk data. Label adalah nama tampilan di halaman CRM. Jenis adalah jenis nilai.
string
- String JSON
angka
- integer, float
tanggal
- Format stempel waktu Unix UTC dengan 13 digit. (berisi milidetik)
URL
- Format URL HTTP
Contoh CRM
Berikut adalah contoh CRM.
Lokasi
Gunakan framework CoreLocation. Untuk mengetahui detail selengkapnya, lihat AppDelegate.m.
Versi OS Perangkat
[customData set:@"os_version" label:@"OS Version" stringValue:[[UIDevice currentDevice] systemVersion]];
Mencegah tampilan data pelanggan
Anda dapat menggunakan properti invisible_to_agent dengan objek data kustom untuk
mencegah data kustom yang ditandatangani atau tidak ditandatangani ditampilkan di adaptor
agen. Dalam contoh sebelumnya, nomor jaminan sosial pengguna akhir tidak
ditampilkan di adaptor agen karena "invisible_to_agent" : true disertakan dalam
objek ssn.
Jika Anda menyertakan properti "invisible_to_agent" : true dengan objek data kustom,
Anda dapat mengharapkan perilaku berikut:
- Data kustom disertakan dalam file metadata sesi.
- Data kustom tidak disertakan dalam data CRM.
Untuk mengetahui informasi selengkapnya, lihat Melihat data sesi di adaptor agen.
Properti data yang dicadangkan
Anda dapat mengirim properti data yang dicadangkan ke Contact Center AI Platform (CCAI Platform) sebagai data kustom yang ditandatangani saat sesi dimulai. Untuk mengetahui informasi selengkapnya, lihat Mengirim properti data yang dicadangkan.
Berikut adalah contoh properti data yang dicadangkan dalam data kustom:
{
"custom_data": {
"reserved_verified_customer": {
"label": "Verified Customer",
"value": false,
"type": "boolean"
},
"reserved_bad_actor": {
"label": "Bad Actor",
"value": false,
"type": "boolean"
},
"reserved_repeat_customer": {
"label": "Repeat Customer",
"value": false,
"type": "boolean"
}
}
}
Tetapkan setiap nilai ke true atau false.
reserved_verified_customer:truejika Anda menganggap pengguna akhir ini sebagai pelanggan yang sah.reserved_bad_actor:truejika Anda menganggap pengguna akhir ini berpotensi menjadi pelaku kejahatan.reserved_repeat_customer:truejika Anda telah menentukan bahwa pengguna akhir ini pernah menghubungi pusat kontak Anda sebelumnya.
Sesuaikan Alur
Bagian ini menjelaskan cara menyesuaikan alur.
Memutuskan hubungan CCAI Platform untuk menangani peristiwa aplikasi Host
// CCAI Platform is connected
...
// An event has come
[UJET disconnect:^{
// Handle an event
}];
Menunda panggilan masuk atau chat CCAI Platform
Terapkan metode delegasi untuk menangani peristiwa yang masuk:
- (BOOL)shouldConnectUjetIncoming:(NSString *)identifier forType:(UjetIncomingType)type {
if (weDoingSomething) {
// save identifier and type
return NO; // postpone
} else {
return YES;
}
}
Menghubungkan acara yang ditunda
[UJET connect:identifier forType:UjetIncomingTypeCall];
Menyiapkan Deep link
Hal ini memungkinkan agen pada panggilan PSTN menggunakan tindakan cerdas melalui SMS, baik saat pengguna akhir memiliki maupun tidak memiliki aplikasi.
Buka Settings > Operation Management > Enable Send SMS to Download App di portal CCAI Platform.
Anda dapat menetapkan URL Aplikasi dengan halaman web Anda (yaitu, https://your-company.com/support) setelah mengonfigurasi Link Universal atau skema URL kustom. Anda dapat memilih salah satu cara.
Menerapkan metode delegasi untuk menangani deep link
Link universal dan URL kustom masing-masing terlihat seperti
https://your-company.com/support?call_id=x&nonce=y dan
your-company://support?call_id=x&nonce=y. Masukkan salah satu link Anda
tanpa parameter kueri di bagian URL Aplikasi di Portal Admin. Misalnya, masukkan
your-company://support jika menggunakan skema URL kustom.
Dalam metode delegasi, pastikan untuk hanya memanggil [UJET start] jika jalur dan parameter URL di link universal atau URL kustom bersifat spesifik untuk CCAI Platform.
- (BOOL)application:(UIApplication *)app continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray * _Nullable))restorationHandler {
...
if ([NSUserActivityTypeBrowsingWeb isEqualToString:userActivity.activityType]) {
NSURL *url = userActivity.webpageURL;
NSArray *availableSchema = @[
@"your-company", // custom URL scheme
@"https" // universal link
];
NSArray *availableHostAndPath = @[
@"ujet", // custom URL scheme
@"your-comany.com/ujet" // universal link
];
if (![availableSchema containsObject:url.scheme]) {
return NO;
}
NSString *hostAndPath = [NSString stringWithFormat:@"%@%@", url.host, url.path];
if (![availableHostAndPath containsObject:hostAndPath]) {
return NO;
}
// your-company://ujet?call_id={call_id}&nonce={nonce}
// https://your-company.com/ujet?call_id={call_id}&nonce={nonce}
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url
resolvingAgainstBaseURL:NO];
NSArray *queryItems = urlComponents.queryItems;
NSString *callId = [self valueForKey:@"call_id" fromQueryItems:queryItems];
// validate call ID
if (![self isValidCallId:callId]) {
return NO;
}
NSString *nonce = [self valueForKey:@"nonce" fromQueryItems:queryItems];
UJETStartOptions *options = [[UJETStartOptions alloc] initWithCallId:callId nonce:nonce];
[UJET startWithOptions:options];
}
...
}
Jika aplikasi Anda menggunakan UIWindowSceneDelegate, tambahkan cuplikan kode ini:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//if app is called with universal Link and started from cold
if connectionOptions.urlContexts.first != nil {
self.scene(scene, openURLContexts: connectionOptions.urlContexts)
}
guard let _ = (scene as? UIWindowScene) else { return }
}
func scene(_ scene: UIScene, willContinueUserActivityWithType userActivityType: String) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let _ = appDelegate.application(UIApplication.shared,
continue: NSUserActivity(activityType: userActivityType)) { _ in
}
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let _ = appDelegate.application(UIApplication.shared,
open: url,
options: [:])
}
}
Untuk mengetahui informasi selengkapnya, lihat kode contoh dari file UJETObject+DeepLink.
Mengamati peristiwa CCAI Platform
Kami memposting peristiwa berikut melalui NSNotificationCenter.defaultCenter. Anda dapat memprosesnya dan menyesuaikan alur bergantung pada kasus penggunaan, misalnya, tata letak keyboard kustom.
UJETEventEmailDidClick
- Data Menu Antrean
UJETEventEmailDidSubmit
Data Menu Antrean
has_attachment: (NSNumber) @YES, @NO
UJETEventSessionViewDidAppear
type: @"call", @"chat"
timestamp: (NSString) ISO 8601
UJETEventSessionViewDidDisappear
type: @"call", @"chat"
timestamp: (NSString) ISO 8601
UJETEventSessionDidCreate
- Data Sesi
UJETEventSessionDidEnd
Data Sesi
agent_name: (NSString) null jika agen tidak bergabung
duration: (NSNumber) hanya untuk panggilan
ended_by: (NSString)
type=call: @"agent", @"end_user"
type=chat: @"agent", @"end_user", @"timeout", @"dismissed"
UJETEventSdkDidTerminate
UJETEventPostSessionOptInDidSelected
- opt_in_selected: (NSString) @"Yes", @"No"
Data Peristiwa
Metadata
application: @"iOS"app_id: (NSString) ID paketapp_version: (NSString)company: (NSString) subdomaindevice_model: (NSString)device_version: (NSString)sdk_version: (NSString)timestamp: (NSString) ISO 8601
Data Menu Antrean
Metadata
menu_id: NSStringmenu_key: NSString, nullablemenu_name: NSStringmenu_path: NSString
Data Sesi
Metadata
session_id: NSStringtype: @"call", @"chat"end_user_identifier: NSString
Menyiapkan berbagi layar
Jika Anda ingin menggunakan fitur berbagi layar, integrasikan
UJETCobrowseKit.xcframework.
CocoaPods
Tambahkan subspec ini ke target aplikasi Anda:
ruby
target 'MyApp' do
pod 'UJET'
pod 'UJET/Cobrowse'
end
Menyiapkan berbagi layar dengan Carthage
Tambahkan baris ini di Cartfile:
binary "https://sdk.ujet.co/ios/UJETKit.json"
SwiftPM
Pilih produk UJET dan UJETCobrowse, lalu tambahkan ke target aplikasi Anda.
Dan tetapkan nilai UJETGlobalOptions.cobrowseKey ke kunci cobrowse perusahaan Anda.
swift
let options = UJETGlobalOptions()
options.cobrowseKey = cobrowseKey
UJET.setGlobalOptions(options)
Berbagi layar perangkat penuh (opsional)
Berbagi layar perangkat penuh memungkinkan agen dukungan Anda melihat layar dari aplikasi di luar aplikasi Anda. Hal ini sering kali berguna saat agen dukungan perlu memeriksa status setelan sistem, atau perlu melihat pengguna beralih di antara beberapa aplikasi. Jika tidak menginginkan fitur ini, Anda dapat melewati bagian ini.
Menyesuaikan dialog izin berbagi layar
Untuk menyesuaikan dialog izin berbagi layar, Anda harus menerapkan
protokol UJETCobrowseAlertProvider di class penyedia. Dalam
implementasi ini, tampilkan UIViewController kustom atau objek lain yang diwarisi
UIViewController melalui metode protokol masing-masing. UIViewController
harus memiliki dua tombol, satu untuk menerima, dan satu lagi untuk menolak.
Setelah mendapatkan izin, teruskan ke SDK kami dengan memanggil closure
consentStatus. UIViewController dari cobrowseFullDeviceRequestAlert. Delegasi
harus berisi RPSystemBroadcastPickerView dengan judul (lihat dalam
kode contoh di bawah) dan harus memiliki tombol tolak lainnya. Panggil penutupan yang ditutup
saat mengklik tombol tolak.
class CobrowseAlertProvider: NSObject, UJETCobrowseAlertProvider {
func cobrowseSessionInitializationAlert(consentStatus: @escaping (Bool) -> Void) -> UIViewController? {
let customAlertViewController = CustomAlertViewController()
customAlertViewController.consentStatus = consentStatus
return customAlertViewController
}
func cobrowseSessionRequestAlert(consentStatus: @escaping (Bool) -> Void) -> UIViewController? {
// Same as cobrowseSessionInitializationAlert
}
func cobrowseRemoteRequestAlert(consentStatus: @escaping (Bool) -> Void) -> UIViewController? {
// Same as cobrowseSessionInitializationAlert
}
func cobrowseFullDeviceRequestAlert(dismissed: @escaping () -> Void) -> UIViewController? {
let customAlertViewController = CustomFullDeviceAlertViewController()
cobrowseSessionAlertViewController.dismissed = dismissed
return customAlertViewController
}
func cobrowseSessionEndAlert(consentStatus: @escaping (Bool) -> Void) -> UIViewController? {
// Same as cobrowseSessionInitializationAlert
}
}
Pengontrol tampilan kustom harus memiliki penutupan untuk meneruskan status izin ke SDK.
class CustomAlertViewController: UIViewController {
var consentStatus: ((Bool) -> Void)?
@IBAction func allowButtonClicked(_ sender: Any) {
dismiss(animated: true) {[weak self] in
self?.consentStatus?(true)
}
}
@IBAction func denyButtonClicked(_ sender: Any) {
dismiss(animated: true) {[weak self] in
self?.consentStatus?(false)
}
}
}
Pengontrol tampilan kustom untuk pemberitahuan permintaan perangkat lengkap harus memiliki
RPSystemBroadcastPickerView dan penutupan untuk meneruskan status dismiss ke
SDK.
class CustomFullDeviceAlertViewController: UIViewController {
var broadcastPickerView: RPSystemBroadcastPickerView!
var dismissed: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
let frame = CGRect(x: x, y: y, width: 50, height: 50) // Set your own value
broadcastPickerView = RPSystemBroadcastPickerView(frame: frame)
broadcastPickerView.preferredExtension = Bundle.main.object(forInfoDictionaryKey: "CBIOBroadcastExtension") as? String // Should have this value as it is
view.addSubview(broadcastPickerView)
}
@IBAction func denyButtonClicked(_ sender: Any) {
dismiss(animated: true) {[weak self] in
self?.dismissed?()
}
}
}
Jangan lupa untuk meneruskan penyedia ini ke SDK kami melalui API berikut:
let provider = CobrowseAlertProvider()
UJET.setCobrowseAlertProvider(provider)
Ekstensi Siaran
Fitur ini memerlukan penambahan Broadcast Extension.
Buka project Xcode Anda.
Buka File > Target.
Pilih Broadcast Upload Extension.
Masukkan Nama untuk target.
Hapus centang pada kotak Include UI Extension.
Buat target, dan catat ID paket-nya.
Ubah SDK target Ekstensi Siaran Anda ke iOS 12.0 atau yang lebih tinggi.
Mengintegrasikan SDK
CocoaPods{: Tambahkan subspec berikut ke target ekstensi Anda:
target 'MyApp' do
pod 'UJET'
pod 'UJET/Cobrowse'
end
target 'MyAppExtension' do
pod 'UJET/CobrowseExtension'
end
Jika Anda menggunakan SwiftPM, pilih produk UJETCobrowseExtension dan tambahkan ke target ekstensi Anda.
Menyiapkan berbagi keychain
Aplikasi Anda dan ekstensi aplikasi yang Anda buat sebelumnya perlu berbagi beberapa rahasia melalui Keychain iOS. Mereka melakukannya menggunakan grup Keychain mereka sendiri sehingga terisolasi dari keychain aplikasi Anda yang lain.
Di Xcode, pilih target aplikasi dan target ekstensi Anda. Tambahkan hak berbagi keychain untuk grup keychain io.cobrowse.
Menambahkan ID paket ke plist Anda
Ambil ID paket ekstensi yang Anda buat sebelumnya dan tambahkan entri ini di Info.plist aplikasi Anda.
xml
<key>CBIOBroadcastExtension</key>
<string>your.app.extension.bundle.ID.here</string>
Mengimplementasikan ekstensi
Xcode akan menambahkan file SampleHandler.m dan SampleHandler.h (atau
SampleHandler.swift) sebagai bagian dari target yang Anda buat sebelumnya. Ganti
konten file dengan kode berikut:
Swift:
Pilih produk UJETCobrowseExtension dan tambahkan ke target ekstensi Anda:
import CobrowseIOAppExtension
class SampleHandler: CobrowseIOReplayKitExtension {
}
ObjC:
objc// SampleHandler.h
@import CobrowseIOAppExtension;
@interface SampleHandler : CobrowseIOReplayKitExtension
@end// SampleHandler.m
#import "SampleHandler.h"
@implementation SampleHandler
@end
Buat dan jalankan aplikasi Anda
Sekarang Anda siap untuk membangun dan menjalankan aplikasi. Kemampuan perangkat lengkap hanya tersedia di perangkat fisik, dan tidak akan berfungsi di iOS Simulator.
Meminimalkan SDK
SDK Contact Center AI Platform dapat diperkecil saat sesi chat atau panggilan sedang berlangsung. Hal ini dapat berguna saat Anda ingin mengarahkan pengguna kembali ke aplikasi Anda setelah peristiwa SDK diterima, seperti kartu konten yang diklik. Untuk meminimalkan SDK dan mengarahkan pengguna kembali ke aplikasi, Anda dapat menggunakan:
UJET.minimize(nil)
// Or if you want to take some action once the SDK has been minimized:
UJET.minimize {
// Add the code you want to run once the SDK has been minimized here
}
Pengganti
Anda dapat menggunakan fungsi didHandleUjetError untuk penggantian error yang tidak terduga. Jika Anda tidak menggunakan fungsi ini atau fungsi ini menampilkan false, iOS SDK akan menangani error tersebut.
Tabel berikut menunjukkan error yang diproses oleh fungsi didHandleUjetError:
| Jenis error | Kode error | Deskripsi |
|---|---|---|
networkError |
1 | Jaringan tidak tersedia. Catatan: Error ini tidak dipicu saat jaringan tidak tersedia selama sesi chat atau panggilan atau layar rating. |
authenticationError |
100 | Terjadi error tidak terduga selama autentikasi. |
authenticationJwtError |
101 | Terjadi error tidak terduga selama validasi JWT—misalnya, error penguraian. |
voipConnectionError |
1000 | Gagal membuat koneksi ke penyedia VoIP. Callback SDK VoIP menangani hal ini. |
voipLibraryNotFound |
1001 | Sistem mengharapkan panggilan terhubung melalui penyedia VoIP, tetapi tidak dapat menemukannya. Hal ini dapat terjadi jika Anda mengintegrasikan SDK yang salah atau tidak menambahkan library penyedia VoIP ke dependensi Anda. |
chatLibraryNotFound |
1.100 | Terjadi saat sistem tidak dapat menemukan library chat. Hal ini dapat terjadi saat Anda mengintegrasikan SDK yang salah atau tidak menambahkan library chat Twilio ke dependensi Anda. |
Contoh kode berikut menunjukkan cara menggunakan fungsi didHandleUjetError:
public func didHandleUjetError(_ errorCode: Int32) -> Bool {
guard let ujetError = UjetErrorCode(rawValue: Int(errorCode)) else {
return false // Let the SDK handle unknown integer codes.
}
switch ujetError {
case .networkError:
// Example for if you have a custom UI for network errors. You can
// handle the error and prevent the SDK from showing its own alert.
showCustomNetworkAlert() // Your custom UI for this type of error.
return true
case .authenticationError, .voipConnectionError:
// For all other errors, use the default SDK behavior.
return false
@unknown default:
// Let the SDK handle future errors.
return false
}
}
Pemecahan masalah
Bagian ini memberikan informasi untuk membantu Anda memecahkan masalah umum.
Penolakan pengiriman aplikasi
Pengiriman aplikasi ditolak karena penyertaan framework CallKit di wilayah China.
Jika aplikasi Anda ditolak oleh Apple karena alasan ini, cukup tinggalkan komentar karena sistem dirancang untuk menonaktifkan framework CallKit untuk wilayah China pada panggilan VoIP. Hal ini berlaku mulai SDK versi 0.31.1.
Ukuran SDK terlalu besar
Jika ukuran SDK terlalu besar dan sulit dilacak di GitHub
Dalam artikel ini, mereka menawarkan dua pilihan. Sebaiknya gunakan Git lfs.
Jika Anda tidak menggunakan Bitcode, menghapus bitcode dari biner dapat menjadi opsi lain. Jalankan perintah ini di folder UJETKit.xcframework.
xcrun bitcode_strip -r UJET -o UJET
Error dyld: Library not loaded
Tambahkan @executable_path/Frameworks di Runpath Search Paths dari Target > Build Settings > Linking.
Pengiriman aplikasi di iTunes Connect
Apple mungkin akan mengajukan pertanyaan berikut saat dalam proses peninjauan karena mode latar belakang Voice over IP diaktifkan:
Dapatkah pengguna menerima panggilan VoIP di aplikasi Anda?
Jawab Yes untuk pertanyaan tersebut.
Notifikasi Pemberitahuan tidak tersedia saat memulai SDK
Periksa hal-hal berikut:
Gunakan perangkat sebenarnya, bukan simulator.
Aktifkan Notifikasi push dan kemampuan Background Modes > Voice over IP.
Jika hal tersebut tidak membantu, coba build dengan profil penyediaan distribusi (Ad-hoc atau Apple Store).
Menguji notifikasi push terhadap aplikasi pengujian Anda
Siapkan sertifikat VoIP dan token perangkat Anda.
Di portal CCAI Platform, lihat bagian Debug Notifikasi Push di menu Settings > Developer Settings.
Jika sudah menetapkan sertifikat untuk APNS, Anda tidak perlu memasukkan sertifikat lagi.
Masukkan sertifikat Anda (opsional) dan centang apakah sandbox atau tidak (opsional), lalu masukkan token perangkat notifikasi push aplikasi pengujian Anda.
Memulai chat baru memerlukan waktu lebih dari 30 detik
Periksa apakah Anda merespons metode delegasi data kustom. Anda harus menampilkan data kustom yang valid berdasarkan permintaan atau cukup menampilkan nil pada blok keberhasilan.
Gunakan cuplikan kode ini sebagai contoh konfigurasi:
public func signPayload(_ payload: [AnyHashable: Any]?, payloadType: UjetPayloadType, success: (String?) -> Void, failure: (Error?) -> Void)
{
if payloadType == .customData {
success(nil)
}
}