1. 程式人生 > >APNs(Apple Push Notification server)伺服器程式碼C#編寫

APNs(Apple Push Notification server)伺服器程式碼C#編寫

使用最簡單的方式通過APNs傳送通知, 本庫使用C#寫的伺服器端程式碼,C/Objective-C客戶端程式碼

APNs 概述

Apple推送通知服務,是一個穩健性和高效率性的遠端通知,具有中心化的特性。APNs可以傳送通知訊息到iOS,WatchOS, tvOS 和macOS的裝置。 在應用初始化啟動時,會建立一個受信任的和加密的IP連結到APNs伺服器。APNs傳送通知是使用一個持久連線的方式。如果一個通知到達了使用者的裝置,但是應用沒有啟動,那麼裝置暫存通知,直到在合適的時間裡相應的應用去處理它。

另外,APNs和你的應用需要用通知來互動,所以你必須配置你自己的伺服器(公司的伺服器)作為原始傳送的通知的伺服器,叫做provider, 這個provider需要做到如下幾條
* 接收裝置的device token和傳送相關的通知到APNs,APNs會把相應的通知傳送給具體的裝置的具體應用
* 何時傳送遠端通知到使用者裝置上
* 構建JSON字典,該字典就是通知的payload, 用來描述通知的具體顯示
* 傳送正確的payload和device token到APNs伺服器
* 通過持久的和安全的通道傳送請求到APNs,使用HTTP/2網路協議

這裡寫圖片描述

  • 提供最簡單的方式傳送遠端通知到使用者的裝置,並且是C#寫的
  • 使用最簡單的C#/Objective-C程式碼去編寫,即時是新手也能很容易理解
  • 如果你是一名iOS開發者,那麼這個庫很方便與你的iOS測試
  • 如果你是一名ASP.NET/C#開發者,那麼這個庫很方便的讓你編寫APNs伺服器端程式碼

更多詳情,請看 這裡.

簡介

伺服器端程式碼(C#)
- 以下是一個最簡單的payload遠端通知

{"aps":{"alert":"This is a message for testing APNs","badge":123,"sound":"default"}}

這些標頭檔案需要被引用

using System;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
  • 讀取p12檔案,從Apple Developer Website下載的,變數certFilePath是p12證書的完整路徑,變數certPwd是證書密碼,以下是呼叫程式碼:
X509Certificate2 cert = new X509Certificate2(certFilePath, certPwd);
X509CertificateCollection certificate = new X509CertificateCollection();
certificate.Add(cert);
  • 然後,傳遞主機地址和埠,建立一個SslStream例項,並且握手,程式碼如下:
//釋出模式, 主機地址是 gateway.push.apple.com    
//開發模式, 主機地址是 gateway.sandbox.push.apple.com
TcpClient client = new TcpClient("gateway.push.apple.com", 2195);

SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ServerCertificateValidationCallback), null);

//方法AuthenticateAsClient()可能會引起異常,我們需要try..catch..起來
try
{
    //SslStream參考 
    //https://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

    sslStream.AuthenticateAsClient(_host, certificate, SslProtocols.Default, false);
}
catch (Exception e)
{
    Console.WriteLine("Exception Message: {0} ", e.Message);
    sslStream.Close();
}

//這是握手後的回撥
bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    if (sslPolicyErrors == SslPolicyErrors.None)
    {
        Console.WriteLine("Specified Certificate is accepted.");
        return true;
    }
    Console.WriteLine("Certificate error : {0} ", sslPolicyErrors);
    return false;
}
  • 構建payload字串,傳送遠端通知
//PushNotificationPayload是一個結構體的定義 
public struct PushNotificationPayload
{
    public string deviceToken;
    public string message;
    public string sound;
    public int badge;

    public string PushPayload()
    {
        return "{\"aps\":{\"alert\":\"" + message + "\",\"badge\":" + badge + ",\"sound\":\"" + sound + "\"}}";
    }
}

//把值賦給payload
PushNotificationPayload payload = new PushNotificationPayload();
payload.deviceToken = "dc67b56c eb5dd9f9 782c37fd cfdcca87 3b7bc77c 3b090ac4 c538e007 a2f23a24";
payload.badge = 56789;
payload.sound = "default";
payload.message = "This message was pushed by C# platform.";

//然後呼叫Push()方法
public void Push(PushNotificationPayload payload)
{
    string payloadStr = payload.PushPayload();
    string deviceToken = payload.deviceToken;

    MemoryStream memoryStream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(memoryStream);

    writer.Write((byte)0); //The command
    writer.Write((byte)0); //deviceId長度的第一個位元組,大頭位元組序第一個位元組
    writer.Write((byte)32); //deviceId長度,大頭位元組序第二個位元組

    //方法DataWithDeviceToken() , [具體看原始碼](https://github.com/Victor-Studio/PushNotification)
    byte[] deviceTokenBytes = DataWithDeviceToken(deviceToken.ToUpper());
    writer.Write(deviceTokenBytes);

    writer.Write((byte)0); //payload的長度的第一個位元組,大頭位元組序的第一個位元組
    writer.Write((byte)payloadStr.Length); //payload的長度,大頭位元組序的第二個位元組

    byte[] bytes = Encoding.UTF8.GetBytes(payloadStr);
    writer.Write(bytes);
    writer.Flush();

    _sslStream.Write(memoryStream.ToArray());
    _sslStream.Flush();

    Thread.Sleep(3000);

    //方法ReadMessage() , 具體看[本庫的原始碼](https://github.com/Victor-Studio/PushNotification)
    string result = ReadMessage(_sslStream);
    Console.WriteLine("server said: " + result);

    _sslStream.Close();
}

好了,就是這麼簡單,如果有疑問,歡迎在github上提問。
高手請略過