似乎每个人都使用PushSharp从C#向iOS设备发送推送通知。但是该库有一个它使用的队列,而不是直接发送通知,这意味着您需要一个Windows服务或其他东西来正确托管它(根据自己的文档)这对我来说是过度的。我有一个传入Web请求到我的ASP.NET Web服务,作为处理它的一部分,我想立即发送推送通知。就这么简单。
任何人都可以告诉我如何使用PushSharp立即发送一个(绕过其队列机制)或如何自己正确发送推送通知?我已经有了制定JSON消息的代码,但我不知道如何将.p12文件应用于请求。我找不到任何有关如何操作的Apple文档。
答案 0 :(得分:0)
我花了很多时间试图找到推送通知的方法,然后我找到了一段为我做的代码。
首先确保您正确安装了证书,这是一个可以帮助您的链接。 https://arashnorouzi.wordpress.com/2011/04/13/sending-apple-push-notifications-in-asp-net-%E2%80%93-part-3-apns-certificates-registration-on-windows/
以下是我用来推送通知的代码:
public static bool ConnectToAPNS(string deviceId, string message)
{
X509Certificate2Collection certs = new X509Certificate2Collection();
// Add the Apple cert to our collection
certs.Add(getServerCert());
// Apple development server address
string apsHost;
/*
if (getServerCert().ToString().Contains("Production"))
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 sslStream1 = new SslStream(tcpClient.GetStream());
// Authenticate using the Apple cert
sslStream1.AuthenticateAsClient(apsHost, certs, SslProtocols.Default, false);
PushMessage(deviceId, message, sslStream1);
return true;
}
private static X509Certificate getServerCert()
{
X509Certificate test = new X509Certificate();
//Open the cert store on local machine
X509Store store = new X509Store(StoreLocation.CurrentUser);
if (store != null)
{
// store exists, so open it and search through the certs for the Apple Cert
store.Open(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("Apple Development IOS Push Services"))
{
//Cert found, so return it.
Console.WriteLine("Found It!");
return certs[i];
}
}
}
return test;
}
return test;
}
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;
}
请注意,此代码适用于开发证书&#34; Apple Development IOS推送服务&#34;。
答案 1 :(得分:0)
这是一个古老的问题,但答案并不完整。
这是我的代码:
document.getElementById('uploadID').addEventListener('change', () => {
//Your code...
});
提示:在iOS13中,设备令牌的接收方式有所不同。
// private fields
private static readonly string _apnsHostName = ConfigurationManager.AppSettings["APNS:HostName"];
private static readonly int _apnsPort = int.Parse(ConfigurationManager.AppSettings["APNS:Port"]);
private static readonly string _apnsCertPassword = ConfigurationManager.AppSettings["APNS:CertPassword"];
private static readonly string _apnsCertSubject = ConfigurationManager.AppSettings["APNS:CertSubject"];
private static readonly string _apnsCertPath = ConfigurationManager.AppSettings["APNS:CertPath"];
private readonly ILogger _log;
private X509Certificate2Collection _certificatesCollection;
ctor <TAB key>(ILogger log)
{
_log = log ?? throw new ArgumentNullException(nameof(log));
// load .p12 certificate in the collection
var cert = new X509Certificate2(_apnsCertPath, _apnsCertPassword);
_certificatesCollection = new X509Certificate2Collection(cert);
}
public async Task SendAppleNativeNotificationAsync(string payload, Registration registration)
{
try
{
// handle is the iOS device Token
var handle = registration.Handle;
// instantiate new TcpClient with ApnsHostName and Port
var client = new TcpClient(_apnsHostName, _apnsPort);
// add fake validation
var sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
try
{
// authenticate ssl stream on ApnsHostName with your .p12 certificate
sslStream.AuthenticateAsClient(_apnsHostName, _certificatesCollection, SslProtocols.Tls, false);
var memoryStream = new MemoryStream();
var writer = new BinaryWriter(memoryStream);
// command
writer.Write((byte)0);
// first byte of the deviceId length (big-endian first byte)
writer.Write((byte)0);
// deviceId length (big-endian second byte)
writer.Write((byte)32);
// deviceId data (byte[])
writer.Write(HexStringToByteArray(handle.ToUpper()));
// first byte of payload length; (big-endian first byte)
writer.Write((byte)0);
// payload length (big-endian second byte)
writer.Write((byte)Encoding.UTF8.GetByteCount(payload));
byte[] b1 = Encoding.UTF8.GetBytes(payload);
// payload data (byte[])
writer.Write(b1);
writer.Flush();
byte[] array = memoryStream.ToArray();
await sslStream.WriteAsync(array, 0, array.Length);
// TIP: do not wait a response from APNS because APNS return a response only when an error occurs;
// so if you wait the response your code will remain stuck here.
// await ReadTcpResponse();
sslStream.Flush();
// close client
client.Close();
}
catch (AuthenticationException ex)
{
_log.Error($"Error sending APNS notification. Exception: {ex}");
client.Close();
}
catch (Exception ex)
{
_log.Error($"Error sending APNS notification. Exception: {ex}");
client.Close();
}
}
catch (Exception ex)
{
_log.Error($"Error sending APNS notification. Exception: {ex}");
}
}
private static byte[] HexStringToByteArray(string hex)
{
if (hex == null)
{
return null;
}
// added for newest devices (>= iPhone 8)
if (hex.Length % 2 == 1)
{
hex = '0' + hex;
}
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
//if (sslPolicyErrors == SslPolicyErrors.None)
// return true;
//// do not allow this client to communicate with unauthenticated servers.
//return false;
}
private async Task<byte[]> ReadTcpResponse(SslStream sslStream)
{
MemoryStream ms = new MemoryStream();
byte[] buffer = new byte[2048];
int bytes = -1;
do
{
bytes = await sslStream.ReadAsync(buffer, 0, buffer.Length);
await ms.WriteAsync(buffer, 0, bytes);
} while (bytes != 0);
return ms.ToArray();
}
在iOS13中,您必须将令牌转换为字符串或跳过方法 'HexStringToByteArray',因为您已经有一个字节[]。
如果您有问题,我很乐意回答。