I am using php in the backend to send apple push notification.
Sometimes i am receiving the notifications sometimes i am not.
i know this is a simple code to use, if there any other ways to send the notifications. cant understand why its not delivering always and sometimes it does.
ps: this is i am using for production build
function sendPush($user_id,$message,$video_id,$not_type,$deviceToken)
{
$passphrase = 'xxxxx';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'xxx.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
$body['aps'] = array(
'alert' => $message,
'badge' => '1',
'sound' => 'default');
$body['payload'] = array(
'type' => $not_type,
'user_id' => $user_id,
'video_id' => $video_id
);
$payload = json_encode($body);
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
fclose($fp);
}
Apple:
Keep your connections with APNs open across multiple
notifications; don’t repeatedly open and close connections. APNs
treats rapid connection and disconnection as a denial-of-service
attack. You should leave a connection open unless you know it will be
idle for an extended period of time—for example, if you only send
notifications to your users once a day it is ok to use a new
connection each day.
check this link Troubleshooting Push notifications from apple documentation.
There are several issues involved in not getting push notification. Based on your scenario test your code.
Related
I try to send multiple notifications with one hit. Many users have more than one device and i put their device tokens into an array. It is working fine but if there is a wrong token Apple is disconnecting me and the device with working token gets no push notification. I've read about a error-response-solution at this post: Apple Push Notification Limits
But this solution is not working for me. It says: Status:7-Invalid payload size.
But there is only the message "test" and I'm sure the reason is the wrong token. How could I continue the foreach script without disconnecting?
// Put your device token here (without spaces):
$deviceToken = array('WRONG_TOKEN', 'WORKING_TOKEN');
// Put your private key's passphrase here:
$passphrase = 'PASS';
// Put your alert message here:
$message = "test";
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'cer.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' => "www/sound.mp3",
'content-available' => 1,
'badge' => 1
);
// Encode the payload as JSON
$payload = json_encode($body);
//foreach für array
foreach($deviceToken as $token){
$msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
}//foreach end
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
//checkAppleErrorResponse($fp);
// Close the connection to the server
fclose($fp);
I'm working on an iOS app that use iOS Push Notifications. I want to send the notification from a php script on my windows PC. I use this php script to send notification and it works well too:
// Put your device token here (without spaces):
$deviceToken = 'sdsdsdsdsczc2';
$sound = '';
// Put your private key's passphrase here:
$passphrase = 'awertf';
// 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.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(
'badge' => +1,
'alert' => $message,
'sound' => $sound
);
// 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 php script works well on windows but now i'm working on Ubuntu 14.04 operating system and same php script is giving me error.
Message: stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
I guess it's something related with port 2195. But how to solve this!
This was an enormously helpful link to find:
http://php.net/manual/en/migration56.openssl.php
http://php.net/manual/en/context.php
An official document describing the changes made to openssl in PHP 5.6
It's usefull to learn one more parameter that Tou should have set to false/true: for example "verify_peer_name"=>false
So some code looks like this:
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$response = file_get_contents('ssl://'.$host.':'.$port, false, stream_context_create($arrContextOptions));
echo $response; ?>
Im in a situation where i have one server that needs to send push notification to two different client apps without knowing which app is it.
I have two different iOS apps (2 different bundle identifiers) and i have 2 different sets of all the necessary certifications, one for each app.
I have a PHP code that receives the deviceToken and a the message to be pushed.
the code is based on reywenderlich's SimplePush that can be found here: http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
The only part that need to change is the ck.pem file that will be different for each app.
One solution i can think of would be to try the two different ck.pem files, if one fails try the other one.
Can any one help me with implementing that in this PHP code ? or if there are any better solution suggestions ?
<?php
// Put your device token here (without spaces):
//$deviceToken = 'a6a543b5b19ef7b997b2328';
$deviceToken = $_GET["device_token"];
$message = $_GET["message"];
$elementID = $_GET["element_ID"];
// Put your private key's passphrase here:
$passphrase = '123456';
// Put your alert message here:
//$message = 'My first push notification! yay';
////////////////////////////////////////////////////////////////////////////////
$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'
);
// Create the extra data
$body['extra'] = array(
'element_id' => $elementID
);
// 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);
UPDATE:
the solution is to add another piece of code at the end, to send the same payload to the second server:
//connecting to second server
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'SecondCk.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 to note server: $err $errstr" . PHP_EOL);
// connected to server sending note msg
$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 don't know how to do this in PHP, but you should simply create the payload body + binary notification before opening the first connection and then create 2 connections(or loop a connection, if possible) to Apple's Push Server and send the same binary notification to both of them.
Best regards,
Gabriel Tomitsuka
How to implpement on below code for send 1000 push notification at same time server to ios deivce using php.
function push_iphone($deviceTokenid,$message){
$passphrase = '12345';
$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)
return false;
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'message' => $message,
'sound' => 'default',
'flag' => '0'
);
// Encode the payload as JSON
$payload = json_encode($body);
//echo $device_token_id;
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceTokenid) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if(!$result){
echo "tst";
return true;
}else{ echo "test ";
return false;
}
fclose($fp);
}
Can any body help me about it.
Apple has an answer to this in their documentation:
You may establish multiple connections to the same gateway or to
multiple gateway instances. If you need to send a large number of
remote notifications, spread them out over connections to several
different gateways. This improves performance compared to using a
single connection: it lets you send the remote notifications faster,
and it lets APNs deliver them faster.
Keep your connections with APNs open across multiple notifications;
don’t repeatedly open and close connections. APNs treats rapid
connection and disconnection as a denial-of-service attack. You should
leave a connection open unless you know it will be idle for an
extended period of time—for example, if you only send notifications to
your users once a day it is ok to use a new connection each day.
By threading your php application you can achieve this at (almost) the same time. Take a look at Patterns for PHP multi processes? for a direction which to take to setup forks.
I have the following php code for ios push notification.Here i code for 2 devices using loop in fwrite() section . the current code is working properly . My doubt is , can i pass the array of device tokens directly without using the for loop?.
<?php
// Put your device token here (without spaces):
$deviceToken[0] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$deviceToken[1] = 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy';
// Put your private key's passphrase here:
$passphrase = '123456';
// Put your alert message here:
$message = 'multiple device push notification...!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'abc.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' => '+1'
);
// Encode the payload as JSON
$payload = json_encode($body);
for($i=0;$i<2;$i++)
{
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken[$i]) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
echo "msg may be delivered";
}
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
Its design by default, yet there is no option for passing array of device tokens. You have to iterate through the loop.
Alternate to this approach will be using third party like amazon SNS service. Here you can publish to topic(one request) and all devices that are subscribed to this topic will receive the notification.