Categories
Developers Software Development Tools Web

Step-by-Step PHP script to connect to Apple Push Notification Service – IOS

HTTP/2 is the new standard (soon in November 2020 the only way to connect to the APNS) in this article i’ll explain how to use PHP to connect to APNS using JWT tokens. You can also use certificates, but they expire and are a pain in the *ss if you manage multiple apps.

I18N: Deze blog is ook het Nederlands beschikbaar.

Pssst… Don’t like PHP? Scroll down to the other options at the bottom.

Apple’s service to send push notifications to iPhones, iPads and even to Apple’s watches is called APNS: Apple Push Notification Service) .

In order to send Push Notifications you’ll need an IOS app and a server to send the message from. In this article I will provide information on how to send the messages via PHP using a library to make it easier to generate the required JWT token.

What do you need in order to send Push Notifications via APNS?

The delivery of remote notifications involves several key components. We’ll be needing a receiver (iPad, iPhone, ect) and a server to send the message from (provider server)

We’ll be creating a provider server (left). To send a message to a IOS device (right)
  • Your company’s/personal server (known as the provider server)
    • We’ll be using PHP on our provider server
  • Apple Push Notification service (APNs)
    • Private key (or certificate) from Apple (.p8 file)
  • The user’s (apple) device (iPad, iPhone, ect.)
  • IOS application (Your app running on the user’s device)
    • for example: nl.samauto.ios-application

Getting the private key from Apple

Apple Push Notification service (APNs) must know the address of a user’s device before it can send notifications to that device. The address takes the form of a device token unique to both the device and your app ( nl.samauto.ios-application ) . At launch time, your app communicates with APNs and receives its device token, which you then forward to your provider server (the one we are going to build with PHP). Our server will include that token with any notifications it sends to Apple.

Head over to developer.apple.com and login with your AppleId.
Go to “Certificates, Identifiers & Profiles > Keys“

Generate a new key for your application, make sure to enable the Push Notifications Capability.

Download the .p8 file and save it to a secure location.
IT CANNOT BE DOWNLOADED AGAIN (APPLE DELETES THE PRIVATE KEY)

Samauto PHP Push Server

We’ll be building our server with PHP.

To authenticate to APNS we are utilizing JWT (JSON Web Tokens – RFC 7519) to create a Token Based Authenticated connection to Apple’s servers.

We will use composer to add a package (jwt) developed by Luís Cobucci. View lcobucci/jwt on GitHub or at packagist.org)

To add the package (via composer) to the project use the following command:

composer require lcobucci/jwt

We’ll have something like this in our composer.json.
We can now use it (using a PSR autoloader) in our script

<?php
require __DIR__ . '/vendor/autoload.php'; // Step 0: PSR-0 Autoloader
// Step 1: Import the library
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Ecdsa\Sha256;
use Lcobucci\JWT\Configuration;

// Step 2: declare config variables
$device_token = "device_token_here";
$apns_topic = 'nl.samauto.ios-application';
$p8file = "/home/dave/samauto/key_from_apple.p8";
$url = "https://api.sandbox.push.apple.com/3/device/$device_token"; // call either the sandbox or production API's


$config = $container->get(Configuration::class);
assert($config instanceof Configuration);

// Step 3: Generate a JWT Token.
$token = (string) $config->createBuilder()
->issuedBy("DEF123GHIJ") // (iss claim) // teamId
->issuedAt(time()) // time the token was issuedAt
->withHeader('kid', "ABC123DEFG")
->setKey('file://' . $p8file)
->setSigner(new Sha256()) // APNs only supports the ES256 algorithm
->getToken(); // get the generated token

// Step 4: Generate a payload (PushMessage) to send to the device
$payloadArray['aps'] = [
  'alert' => [
    'title' => "Dev.To Push Notification", // title of the notification
    'body' => "Visit SamAuto.nl for more awesome scripts", // content/body of the notification
  ],
  'sound' => 'default',
  'badge' => 1
];
// Step 4.1: Encode it as json.
$payloadJSON = json_encode($payloadArray);


// Step 5: create and send the cURL HTTP/2 request
$ch = curl_init($url);

curl_setopt($ch, CURLOPT_POSTFIELDS, $payloadJSON);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer $token","apns-topic: $apns_topic"]);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// On successful response you should get true in the response and a status code of 200
// A list of responses and status codes is available at
// https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/TheNotificationPayload.html#//apple_ref/doc/uid/TP40008194-CH107-SW1

var_dump($response);
var_dump($httpcode);
?>

What if you leak your Push Notification key to GitHub.com?

Immediately revoke the key or certificate!
(you can do this on the developer.apple.com site)

Then… add a .gitignore file to your repository in order to prevent this from happening again.

– Get a new key and install it on the provider server.

All the code is on our GitHub account!

Do you really want to get started right now?

just use the following composer command:

composer require edamov/pushok

This will download edamov/pushok which is a super nice library that basically does the same thing as the example, but better.

<?php

require __DIR__ . '/vendor/autoload.php';

use Pushok\AuthProvider;
use Pushok\Client;
use Pushok\Notification;
use Pushok\Payload;
use Pushok\Payload\Alert;

$options = [
    'key_id' => 'ABC123DEFG', // The Key ID obtained from Apple developer account
    'team_id' => 'DEF123GHIJ', // The Team ID obtained from Apple developer account
    'app_bundle_id' => 'com.app.Test', // The bundle ID for app obtained from Apple developer account
    'private_key_path' => __DIR__ . '/private_key.p8', // Path to private key
    'private_key_secret' => null // Private key secret
];

$authProvider = AuthProvider\Token::create($options);

$alert = Alert::create()->setTitle('Hello!');
$alert = $alert->setBody('First push notification');

$payload = Payload::create()->setAlert($alert);

//set notification sound to default
$payload->setSound('default');

//add custom value to your notification, needs to be customized
$payload->setCustomValue('key', 'value');

$deviceTokens = ['<device_token_1>', '<device_token_2>', '<device_token_3>'];

$notifications = [];
foreach ($deviceTokens as $deviceToken) {
    $notifications[] = new Notification($payload,$deviceToken);
}

$client = new Client($authProvider, $production = false);
$client->addNotifications($notifications);



$responses = $client->push(); // returns an array of ApnsResponseInterface (one Response per Notification)

foreach ($responses as $response) {
    $response->getApnsId();
    $response->getStatusCode();
    $response->getReasonPhrase();
    $response->getErrorReason();
    $response->getErrorDescription();
}

All clean code and nice and easy to use. Happy coding!

GoRush: Push Notification Server written in Golang (supports IOS and Android)

It’s 2020… PHP has come a long way, but it cannot match the sheer performance of Golang…

  ________                              .__
 /  _____/   ____ _______  __ __  ______|  |__
/   \  ___  /  _ \\_  __ \|  |  \/  ___/|  |  \
\    \_\  \(  <_> )|  | \/|  |  /\___ \ |   Y  \
 \______  / \____/ |__|   |____//____  >|___|  /
        \/                           \/      \/

Usage: gorush [options]

I can recommend a very fast and versatile program written in Go. It’s called GoRush. You’ll get way way more performance, and features like an out-of-the-box Web API, Monitoring, Memory Usage, CLI, Retry/Resend and it also supports Push notification to Google/Android/FCM previously known as Google Cloud Messaging.

Give it a try and tell me what you think.

3 replies on “Step-by-Step PHP script to connect to Apple Push Notification Service – IOS”

Leave a Reply

Your email address will not be published. Required fields are marked *