Apple Push Notification with PHP script not working? - ios

When i run below script on terminal it gives the error :
Warning: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure in
/Applications/MAMP/htdocs/SimplePush/simplepush.php on line 21
Warning: stream_socket_client(): Failed to enable crypto in /Applications/MAMP/htdocs/SimplePush/
simplepush.php on line 21
Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195
(Unknown error) in /Applications/MAMP/htdocs/SimplePush/simplepush.php on line 21
Failed to connect: 0
Here is the code:
<?php
// Put your device token here (without spaces):
$deviceToken = '*******';
// Put your private key's passphrase here:
$passphrase = '***';
// Put your alert message here:
$message = 'Want more credits!';
$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.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);
?>

Since it sounds like your are using the development cert you might want to try pointing to: gateway.sandbox.push.apple.com:2195. The URL gateway.push.apple.com:2195 is for production certs.

Old Question, but I faced same problem. And I solved it by changing the following code:
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
to
stream_context_set_option($ctx, 'ssl', 'local_cert', '/Users/Ohemod/Desktop/ck.pem');
The script was looking for ck.pem file, but for not providing the actual directory I got the error message everytime. If anyone face the same problem please try with the second one. Remember the directory of your file and my codes directory will not same. Put the actual directory link of your ck.pem file.

Download cacert.pem from https://curl.haxx.se/ca/cacert.pem and keep it in the same folder where PHP script is available.
Include the statement stream_context_set_option($ctx, 'ssl', 'cafile', 'cacert.pem'); after the line $ctx = stream_context_create();
fyi:
Syntax: bool stream_context_set_option ( resource $stream_or_context , string $wrapper , string $option , mixed $value )
For additional options check http://php.net/manual/en/context.ssl.php

I've used your script just like that, and the solution I found was to invoke it from a CURL call, inside the php script:
This is the code that works for me. Remember to call it via HTTPS
script 1 (to invoke the one via CURL):
// set post fields
$post = [
'mensaje' => 'THE MESSAGE TO SEND',
'device_id' => $device_id,
];
$ch = curl_init('https://www.DOMAIN/push-curl-script.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$response = curl_exec($ch);
curl_close($ch);
push-curl-script.php:
$certificado_push = "*****.pem";
// Put your device token here (without spaces):
$deviceToken = $_POST["device_id"];
// Put your private key's passphrase here:
$passphrase = '***';
// Put your alert message here:
$message = $_POST["mensaje"];
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $certificado_push);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.'.($sandbox ? 'sandbox.' : '').'push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp) {
echo "Failed to connect: $err $errstr" ;
}else{
echo 'Connected to APNS' ;
// 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' ;
}else{
echo 'Message successfully delivered' ;
}
// Close the connection to the server
fclose($fp);
}

Related

push Notification, php error and warnings

I know there are many questions for this but I have tried doing all the suggestions with no luck, I have the below error when running my push.php in shell command., I am following this tutorial and everything worked untill the php. i recreated the certificates and keys many many times and since it's letting me connect using openssh then i guess the problem is not with it. today i have again recreated all the certificates and did a new project now I don't even receive the first prompt of do you accept to allow push notification in this app. I am stuck I am on a deadline and was facing this problem for week, please help me, my php is exact same file as the tutorial with modified token and passcode I have added the path to ck.pem as was suggested by some of the S.O.answers but not working yet.also I have added CA file entrust_2048_ca.cer , it didn't help resolving the issue. and all this is using development certificate and not yet on a server, what might be the issues your ideas? is using external library will be better ?
Thank you for your help in advance.
Warning: stream_socket_client(): Unable to set private key file
`/Users/.../..../.../.../ck.pem' in
/Users/dalyaseen/Documents/test3d/test3d/push.php on line 19
Warning: stream_socket_client(): failed to create an SSL handle in
/.../..../.../.../push.php on line 19
Warning: stream_socket_client(): Failed to enable crypto in
/Users/.../..../.../.../push.php on line 19
Warning: stream_socket_client(): unable to connect to
ssl://gateway.sandbox.push.apple.com:2195 (Unknown error) in
/Users/.../..../.../.../push.php on line 19 Failed to connect: 0
here is the php script
<?php
#$deviceToken='ac49c9c8 a7d7f340 1c5c9af8 b8afeada ee7cdb77 051f12e8 90c314e1 129af45e';
$deviceToken='ac49c9c8a7d7f3401c5c9af8b8afeadaee7cdb77051f12e890c314e11y8u89i9o0lp';
# Put your private key's passphrase here:
$passphrase = '1234';
# Put your alert message here:
$message = 'push msg!';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', '/Users/d/Documents/test/test/ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
stream_context_set_option($ctx, 'ssl', 'cafile', '/Users/d/Documents/test/test/entrust_2048_ca.cer');
#stream_context_set_option($ctx, 'ssl', 'allow_self_signed', 1);
#stream_context_set_option($ctx, 'ssl', 'verify_peer', 1);
//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);
?>
Try This Code :
<?php
$deviceToken='ac49c9c8a7d7f3401c5c9af8b8afeadaee7cdb77051f12e890c314e11y8u89i9o0lp';
$passphrase = '1234';
$message = 'push msg!';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
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);
//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)
return 'Message not delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
IMP: Put your ck.pem file parallel to this code.
Once your code works you can change the position of your .pem file.
Make Sure the certificate you created is in "Developer" Mode
Also, the device is added to the provisioning profile.

Push IOS don't work

I created a PhoneGap application and I use PushPlugin for notifications.
I created my ck.pem and everything worked in development.
Then I posted my application and created ck.pem production and it does not work.
This is my function to push :
$passphrase = '********';
$message = $titre;
$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.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
var_dump($fp); echo "<br/>";
if (!$fp)
die("Failed to connect: $err $errstr" . PHP_EOL);
$body['aps'] = array(
'alert' => $message,
'sound' => 'default',
'id' => $id
);
// Encode the payload as JSON
$payload = json_encode($body);
echo $payload."<br/>";
$ids = get_list_ids_smartphone_ios();
foreach ($ids as $id){
echo $id."<br/>";
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $id) . pack('n', strlen($payload)) . $payload;
echo $msg."<br/>";
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
var_dump($result); echo "<br/>";
if (!$result)
die('Erreur à l\'envoi d\'une notification push pour IOS');
}
die();
// Close the connection to the server
fclose($fp);
and the result :
resource(1280) of type (persistent stream)
{"aps":{"alert":"this is a test","sound":"default","id":13299}}
abc46897b077eec6bb477edabb7a620e9d79a967c0a0d689dbc6c17d10eb9fef
îÄh—°wîÆ»G~Ú»zby©gÀ Ö‰ÛÆÁ}ëŸïl{"aps":{"alert":"this is a test","sound":"default","id":13299}}
int(145)
ab33c500d0e8ac8211ac7b8834e4053266e65f046aca5af7ae1fa4bc41ca33e5
Ö3ÅÐ謂¬{ˆ4ä2fæ_jÊZ÷®¤¼AÊ3ål{"aps":{"alert":"this is a test","sound":"default","id":13299}}
int(145)
Thanks for your help.
Make sure your application is using an Ad-Hoc certificate when attempting to use the production environment for APNS or it will most likely silently fail.

connection in APNS server works from terminal but not from php server (IOS push notifications)

if I run this:
openssl s_client -connect gateway.sandbox.push.apple.com:2195
-cert PushChatCert.pem -key PushChatKey.pem
Enter pass phrase for PushChatKey.pem:
by following the tutorial in here I can see the response and the connection to APNS server works fine.
Then in my php server, I have that code for example:
// Put your device token here (without spaces):
$deviceToken = '6bdccb83e15333b7dd29c5e45a20f7bc1b8291b52e1d017e0e41fceb9959e5ba';
// Put your private key's passphrase here:
$passphrase = 'code';
// Put your alert message here:
$message = 'My first push notification!';
////////////////////////////////////////////////////////////////////////////////
$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);
////////////////////////////////////////////////////////////////////////////////
$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);
But I get a connection time out. What do you think it might be?

APNS: First push delivers only

I've a really strange behavior in my app.
Only the first push notification send will be delivered.
All other won't arrive. I waited for 1 week, and still it wasn't delivery.
But if I reinstall the app, the first notification will be delivered instantaneously.
I never had this problem before. All other apps are working with APNS.
Thanks,
Maik
EDIT:
<?php
// Put your device token here (without spaces):
$deviceToken = 'token';
// Put your private key's passphrase here:
$passphrase = 'pw';
// Put your alert message here:
$message = 'message';
////////////////////////////////////////////////////////////////////////////////
$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.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);
(i tested development and production push)
fixed it, created a new app id. Think the problem was, that i deleted the appId from the old account and created it on the new developer account.

Batch iOS Push Notification

First of all thanks for your attention. The escenario here is that I need to send the same PUSH notification to thousands of devices. I've been reading the Apple documentation regarding to this topic and I found out that I have to batch multiple notifications.
The theory is clear, but I'm having doubts in the implementation.
For example, I normally use this PHP webservice to send one notification:
$deviceToken = 'f9082e0e26fe72f4c9ef04bff33b8274186b51abeecb86e4a4e7ac773081****';
$passphrase = '********';
$message = "Hi, world";
$badge = 2;
$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', 'badge'=>$badge);
$body['mis_parametros'] = array('hora' => date("F j, Y, g:i a"));
// 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. ' to device token: '. $deviceToken;
// Close the connection to the server
fclose($fp);
I don't see how I am supposed to send them in batch. Should I call:
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
then change the deviceToken and call again
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
and finally, after all the notifications, close the connection to APNs calling ??
// Close the connection to the server
fclose($fp);
I'll be waiting your answer, guys. I hope this code also helps people who are implementing the server side for sending normal PUSH notifications.
Thanks in advance!!

Resources