Apple hatte wirklich schlechte Dokumentation darüber, wie der Anbieter sich mit seinem Dienst verbindet und kommuniziert (zum Zeitpunkt des Schreibens - 2009). Ich bin verwirrt über das Protokoll. Wenn jemand da draußen ein C# -Probe zur Verfügung stellen könnte, wäre dies sehr zu begrüßen.Kann jemand einen Apple Push Notification Provider in C# schreiben?
Antwort
Arbeitscodebeispiel:.
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();
Ich hoffe, das ist relevant (leicht), aber ich habe gerade erfolgreich eine für Java, also konzeptionell ganz ähnlich wie C# (außer vielleicht die SSL-Zeug, aber das sollte nicht zu schwer zu ändern. Unten ist ein Beispielnachrichtennutzlast und Krypto-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();
}
wieder einmal nicht C#, aber zumindest näher als die Armen ObjC Probe, dass Apple bietet
Ich versuche immer noch, dies zur Arbeit zu bringen. Ich habe Ihren Code in C# dupliziert, aber da .NET eine andere Art von Objekt verwendet, um eine Verbindung über SSL "SSLStream" herzustellen, gibt es keine "Handshake" -Methode. Ich kann nicht herausfinden, wie man den richtigen Handshake zustande bringt. – Phobis
Schauen Sie hier: http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx (etwa drei Viertel der Seite nach unten, gibt es ein C# SSL-Client-Handshake-Beispiel, mit dem SSL-Stream Objekt scheint der Weg zu sein, es zu sehen (ein Rückruf) – Chaos
Dies ist falsch.Es ist nicht ein Server-Socket erstellen.Es schafft einen Client-Socket.TS und Tmf werden manchmal verwendet, um "Trust Store "und" trust manager factory ", aber hier beziehen sie sich auf das Client-Key-Material ... wirklich seltsam. – erickson
Das beste APNSSharp Projekt auf Github. Es funktionierte für mich absolut in Ordnung in wenigen Minuten!
Sie können die Bibliothek PushSharp in GitHub verwenden.
Ich benutze es in allen meinen Projekten
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);
}
Während dieser Code die Frage beantworten kann, wäre es besser zu erklären, wie es das Problem löst, ohne andere einzuführen und warum es zu verwenden. Nur-Code-Antworten sind auf lange Sicht nicht nützlich. – Mateus
Meiner Meinung nach ist Apples Dokumentation ist ziemlich klar: http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/ RemoteNotificationsPG/CommunicatingWIthAPS/CommunicatingWIthAPS.html # // Apple_ref/doc/uid/TP40008194-CH101-SW1 – Linulin
Diese Antwort wurde vor langer Zeit gewählt. Sehen Sie sich auch die Antwort von shay an - http://stackoverflow.com/a/36963561/19854 Wenn Sie nach einem manuellen Weg suchen, um diesen Code zu schreiben, dann schauen Sie sich die ursprünglich gewählte Antwort an: http://stackoverflow.com/a/1077664/19854 – Phobis