Saturday, August 3, 2013

Send APNS- Push Notification on Apple device using C#.NET

Send APNS- Push Notification on Apple device using C#.NET : 

=======================
Please, Install your certificate *.p12 on pc, and take firend name use here for refernce.
Please, set configuration file :

 <appSettings>
 <add key="FriendName" value="Apple Production IOS Push Services: com.ABC.XYZ"/>
    <add key="ProductionKeyFriendName" value="Production"/>  
  </appSettings>
==============
Send, push as per below in your class to call apns class:
   Cls_APNS _Cls_APNS = new class_apns();
  //Here pass custom fiels as per seprated by ";" ann asssigb value by "key=value;key=value"
   _Cls_APNS.PushMessage("Message","DeviceToken",0,"id=12;name=ABC");
==================
Please create a class as per below (class_apns.cs). :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Configuration;
using System.Data;
using System.Security.Authentication;
using System.IO;

namespace Push.Class
{
    public class class_apns
    {
        String CertificateName = "";
        String CertificatePwd = "";
        String FriendName = "Apple Development IOS Push Services: com.ABC.XYZ";
        String ProductionKeyFriendName = "Production";
        SslStream sslStream;    

        public Cls_APNS()
        {                
            FriendName = ConfigurationManager.AppSettings["FriendName"].ToString();
            ProductionKeyFriendName = ConfigurationManager.AppSettings["ProductionKeyFriendName"].ToString();        
        }

        public bool ConnectToAPNS()
        {
            X509Certificate2Collection certs = new X509Certificate2Collection();

            // Add the Apple cert to our collection
            certs.Add(getServerCert());

            // Apple development server address
            string apsHost;

            if (getServerCert().ToString().Contains(ProductionKeyFriendName))
                apsHost = "gateway.push.apple.com";
            else
                apsHost = "gateway.sandbox.push.apple.com";

            // Create a TCP socket connection to the Apple server on port 2195
            TcpClient tcpClient = new TcpClient(apsHost, 2195);

            // Create a new SSL stream over the connection
            sslStream = new SslStream(tcpClient.GetStream());

            // Authenticate using the Apple cert
            sslStream.AuthenticateAsClient(apsHost, certs, SslProtocols.Default, false);

            //PushMessage();

            return true;
        }

        private X509Certificate getServerCert()
        {
            X509Certificate test = new X509Certificate();

            //Open the cert store on local machine        
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

            if (store != null)
            {
                // store exists, so open it and search through the certs for the Apple Cert        
                store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
                X509Certificate2Collection certs = store.Certificates;

                if (certs.Count > 0)
                {
                    int i;
                    for (i = 0; i < certs.Count; i++)
                    {
                        X509Certificate2 cert = certs[i];

                        if (cert.FriendlyName.Contains(FriendName))
                        {
                            //Cert found, so return it.
                            return certs[i];
                        }
                    }
                }
                return test;
            }
            return test;
        }

        private  byte[] HexToData(string hexString)
        {
            if (hexString == null)
                return null;

            if (hexString.Length % 2 == 1)
                hexString = '0' + hexString; // Up to you whether to pad the first or last byte

            byte[] data = new byte[hexString.Length / 2];

            for (int i = 0; i < data.Length; i++)
                data[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

            return data;
        }

        public bool PushMessage(string Mess, string DeviceToken, int Badge, string Custom_Field)
        {              
            ConnectToAPNS();    
            List<string> Key_Value_Custom_Field = new List<string>();
            String cToken = DeviceToken;
            String cAlert = Mess;
            int iBadge = Badge;

            // Ready to create the push notification
            byte[] buf = new byte[256];
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);
            bw.Write(new byte[] { 0, 0, 32 });

            byte[] deviceToken = HexToData(cToken);
            bw.Write(deviceToken);

            bw.Write((byte)0);

            // Create the APNS payload - new.caf is an audio file saved in the application bundle on the device
            string msg = "";      
           msg = "{\"aps\":{\"alert\":\"" + cAlert + "\",\"badge\":\"" + iBadge.ToString() + "\",\"sound\":\"noti.aiff\"}";
       
            String PayloadMess = "";
            if (string.IsNullOrWhiteSpace(Custom_Field) == false)
            {
                List<string> list_Custom_Field = Custom_Field.Split(';').ToList();

                if (list_Custom_Field.Count > 0)
                {
                    for (int indx = 0; indx < list_Custom_Field.Count; indx++)
                    {
                        Key_Value_Custom_Field = list_Custom_Field[indx].Split('=').ToList();
                        if (Key_Value_Custom_Field.Count > 1)
                        {
                            if (PayloadMess != "") PayloadMess += ", ";                        
                            PayloadMess += "\"" + Key_Value_Custom_Field[0].ToString() + "\":\"" + Key_Value_Custom_Field[1].ToString() + "\"";
                        }
                    }
                }
            }

            if (PayloadMess != "")
            {
                msg += ", " + PayloadMess;
            }
            msg += "}";

            // Write the data out to the stream
            bw.Write((byte)msg.Length);
            bw.Write(msg.ToCharArray());
            bw.Flush();

            if (sslStream != null)
            {
                sslStream.Write(ms.ToArray());
                return true;
            }

            return false;
        }  
 
    }
}

10 comments:

  1. Hi,

    when i have uese this code irst of all i caan't get friendly name on the file.

    and when i install p12 file it shows the file is empty.

    ReplyDelete
  2. I have installed .p12
    But I don't know the Friendly name. Is it .p12 path or else?
    and What should be ProductionKeyFriendName?

    I am getting error on below line.
    sslStream.AuthenticateAsClient(apsHost, certs, SslProtocols.Default, false);

    Error: "a call to sspi failed see inner exception"

    Need help to resolve above error.

    Thanks

    ReplyDelete
  3. Thanks for this piece of code Vikram, will you please tell me, what does the custom field and badge contain in this code ?

    ReplyDelete
  4. I struggled for the entire day trying to find a working code on the internet with no success. an hour ago I found your piece of art. It worked from the first hit. I can't thank you enough.

    ReplyDelete
  5. How do i add certificate Name and password manually because my server is not MAC.

    ReplyDelete
  6. Hi @vikram,
    Thanks for your excellent piece of code.Everything working fine for me.but i didn't get the notification.Any clue will be very helpful for us.

    We have using apns service with ionic framework(cordova application)

    ReplyDelete