‫Headless Mobile SDK ל-iOS: תחילת העבודה

במאמר הזה מוסבר איך מתחילים להשתמש ב-Headless Mobile SDK ל-iOS.

‫Headless Mobile SDK ל-iOS מאפשר לכם להוסיף תמיכה מבוססת-CCAI Platform ישירות לחוויית iOS המובנית שלכם, בלי להשתמש בממשק משתמש מוכן מראש של CCAI Platform.

במקום להציג ווידג'ט עם המיתוג של CCAI Platform, אתם:

  • משלבים את CCAI iOS SDK באפליקציה.

  • ליצור מסכים, ניווט ועיצוב חזותי משלכם.

  • אפשר להשתמש ב-SDK כדי:

    • התחלה וניהול של סשנים של צ'אט ושיחות קוליות.

    • הצעת אפשרויות של אימייל, שיחות מתוזמנות והפניה לפתרון עצמי.

    • תמיכה בפעולות חכמות, בקבצים מצורפים ובזרימות אחרי סיום הסשן (שביעות רצון לקוחות, סקרים, נציג וירטואלי).

פלטפורמת CCAI מטפלת בלוגיקה של מוקד שירות הלקוחות (ניתוב, תורים, ערוצים, הגדרה, דיווח). אתם הבעלים של חוויית השימוש המלאה באפליקציה (ממשק המשתמש, תהליכי העבודה והמיתוג).

אם אתם מעדיפים להשתמש בממשק משתמש מוגדר מראש במקום ליצור ממשק משתמש משלכם, אתם יכולים להשתמש בStandard Mobile SDK.

דרישות

אלה הדרישות לשילוב Headless Mobile SDK ל-iOS.

הדרישות של פלטפורמת iOS

  • גרסת iOS מינימלית: iOS 16.6 ואילך

  • שפה: Swift

  • IDE: הגרסה היציבה העדכנית ביותר של Xcode שנתמכת על ידי האפליקציה

  • ארכיטקטורות: ארכיטקטורות iOS רגילות שנתמכות על ידי ערכת הכלים הנוכחית של Xcode.

הרשאות שניתנות לאפליקציות

מכיוון שהאפליקציה המובנית שלך מטפלת בממשק המשתמש של פעולות חכמות (צילום תמונות, הקלטת סרטונים או אימות זהות), עליך להצהיר על הרשאות הפרטיות הנדרשות של Apple.

מוסיפים את המפתחות הבאים לInfo.plist עם תיאור של אופן השימוש בנתונים באפליקציה:

  • ‫NSCameraUsageDescription: נדרש כדי שהמשתמשים יוכלו לצלם ולשלוח תמונות או סרטונים, או כדי שהסוכן יוכל לבקש פעולות חכמות.

  • ‫NSMicrophoneUsageDescription: נדרשת לביצוע שיחות קוליות מיידיות ולצילום סרטונים עם אודיו.

  • ‫NSPhotoLibraryUsageDescription: נדרשת כדי שהמשתמשים יוכלו להעלות תמונות או סרטונים קיימים מזיכרון המצלמה.

  • ‫NSFaceIDUsageDescription: חובה אם אתם תומכים באימות ביומטרי בפעולות חכמות.

הדרישות לגבי מופע של CCAI Platform

כדי לקבל את הפרטים הבאים, צריך גישה להגדרות הפיתוח של מופע CCAI Platform:

  • מפתח החברה

  • קוד סודי של החברה

  • כתובת ה-URL של המארח – שם המארח של פלטפורמת CCAI (לדוגמה, your_subdomain.ccaiplatform.com)

הערכים האלה משמשים למטרות הבאות:

  • מפתח חברה + כתובת URL של המארח: באפליקציית iOS כדי להפעיל את ה-SDK.

  • קוד סודי של החברה: בקצה העורפי שלכם כדי לחתום על אסימוני אינטרנט מסוג JSON‏ (JWT) שמשמשים לאימות משתמשים.

התראות

כדי להתקשר ולבצע פעולות חכמות מסוימות, צריך:

  • הגדרת שירות ההתראות של אפל (APNs) להתראות פוש רגילות.

  • אישור של שירותי VoIP כדי לתמוך בשיחות נכנסות ובהתראות ספציפיות שקשורות לשיחות.

תצטרכו:

  • מגדירים את פרטי הכניסה ל-APNs ול-VoIP בפורטל למפתחים של Apple.

  • מעלים את האישורים שהומרו בפורטל האדמין של פלטפורמת CCAI בקטע הגדרות > הגדרות למפתחים > אפליקציה לנייד.

  • נרשמים לקבלת התראות מרחוק והתראות VoIP באפליקציה.

  • מעבירים את טוקני המכשיר המתאימים ל-SDK.

  • בקטע Target > Signing & capabilities (יעד > חתימה ויכולות), מפעילים את האפשרויות הבאות:

    • היכולת לשלוח התראות.

    • היכולת מצבי הפעלה ברקע עם הסימון של הפריטים הבאים:

      • פרוטוקול העברת קול באינטרנט (VoIP) – נדרש לקבלת התראות פוש על שיחות VoIP (שיחות נכנסות, פעולות חכמות באמצעות PSTN).

      • אודיו, AirPlay ותמונה בתוך תמונה – נדרש כדי שאודיו של שיחות קוליות ימשיך לפעול כשהאפליקציה פועלת ברקע.

      • התראות מרחוק – נדרש לשליחת התראות רגילות ב-APNs.

איך headless iOS SDK משתלב באפליקציה

‫Headless Mobile SDK ל-iOS מורכב משלוש שכבות:

פלטפורמת CCAI ו-SDK

ערכת ה-SDK מבצעת אינטראקציה מאובטחת עם פלטפורמת CCAI Platform ומספקת:

  • אימות באמצעות אסימוני JWT (‏JSON Web Tokens).

  • מטא-נתונים של תורים וניתוב ערוצים (צ'אט, שיחות קוליות, שיחות מתוזמנות, אימייל, קישורים להפניית שיחות חיצוניות).

  • ניהול מצב הסשן בזמן אמת.

  • צינור התעבורה המאובטח לפעולות חכמות, לקבצים מצורפים ולשיתוף מסך.

  • לוגיקת ההפניה והערכה של ההיררכיה אחרי הסשן.

אפליקציית iOS (ממשק המשתמש והלוגיקה מנוהלים על ידכם)

אתם שולטים בחוויה החזותית ובחוויית הניווט:

  • נקודות כניסה: לדוגמה, כרטיסיית עזרה או לחצן יצירת קשר.

  • תפריטים: איך מציגים תורים (לדוגמה, חיוב, תמיכה טכנית).

  • ממשק משתמש במהלך השיחה: בועות הצ'אט, מסכי השיחה והפקדים המותאמים אישית.

  • מה האפליקציה עושה: קוראת ל-SDK APIs כדי להתחיל ולהסיים סשנים, מאזינה לאירועי SDK ומניעה את הניווט בבקר התצוגה.

הגדרה של פורטל האדמין של CCAI Platform

האדמינים שלכם ב-CCAI Platform מגדירים את כללי האינטראקציה (שעות הפעילות, הערוצים הזמינים, ספי הזמן להמתנה וסקרים). ה-SDK קורא את ההגדרה הזו ומציג אותה לאפליקציה כנתונים גולמיים ואירועים. אתם קובעים איך ההגדרה הזו תוצג על המסך.

אחזור פרטי הכניסה של החברה

לפני שמשלבים את ה-SDK, צריך לקבל את פרטי הכניסה ממופע CCAI Platform:

  1. נכנסים לפורטל האדמין של CCAI Platform באמצעות חשבון אדמין.

  2. עוברים אל הגדרות > הגדרות למפתחים.

  3. בקטע מפתח החברה וקוד סודי, מעתיקים את:

    • מפתח החברה

    • קוד סודי של החברה

  4. רושמים את כתובת ה-URL של המארח:שם המארח של פלטפורמת CCAI (לדוגמה, your_subdomain.ccaiplatform.com).

תשתמשו ב:

  • באפליקציית iOS: מפתח החברה + כתובת ה-URL של המארח.

  • בשרת העורפי: קוד סודי של החברה לחתימה על JWTs עבור:

    • אימות משתמשי קצה.

    • נתונים מותאמים אישית או הקשר אופציונליים שמשמשים את CCAI Platform.

הוספת ה-SDK לאפליקציית iOS

ערכת ה-SDK ללא GUI מבוססת על ארכיטקטורה מודולרית. מתקינים את ליבת CCAIKit לצד מודולי התכונות הספציפיים שהאפליקציה דורשת (לדוגמה, CCAIChat או CCAIScreenShare).

כדי לשלב את iOS SDK באפליקציה, פועלים לפי רצף השלבים הבא.

  1. מוסיפים לקובץ 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")
           ]
       )
    ]
    
  2. ייבוא של CCAIKit בקובץ AppDelegate:

    import CCAIKit
    
  3. אם הפרויקט שלכם הוא SwiftUI, צריך להצהיר על @UIApplicationDelegateAdaptor במבנה App:

    @main
    struct YourAppName: App {
       @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
       // ...
    }
    

אתחול של headless 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 ה-singleton:

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)")
}

אימות משתמשי קצה

ערכת ה-SDK לנייד ללא ממשק משתמש משתמשת באסימוני JWT‏ (JSON Web Tokens) כדי לאמת משתמשים ולהעביר באופן מאובטח מידע הקשרי לסוכן ה-CRM.

איך זה עובד

ה-SDK משתמש בתהליך אימות אסינכרוני פשוט בשני שלבים:

  1. ערכת ה-SDK קובעת שצריך לאמת את המשתמש.

  2. היא מפעילה את השיטה CCAIDelegate – ccaiShouldAuthenticate() – שהיא פונקציה אסינכרונית.

  3. האפליקציה שלך חותמת על JWT מרחוק בשרת הקצה העורפי באמצעות הקוד הסודי של החברה.

  4. האפליקציה מעבירה את ה-JWT החתום אל CCAI.shared.authService?.authenticate(jwt) כדי להחליף אותו באסימון אימות.

  5. אסימון האימות מוחזר ל-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

אם רוצים להעביר נתונים הקשריים לסוכן (לדוגמה, מערכת ההפעלה הנוכחית של המכשיר של המשתמש, המיקום שלו או רמת החשבון שלו), ה-backend צריך להוסיף אובייקט custom_data למטען הייעודי (payload) של ה-JWT לפני החתימה עליו.

כל נתון מותאם אישית צריך להיות בפורמט של אובייקט JSON שמכיל את השדות label (מה שהסוכן רואה), value ו-type.

סוגי נתונים נתמכים

  • ‫string: טקסט רגיל (לדוגמה, iPhone 14 Pro).

  • ‫number: מספרים שלמים או מספרים עשרוניים (לדוגמה, 1234 או 99.99).

  • ‫date: חותמת זמן של מערכת Unix לפי שעון UTC, באורך 13 ספרות, כולל אלפיות השנייה (לדוגמה, 1537399655992).

  • ‫url: פורמט סטנדרטי של כתובת URL מסוג HTTP/HTTPS.

  • ‫boolean: ערך True או False רגיל.

מפתחות שמורים של CRM

פלטפורמת CCAI תומכת במקשים שמורים ספציפיים שמפעילים התנהגויות מוכללות בפלטפורמה, כמו סימון משתמש כ-VIP או אזהרה לסוכן לגבי גורם זדוני. הם צריכים להיות בפורמט של סוגים בוליאניים, והמערכת מקבלת אותם רק אם מטען הייעודי (payload) חתום באמצעות שיטת ה-JWT המאובטחת.

  • ‫reserved_verified_customer: מציין אם הלקוח אומת בהצלחה על ידי המערכות הפנימיות שלכם.

  • ‫reserved_bad_actor: מסמן את המשתמש לסוכן כמישהו שעשוי להיות שולח ספאם או כחשבון מזויף.

  • ‫reserved_repeat_customer: מציין אם הלקוח הזה פנה לתמיכה לעיתים קרובות לאחרונה.

דוגמה למטען ייעודי (payload) עם מפתחות שמורים

{
  "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)

סכימת מטען ייעודי (payload) של 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 Platform נדרשים שני סוגים שונים של אישורי Apple Push כדי לשמור אותם בפורטל האדמין של CCAI Platform:

  • אישור SSL של שירות ההתראות של אפל (APNs) – משמש לשליחת התראות פוש רגילות מרחוק.

  • אישור של שירות VoIP – משמש להתראות על שיחות נכנסות ולפעולות חכמות מסוימות שקשורות לשיחות.

שני האישורים נוצרים בפורטל Apple Developer, מומרים לפורמט PEM ומועלים לפורטל האדמין של פלטפורמת CCAI.

יצירת אישור SSL של APNs

כדי ליצור אישור SSL של APNs, פועלים לפי השלבים הבאים – על סמך המדריך הרשמי של אפל בנושא יצירת חיבור מבוסס-אישור ל-APNs.

  1. נכנסים אל developer.apple.com ועוברים אל Certificates, Identifiers & Profiles (אישורים, מזהים ופרופילים).

  2. לוחצים על הלחצן + כדי ליצור אישור חדש.

  3. בקטע Services (שירותים), בוחרים באפשרות Apple Push Notification service SSL (Sandbox & Production) (שירות ה-SSL של Apple להתראות פוש (סביבת בדיקה וסביבת ייצור)).

  4. בוחרים את מזהה האפליקציה שמתאים למזהה החבילה של האפליקציה, ואז לוחצים על המשך.

  5. מעלים בקשת חתימה על אישור (CSR) שנוצרה מ-Keychain Access ב-Mac:

    • פותחים את Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority…‎

    • מזינים את כתובת האימייל, משאירים את השדה 'כתובת אימייל של CA' ריק, בוחרים באפשרות נשמר בדיסק ולוחצים על המשך.

  6. לוחצים על המשך ואז על הורדה כדי להוריד את קובץ .cer שנוצר.

  7. לוחצים לחיצה כפולה על הקובץ .cer כדי להתקין אותו ב-Keychain.

  8. ב-Keychain Access, מאתרים את האישור המותקן, לוחצים עליו לחיצה ימנית ובוחרים באפשרות Export… (ייצוא…) כדי לשמור אותו כקובץ .p12. תוצג בקשה להגדיר סיסמה לייצוא.

  9. ממירים את הקובץ .p12 לפורמט PEM באמצעות openssl:

    # 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 מאפשרים לאפליקציה לקבל התראות פוש בעדיפות גבוהה דרך מסגרת PushKit של Apple, שיכולה להפעיל את האפליקציה ממצב סגור כדי לטפל בשיחות נכנסות. השלבים הרשמיים העדכניים זמינים במאמר יצירת אישורים לשירותי VoIP במאמרי העזרה של אפל למפתחים.

  1. נכנסים אל developer.apple.com ועוברים אל Certificates, Identifiers & Profiles (אישורים, מזהים ופרופילים).

  2. לוחצים על הלחצן + כדי ליצור אישור חדש.

  3. בקטע 'שירותים', בוחרים באפשרות אישור שירותי VoIP.

  4. בוחרים את מזהה האפליקציה שמתאים למזהה החבילה של האפליקציה, ואז לוחצים על המשך.

  5. מעלים את אותה בקשה לחתימה על אישור (CSR) שיצרתם לאישור ה-SSL של APNs (או יוצרים בקשה חדשה).

  6. לוחצים על המשך ואז על הורדה כדי להוריד את קובץ .cer שנוצר.

  7. לוחצים לחיצה כפולה על הקובץ .cer כדי להתקין אותו ב-Keychain.

  8. ב-Keychain Access, מאתרים את האישור של שירות ה-VoIP המותקן, לוחצים עליו לחיצה ימנית ובוחרים באפשרות Export… (ייצוא…) כדי לשמור אותו כקובץ .p12.

  9. ממירים את הקובץ .p12 לפורמט PEM באמצעות openssl:

    # 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

  1. נכנסים לפורטל האדמינים של CCAI Platform.

  2. עוברים אל הגדרות > הגדרות למפתחים > אפליקציה לנייד.

  3. מעלים את אישור ה-PEM של APNs.

  4. מעלים את אישור ה-PEM של ה-VoIP.

בקשת הרשאות לשליחת התראות פוש

ערכת ה-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
        )
    }
}

חשוב להפעיל גם את האפשרויות Capabilities > Push notifications (יכולות > התראות פוש) ו-Background modes (מצבי רקע) להתראות מרחוק בכרטיסייה Target > Signing & capabilities (יעד > חתימה ויכולות) ב-Xcode.

טיפול בהתראות פוש נכנסות

כשמקבלים מטען ייעודי (payload) של הודעת פוש, מעבירים אותו ל-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 דורש טוקן דחיפה של VoIP בנוסף לטוקן APNs הרגיל. התראות פוש של VoIP מועברות בעדיפות גבוהה ויכולות להפעיל את האפליקציה ממצב סגור.

ייבוא של PushKit ויצירה של PKPushRegistry בdidFinishLaunchingWithOptions של 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
    }
}

הטמעה של שיטות PKPushRegistryDelegate להעברת טוקנים ומטענים ייעודיים (payloads) של 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() }
}