# .Net Core 後台FCM推播 ###### tags: `.net core` `FCM` `推播` 使用Firebase進行推播,方法相當單純 [chrome推播測試工具](https://github.com/GoogleChrome/chrome-extensions-samples) [工具使用說明](https://ithelp.ithome.com.tw/articles/10211813) ## 在FireBase上建立專案 https://console.firebase.google.com/ 建立好的樣子 ![](https://i.imgur.com/wFWF4ls.jpg) ## 使用FirebaseAdmin 需安裝套件FirebaseAdmin https://firebase.google.com/docs/cloud-messaging/send-message?authuser=0#admin_sdk_error_reference https://github.com/firebase/firebase-admin-dotnet/blob/d44de7bb50bedec5ff1ee5944d7eecd064b068e6/FirebaseAdmin/FirebaseAdmin.Snippets/FirebaseMessagingSnippets.cs#L327-L341 ### 啟動FirebaseAdmin ### 建立私鑰 產生私鑰後會下載私鑰的json檔案 ![](https://i.imgur.com/6GilJ2M.jpg) ### 服務初始化 可在需要時才執行來開啟,此處選擇網站開啟時即啟動(重複啟動會報錯)! #### Program.cs(.Net 5以下Startup) ``` string path = builder.Environment.ContentRootPath + "firebase-adminsdk.json"; FirebaseApp.Create(new AppOptions() { Credential = GoogleCredential.FromFile(path), ServiceAccountId = "firebase-adminsdk-qfvow@fir-test-1c603.iam.gserviceaccount.com", }); ``` ### 對單一設備發送請求 ``` var message = new Message() { Data = new Dictionary<string, string>() { { "score", "850" }, { "time", "2:45" }, }, Token = "", }; string response = await FirebaseMessaging.DefaultInstance.SendAsync(message); ``` ### 對多個設備發送請求 ``` var registrationTokens = new List<string>() { "YOUR_REGISTRATION_TOKEN_1", // ... "YOUR_REGISTRATION_TOKEN_n", }; var message = new MulticastMessage() { Tokens = registrationTokens, Data = new Dictionary<string, string>() { { "score", "850" }, { "time", "2:45" }, }, }; var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message); ``` ### 設備主題註冊與取消註冊 ``` [HttpPost] //主題註冊 public async Task<string> SubscribeToTopicAsync([FromBody] DeviceRegistrationModel request) { var response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(request.DeviceId, request.Topic); return response.ToString(); } [HttpPost] //取消註冊 public async Task<string> UnsubscribeFromTopicAsync([FromBody] DeviceRegistrationModel request) { var response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(request.DeviceId, request.Topic); return response.ToString(); } ``` ### 對主題進行推播 ``` var message = new Message() { Data = new Dictionary<string, string>() { { "score", "850" }, { "time", "2:45" }, }, Topic = topic, }; // Send a message to the devices subscribed to the provided topic. string response = await FirebaseMessaging.DefaultInstance.SendAsync(message); ``` ## 使用FirebaseApi ### 1.點選齒輪進入專案設定 ![](https://i.imgur.com/ZLpvykF.jpg) ### 2.在雲端通訊建立伺服器金鑰 建立好金鑰之後,伺服器金鑰跟寄件者ID就是我們後端會用到的東西了。 ![](https://i.imgur.com/5FqLB2A.jpg) 可以將金鑰跟senderId寫入appsetting EX:`_configuration["FCM:SenderId"]` ### 3.後端內容 ``` [HttpPost] public string SendPushNotification([FromBody] NotificationData request) { try { //FCM伺服器金鑰 string applicationID = "AAAASLO7bNM:APA91bHeSO8oechmbvPkVaIe9_BAAuZsXFax9YK6LH9AJAVS4_LVKyIy0w9xCx1dG-JRdazIjqyu9IjxSMJXorBh-lHPJ7LrpddZT_L65lmNZGy2FFyW6p1TstN1mZ8dVjKWIj4nFRtp"; //SenderId string senderId = "312253050067"; //Service url string url = "https://fcm.googleapis.com/fcm/send"; //設備ID string deviceId = null; if (request.topic) deviceId = "/topics/" + request.DeviceId; else deviceId = request.DeviceId; //要推播的資料 var data = new { to = deviceId, notification = new { body = request.Body, title = request.Title, sound = "Enabled" }, }; var json = JsonConvert.SerializeObject(data); Byte[] byteArray = Encoding.UTF8.GetBytes(json); HttpClient client = new HttpClient(); var httpRequestMessage = new HttpRequestMessage(); httpRequestMessage.Method = HttpMethod.Post; httpRequestMessage.RequestUri = new Uri(url); httpRequestMessage.Content = new StringContent(json, Encoding.UTF8, "application/json"); httpRequestMessage.Headers.Add(HttpRequestHeader.ContentType.ToString(), "application/json"); httpRequestMessage.Headers.TryAddWithoutValidation("Authorization",string.Format("key={0}", applicationID)); httpRequestMessage.Headers.TryAddWithoutValidation("Sender", string.Format("id={0}", senderId)); //Sender沒有也沒關係,為了防止之後需要一樣寫出來註記 httpRequestMessage.Headers.Add(HttpRequestHeader.ContentLength.ToString(), byteArray.Length.ToString()); HttpResponseMessage response = client.SendAsync(httpRequestMessage).Result; if(response.StatusCode == HttpStatusCode.OK) { //return "推播成功"; return response.ReasonPhrase.ToString(); } else { return response.ReasonPhrase.ToString(); } } catch (Exception ex) { Console.WriteLine("{0:s}推播失敗:{1}", DateTime.Now, ex.Message); return ex.Message; } } ``` ### Model ``` public class NotificationData { public string DeviceId { get; set; } public string Title { get; set; } public string Body { get; set; } public bool topic { get; set; } } ```