0

I have to send push notifications for pkPasses on iOS devices.

I have found a code on git hub.

Using SendEmptyPushNotification method for sending push notification. I am sending PushToken for deviceIdentifier
But its not working. Sometimes this code is taking too much time and sometimes it takes no time. But in both the cases i am not able to get any push notification on my iOS device. I really stuck here. Can anyone help??

public class IPhonePushNotificationService
{
    public void SendEmptyPushNotification(string deviceIdentifier, string thumbprint)
    {
        string server = "gateway.push.apple.com";
        using (TcpClient tcpClient = new TcpClient(server, 2195))
        {
            Trace.TraceInformation("Opening SSL Connection...");
            using (SslStream sslStream = new SslStream(tcpClient.GetStream()))
            {
                try
                {
                    X509Certificate2Collection certs = new X509Certificate2Collection();

                    Trace.TraceInformation("Adding certificate to connection...");
                    X509Certificate cert = GetAppleServerCert(thumbprint);
                    certs.Add(cert);

                    Trace.TraceInformation("Authenticating against the SSL stream...");
                    sslStream.AuthenticateAsClient(server, certs, SslProtocols.Default, false);
                }
                catch (AuthenticationException exp)
                {
                    Trace.TraceError("Failed to authenticate to APNS - {0}", exp.Message);
                    return;
                }
                catch (IOException exp)
                {
                    Trace.TraceError("Failed to connect to APNS - {0}", exp.Message);
                    return;
                }

                byte[] buf = new byte[256];
                MemoryStream ms = new MemoryStream();
                BinaryWriter bw = new BinaryWriter(ms);
                bw.Write(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32 });

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

                string msg = "{}";

                bw.Write(new byte[] { 0, 2 });
                bw.Write(msg.ToCharArray());
                bw.Flush();

                Trace.TraceInformation("Message sent. Closing stream...");

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

                byte[] response = new byte[6];
                sslStream.Read(response, 0, 6);

                sslStream.Flush();
            }
        }
    }

    private static X509Certificate GetAppleServerCert(string thumbprint)
    {
        X509Store store;
        store = new X509Store(StoreLocation.CurrentUser);

        if (store != null)
        {
            store.Open(OpenFlags.ReadOnly);

            X509Certificate2Collection certs = store.Certificates;

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

                    if (cert.Thumbprint.Equals(thumbprint, StringComparison.InvariantCultureIgnoreCase))
                    {
                        return certs[i];
                    }
                }
            }
        }

        Trace.TraceError("Could not find the certification containing: {0} ", "R5QS56362W:R5QS56362W");

        throw new InvalidDataException("Could not find the Apple Push Notification certificate");
    }

    private static 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;
    }
  • What certificate are you using? You need to use the PassTypeID Certificate to connect to APNS. – PassKit Apr 25 '18 at 13:31
  • Yes I am using the PassTypeID certificate. At the time of certificate creation it was showing for Production only, there was no option for development. And I am using http at server. Could it be an issue?? – Sam Khan Apr 27 '18 at 06:35
  • Yes http will be a problem unless you have enabled http for Wallet in the developer options on your iPhone. – PassKit Apr 27 '18 at 06:37
  • Yes http is enabled in the developer options in iPhone – Sam Khan Apr 27 '18 at 07:25
  • Other methods of pkpass like registration and update are working correctly, I am able to get the Push Token every time a pass gets added in iPhone. Its just push notification not working. One more thing i have noticed that when I add certificate from [apple.com/certificateauthority](http://www.apple.com/certificateauthority/) WWDR expiry 23. The send notification code gets crashed. Showing exception _'Certificate could not be found. Please ensure the thumbprint and cert location values are correct._ – Sam Khan Apr 27 '18 at 12:10
  • Does pulling down on the back refresh the pass? Also, just to check, is the new pass different to the old pass and has a changeMessage set? – PassKit Apr 27 '18 at 13:03
  • Yes Refresh is working and when I set changeMessage key it shows a local notification. But I want push notification. – Sam Khan Apr 27 '18 at 13:11
  • So that confirms your web service is functioning properly. Your issue must be with the call to APNS. If you are using the correct certificate to connect, then the only thing I can suggest is to add some logging. – PassKit Apr 27 '18 at 13:15

0 Answers0