Skip to content

Instantly share code, notes, and snippets.

@ger86
Created January 24, 2019 11:45
Show Gist options
  • Save ger86/c88fd44922c23e8a874bd0205eca6df8 to your computer and use it in GitHub Desktop.
Save ger86/c88fd44922c23e8a874bd0205eca6df8 to your computer and use it in GitHub Desktop.
A Symfony Service to send iOS Push Notifications.
<?php
namespace App\Service\PushNotification;
class SendIOSPushNotification {
/**
* Constructor
*
* @param string $iosPushNotificationsKey
* @param string $iosPushNotificationsKeyId
* @param string $iosTeamId
* @param string $iosAppBundleId
* @param string $iosApnUrl
*/
public function __construct(
string $iosPushNotificationsKey,
string $iosPushNotificationsKeyId,
string $iosTeamId,
string $iosAppBundleId,
string $iosApnUrl
) {
$this->iosPushNotificationsKey = $iosPushNotificationsKey;
$this->iosPushNotificationsKeyId = $iosPushNotificationsKeyId;
$this->iosTeamId = $iosTeamId;
$this->iosApnUrl = $iosApnUrl;
$this->iosAppBundleId = $iosAppBundleId;
}
/**
* Sends a push notification to an iOS device
*
* @param string $deviceToken
* @param string $title
* @param string $subtitle
* @param string $body
* @return void
*/
public function __invoke(string $deviceToken, string $title, string $subtitle, string $body) {
$payload = $this->getNotificationPayload($title, $subtitle, $body);
$key = openssl_pkey_get_private('file://'.$this->iosPushNotificationsKey);
$header = $this->base64([
'alg' => 'ES256',
'kid' => $this->iosPushNotificationsKeyId
]);
$claims = $this->base64([
'iss' => $this->iosTeamId,
'iat' => time()
]);
$signature = '';
openssl_sign($header . '.' . $claims, $signature, $key, 'sha256');
$jwt = $header . '.' . $claims . '.' . base64_encode($signature);
$http2ch = curl_init();
curl_setopt_array($http2ch, [
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_URL => $this->getUrlForDeviceToken($deviceToken),
CURLOPT_PORT => 443,
CURLOPT_HTTPHEADER => [
"apns-topic: {$this->iosAppBundleId}",
"authorization: bearer $jwt"
],
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_TIMEOUT => 30,
CURLOPT_HEADER => 1
]);
$result = curl_exec($http2ch);
if ($result === FALSE) {
throw new \Exception("Send push notification failed: ".curl_error($http2ch));
}
$status = curl_getinfo($http2ch, CURLINFO_HTTP_CODE);
if ($status !== 200) {
throw new \Exception("Send push notification failed: ".$result);
}
}
/**
* Obtains a base64 representation of an array
*
* @param array $data
* @return string
*/
private function base64(array $data) : string {
return rtrim(strtr(base64_encode(json_encode($data)), '+/', '-_'), '=');
}
/**
* Gets the notification payload as array
*
* @param string $title
* @param string $subtitle
* @param string $body
* @return string
*/
private function getNotificationPayload(string $title, string $subtitle, string $body) : string {
$notificationBody = [
'aps' => [
'alert' => [
'title' => $title,
'subtitle' => $subtitle,
'body' => $body
]
]
];
return json_encode($notificationBody);
}
/**
* Gets the full url for send a push notification for a device
*
* @param string $deviceToken
* @return string
*/
private function getUrlForDeviceToken(string $deviceToken) : string {
return "{$this->iosApnUrl}/3/device/{$deviceToken}";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment