How to write an Apple Push Notification Provider in C#?

后端 未结 5 1226
感动是毒
感动是毒 2020-12-02 06:31

Apple really had bad documentation about how the provider connects and communicates to their service (at the time of writing - 2009). I am confused about the protocol. How i

相关标签:
5条回答
  • 2020-12-02 07:00
      public ActionResult ios()
        {
            string message = string.Empty;
    
            var certi = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Certificates2.p12");
            var appleCert = System.IO.File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Certificates2.p12"));
    
            ApnsConfiguration apnsConfig = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Production, appleCert, "Password");
    
            var apnsBroker = new ApnsServiceBroker(apnsConfig);
            apnsBroker.OnNotificationFailed += (notification, aggregateEx) =>
            {
                aggregateEx.Handle(ex =>
                {
                    if (ex is ApnsNotificationException)
                    {
                        var notificationException = (ApnsNotificationException)ex;
                        var apnsNotification = notificationException.Notification;
                        var statusCode = notificationException.ErrorStatusCode;
                        var inner = notificationException.InnerException;
                        message = "IOS Push Notifications: Apple Notification Failed: ID=" + apnsNotification.Identifier + ", Code=" + statusCode + ", Inner Exception" + inner;
                    }
                    else
                    {
                        message = "IOS Push Notifications: Apple Notification Failed for some unknown reason : " + ex.InnerException;
                    }
                    return true;
                });
            };
    
            apnsBroker.OnNotificationSucceeded += (notification) =>
            {
                message = "IOS Push Notifications: Apple Notification Sent!";
            };
    
            apnsBroker.Start();
            try
            {
                string deviceToken = "33c2f3a13c90dc62660281913377c22066c1567e23c2ee2c728e0f936ff3ee9b";
    
                apnsBroker.QueueNotification(new ApnsNotification
                {
                    DeviceToken = deviceToken,
                    Payload = JObject.Parse("{\"aps\":{\"alert\":\" Test Message\", \"badge\":1, \"sound\":\" default\",}}")
                });
            }
            catch (Exception ex)
            {
                Console.Write(ex);
            }
            apnsBroker.Stop();
    
            return View(message);
        }
    
    0 讨论(0)
  • 2020-12-02 07:02

    Working code example:

    int port = 2195;
    String hostname = "gateway.sandbox.push.apple.com";
    
    //load certificate
    string certificatePath = @"cert.p12";
    string certificatePassword = "";
    X509Certificate2 clientCertificate = new X509Certificate2(certificatePath, certificatePassword);
    X509Certificate2Collection certificatesCollection = new X509Certificate2Collection(clientCertificate);
    
    TcpClient client = new TcpClient(hostname, port);
    SslStream sslStream = new SslStream(
            client.GetStream(),
            false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate),
            null
    );
    
    try
    {
        sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls, true);
    }
    catch (AuthenticationException ex)
    {
        client.Close();
        return;
    }
    
    // Encode a test message into a byte array.
    MemoryStream memoryStream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(memoryStream);
    
    writer.Write((byte)0);  //The command
    writer.Write((byte)0);  //The first byte of the deviceId length (big-endian first byte)
    writer.Write((byte)32); //The deviceId length (big-endian second byte)
    
    String deviceId = "DEVICEIDGOESHERE";
    writer.Write(ToByteArray(deviceId.ToUpper()));
    
    String payload = "{\"aps\":{\"alert\":\"I like spoons also\",\"badge\":14}}";
    
    writer.Write((byte)0); //First byte of payload length; (big-endian first byte)
    writer.Write((byte)payload.Length); //payload length (big-endian second byte)
    
    byte[] b1 = System.Text.Encoding.UTF8.GetBytes(payload);
    writer.Write(b1);
    writer.Flush();
    
    byte[] array = memoryStream.ToArray();
    sslStream.Write(array);
    sslStream.Flush();
    
    // Close the client connection.
    client.Close();
    
    0 讨论(0)
  • 2020-12-02 07:09

    I hope this is relevant (slightly), but I have just successfully created one for Java, so conceptually quite similar to C# (except perhaps the SSL stuff, but that shouldn't be too hard to modify. Below is a sample message payload and crypto setup:

        int port = 2195;
        String hostname = "gateway.sandbox.push.apple.com";
    
    
        char []passwKey = "<keystorePassword>".toCharArray();
        KeyStore ts = KeyStore.getInstance("PKCS12");
        ts.load(new FileInputStream("/path/to/apn_keystore/cert.p12"), passwKey);
    
        KeyManagerFactory tmf = KeyManagerFactory.getInstance("SunX509");
        tmf.init(ts,passwKey);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(tmf.getKeyManagers(), null, null);
        SSLSocketFactory factory =sslContext.getSocketFactory();
        SSLSocket socket = (SSLSocket) factory.createSocket(hostname,port); // Create the ServerSocket
        String[] suites = socket.getSupportedCipherSuites();
        socket.setEnabledCipherSuites(suites);
        //start handshake
    
        socket.startHandshake();
    
    
        // Create streams to securely send and receive data to the server
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
    
    
    
        // Read from in and write to out...
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos.write(0); //The command
        System.out.println("First byte Current size: " + baos.size());
    
        baos.write(0); //The first byte of the deviceId length    
        baos.write(32); //The deviceId length
    
        System.out.println("Second byte Current size: " + baos.size());
    
        String deviceId = "<heaxdecimal representation of deviceId";
        baos.write(hexStringToByteArray(deviceId.toUpperCase()));
        System.out.println("Device ID: Current size: " + baos.size());
    
    
        String payload = "{\"aps\":{\"alert\":\"I like spoons also\",\"badge\":14}}";
        System.out.println("Sending payload: " + payload);
        baos.write(0); //First byte of payload length;
        baos.write(payload.length());
        baos.write(payload.getBytes());
    
        out.write(baos.toByteArray());
        out.flush();
    
        System.out.println("Closing socket..");
        // Close the socket
        in.close();
        out.close();
    

    }

    Once again, not C#, but at least closer than the poor ObjC sample that Apple provides.

    0 讨论(0)
  • 2020-12-02 07:10

    You can use the PushSharp library in GitHub.

    I am using it in all of my projects

    0 讨论(0)
  • 2020-12-02 07:25

    The best APNSSharp project available on Github. It worked for me absolutely fine in just couple of minutes!

    0 讨论(0)
提交回复
热议问题