I'm trying to implement the APNS (Push notification). I've created the certificates, etc.. everything was created like iv'e done many many times. but i cant get an error from apple APNS server and it seems that everything is ok but i still not getting any push in the devices. this is the PHP code I'm using to make the magic :) I ensure that the PORTS are open in the hosting.
basically I'm getting the user token from the DB and sending the push text with default sound.
can someone please look and tell me if you can see any problem in this code or let me know how can i get the real result of the process / response from APNS Server?
<?php
error_reporting(0);
header("Content-type: application/json; charset=utf-8");
include "dbconn.php";
$data = array();
$json= array();
$users = array();
$opponent_id = $_REQUEST['opponent_id'];
$sender_id = $_REQUEST['sender_id'];
$message = $_REQUEST['message'];
$sql = "SELECT * FROM `registration` WHERE `chat_id` ='$opponent_id'";
$result = mysql_query($sql);
if (!$result) {
echo "Could not successfully run query ($sql) from DB: " . mysql_error();
exit;
}
if (mysql_num_rows($result) == 0) {
echo "No rows found, nothing to print so am exiting";
exit;
}
while ($row = mysql_fetch_assoc($result)) {
$token = $row['token'];
}
echo "\n$token";
$passphrase = 'certificate_password';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
//stream_context_set_option($ctx, 'ssl', 'local_cert','push/some_prod_certificate.pem');
stream_context_set_option($ctx, 'ssl', 'local_cert','push/some_dev_certificate.pem');
stream_context_set_option($ctx, 'ssl', 'cafile', 'push/entrust_root_certification_authority.pem');
# Open a connection to the APNS server
$fp = stream_socket_client(//'ssl://gateway.push.apple.com:2195', $err,
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp){
echo "Error: ".$err;
exit;
}
echo "\n".'Connected to APNS Push Notification' . PHP_EOL;
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
$payload = json_encode($body);
echo "\n$payload";
// Build the binary notification
$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));
//set blocking
stream_set_blocking($fp,0);
//Check response
checkAppleErrorResponse($fp);
// Close the connection to the server
fclose($fp);
function checkAppleErrorResponse($fp) {
$apple_error_response = fread($fp, 6); //byte1=always 8, byte2=StatusCode, bytes3,4,5,6=identifier(rowID). Should return nothing if OK.
//NOTE: Make sure you set stream_set_blocking($fp, 0) or else fread will pause your script and wait forever when there is no response to be sent.
if ($apple_error_response) {
$error_response = unpack('Ccommand/Cstatus_code/Nidentifier', $apple_error_response); //unpack the error response (first byte 'command" should always be 8)
if ($error_response['status_code'] == '0') {
$error_response['status_code'] = '0-No errors encountered';
} else if ($error_response['status_code'] == '1') {
$error_response['status_code'] = '1-Processing error';
} else if ($error_response['status_code'] == '2') {
$error_response['status_code'] = '2-Missing device token';
} else if ($error_response['status_code'] == '3') {
$error_response['status_code'] = '3-Missing topic';
} else if ($error_response['status_code'] == '4') {
$error_response['status_code'] = '4-Missing payload';
} else if ($error_response['status_code'] == '5') {
$error_response['status_code'] = '5-Invalid token size';
} else if ($error_response['status_code'] == '6') {
$error_response['status_code'] = '6-Invalid topic size';
} else if ($error_response['status_code'] == '7') {
$error_response['status_code'] = '7-Invalid payload size';
} else if ($error_response['status_code'] == '8') {
$error_response['status_code'] = '8-Invalid token';
} else if ($error_response['status_code'] == '255') {
$error_response['status_code'] = '255-None (unknown)';
} else {
$error_response['status_code'] = $error_response['status_code'].'-Not listed';
}
echo '<br><b>+ + + + + + ERROR</b> Response Command:<b>' . $error_response['command'] . '</b> Identifier:<b>' . $error_response['identifier'] . '</b> Status:<b>' . $error_response['status_code'] . '</b><br>';
echo 'Identifier is the rowID (index) in the database that caused the problem, and Apple will disconnect you from server. To continue sending Push Notifications, just start at the next rowID after this Identifier.<br>';
return true;
}
echo "\nPush respnse OK";
return false;
}
?>
You can't get error responses from Apple because you are using the simple binary format that doesn't return error responses :
$msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;
If you want a format that can returns an error response, you can use one of the enhanced formats.
For example, the format that starts with 1 :
The msg would start with chr(1)
, followed by 4 bytes of message ID, 4 bytes of expiration time and the rest of the message would be the same as what you have now pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload
It should look like this :
$msg = chr(1) . pack("N", $msg_id) . pack("N", $expiry) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;