Reputation: 102
This script used to send test push notifications to test devices before Apple made the switch to the new APNs Provider API, which I'm surprised more people aren't talking about.
Now when I run the script from the terminal typing and entering php simplepush.php
, the output says
Though no message is received.
//simplepush.php
<?php
// Put your device token here (without spaces):
$deviceToken = 'EXAMPLETOKEN';
// 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://api.sandbox.push.apple.com:443', $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);
Since Apple made the switch last March, I have:
And I am able to get a test notification when I follow Sending Push Notifications Using Command-Line Tools.
curl -v --header 'apns-topic: com.your.site' --header apns-push-type: alert --cert aps.cer --cert-type DER --key PushChatKey.pem --key-type PEM --data '{"aps":{"alert":"Test"}}' --http2 https://api.sandbox.push.apple.com/3/device/DEVICETOKEN
Is it possible to still use this php script to send test push notifications since apple made the change to the new APNs Provider API? I know that the Apple developer documentation mentions required header request fields but I honestly can't tell if those are to be implemented from the terminal or from directly within the script.
Upvotes: 0
Views: 1707
Reputation: 135
I've just written a some code for new version APNS. For comunication we need "The 10-character Key ID you obtained from your developer account", "Team ID" and token refreshing... : "...once every 20 minutes and no less than once every 60 minutes..."
More: Apple Documentation
When I send noticication first time, I save token to cache file to use it again..
class PushNotifications {
public function iOS($data, $devicetoken) {
$tokenTMP = 'files/cert/token_apn'; //TOKEN CACHE
$domain = 'pl.domain.*****';
$def = 'alert';
$url = 'https://api.push.apple.com:443';
if($devicetoken =='e9886c41112d766eb3513ffbcc12ed92cbcb68ecf1e42413319b115d3c3a1ebec') //My test token
{
$url = 'https://api.sandbox.push.apple.com:443'; //sandbox
$def = 'alert';
}
//----------------
//For security, APNs requires you to refresh your token regularly. Refresh your token no more than once every 20 minutes and no less than once every 60 minutes.
$token = '';
if(file_exists($tokenTMP))
{
$fileTime = filemtime($tokenTMP);
$maxT = time() - 1800; //max 30 min.
$min = time() - 3600; //max 30 min.
if( $fileTime > $min && $fileTime < $maxT )
{
$token = file_get_contents($tokenTMP);
// echo 'I get last generated token..';
}
}
//----------------
if($token == '') //Let's generate new token...
{
// echo 'Generate new token...';
//https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token-based_connection_to_apns
$assocToken = array();
$assocToken['alg'] = 'ES256'; //The encryption algorithm you used to encrypt the token. APNs supports only the ES256 algorithm, so set the value of this key to ES256.
$assocToken['kid'] = '*******'; //The 10-character Key ID you obtained from your developer account
$assocToken['iss'] = '*******'; //The issuer key, the value for which is the 10-character Team ID you use for developing your company’s apps. Obtain this value from your developer account.
$assocToken['iat'] = time(); //The “issued at” time, whose value indicates the time at which this JSON token was generated. Specify the value as the number of seconds since Epoch, in UTC. The value must be no more than one hour from the current time.
$header = '{'
. ' "alg" : "'.$assocToken['alg'].'",'
. ' "kid" : "'.$assocToken['kid'].'"'
. '}';
$payload = '{'
. ' "iss" : "'.$assocToken['iss'].'",'
. ' "iat" : "'.$assocToken['iat'].'"'
. '}';
$headerB64URL = $this->base64url_encode($header);
$payloadB64URL = $this->base64url_encode($payload);
$secret = file_get_contents('files/cert/AuthKey_********.p8');
$signature = '';
openssl_sign($headerB64URL.'.'.$payloadB64URL, $signature, $secret, \OPENSSL_ALGO_SHA256);
$token = $headerB64URL.'.'.$payloadB64URL.'.'.$this->base64url_encode($signature);
//save to use next time..
$fp = fopen($tokenTMP, 'w');
fwrite($fp, $token);
fclose($fp);
}
$apns_id = '8-4-4-5-12';
// Create the payload body
$encode= json_decode( $data['mdesc'],true) ;
$message = $encode['message'];
$body['aps'] = array(
'sound' => 'default',
'alert' => array
(
'title' => $data['mtitle'],
'body' => $message,
'mdesc' => $data['mdesc'] ?? array()
),
'mutable-content' => '1',
);
// Encode the payload as JSON
$payloadData = json_encode($body);
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url . '/3/device/'.$devicetoken,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 1,
CURLOPT_TIMEOUT => 10,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_HTTPHEADER => array(
"authorization: bearer ".$token,
// "apns-id: ".$apns_id, //
"apns-push-type: $def",
"apns-expiration: ". strtotime('+1 days ' .date('Y-m-d')),//ponawiaj przez 1 dzień..
"apns-priority: 10", //wyślij natychmiast..
"apns-topic: ".$domain,
),
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_POST => '1',
CURLOPT_POSTFIELDS => $payloadData
));
$response = curl_exec($curl);
if(curl_errno($curl) == 0)
{
return 'ret: '.$response;
}else
{
return 'err: '.curl_error($curl);
}
}
}
Upvotes: 1
Reputation: 333
If your curl call works, why not convert it to PHP
Example:
$url = "https://api.sandbox.push.apple.com/3/device/DEVICETOKEN";
$ch = curl_init($url);
$data = json_encode(["aps" => ["alert" => "Test"]]);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // can be URL encoded string
$headers = array();
$headers[] = 'Apns-Topic: com.your.site';
$headers[] = 'Apns-Push-Type: ';
$headers[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error:' . curl_error($ch);
}
curl_close($ch);
If you need to know how to use cert with CURL in PHP check this answer
Upvotes: 0