C# MemoryStream中的APNS有效负载格式异常

C# MemoryStream中的APNS有效负载格式异常,c#,.net,.net-core,apple-push-notifications,C#,.net,.net Core,Apple Push Notifications,我正试图从C#/dotnetcore发送推送通知,在序列化并将有效负载发送到APN时遇到了问题 如果您查看下面的代码示例,那么iosPayload对象有一个注释掉的属性。如果有效负载中没有它,则会成功接收通知,有了它,通知不会到达设备 public void SendNotification(string deviceToken) { int port = 2195; string hostname = "gateway.sandbox.push.apple.com";

我正试图从C#/dotnetcore发送推送通知,在序列化并将有效负载发送到APN时遇到了问题

如果您查看下面的代码示例,那么iosPayload对象有一个注释掉的属性。如果有效负载中没有它,则会成功接收通知,有了它,通知不会到达设备

public void SendNotification(string deviceToken)
{
    int port = 2195;
    string hostname = "gateway.sandbox.push.apple.com";

    var iosPayload = new {
        aps = new {
            alert = "The title",
            sound = "default"
        },
        app_group_id = 1,
        notification_id = "notification_id",
        campaignName = "Campaign Name",
        push_title = "Campaign Title",
        push_message = "The main body",
        type = "sdkNotification",
        push_on_click_behaviour = "1"//,
        //another_property = "4"
    };

    string certificatePath = @"./com.myCompany.sampleIOS.DEV.p12";
    X509Certificate2 clientCertificate = new X509Certificate2(File.ReadAllBytes(certificatePath), "");
    X509Certificate2Collection certificatesCollection = new X509Certificate2Collection(clientCertificate);
    TcpClient tcpClient = new TcpClient(hostname, port);
    SslStream sslStream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
    try
    {
        sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls, false);
        MemoryStream memoryStream = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(memoryStream);
        writer.Write((byte)0);
        writer.Write((byte)0);
        writer.Write((byte)32);
        writer.Write(HexStringToByteArray(deviceToken.ToUpper()));
        var payload = JsonConvert.SerializeObject(iosPayload);
        writer.Write((byte)0);
        writer.Write((byte)payload.Length);
        byte[] payloadBytes = System.Text.Encoding.UTF8.GetBytes(payload);
        writer.Write(payloadBytes);
        writer.Flush();
        byte[] memoryStreamAsBytes = memoryStream.ToArray();
        sslStream.Write(memoryStreamAsBytes);
        sslStream.Flush();


    }

    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        tcpClient.Close();
    }
}

private byte[] HexStringToByteArray(string hexString)
{
    return Enumerable.Range(0, hexString.Length)
             .Where(x => x % 2 == 0)
             .Select(x => Convert.ToByte(hexString.Substring(x, 2), 16))
             .ToArray();
}

private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    if (sslPolicyErrors == SslPolicyErrors.None) return true;
    return false;
}
错误为
System.FormatException
,消息为
,字符串末尾有其他不可解析字符。实际上,我是从Azure Webjob中发送的,只有在那里我才会收到错误消息,在本地运行的简单控制台应用程序不会显示任何错误,但也不会到达设备

public void SendNotification(string deviceToken)
{
    int port = 2195;
    string hostname = "gateway.sandbox.push.apple.com";

    var iosPayload = new {
        aps = new {
            alert = "The title",
            sound = "default"
        },
        app_group_id = 1,
        notification_id = "notification_id",
        campaignName = "Campaign Name",
        push_title = "Campaign Title",
        push_message = "The main body",
        type = "sdkNotification",
        push_on_click_behaviour = "1"//,
        //another_property = "4"
    };

    string certificatePath = @"./com.myCompany.sampleIOS.DEV.p12";
    X509Certificate2 clientCertificate = new X509Certificate2(File.ReadAllBytes(certificatePath), "");
    X509Certificate2Collection certificatesCollection = new X509Certificate2Collection(clientCertificate);
    TcpClient tcpClient = new TcpClient(hostname, port);
    SslStream sslStream = new SslStream(tcpClient.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
    try
    {
        sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls, false);
        MemoryStream memoryStream = new MemoryStream();
        BinaryWriter writer = new BinaryWriter(memoryStream);
        writer.Write((byte)0);
        writer.Write((byte)0);
        writer.Write((byte)32);
        writer.Write(HexStringToByteArray(deviceToken.ToUpper()));
        var payload = JsonConvert.SerializeObject(iosPayload);
        writer.Write((byte)0);
        writer.Write((byte)payload.Length);
        byte[] payloadBytes = System.Text.Encoding.UTF8.GetBytes(payload);
        writer.Write(payloadBytes);
        writer.Flush();
        byte[] memoryStreamAsBytes = memoryStream.ToArray();
        sslStream.Write(memoryStreamAsBytes);
        sslStream.Flush();


    }

    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        tcpClient.Close();
    }
}

private byte[] HexStringToByteArray(string hexString)
{
    return Enumerable.Range(0, hexString.Length)
             .Where(x => x % 2 == 0)
             .Select(x => Convert.ToByte(hexString.Substring(x, 2), 16))
             .ToArray();
}

private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    if (sslPolicyErrors == SslPolicyErrors.None) return true;
    return false;
}

编辑:奇怪的是,我可以从Pusher发送我的全部有效载荷…

结果是,我调用的是由序列的第一个字节决定命令的。我将0作为命令发送,该API的最大有效负载大小为256字节。很明显,我的有效载荷比这个稍大,所以被拒绝了

然后我发送了2作为命令,并建立了必要的帧数据