swiftfirebasepush-notificationfirebase-cloud-messaging

In swift, need precisions about the bearer from the migration from de API Cloud Messaging Legacy to the HTTP V1 of Firebase


Here is my new method to send push notifications for the HTTP V1: I was on the Legacy version before.

    func sendPushNotification(to token: String, title: String, body: String) {
        //let urlString = "https://fcm.googleapis.com/fcm/send"
        let urlString = "fcm.googleapis.com/v1/projects/myproject-77a88/messages:send"
        let url = NSURL(string: urlString)!
        let paramString: [String : Any] = ["to" : token, "notification" : ["title" : title, "body" : body, "badge": "1", "sound": "default"]
        ]
        let request = NSMutableURLRequest(url: url as URL)
        request.httpMethod = "POST"
        request.httpBody = try? JSONSerialization.data(withJSONObject:paramString, options: [.prettyPrinted])
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("key=\(KSERVERKEY)", forHTTPHeaderField: "Authorization")
        let task =  URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
            do {
                if let jsonData = data {
                    if let jsonDataDict  = try JSONSerialization.jsonObject(with: jsonData, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: AnyObject] {
                        NSLog("Received data:\n\(jsonDataDict)")
                    }
                }
            } catch let err as NSError {
                print(err.debugDescription)
            }
        }
        task.resume()
    }

I change the UrlString from:

"https://fcm.googleapis.com/fcm/send"

to

"fcm.googleapis.com/v1/projects/myproject-77a88/messages:send"

and the Token from Legacy version to the new one from

https://console.cloud.google.com/iam-admin/serviceaccounts/

This is the page where firebase explains these things: https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=fr

If understand well, the bearer will be different each time push notification has to be sent. The bearer is temporary. But even if i read the explanation from Firebase documentation, i didn't know how to retrieve a new bearer each time. Could someone help.


Solution

  • Finally, here is the code to retrieve the bearer and to send the push notifications:

    class PushNotificationSender {
        let API_Key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        func getFirebaseBearerToken(completion: @escaping (String?) -> Void) {
                guard let url = URL(string: "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=\(API_Key)") else {
                    completion(nil)
                    return
                }
                var request = URLRequest(url: url)
                request.httpMethod = "POST"
                let task = URLSession.shared.dataTask(with: request) { data, response, error in
                    guard let data = data, error == nil else {
                        completion(nil)
                        return
                    }
                    do {
                        if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
                           let idToken = json["idToken"] as? String {
                            completion(idToken)
                        } else {
                            completion(nil)
                        }
                    } catch {
                        completion(nil)
                    }
                }
                task.resume()
            }
        func sendPushNotification(to token: String, title: String, body: String) {
                getFirebaseBearerToken { bearerToken in
                    guard let bearerToken = bearerToken else {
                        print("Failed to retrieve Bearer token.")
                        return
                    }
                    
                    let urlString = "https://fcm.googleapis.com/v1/projects/myprojectID-99a99/messages:send"
    
                    guard let url = URL(string: urlString) else {
                        print("@@Invalid URL")
                        return
                    }
    
                    let payload: [String: Any] = [
                        "message": [
                            "token": token,
                            "notification": [
                                "title": title,
                                "body": body
                            ]
                        ]
                    ]
    
                    let jsonData = try? JSONSerialization.data(withJSONObject: payload)
    
                    var request = URLRequest(url: url)
                    request.httpMethod = "POST"
                    request.httpBody = jsonData
                    request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
                    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
                    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
                        if let error = error {
                            print("Error: \(error.localizedDescription)")
                            return
                        }
    
                        if let data = data {
                            do {
                                let responseJSON = try JSONSerialization.jsonObject(with: data, options: [])
                                print("Response: \(responseJSON)")
                            } catch {
                                print("Error parsing response JSON: \(error.localizedDescription)")
                            }
                        }
                    }
                    task.resume()
                }
            }
    }
    

    So the code for sending is:

    let pushSender = PushNotificationSender()
    pushSender.sendPushNotification(to: "DEVICE_TOKEN", title: "Hello", body: "Sample Notification")
    

    If the Firebase SDK is installed in Package Dependencies, there is no need to retrieve the bearer. Firebase manages that himself. otherwise, my solution can be used.