PHP For iOS Push Notifications, Sometimes More Than 1 Device - ios

I am building an app in which I am using NSUserDefaults to store various pieces of information, including the deviceToken that is used for APNS on iOS. The way it is currently working is that a user submits a request, and it adds an entry to an XML, one of the elements in that XML is called deviceToken. When someone responds to that request, it triggers the PHP at the bottom of the page to send a Push Notification to the deviceToken of that particular request. My issue is that some people have more than one device, and it would be nice to send the Push Notification to all of that owner's devices. As you can see in the code below, I have 2 areas for deviceTokens. If the XML contains 2 device tokens, everything is great. The issue is that for the ones that there is only 1 token, it will fail to deliver even the one. How can I fix this PHP so that it will be able to accept 2 deviceTokens, but still deliver if only 1 is available?
<?php
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$title = $_POST['title'];
$deviceToken = $_POST['deviceToken'];
$deviceToken2 = $_POST['deviceToken2'];
$xml = simplexml_load_file("http://www.URL.xml") or die("Not loaded!\n");
$passphrase = 'passphrase';
// Put your alert message here:
$message = 'Someone just responded to you!';
////////////////////////////////////////////////////////////////////////////////
$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;
$msg2 = chr(0) . pack('n', 32) . pack('H*', $deviceToken2) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
$result = fwrite($fp, $msg2, strlen($msg2));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>

What you can do is use the function as a generic one: that is, it accepts a device token object. This could be a single string, or an array of multiple strings.
Then, check whether$deviceToken is an array using the is_array function. Ref:http://us3.php.net/manual/en/function.is-array.php
For this, you may have to rewrite small bits of the code. So overall, it would look something like this:
if(is_array($deviceToken)) {
// Iterate over the array and call the same function with each string
return;
}
// You're code to actually send the push notification just as you have it above.

Related

Apple APNs push notification is not working

My team is using the Apple push notifications for the last 7 years which was working like a Gem. Recently generated builds in both the Development certificate and the App Store certificate are not receiving notifications.
The notification is sent from the PHP code.
<?php
// Put your device token here (without spaces):
$deviceToken = '****************';
// Put your private key's passphrase here:
$passphrase = '******';
// Put your alert message here:
$message = 'Hi User!';
//$message =$_REQUEST['message'];
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'cert.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
echo $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);
?>
The Push notification results as a success. But the App is not receiving the notification. Is there any new update in this code? Is there any chance for errors in receiving notifications on the device?
If you was sending push using p12 or pem file then it's stopped.
You have to use new way using P8 files
Check below link for further details.
https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns/

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.

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.

How to setup push notification for development?

I've developed an app for ios and it has been published on the app store.
The push notification system worked fine in development but now, i receive no notification at all.
Before publishing, i've generated the Development Provisioning Profiles associated with an App Id having enabled the push and configurated the Production Push SSL Certificate. I've downloaded the Production Push SSL Certificate and installed it in my keychain access, exported it and its private key, converted them to pem and united them in a unique pem file, which i uploaded to my server containing the php script which send the notifications.
I've changed the server in my php script to the one of production (ssl://gateway.push.apple.com:2195).
Still the script seems to send the notification and doesn't fire any error.
What i'm missing?
Here's my php script:
<?PHP
/* Here there's Code to retrieve device tokens and put it in a variable $deviceToken from my online database and then...*/
$message = "Message to be sent";
$payload = '{
"aps" :
{ "alert" : "'.$message.'",
"badge" : 1,
"sound" : "bingbong.aiff"
}
}';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', 'secret');
// se l'app è già sull'appstore togliere sandbox e lasciare solo gateway.push.apple.com:2195
// invece di gateway.sandbox.push.apple.com:2195
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
if(!$fp){
print "Failed to connect $err $errstrn";
return;
} else {
print "Notifications sent! </br>";
}
foreach($devArray as $deviceToken){
$msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack ("n",strlen($payload)) . $payload;
print "sending message :" . $payload . "n to device:".$deviceToken."</br>";
fwrite($fp, $msg);
}
fclose($fp);
?>
Cause you have to regenerate the PEM with a valid "Production Push SSL Certificate" not with the "Development Push SSL Certificate".
EDIT: Sorry i've read two times the wrong row. The procedure looks good, i post the php code that i always use, it looks very similar but you can try to edit it.
<?php
// Passphrase for the private key (ck.pem file)
// $pass = ”;
// Get the parameters from http get or from command line
$message = 'Testo Notifica Push';
$badge = 1;
$sound = 'default';
// Put your private key's passphrase here:
$passphrase = '';
// Construct the notification payload
$body = array();
$body['aps'] = array('alert' => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['sound'] = $sound;
/* End of Configurable Items */
// Put your device token here (without spaces):
$deviceToken = '20afc981ce9f0c63b5beb83d561d086a1338b2d42dd6defef67e4b7dbabe72b9';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'cert.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;
// Construct the notification payload
$body = array();
$body['aps'] = array(’alert’ => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['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);
?>
One last step to do when setting up push is be sure you didn't mixed production and development device token!
In my case, in my db the first device token the push was send to, was a development one. When this happens, Apple server kill the connection, avoid any other notification to be sent. Thanks Apple!

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