2009-06-20 12 views
13

Apple ha davvero una cattiva documentazione su come il provider si connette e comunica al proprio servizio (al momento della stesura di questo documento - 2009). Sono confuso riguardo al protocollo. Se qualcuno là fuori potrebbe fornire un campione in C# di come è fatto, sarebbe molto apprezzato.Qualcuno sa come scrivere un Apple Push Notification Provider in C#?

+1

A mio parere, la documentazione di Apple è abbastanza chiaro: http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/ RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html # // apple_ref/doc/uid/TP40008194-CH101-SW1 – Linulin

+0

Questa risposta è stata scelta molto tempo fa. Guarda anche la risposta di shay - http://stackoverflow.com/a/36963561/19854 Se stai cercando un modo manuale per scrivere questo codice, guarda la risposta scelta in origine: http://stackoverflow.com/a/1077664/19854 – Phobis

risposta

23

lavoro esempio:.

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

maggiori informazioni: http://x-cake.ning.com/profiles/blogs/setting-up-a-push-notification – SteveCav

+0

quale lingua è questa? Immagino sia Java, ma ho bisogno di una conferma. –

+1

è C# che è asp.net – Summit

6

Spero che questo sia rilevante (leggermente), ma ne ho appena creato uno per Java, quindi concettualmente abbastanza simile a C# (eccetto forse il materiale SSL, ma non dovrebbe essere troppo difficile da modificare. campione messaggio payload e crypto configurazione:

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 il codice almeno più vicino di quanto il campione poveri objC che Apple fornisce

+0

Sto ancora cercando di farlo funzionare. Ho duplicato il tuo codice in C#, ma dal momento che .NET utilizza un diverso tipo di oggetto per connettersi tramite SSL "SSLStream" non ha un metodo "handshake". Non riesco a capire come ottenere la corretta stretta di mano. – Phobis

+0

Guarda qui: http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx (circa tre quarti della pagina in basso, c'è un esempio di handshake del client C# SSL, usando SSLStream Sembra essere il modo per farlo, a prima vista (una richiamata) – Chaos

+0

Questo è sbagliato: non sta creando un socket del server, ma sta creando un socket client. ts e tmf sono talvolta usati per fare riferimento a "trust store" "e" fabbrica di fiducia manager ", ma qui si riferiscono al materiale chiave del client ... davvero strano – erickson

2

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

1

È possibile utilizzare la libreria PushSharp in GitHub.

Io lo utilizzo in tutti i miei progetti

0
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

Sebbene questo codice possa rispondere alla domanda, sarebbe meglio spiegare come risolve il problema senza introdurre gli altri e perché utilizzarlo. Le risposte al solo codice non sono utili a lungo termine. – Mateus