-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPushNotificationService.swift
More file actions
165 lines (140 loc) · 6.06 KB
/
PushNotificationService.swift
File metadata and controls
165 lines (140 loc) · 6.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//
// PushNotificationService.swift
// RealEstate
//
// Created by xqsadness on 30/10/24.
//
//Migrate from Legacy FCM APIs to HTTP v1
import Foundation
//pod or package https://github.com/Kitura/Swift-JWT
import SwiftJWT
fileprivate struct ServiceAccountCredentials: Codable {
let type: String
let project_id: String
let private_key_id: String
let private_key: String
let client_email: String
let client_id: String
let auth_uri: String
let token_uri: String
let auth_provider_x509_cert_url: String
let client_x509_cert_url: String
}
fileprivate struct GoogleJWTClaims: Claims {
let iss: String
let scope: String
let aud: String
let iat: Date
let exp: Date
}
struct PushNotificationService{
static let shared = PushNotificationService()
private init(){}
func getAccessToken(completion: @escaping (String?) -> Void) {
//PrivateKey is json file can download in Firebase console -> Project settings -> Service accounts -> generate new private key and then add it to your project.
guard let serviceAccountPath = Bundle.main.path(forResource: "PrivateKey", ofType: "json"),
let credentialsData = try? Data(contentsOf: URL(fileURLWithPath: serviceAccountPath)),
let credentials = try? JSONDecoder().decode(ServiceAccountCredentials.self, from: credentialsData) else {
completion(nil)
return
}
let iat = Date()
let exp = iat.addingTimeInterval(3600) // Token expired after 1 hour
let claims = GoogleJWTClaims(
iss: credentials.client_email,
scope: "https://www.googleapis.com/auth/cloud-platform",
aud: credentials.token_uri,
iat: iat,
exp: exp
)
var jwt = JWT(claims: claims)
let privateKeyString = credentials.private_key
.replacingOccurrences(of: "-----BEGIN PRIVATE KEY-----", with: "")
.replacingOccurrences(of: "-----END PRIVATE KEY-----", with: "")
.replacingOccurrences(of: "\n", with: "")
guard let privateKeyData = Data(base64Encoded: privateKeyString) else {
completion(nil)
return
}
let signer = JWTSigner.rs256(privateKey: privateKeyData)
do {
let jwtString = try jwt.sign(using: signer)
// request to endpoint for get access token
var request = URLRequest(url: URL(string: credentials.token_uri)!)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let bodyString = "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=\(jwtString)"
request.httpBody = bodyString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("Error fetching access token: \(error?.localizedDescription ?? "Unknown error")")
completion(nil)
return
}
// Parse response to extract the access token
if let json = try? JSONSerialization.jsonObject(with: data, options: []),
let dictionary = json as? [String: Any],
let accessToken = dictionary["access_token"] as? String {
completion(accessToken)
} else {
completion(nil)
}
}
task.resume()
} catch {
print("Error creating JWT: \(error)")
completion(nil)
}
}
func sendNotificationMessage(to token: String, title: String, body: String) {
let projectID = "YOUR_PROJECT_ID" // Get in Firebase console -> Project settings
let url = URL(string: "https://fcm.googleapis.com/v1/projects/\(projectID)/messages:send")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
let message: [String: Any] = [
"message": [
"token": token,
"notification": [
"title": title,
"body": body
],
"data": [
"title": title,
"body": body,
"name" : "your_name"
// add some data if needed
]
]
]
request.httpBody = try? JSONSerialization.data(withJSONObject: message, options: [])
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error sending notification: \(error.localizedDescription)")
return
}
if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
print("Notification sent successfully with image and sound!")
} else {
print("Failed to send notification. Status code: \(httpResponse.statusCode)")
if let data = data,
let responseBody = String(data: data, encoding: .utf8) {
print("Error response body: \(responseBody)")
}
}
}
}
task.resume()
}
}
//MARK: - USAGE
//PushNotificationService.shared.getAccessToken { accessToken in
// guard let token = accessToken else {
// print("Failed to retrieve access token.")
// return
// }
// let toFcmToken = "FCM_TOKEN_DEVICE_HERE"
// PushNotificationService.shared.sendNotificationMessage(to: toFcmToken, title: "Test title", body: "Test body",accessToken: token)
//}