I have a quick question. For the apple push notification service, I need to have my own server, which will send out the push notifications to the apple servers, right?
Can I do this with a simple PHP script on a regular webhosting account, or do I need a dedicated server with full blown admin access for that?
If this is possible in PHP, can anyone point me to some samples that can help me get started on this? Right now, I am pretty confident I won't have trouble implementing the client-side part, but the server side is still somewhat of a mystery to me...
Thank you!
Florian
You probably will be able to do this on a limited hosting account, as long as you can leave the connection open to the server most of the time. Some sample code:
http://code.google.com/p/php-apns/
Note also that some companies are starting up services to help you specifically with push hosting (I'll keep the post neutral and not mention names, I'm not sure which services are running just yet).
The Main problem with APNS is ports
so many providers doesnt open 2195 port
so concentrate on that initially then go for the host provider
Here is the code what i tried, but one problem is not able to get device notification
Hi ,
i tried the following code (PHP)
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apple_push_notification_production.pem';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if($apns)
{
echo "Connection Established<br/>";
$deviceToken = '**********';//masked
$body = array();
$body['aps'] = array(’alert’ => "test message");
//$body['aps']['badge'] = 1;
$payload = json_encode($body);
$apnsMessage = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
print "sending message :" . $apnsMessage . "<br/>";
print "sending payload :" . $payload . "<br/>";
fwrite($apns, $apnsMessage);
}
else
{
echo "Connection Failed";
echo $errorString;
echo $error;
}
socket_close($apns);
fclose($apns);
reply is Connection Established
sending message :�� d^÷Îå0ZCd%1ÄuwOOYš'ÊÈ}ârðm¾Í�,{"aps":{"\u2019alert\u2019":"test message"}}
sending payload :{"aps":{"\u2019alert\u2019":"test message"}}
But am not able to get the notification
any help?
Related
i have a problem with Notifications in ios13. If i use gateway.sandbox i can see the notification, but i'have downloaded the app directly from AppStore. Instead using gateway.apple i see 'Delivered Message to APNS', but nothing on my device.
I also tried to recreate the Certificate, .p12 and .pem file.
Any idea? Thank you
This is my php
public function iOS($data, $devicetoken)
{
// $tHost = 'gateway.sandbox.push.apple.com';
$tHost = 'gateway.push.apple.com';
$tPort = 2195;
$tCert = 'pushcert.pem';
$tPassphrase = 'pushcertpsw12';
$tToken = $devicetoken;
$tSound = 'default';
$tPayload = 'APNS payload';
$tBody['aps'] = array(
'apns-priority' => 10,
'badge' => +1,
'alert' => $data['mtitle'] .' ' .$data['mdesc'],
'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 (0) . chr (0) . chr (32) . pack ('H*', $tToken) . pack ('n', strlen ($tBody)) . $tBody;
// Send the Notification to the Server.
$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;
// Close the Connection to the Server.
fclose ($tSocket);
There are two different environments of APNS tokens; Sandbox and Production. They require completely separate setups, permissions, registration, and push setups. Pushing a Sandbox APNS notification to a Production token will not work, the same with Production APNS to Sandbox token.
If you have verified in Sandbox but not in production, you probably need to dupe all your permissions and certificates for production.
Also double check where you're pushing to with your PHP code and ensure it's the correct environment (Sandbox vs Prod).
This is the code I wrote to send apple push notifications.
in the device_tokens i'm sending an array with all of the tokens I want to send message to.
For some reason, I stopped recieving messages from this system.
and it used to work before!
private function send_iphone_notification($device_tokens, $message)
{
define("PRODUCTION_MODE", true);
$apnsPort = 2195;
// Choose dev or production apns host and certificate
if(PRODUCTION_MODE) {
$apnsHost = 'gateway.push.apple.com';
$apnsCert = $_SERVER['DOCUMENT_ROOT'].'/ant/www/apns/PushIphone.pem';
} else {
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsCert = $_SERVER['DOCUMENT_ROOT'].'/ant/www/apns/CertificatesDev.pem';
}
// Notification content
$payload = json_encode(array('notification_from_panel' => 1, 'aps' => array('alert' => $message, 'badge' => 1, 'sound' => 'default')));
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', "");
// loop all devices tokens
foreach ($device_tokens as $device_token)
{
try {
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
} catch(Exception $e) {
echo $e->getMessage();
continue;
}
$deviceToken = str_replace(" ","",substr($device_token,1,-1));
//echo $deviceToken;
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(mb_strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
//socket_close($apns);
fclose($apns);
}
}
I have some experience with Apple's push service and i have to say that apple seems to have soem restrictions in place.
First of all you dont need to close and open the socket connection for every message. That will save you a lot of time. On the other hand you have to check if the connection is broken before you send the next message.
Anyway, it seemed that apple does not like it much when you connect a hundred times a second and send messages. Apples has blocked me for that as well in the passed.
But when you send the message with a already established connection, and at some point the connection is returning an error/ is disconnected, you dont know at what message he stopped. But you can define a identifier for each message and check the error returned when the connection is broken.
I noticed that apples server returns the error with a couple of seconds delay. That makes it hard do deal with it the easy way.
I have written a class to handle all of that but did not jet have time to publish it! If you are interested in it, check the github project for it at https://github.com/tinned-software/PHP-Tinned-MobilePush
I hope to finish the documentation soon.
So, I moved my application to an EC2 instance, and Apple Push Notification Service stopped working. I'm using the same certificate, same script, same everything.
I've opened port 2195 in the security group for the EC2 instance.
from the EC2 intance, telnet gateway.push.apple.com 2195 works
my script receives no errors... everything gets to the end, even fwrite returns true... yet, I receive no push.
Things to note.
My EC2 instance is accessed via https where my old server was http, but since the script would be running locally, and has nothing to do with Apache, I don't see why this should matter. But, perhaps it does, so I'm letting you know :D
My script:
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$ssl = 'ssl://' . $apnsHost . ':' . $apnsPort;
$apns = stream_socket_client($ssl, $error, $errorString, 30, STREAM_CLIENT_CONNECT, $streamContext);
if($apns == false){
echo "Error: $errorString";
return false;
}
$payload['aps'] = array('alert' => $message, 'badge'=>$badge, 'sound' => 'default');
$payload = json_encode($payload);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device_id)) . chr(0) . chr(strlen($payload)) . $payload;
if(fwrite($apns, $apnsMessage)){
return true;
}
return false;
I've checked all of my variables, they are set.
Any help would be greatly appreciated. This is driving me bonkers :P
Turns out I was giving a bad device id. The databases were different, and I stored something poorly. :(
My task is sending push notification to multiple users which is working fine with following function
function push_to_apns_badge($token_array)
{
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$pem_path = MODULE_DIR.'push_notification'.DIRECTORY_SEPARATOR;
$apnsCert = $pem_path.'apns-dev.pem';
if(is_array($token_array) && count($token_array))
{
foreach ($token_array as $token)
{
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
$badge_count = (int)$token['badge'];
$payload = get_payload_badge($badge_count);
$apnsMessage = get_one_message_to_write_badge($token['token'],$payload);
$wrt = fwrite($apns, $apnsMessage);
$_error_str .= " $error $errorString ";
socket_close($apns);
fclose($apns);
}
}
return array(true,$_error_str);
}
But it will take too much cpu usage.
Can I improve Performance somehow? or something missing there?
Thanks
You are making too many connections to Apple and they could block you if you do it this way.
I suspect the creating and tearing down of the connection with each message is also your slow point there!
Apple recommend opening a connection, sending your messages, leaving it open for as long as you can, and to send future messages down that same connection too.
You may want to look at Urban Airship which will send 1 million messages a month free?
Or, you can do it for free using apns-php
http://code.google.com/p/apns-php/
A nice easy to use APNS class which you can queue up a bunch of messages and send them at once with.
My client currently pays a fortune for UA and we're moving away from them.
I successfully manage to implement an iPhone push notification server (PHP) last year; I had to change the server, and was thinking that moving files was sufficient... I was wrong, since the modification notifications are not sent anymore. There's no error, everything seems ok, but notification aren't received.
Below is my server code; anyone can think of a cause, or a way to find the problem ? (notes: the $deviceTokens var is correct, contains the device tokens, and I've successfully tested my .pem certificate with an openssl command).
$payload['aps'] = array('alert' => 'notification!!', 'sound' => 'push.aif');
$payload = json_encode($payload);
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', 'libraries/ck_prod.pem');
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:' . 2195, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if($error) {
log_message('error', $errorString);
return;
}
log_message('debug', 'sending push notification...');
if($apns) {
foreach($deviceTokens as $deviceToken) {
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
}
fclose($apns);
} else {
log_message('error', 'error while sending push notification');
}
Well well... Maybe I should have notice that I was contacting the test server (gateway.sandbox.push.apple.com)... Some days are just difficult...