[C#][Javascript] 簡單實作 Web 推送 - Web Push Notification by Firebase.

2018-01-10

現在網路上很多網站都在做 Notification , 至於要怎麼推送呢 ?  當然你也可以自己去實作 很多東西 去實作,但是我這邊是用網路上最多人用的 Google Firebase Messaging 去實作他..

image

關於顯示通知的一些相關你可以先參考這篇文章 對你會有些許幫助 :  http://no2don.blogspot.com/2018/01/javascript.html

Step 1. 去這邊申請一個新的專案 https://console.firebase.google.com

Image 593

之後 按下專案設定 ,你要的資訊都在這裡…
Image 594


Step 2. 拿到專案的 設定 Code ,在 firebase console 你會看這裡 點下去

Image 596

你就會拿到 firebase init 的 code :

image

文中範例為 :

<script src="https://www.gstatic.com/firebasejs/4.8.1/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "AIzaSyCjRf8Ulp2PKtZO-FWh6OAB8_ig2GJMZAU",
    authDomain: "donma-test-web-push.firebaseapp.com",
    databaseURL: "https://donma-test-web-push.firebaseio.com",
    projectId: "donma-test-web-push",
    storageBucket: "donma-test-web-push.appspot.com",
    messagingSenderId: "548756765078"
  };
  firebase.initializeApp(config);
</script>

  再來就是寫 Code 的部分

Step 3 . 首先引入 scripts

    <!-- Scripts -->
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/4.8.1/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js"></script>


之後要 Init firebase ,這要放在主要運行的 .html 中
        var messaging = null;

        $(document).ready(function () {


            var config = {
                apiKey: "AIzaSyCjRf8Ulp2PKtZO-FWh6OAB8_ig2GJMZAU",
                authDomain: "localhost:61441",
                databaseURL: "https://donma-test-web-push.firebaseio.com",
                projectId: "donma-test-web-push",
                storageBucket: "donma-test-web-push.appspot.com",
                messagingSenderId: "548756765078"
            };

            firebase.initializeApp(config);


            messaging = firebase.messaging();

            //收到訊息後的處理
            messaging.onMessage(function (payload) {
                //Log
                $('#log').prepend("Message received :" + JSON.stringify(payload) + "<br><br>")

                //如果可以顯示通知就做顯示通知
                if (Notification.permission === 'granted') {
                    ShowNotification(payload.data.title, payload.data.body);
                    //三秒後自動關閉
                    setTimeout(notification.close.bind(notification), 3000);
                }
            });


        });

之後就是去要 user token ,簡單的說 ,你得透過 firebase 取的一個 此device 之於你這專案 的一個獨一無二的 token ,並且送回給 server 你保存這 user token 之後你可以對 firebase 進行推送你要的資料 …

取得 user token 的  javascript code :

        function RegistUserTokenToSelfServer(user_token, successFunc, errorFunc) {
            var $res = '';
            $.ajax({
                type: "POST",
                url: "receive_user_token.aspx",
                contentType: 'application/x-www-form-urlencoded',
                async: true,
                cache: false,
                dataType: 'text',
                data: { user_token: user_token },
                success: function (data) {
                    if (data.hasOwnProperty("d")) {
                        $res = data.d;
                        if (successFunc != null)
                            successFunc(data.d);
                    }
                    else {
                        $res = data;
                        if (successFunc != null)
                            successFunc(data);
                    }
                },
                error: function (e) {
                    if (errorFunc != null)
                        errorFunc(e);
                }


            });
            return $res;
        }


        $('#btnStarGetTokenAndReceivePush').click(function () {

            messaging.getToken()
                .then(function (currentToken) {
                    $('#log').append("TOKEN: " + currentToken + "<br><br>")
                    if (currentToken) {
                        RegistUserTokenToSelfServer(currentToken, function (result) {
                            $('#log').prepend("送回給自己 Server 的結果 :" + result + "<br><br>")
                        });
                    } else {
                        $('#log').prepend('註冊失敗請檢查相關設定.');
                    }
                })
                .catch(function (err) {

                    $('#log').prepend("跟 Server 註冊失敗 原因:" + err + "<br>");
                });

        });

其中取得 token 後我是透過 ajax 送回給 server 所以會有上面 RegistUserTokenToSelfServer 的 function
呼叫的 receive_user_token.aspx 的 soure code

using System;

namespace CSharp_Web_Notification_Sample
{
    public partial class receive_user_token : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(Request["user_token"]))
            {

                System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "user_token");

                System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "user_token" + System.IO.Path.DirectorySeparatorChar + GetMD5String(Request["user_token"]), Request["user_token"]);

                Response.Write("SUCCESS");
            }
            else
            {
                Response.Write("ERROR");
            }
        }

        public string GetMD5String(string input)
        {
            var md5 = System.Security.Cryptography.MD5.Create();
            var sb = new System.Text.StringBuilder();
            for (int i = 0; i < md5.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input)).Length; i++)
            {
                sb.Append(md5.ComputeHash(System.Text.Encoding.ASCII.GetBytes(input))[i].ToString("X2"));
            }
            return sb.ToString();

        }

    }
}

這邊我先把所有 user key 都用檔案存起來,之後就是全部讀取後推送

Step 4 . 這一點就比較 tricky ,基本上要註冊 service wroker 在前端,所以你得在專案目錄下面 建立一個 firebase-messaging-sw.js 內容的 code :

importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');

var config = {
    messagingSenderId: "548756765078"
};

firebase.initializeApp(config);
messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
    console.log('Received background message ', payload);

});

console.log("Loaded SW..");

再來 要建立網站的 manifest.json  你可以透過 http://favicon-generator.org 這網站去建立,其實很方便,你只要在他給你的 manifest.json 加入 "gcm_sender_id": "103953800507" 就可以了

image

之後我們來看如何推送

Step 5. 推送 C# Code :

        protected void btnPushAllUsers_Click(object sender, EventArgs e)
        {

            string serverKey = "AAAAf8RzuZY:.... Server 密鑰";

            var files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "user_token");

            var wc = new System.Net.WebClient();
            wc.Headers.Add("Authorization", "key="+ serverKey);
            wc.Headers.Add("Content-Type", "application/json");
            wc.Encoding = System.Text.Encoding.UTF8;

            if (files != null)
            {

                foreach (var file in files)
                {

                    var token = System.IO.File.ReadAllText(file);
                    Response.Write("TOKEN:" + token.ToString() + "<br>");


                    var d = new PushRequestInfo();
                    d.registration_ids = new List<string>();
                    d.registration_ids.Add(token);

                    d.priority = "normal";
                    d.data = new Data();
                    d.data.body = "Donma TEST";
                    d.data.title = "HI,許當麻";

                    var res = wc.UploadString("https://fcm.googleapis.com/fcm/send", Newtonsoft.Json.JsonConvert.SerializeObject(d));
                    Response.Write(res + "<br><br>");
                }
            }
        }


結果:

image


全部的 source code :

https://github.com/donma/CSharp-Firebase-Web-Notification-Sample


Rerfernce :


Sending your first message : https://github.com/tiagomtotti/firebaseNet

FCM Sever :https://firebase.google.com/docs/cloud-messaging/server?hl=zh-cn

Sample : https://github.com/realtime-framework/WebPushNotifications/blob/master/service-worker.js

Spec : https://firebase.google.com/docs/cloud-messaging/http-server-ref#downstream-http-messages-json


好用的測試Tool: https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo


參考 : http://jasonchiucc.github.io/2016/07/11/firebase-tutorial-cloud-messaging/


當麻許的超技八 2014 | Donma Hsu Design.