Настройка iOS приложения#

Настройка приложения для получения и отображения push-уведомлений#

Для получения и отображения push-уведомлений выполните следующие шаги:

  1. Зарегистрируйте приложение в Apple Push Notification Service (APNs): Registering Your App with APNs.

  2. Запросите разрешение на показ уведомлений: Asking Permission to Use Notifications.

  3. Реализуйте метод userNotificationCenter(_:willPresent:withCompletionHandler:) для отображения уведомлений, когда приложение запущено и активно: Handling Notifications and Notification-Related Actions.

  4. Реализуйте отправку токена на мобильный бекенд при вызове метода application(_:didRegisterForRemoteNotificationsWithDeviceToken:).

Пример AppDelegate после выполнения вышеуказанных действий#

@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        UNUserNotificationCenter.current().delegate = self
        UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { (granted, error) in
            if let error = error {
                print("Failed to request notification center authorization: \\(error)")
            }
        }
        
        application.registerForRemoteNotifications()
        return true
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let stringToken = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
        self.sendDeviceTokenToBackend(token: stringToken)
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register for remote notifications: \\(error)")
        // Try again later.
    }
    
    // MARK: - UNUserNotificationCenterDelegate

    // The method will be called on the delegate only if the application is in the foreground.
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .sound, .badge])
    }
}

Отслеживание статусов доставки#

При получении уведомления вам необходимо передавать на наш сервер информацию об идентификаторе сообщения на нашей платформе и статусе уведомления. Для этого необходимо выполните следующие шаги:

  1. Добавьте к приложению расширение Notification Service Extension.

  2. В методе didReceive(_:withContentHandler:) расширения отправляйте следующий HTTP-запрос:

POST <https://nativepush.i-dgtl.ru/notification-state>
Content-Type: application/json

{
	"messageId": "MESSAGE_ID",
	"state": "RECEIVED"
}

В ответ наш сервер должен вернуть 204 No Content.

Как добавить расширение Notification Service Extension?#

  1. В Xcode выберите FileNewTarget.

  2. Выберите из списка шаблонов Notification Service Extension и нажмите Next.

  1. Введите название расширения и нажмите Finish.

Пример реализации расширения#

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            if let messageId = bestAttemptContent.userInfo["messageId"] as? String {
                sendReceivedStateCallback(messageId: messageId) { error in
                    if let error = error {
												// handle request error
                    }
                    contentHandler(bestAttemptContent)
                }
            } else {
                contentHandler(bestAttemptContent)
            }
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
    
    func sendReceivedStateCallback(messageId: String, completionHandler: @escaping (Error?) -> Void) {
        #if DEBUG
        let callbackUrl = "<https://nativepush-test.i-dgtl.ru/notification-state>"
        #else
        let callbackUrl = "<https://nativepush.i-dgtl.ru/notification-state>"
        #endif
        
        let callbackParams = ["messageId": messageId, "state": "RECEIVED"]
        var request = URLRequest(url: URL(string: callbackUrl)!, timeoutInterval: 15)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = try? JSONSerialization.data(withJSONObject: callbackParams)
        
        let task = URLSession.shared.dataTask(with: request, completionHandler: { _, response, error in
            guard error == nil else {
                completionHandler(error)
                return
            }
            if let httpResponse = response as? HTTPURLResponse {
                guard (200...299).contains(httpResponse.statusCode) else {
                    completionHandler(NSError(domain: "unsuccessful http status code", code: httpResponse.statusCode, userInfo: nil))
                    return
                }
            }
            completionHandler(nil)
        })
        
        task.resume()
    }
}

{% hint style=»info» %} Время выполнения метода didReceive(_:withContentHandler:) ограничено 30 секундами, однако мы рекомендуем устанавливать меньший таймаут запроса, так как уведомление пользователю будет показано только после вызова contentHandler. {% endhint %}

Отправка уведомлений#

При отправке уведомлений используется ключ в формате.p8 для авторизации на сервере APNs, который вам нужно передать i-Digital.

Как создать ключ p8?#

  1. Войдите в ваш Appple Developer Account и перейдите на страницу Certificates, Identifiers & Profiles.

  2. В меню слева выберите Keys и нажмите на синюю кнопку (+).

  1. Введите название ключа, отметьте Apple Push Notifications service (APNs) и нажмите Continue.

  1. Нажмите Register, после чего скачайте созданный ключ, нажав Download.

Как передать созданный p8 ключ в i-Digital?#

Отправьте письмо на support@i-dgtl.ru с темой «Подключение PUSH i-digital direct», указав в теле письма следующее:

  • название вашей организации,

  • файл ключа,

  • Key ID - отображается после создания ключа,

  • Team ID - можно найти в Appple Developer Account на странице Membership .