I have generated the .cer file, provision file with the correct device ID, generated the .pem file by combining the .cer and private key files, uploaded it to the server. The app id matches. I have provided the passphrase too, which is correct.
I tested the port and connection using telnet from the server, it connects fine.
I have tested the certificate by openssl command, and it returned 0 - no errors.
The certificates and the application is in development/debug mode, the iPhone is set up to receive notifications, the token is received and is delivered to the server correctly and in the same length - 64.
When sending the message from the server, the error code is 0 - which means no errors.
Here is the code sample from the server:
$options = array('ssl' => array(
'local_cert' => 'cert.pem',
'passphrase' => 'pass'
));
$streamContext = stream_context_create();
stream_context_set_option($streamContext, $options);
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
if ($apns)
{
$payload['aps'] = array('alert' => 'push test', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $token)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
fclose($apns);
}
else
{
echo "Connection failed";
echo $errorString."<br />";
echo $error."<br />";
}
What else can I possibly try?
The code that worked in the end is the following:
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'pushcert.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', 'pass');
// Create the payload body
$body['aps'] = array(
'alert' => array('body' => 'Message', 'action-loc-key' => 'Show'),
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Open a connection to the APNS server
$apns = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$apns)
{
echo "Failed to connect: $err $errstr" . PHP_EOL;
}
echo 'Connected to APNS' . PHP_EOL;
$imsg = chr(0) . pack('n', 32) . pack('H*', $message) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$res = fwrite($apns, $imsg, strlen($imsg));
if (!$res)
{
echo 'Message not delivered' . PHP_EOL;
}
else
{
echo 'Message successfully delivered' . PHP_EOL;
}
fclose($apns);
Related
I am trying to migrate an existing API that used APNs to send and receive messages to be compatible with the new APNs Provider API.
The following script worked for sending test notifications to my testing device before Apple stopped supporting the legacy binary protocol.
//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);
Sending Notification Requests to APNs states that the :method and :path header fields are required for a connection to APNs.
I've copied the code from the link to the original test script.
<?php
HEADERS
- END_STREAM
+ END_HEADERS
:method = POST
:scheme = https
:path = /3/device/EXAMPLETOKEN
host = api.sandbox.push.apple.com
apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
apns-push-type = alert
apns-expiration = 0
apns-priority = 10
DATA
+ END_STREAM
{ "aps" : { "alert" : "Hello" } }
// 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);
When I try to run the script, the terminal output is:
PHP Parse error: syntax error, unexpected token ":" in /Users/Desktop/simple push folder/simplepush.php on line 6
What is the correct way to add the newly required header fields to this script?
Note: I've used the following Apple documentation to send a test notification to my testing advice.
PHP said that your file have a syntax error. I believe it has nothing to do with request header.
I've been trying for days now to push notifications from my php script to my iPhone with no luck!
I've tried numerous php scripts, generating pem certificates etc!
When I run the script I get "Delivered Message to APNS" but nothing comes through to my phone.
Also I'm running this as a sandbox and my app is in development.
<?php
$tHost = 'gateway.sandbox.push.apple.com';
$tPort = 2195;
$tCert = 'push.pem';
$tPassphrase = 'password';
$tToken = 'cps2OsFjufQ:APA91xEjcjQK368UOf6XMya8huaITdl_3PrJXPB-7NQCGUu30Z7djHQPKcDCvFkMN-qLZiIA_7ZCV_cpv3zsJh5EtLJ4BpZD6mQ4B6ZYDcoLOrKLVVY67iCcS7UJ4qA2mwsvdgpJ7C6w';
$tSound = 'default';
$tPayload = 'APNS payload';
$tBody['aps'] = array(
'badge' => +1,
'alert' => 'Test notification',
'sound' => 'default'
);
$tBody ['payload'] = $tPayload;
$tBody = json_encode ($tBody);
$tContext = stream_context_create ();
stream_context_set_option ($tContext, 'ssl', 'local_cert', $tCert);
stream_context_set_option ($tContext, 'ssl', 'passphrase', $tPassphrase);
$tSocket = stream_socket_client ('ssl://'.$tHost.':'.$tPort, $error, $errstr, 30, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $tContext);
if (!$tSocket)
exit ("APNS Connection Failed: $error $errstr" . PHP_EOL);
$tMsg = chr(1) . pack('n', 32) . pack('H*', $tToken) . pack('n', strlen($tBody)) . $tBody;
$tResult = fwrite ($tSocket, $tMsg, strlen ($tMsg));
if ($tResult)
echo 'Delivered Message to APNS' . PHP_EOL;
else
echo 'Could not Deliver Message to APNS' . PHP_EOL;
fclose ($tSocket);
?>
Building from samplePush.php I have been able to build a transactional APNS script for my app. This works great and gives me the ability to one to one push notifications to a phone.
I need to move this to batch notifications and so built:
$APNSMessage = 'Test from APNS Bulk!';
// Bulk PUSH is the service designed to send iOS PUSH Notifications to hundreds of devices all at the same time using the same APNS connection.
function bulkPushToAPNS($TokenArray, $MessageToPush) {
echo "Sending to " . count($TokenArray) . " Devices ";
$body = array('aps' => array('alert' => $MessageToPush, 'badge' => 1, 'sound' => 'default'));
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apnsCert.pem');
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if (!$fp) {
print "Failed to connect $token $err $errstrn";
return;
}
print "Connection OK ";
$payload = json_encode($body);
foreach($TokenArray as $token) {
$msg = chr(0) . chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $token)) . pack("n",strlen($payload)) . $payload;
print $payload;
//fwrite($fp, $msg);
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
}
fclose($fp);
}
$TokensToPushToArray = array('ThisIsTokenOne', 'ThisIsTokenTwo');
bulkPushToAPNS($TokensToPushToArray, $APNSMessage);
When the script runs it gets passed an array of iOS tokens that need this message.
The output of the script is:
Sending to 2 Devices Connection OK {"aps":{"alert":"Test from APNS Bulk!","badge":1,"sound":"default"}}Message successfully delivered {"aps":{"alert":"Test from APNS Bulk!","badge":1,"sound":"default"}}Message successfully delivered
So the feedback from Apple is that these are getting delivered. But nothing is making it to the handhelds.
If I run each device token individually they work, so its something in the batch thats playing up..? Any ideas?
Answering my own question here;
Moved the code around so that the foreach is inside the connection:
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apnsCert.pem');
// 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;
foreach ($APNSTokens as $APNSToken) {
// Create the payload body
$body['aps'] = array(
'alert' => $APNSMessage,
'sound' => 'default',
'badge' => 1
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $APNSToken) . 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);
Now the connection is still live and runs until the foreach is complete.
Tested and working.
This is my php push notification code for ios below:
<?php
// Put your device token here (without spaces):
$deviceToken = "********************************************";
// Put your private key's passphrase here:
$passphrase = "********";
function pushIOSNotification($message)
{
GLOBAL $deviceToken;
GLOBAL $passphrase;
$ctx = stream_context_create();
$path = dirname(__FILE__).'/ck.pem';
//echo $path;
stream_context_set_option($ctx, 'ssl', 'local_cert', $path);
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);
}
This code is only for one device,
if I need send to everyone and support localization,
this code will be like these below.
foreach($deviceTokens as $deviceToken){
$deviceOS = "query this device os from memcache";
if($deviceOS == "ios")
{
$lang = "query this device langauge from memcache";
$message = $messageData[$lang];
pushIOSNotification($deviceToken,$message);
}
}
but I doubt this performance of this code,
because deviceTokens length is the number of all members.
i use php to post to apple ..
$message = $error_msg;
$deviceToken = $dtoken;
$badge = 1;
$sound = 'received3.caf';
$body = array();
$body['aps'] = array('alert' => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['sound'] = $sound;
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', '/home/administrator/applecert/apns-dev.pem');
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
error_reporting(E_ALL);
if (!$fp) {
print "Failed to connect $err $errstr\n";
return;
} else {
print "Connection OK\n";
}
$payload = json_encode($body);
$msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
print "sending message :" . $payload . "\n";
fwrite($fp, $msg);
fclose($fp);
and andriod have similar way to post with php?
thanks ,all
Take a look at the C2DM service google offers :
http://code.google.com/intl/fr-FR/android/c2dm/
This code is well tested.
Note : You need to remember 3 points to check.
Passphrase : confirm with IOS developer.
.PEM : Please verify with your IOS develoepr created '.PEM' file is for sandbox or live server.
PORT 2195 : Need to verify whether this port has opened or not on your server.
If you have done these 3 steps, Now you can send push notification with below code with few configuration changes.
function pushNotification($deviceToken, $msg, $sounds, $type) {
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', '');
// Put your private key's passphrase here:
$passphrase = ;
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$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);
$body['aps'] = array(
'alert' => $msg,
'sound' => $sounds,
'badge' => 1,
'type' => $type,
);
$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));
// print_r($result);
fclose($fp);
}