As per apple notification,
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns/
I am trying to upgrade my server side push notification code into standard .net farmworker 4.6.2 to support HTTP/2 and TLS 1.2 based request.
Below is the peace of code which I am trying:
public async Task<ApnsResponse> PushMessage_Http2(string Title, string Message, string DeviceToken, string Badge, string Custom_Field, string PUSH_MODULE, string ITEM_CODE)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
var url = string.Format("https://api.push.apple.com:443/3/device/{0}", DeviceToken);
List<string> Key_Value_Custom_Field = new List<string>();
int iBadge = 1;
if (!string.IsNullOrEmpty(Badge))
iBadge = Convert.ToInt32(Badge);
using (var httpHandler = new Http2CustomHandler() { SslProtocols = SslProtocols.Tls12})// { SslProtocols = SslProtocols.Tls12 })
{
httpHandler.ServerCertificateValidationCallback = (message, cert, chain, errors) => { return true; };
httpHandler.ClientCertificates.Add(getServerCert());
using (var httpClient = new HttpClient(httpHandler, true))
using (var request = new HttpRequestMessage(HttpMethod.Post, url))
{
request.Headers.Add("apns-id", Guid.NewGuid().ToString("D"));
request.Headers.Add("apns-push-type", "alert");
request.Headers.Add("apns-priority", "10");
////request.Headers.Add("apns-topic", topic);
string msg = "";
msg = "{";
msg += "\"aps\": {";
msg += "\"badge\": " + iBadge.ToString() + ", ";
msg += "\"alert\": \"" + Message + "\", ";//Apple side alert title is not in use
msg += "\"sound\": \"default\" ";
msg += "}, ";
msg += "\"data\": {";
msg += "\"item_code\": \"" + ITEM_CODE + "\", ";
msg += "\"push_title\":\"" + Title + "\", ";//This item is not in use into app side
msg += "\"push_module\":\"" + PUSH_MODULE + "\" ";
msg += "} ";
String PayloadMess = "";
if (string.IsNullOrWhiteSpace(Custom_Field) == false)
{
List<string> list_Custom_Field = Custom_Field.Split(';').ToList();
if (list_Custom_Field.Count > 0)
{
for (int indx = 0; indx < list_Custom_Field.Count; indx++)
{
Key_Value_Custom_Field = list_Custom_Field[indx].Split('=').ToList();
if (Key_Value_Custom_Field.Count > 1)
{
if (PayloadMess != "") PayloadMess += ", ";
PayloadMess += "'" + Key_Value_Custom_Field[0].ToString() + "':'" + Key_Value_Custom_Field[1].ToString() + "'";
}
}
}
}
if (PayloadMess != "")
{
msg += ", " + PayloadMess;
}
msg += "}";
request.Content = new StringContent(msg);
request.Version = new Version(2, 0);
try
{
using (var response = await httpClient.SendAsync(request, new System.Threading.CancellationToken()))
{
var succeed = response.IsSuccessStatusCode;
var statuscode = response.StatusCode;
var content = await response.Content.ReadAsStringAsync();
var error = content;
//var error = JsonHelper.Deserialize<ApnsError>(content);
return new ApnsResponse
{
IsSuccess = succeed,
Error = "status code: " + statuscode + " error: " + error
};
}
}
catch (HttpRequestException ex)//Exception
{
return new ApnsResponse
{
IsSuccess = false,
Error = ex.Message + " " + ex.InnerException.Message + " " + ex.InnerException.InnerException + " " + ex.StackTrace.ToString()
};
}
}
}
}
private X509Certificate getServerCert()
{
X509Certificate test = new X509Certificate();
//Open the cert store on local machine
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine); //##### Try either StoreLocation.CurrentUser or StoreLocation.LocalMachine
if (store != null)
{
// store exists, so open it and search through the certs for the Apple Cert
store.Open(OpenFlags.OpenExistingOnly | 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(ProductionKeyFriendName))
{
//Cert found, so return it.
return certs[i];
}
}
for (i = 0; i < certs.Count; i++)
{
X509Certificate2 cert = certs[i];
if (cert.FriendlyName.Contains(FriendName))
{
//Cert found, so return it.
return certs[i];
}
}
}
return test;
}
return test;
}
public class Http2CustomHandler : WinHttpHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
request.Version = new Version("2.0");
return base.SendAsync(request, cancellationToken);
}
}
public class ApnsResponse
{
public bool IsSuccess { get; set; }
public string Error { get; set; }
//public ApnsError Error { get; set; }
}
But I am getting below error while final request call:
Error while copying content to a stream. The write operation failed, see inner exception. System.Net.Http.WinHttpException (0x80072F78): Error 12152 calling WinHttpWriteData, 'The server returned an invalid or unrecognized response'. at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.WinHttpHandler.d__136.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Net.Http.WinHttpHandler.d__109.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at DIS_AdminPortal.ApplePNS.d__8.MoveNext()
Note: Above error we are facing into two different production server which is having windows server 2016 installed but same code when I try with different dev server which is having windows server 2019 then it's working fine.so does this issue related to server configuration or anything related?
Please let me know any help around this issue, Thanks in advance.
User contributions licensed under CC BY-SA 3.0