APNS Failed to connect: 0 - php

I followed Ray Wenderlich's tutorial for remote notifications on iOS, and had no issues with development. In production, however, my notifications are failing with the error: Failed to connect: 0
I've searched around, but nobody seems to have a definitive script, and many of the answers on SO are contradictory. Here is the code I am currently using:
<?php
// Put your device token here (without spaces):
$deviceToken = [my device token];
// Put your private key's passphrase here:
// ITS REALLY THE PEM PASS
$passphrase = [the password];
// Put your alert message here:
$message = 'Hello, User!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
$cert = __DIR__ . '/Notifications_iOS/ck.pem';
stream_context_set_option($ctx, 'ssl', 'local_cert', $cert);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
/*
// Dev
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
*/
// Production
$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);
?>

Related

Parse error: syntax error, unexpected token ":"

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.

Apple disconnected me because of invalid tokens

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);

ios push notification performance

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.

Is it possible to send iOS push notifications to two different apps?

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

APNS Feedback and PHP for a dummie

My last app get a lot of user (> 200 000), i have set my own push solution.
Nevertheless i'm facing new problems and when i want to push all my user the same time.
After opened a ssl connexion i make a loop with all token and using if the token is valid (isDigit and length > 64 ) but what i have understood is that one of the token is no more valid regarding my apns .pem apns will stop the loop. I know i need to call the feedback service to get my invalid token but i push my user for the first the apns will stop my loop and i can't get any feedback service !
I have set a simple php script to get feedback :
<?php
$stream_context = stream_context_create();
stream_context_set_option($stream_context, 'ssl', 'local_cert', 'myApns.pem');
$apns = stream_socket_client('ssl://feedback.push.apple.com:2196',
$errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $stream_context);
if(!$apns) {
echo "ERROR $errcode: $errstr\n";
return;
}
$feedback_tokens = array();
//and read the data on the connection:
while(!feof($apns)) {
$data = fread($apns, 38);
if(strlen($data)) {
$feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data);
}
}
fclose($apns);
print_r($feedback_tokens);
echo("done");
?>
But it always print me a null array (Array()). Is there any solution in php so i send my token to the apns which verify the token is valid or not?
Restrict null value before loop is calling.
And try these code
$passphrase = PASSWORD;
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'MyApns.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);
$body['aps'] = array('alert' => $msg,'sound' => 'default');
$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){
return false;
//echo 'Message not delivered' . PHP_EOL;
}else{
return true;
//echo 'Message successfully delivered' . PHP_EOL;
}fclose($fp);
}

Categories