Domanda

Apple aveva davvero una cattiva documentazione su come il provider si connette e comunica al suo servizio (al momento della scrittura - 2009). Sono confuso riguardo al protocollo. Come si fa in C #?

È stato utile?

Soluzione

Esempio di codice di lavoro:

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();

Altri suggerimenti

Spero che questo sia pertinente (leggermente), ma ne ho appena creato uno con successo per Java, quindi concettualmente abbastanza simile a C # (tranne forse roba SSL, ma non dovrebbe essere troppo difficile da modificare. Di seguito è riportato un esempio payload dei messaggi e configurazione crittografica:

    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();

}

Ancora una volta, non C #, ma almeno più vicino del povero campione ObjC fornito da Apple.

Il miglior APNSSharp disponibile su Github. Ha funzionato perfettamente per me in un paio di minuti!

Puoi utilizzare la libreria PushSharp in GitHub.

Lo sto usando in tutti i miei progetti

  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);
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top