SendEmptyPushNotification to gateway.push.apple.com no longer working

2.8k Views Asked by At

For at least the past couple of days (maybe longer), nothing seems to happen when I send an Empty Push Notification to at least 1 test device. I'm pretty much using the same SendEmptyPushNotification code as the article posted below.

https://medium.com/@yangzhoupostbox/part-2-push-notification-for-updating-apple-pass-in-asp-net-6020768d112

My test device is running iOS 14.4.1. I can manually update the Pass, so the WebServiceURL is working.

My cert expires later this year. I've rebooted my device. This all used to work and I haven't changed anything.

NOTE: It looks like the AppleDeviceLibraryIdentifier & ApplePushToken are changing over time. Should these change or remain the same over the life of the Apple device the passes are installed on? I'm wondering if the new PushToken could be the issue. This seems to be the expected behavior. Does the Device Library Identifier change with the Push Token?

Does anyone know what might be wrong? Is anyone else having an issue?

2

There are 2 best solutions below

11
On

Me too man. Let's figure this out together like Apex Legends.

I have submitted a TSI to Apple. They sent out an email on feb 10 saying:

On March 29, 2021, token and certificate-based HTTP/2 connections to the Apple Push Notification service must incorporate the new root certificate (AAACertificateServices 5/12/2020) which replaces the old GeoTrust Global CA root certificate. To ensure a seamless transition and to avoid push notification delivery failures, verify that both the old and new root certificates for the HTTP/2 interface are included in the Trust Store of each of your notification servers before March 29.

Note that Apple Push Notification service SSL provider certificates issued to you by Apple do not need be to updated at this time.

Learn more about connecting to APNs.

If you have any questions, contact us.

Best regards, Apple Developer Relations

Update - Mon May 3, after submitting a TSI to Apple Dev

  1. Push notifications stopped working for developers on March 31, 2021 after Apple migrated to a new APNS provider API (http/2 protocol).

  2. To continue using push, see this page: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns/

What I learned?

Revoke all developer account certificates related to APNS Make new certs and this time don't make any PEM files when installing them to your providing server. Also, make sure to stop using port 2195 when making a connection to APNS and use 443 or 2197.

The great news? The new APNS provider API is still compatible with Objective C!

<?php
// Put your device token here (without spaces):
$deviceToken = '09a0c8ff92b3621c5f5032c1fa031f2851d01dd99beaf1446c281c5458fe2ffd';
// Put your private key's passphrase here:
$passphrase = 'pushchat';
// Put your alert message here:
$message = 'Hello!';

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', 
strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);

Update: I was wrong about the PEM aspect. Creating a PEM file is still necessary for APNs connections using the new APNs Provider API.

0
On

To get this to work in a non .Net Core Solution, I had to upgrade from Asp.net 4.6.1 to 4.7.2. I then created a folder in my Project called AppleAPNS. I added all the files found here.

NOTE: I had to upgrade to 4.7.2 in order to get the Project to recognize CreateFromValue found in the AppleCryptoHelper file.

https://github.com/andrei-m-code/net-core-push-notifications/tree/master/CorePush/Apple

I then added the files found here to the AppleAPNS folder.

https://github.com/andrei-m-code/net-core-push-notifications/tree/master/CorePush/Utils

I then added the WinHttpHandler Project along with this helper to my AppleAPNS folder. This will ensure that you are calling APNS with an HTTP client capable of 2.0.

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);
        }
    }

Next, add the AppleNotification class found here and use the calling method in the program.cs file.

https://github.com/andrei-m-code/net-core-push-notifications/tree/master/CorePush.Tester

To use the Http2CustomHandler, make these changes.

ApnSender.cs

//private readonly HttpClient http;
        private readonly HttpClient http = new HttpClient(new Http2CustomHandler());

In your calling method make this change.

//private static readonly HttpClient http = new HttpClient();
        private static readonly HttpClient http = new HttpClient(new Http2CustomHandler());

Finally, make this change to send an empty push notification to update passes.

ApnSender.cs

//var json = JsonHelper.Serialize(notification);
            var json = "{\"aps\":\"\"}";

NOTE: Copy the contents of the p8 file as string into the apnP8PrivateKey in your calling method. Do not open/read the file.

Hope this helps! I know this is not a detailed explanation, but hopefully it will help somebody.