Redth / PushSharp

A server-side library for sending Push Notifications to iOS (iPhone/iPad APNS), Android (C2DM and GCM - Google Cloud Message), Windows Phone, Windows 8, Amazon, Blackberry, and (soon) FirefoxOS devices!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The Apple Push Notification service (APNs) will no longer support the legacy binary protocol as of November 2020.

i5kender opened this issue · comments

Hi,
I have been using this library for 2 years. Apple says that "we recommend updating to the HTTP/2-based APNs provider API as soon as possible."
Will we be able to continue sending notifications with this library?

News link : https://developer.apple.com/news/?id=11042019a

This is something I also would like to know. If anyone could shed some light on this it would be greatly appreciated.

Hello,
I need to know this too. The last version is 4.0.10 and we are using it. But when I check the documentation, the URL's don't match with constants in the code.
This is ApnsConfiguration class (https://github.com/Redth/PushSharp/blob/master/PushSharp.Apple/ApnsConfiguration.cs)
image
And this is the apple's documentation page: (https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns#2947606)
image

The commit 96ff502 says "Add basic Http2 support for APNS", but in some articles found that PushSharp doesn't support Http2 API.

It will be really helpful if someone can clear out this confusion.

Thanks

commented

I also saw this and @Redth covered previously (here: #880) that http/2 support requires a bunch of changes/etc. and isn't coming to PushSharp.

Thanks @cvocvo

I went for the azure option, so this is going to make my life so much easier in the long run.

Azure offers the capability of managing devices through their hub, or just use it as a pass through service and you manage your own devices...which fits perfectly into my use case.

Apple changed deadline.
The deadline to upgrade to the APNs provider API has been extended to March 31, 2021.
https://developer.apple.com/news/?id=c88acm2b

And also you can do a little trick by adding ApnsHttp2Connection and other files in project, they are already in source code of PushSharp, you need to make your own PushSharp.Apple.dll
use fork of HttpTwo
https://github.com/Neio/HttpTwo
and lock http2Client, because there are problems with asynchronous

lock (sobject) { response = http2.Send(uri, HttpMethod.Post, headers, data).Result; }
Redth/HttpTwo#7

commented

you can use dotAPNS library to push notifications using HTTP/2
https://github.com/alexalok/dotAPNS

I am using PushSharp .NetCore and worried about this deadline as the current structure is working perfectly fine for me. Any updates?

Apple changed deadline.
The deadline to upgrade to the APNs provider API has been extended to March 31, 2021.
https://developer.apple.com/news/?id=c88acm2b

And also you can do a little trick by adding ApnsHttp2Connection and other files in project, they are already in source code of PushSharp, you need to make your own PushSharp.Apple.dll
use fork of HttpTwo
https://github.com/Neio/HttpTwo
and lock http2Client, because there are problems with asynchronous

lock (sobject) { response = http2.Send(uri, HttpMethod.Post, headers, data).Result; }
Redth/HttpTwo#7

This solution worked well for me. Thank you.

Will PushSharp be updated to support HTTP/2-based Apple Push Notification?

Yes I hope there will be a quick update for this HTTP/2 issue soon.

It is easy to send Apple Push Notification. You don't need any GitHub libraries or Nuget packages. I use this simple function. It only depends on API from .Net Core 3.0.

static async Task Send(string text, string deviceToken)
{
  var cert = new X509Certificate2("certificate.p12", "password", X509KeyStorageFlags.MachineKeySet);
  var req = new HttpRequestMessage(HttpMethod.Post, "https://api.push.apple.com/3/device/" + deviceToken);
  req.Version = new Version(2, 0);
  req.Headers.Add("apns-topic", cert.Subject.Substring(cert.Subject.LastIndexOf('=') + 1));
  req.Content = new StringContent("{\"aps\":{\"alert\":\"" + HttpUtility.JavaScriptStringEncode(text) + "\"}}");
  var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual };
  handler.ClientCertificates.Add(cert);
  var response = await new HttpClient(handler).SendAsync(req);
  string content = await response.Content.ReadAsStringAsync();
  if (!response.IsSuccessStatusCode) throw new Exception("APNS error " + response.StatusCode + ": " + content);
}

It is easy to send Apple Push Notification. You don't need any GitHub libraries or Nuget packages. I use this simple function. It only depends on API from .Net Core 3.0.

static async Task Send(string text, string deviceToken)
{
  var cert = new X509Certificate2("certificate.p12", "password", X509KeyStorageFlags.MachineKeySet);
  var req = new HttpRequestMessage(HttpMethod.Post, "https://api.push.apple.com/3/device/" + deviceToken);
  req.Version = new Version(2, 0);
  req.Headers.Add("apns-topic", cert.Subject.Substring(cert.Subject.LastIndexOf('=') + 1));
  req.Content = new StringContent("{\"aps\":{\"alert\":\"" + HttpUtility.JavaScriptStringEncode(text) + "\"}}");
  var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Manual };
  handler.ClientCertificates.Add(cert);
  var response = await new HttpClient(handler).SendAsync(req);
  string content = await response.Content.ReadAsStringAsync();
  if (!response.IsSuccessStatusCode) throw new Exception("APNS error " + response.StatusCode + ": " + content);
}

I created a .NET Core 3.1 library with the code above. Then I refer to the library from a .NET Framework 4.7.2 project. The problem is that I get this error:

Error CS1705 Assembly 'X' with identity 'X, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' uses 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' which has a higher version than referenced assembly 'System.Runtime' with identity 'System.Runtime, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'

In NuGet Manager for both projects, I have tried to add System.Runtime 4.3.1. Still I get the same error. How can this be fixed?

I created a .NET Core 3.1 library with the code above. Then I refer to the library from a .NET Framework 4.7.2 project.

You can't mix .NET Core and .NET Famework together within the same project. You should convert all your .NET Framework 4.7.2 project to .NET 5. If it is too much difficult for you, it's also possible to compile Send function into standalone EXE file. Then you would use method Process.Start to call it and pass on text and deviceToken as command line parameters.

commented

Hi, anyone here with a working solution for Apple push using HTTP/2?
We are using .NET 4.7.2 and converting our projects to .NET core is not an option.
I tried several solutions found on the internet but nothing seems to work. The solution that "works" (copying all HTTP2 classes from https://github.com/Redth/PushSharp/blob/master/PushSharp.Apple and adding https://github.com/Neio/HttpTwo into the project) throws an exception: System.TimeoutException: The operation has timed out. at HttpTwo.Http2Client.d__19.MoveNext(). Even when setting the timeOut to 60 seconds.
I also can't figure out how to use the WinHttpHandler. It always throws exceptions.
Anyone willing to help me to replace our PushSharp implementation with a working solution using HTTP/2? Would help a lot!

This is my solution:

PushSharp 4.0.10.0: HTTP/2-based Apple Push Notification service (APNs)
https://stackoverflow.com/questions/65703015/pushsharp-4-0-10-0-http-2-based-apple-push-notification-service-apns/66317870#66317870

I removed the iOS structure of PushSharp and implemented dotAPNS. I am still using PushSharp for Google.

commented

Thank you @hussoftware, yes dotAPNS is perfect for core.
Unfortunately we never found a solution to implement in our existing 4.7.2 background worker (maybe there is no solution?), so we decided to create an appservice using .NET Core 3.0, purely for iOS push. Seems to be a good solution.

@ellenkuipers I built a quick helper class for myself within a day and pointed the existing PushSharp calls to this helper. You can use and improve the helper class I shared in stackoverflow or can write a better one from scratch. dotAPNS does pretty much majority of the push notifications work.

commented

Thank you @hussoftware, yes dotAPNS is perfect for core.
Unfortunately we never found a solution to implement in our existing 4.7.2 background worker (maybe there is no solution?), so we decided to create an appservice using .NET Core 3.0, purely for iOS push. Seems to be a good solution.

Hi can you please share some piece of code for NET Core 3.0.. As we are getting error related to SSL after uploading it on server
while working fine for local environment. I want to be sure I missed nothing from my side..

commented

Thank you @hussoftware, yes dotAPNS is perfect for core.
Unfortunately we never found a solution to implement in our existing 4.7.2 background worker (maybe there is no solution?), so we decided to create an appservice using .NET Core 3.0, purely for iOS push. Seems to be a good solution.

Hi can you please share some piece of code for NET Core 3.0.. As we are getting error related to SSL after uploading it on server
while working fine for local environment. I want to be sure I missed nothing from my side..

Hi @21pg ,

I followed all instructions under "dotAPNS ASP.NET Core integration", see https://github.com/alexalok/dotAPNS
Other than that, I resolve one single IApnsService per certificate. On Send I create the X509Certificate2 (creating it once and re-using it gave problems when working with 33+ different push certifificates in our case).

SendPushAsync:
var cert = new X509Certificate2(certificateBytes, string.Empty, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); var response = await apnsService.SendPush(push, cert);

Also we had to change the HTTP version to "2.0" in the configuration settings in Azure. In protocol settings we have HTTPS Only = On and Minimum TLS Version = 1.2. Hope this will help. Good luck!

commented

Thank you @hussoftware, yes dotAPNS is perfect for core.
Unfortunately we never found a solution to implement in our existing 4.7.2 background worker (maybe there is no solution?), so we decided to create an appservice using .NET Core 3.0, purely for iOS push. Seems to be a good solution.

Hi can you please share some piece of code for NET Core 3.0.. As we are getting error related to SSL after uploading it on server
while working fine for local environment. I want to be sure I missed nothing from my side..

Hi @21pg ,

I followed all instructions under "dotAPNS ASP.NET Core integration", see https://github.com/alexalok/dotAPNS
Other than that, I resolve one single IApnsService per certificate. On Send I create the X509Certificate2 (creating it once and re-using it gave problems when working with 33+ different push certifificates in our case).

SendPushAsync:
var cert = new X509Certificate2(certificateBytes, string.Empty, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); var response = await apnsService.SendPush(push, cert);

Also we had to change the HTTP version to "2.0" in the configuration settings in Azure. In protocol settings we have HTTPS Only = On and Minimum TLS Version = 1.2. Hope this will help. Good luck!

Thanks for your reply I tried this but
For me following trick worked-
by setting Load User Profile option as True in IIS
https://stackoverflow.com/questions/9951729/x509certificate-constructor-exception/10048789#10048789

Has anyone had any issues with a certificate that works for Production but not Development? I've generated my wallet pass certificate from apple - the one you use to create apple passes. When I send the HTTP/2 request to the production server - everything works. The moment I send it to the development one though, I get The HTTP/2 server sent invalid data on the connection. HTTP/2 error code 'NO_ERROR' (0x0).

I think the issue might be with the certificate - if it was somehow created only for a production environment.