The following code works, but it sends only around 1000 push notifications after the timeout of 5 minutes, I have set ini_set('max_execution_time', 30000); but not working also set in PHP.ini file
function iphone_push(device<sub>token</sub>, message = "", title = "", badge = 1)
{
try {
$write_data = "";
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $this->certificate_path);
$push_arr = array(
"alert" => $title,
"sound" => "push_sound.wav",
"badge" => 1,
);
$payload = array();
$payload['aps'] = $push_arr;
$payload = json_encode($payload);
for ($i = 0; $i < count($device_token); $i++)
{
$fp = stream_socket_client($this->apns_host, $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
if ($device_token[$i] == "")
continue;
$apnsMessage = chr(0) . Chr(0) . Chr(32) . Pack('H*', str_replace(' ', '', $device_token[$i])) . Chr(0) . Chr(strlen($payload)) . $payload;
fwrite($fp, $apnsMessage);
}
fclose($fp);
} catch (Exception $e) {
write_log("ipush", $e->getMessage());
}
return success_res("iphone_push_sent");
}
Related
Here is my NodeJS code , which is working totally fine.
var options = {
//production
"cert": readCredentialsFile(cert_file),
"key": readCredentialsFile(cert_key_file),
"production" : production_val,
"passphrase": "mypassphrase",
"gateway": gateway_val,
"port": 2195,
"enhanced": true,
"cacheLength": 5,
"retryLimit":-1
};
options.errorCallback = apnError;
var feedBackOptions = {
"cert": readCredentialsFile(cert_file),
"key": readCredentialsFile(cert_key_file),
"passphrase": "mypassphrase",
"production" : production_val,
"batchFeedback": true,
"interval": 300
};
var apnConnection, feedback;
module.exports = {
initAPN : function(){
try {
apnConnection = new apn.Connection(options);
feedback = new apn.Feedback(feedBackOptions);
feedback.on("feedback", function (devices) {
devices.forEach(function (item) {
//TODO Do something with item.device and item.time;
});
});
} catch (error) {
console.log(error);
}
},
sendIOSNotification : function (device_token,message,params){
var myDevice, note;
try{
console.log("iOS device_token ", device_token);
var randomID = require("random-id");
var payloadMultiCast = {
"data": {
"id": randomID(),
"status": params.notification_type,
"title": message,
"body": params,
"message": message
}
};
myDevice = new apn.Device(device_token);
note = new apn.Notification();
note.expiry = Math.floor(Date.now() / 1000) + 3600; // Expires 1 hour from now.
note.badge = 1;
note.sound = "ping.aiff";
note.alert = message;
note.payload = payloadMultiCast;
console.log("iOS Notification ", note);
if(apnConnection) {
apnConnection.pushNotification(note, myDevice);
console.log("iOS res "+ device_token+":::"+JSON.stringify(apnConnection));
}else{
console.log("NO APNS CONNECTION");
}
}catch(err){
console.log("error:-"+err);
}
}
}
And below is my php code , which is not working with same "pem" file and same credentials:-
$streamContext = stream_context_create();
stream_context_set_option($streamContext, $options);
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $error, $errorString, 60000, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns)
$errrrr = json_encode(error_get_last());
echo("Failed to connect 11amarnew: $err $errstr $errrrr" . PHP_EOL);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $dev)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
fclose($apns);
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $file);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$err = ""; $errstr = "";
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195',
$err,
$errstr,
600000,
STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT,
$ctx);
if (!$fp)
$errrrr = json_encode(error_get_last());
exit("Failed to connect amarnew: $err $errstr $errrrr" . PHP_EOL);
//echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$message = "Hello Moto!!";
$body['aps'] = array(
'badge' => +1,
'alert' => $message,
'sound' => 'default'
);
$payload = json_encode($body);
$deviceToken = "ed3d13a56a92027acbb9805bfa5f9a3d6da4fdcf24a57b375bfb638259e9d31c";
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $dev) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
//echo "<pre>"; print_r($result); die();
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered amar'.$message. PHP_EOL;
// Close the connection to the server
fclose($fp);
The error i am getting is -
Failed to connect amarnew: 0 {"type":2,"message":"stream_socket_client(): unable to connect to ssl:\/\/gateway.sandbox.push.apple.com:2195 (Unknown error)","file":"\/var\/www\/html\/push.php","line":42}
FYI , I have allowed 2195 , 2196 ports also on my sever for PHP , NodeJS doesn't need port to be opened.
Then what is issue that causing not working in PHP and working in NodeJS, finally i have to use the php only hence i need to solve the issue.
Thanks,
I have written a function to send push notifications to iOS devices. It sends pushes to more than 100 devices for now. However sometimes it is not sending push notifications. When I debug through the process I identified based on push notification the whole process fails. but the issues is all push tokens are in valid format. So my initial code was like this.
$certificatePath = CERTIFICATE_PATH . "/".APN_CERTIFICATE_FILE;
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $certificatePath);
stream_context_set_option($streamContext, 'ssl', 'passphrase', APN_PASSWORD);
$apns = stream_socket_client(APN_HOST . ':' . APN_PORT , $error, $errorString, 2, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $streamContext);
if (!$apns) {
echo "Failed to connect $err $errstrn";
return false;
}
$payload = array();
$payload['aps'] = array('alert' =>$message,'title'=>$title, 'sound' => 'default','data'=>array());
$payload = json_encode($payload);
foreach ($pushTokens as $pushToken)
{
$pushToken = str_replace(' ', '', $pushToken);
if(!ctype_xdigit($pushToken))
continue;
$apnsMessage = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $pushToken)) . pack ("n",strlen($payload)) . $payload;
$rst = fwrite($apns, $apnsMessage);
}
fclose($apns);
As a fix I changed the code to different way. I know this code is expensive since it open and close connection for every push notification.
$certificatePath = CERTIFICATE_PATH . "/".APN_CERTIFICATE_FILE;
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $certificatePath);
stream_context_set_option($streamContext, 'ssl', 'passphrase', APN_PASSWORD);
$payload = array();
$payload['aps'] = array('alert' =>$message,'title'=>$title, 'sound' => 'default','data'=>array());
$payload = json_encode($payload);
foreach ($pushTokens as $pushToken)
{
$apns = stream_socket_client(APN_HOST . ':' . APN_PORT , $error, $errorString, 2, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $streamContext);
if (!$apns) {
echo "Failed to connect $err $errstrn";
return false;
}
$pushToken = str_replace(' ', '', $pushToken);
if(!ctype_xdigit($pushToken))
continue;
$apnsMessage = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $pushToken)) . pack ("n",strlen($payload)) . $payload;
$rst = fwrite($apns, $apnsMessage);
fclose($apns);
}
I am wondering if it is an issue with fwrite or somewhere else. Appreciate if someone can help me with my first method as it is speed, and run with minimum resources.
This is the code that I am using for notification from PHP to iOS
#--------------- initializations ------------------------------
$message = substr($message, 0, 255);
$sound = 'default';
$development = true;
$badge = '1';
$payload['aps'] = array(
'alert' => $message,
'badge' => intval($badge),
'sound' => $sound
);
$payload = json_encode($payload);
$apns_url = NULL;
$apns_cert = NULL;
$apns_port = 2195;
#-------------------------(/initializations)---------------
// developement or live server certificate
if($development)
{
$apns_url = 'gateway.sandbox.push.apple.com';
$apns_cert = __DIR__.'/app_dev.pem';
}
else
{
$apns_url = 'gateway.push.apple.com';
$apns_cert = __DIR__.'/app_prod.pem';
}
$stream_context = stream_context_create();
stream_context_set_option($stream_context, 'ssl', 'local_cert', $apns_cert);
$apns = stream_socket_client('ssl://' . $apns_url . ':' . $apns_port, $error, $error_string, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_CONNECT, $stream_context);
$device_tokens = $receivers;
foreach($device_tokens as $device_token)
{
$apns_message = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device_token)) . chr(0) . chr(strlen($payload)) . $payload;
$result = fwrite($apns, $apns_message,strlen($apns_message));
}
#socket_close($apns);
fclose($apns);
The error I am getting is
Warning: stream_socket_client(): unable to connect to
ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out)
Can anybody see what is wrong with code ?I have read many posts related to this but nothing is helping me .
i have a little problem with my PHP Code.
I did not get it to work, that the message i sent, will receive on all Devices witch are saved in my Database.
The Push App on the Device registers automatically the deviceToken in my MySQL Database. That is all working fine.
The big problem is, that i get the Push Message only to the FIRST Device from the Database. The other Device don't receive any message.
Here my code:
<?php
require_once('konfiguration.php');
$sql = "SELECT deviceToken FROM DeviceTokens";
$dbquery = mysql_query($sql);
// check checkboxes
$message = $_POST['alert'];
$badge = $_POST['badge'];
$sound = $_POST['sound'];
// Construct the notification payload
$body = array();
// anti-error variable
$nothing = true;
// get user input
if ($message) { $alert=$_POST['message']; $nothing = false;
$body['aps']['alert'] = $alert; }
if ($badge) { $nothing = false;
if($_POST['number']) $number=(int)$_POST['number'];
else $number=1;
$body['aps']['badge'] = $number; }
if ($sound) { $nothing = false;
$body['aps']['sound'] = 'beep.wav'; }
// if input not correct, scream
if ($nothing || ($message && $alert=="")) { echo "Falscher Input!"; exit(); }
//make new stream context
$ctx = stream_context_create();
// set parameters
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', 'w3workProd.pem');
//stream_context_set_option($streamContext, 'ssl', 'passphrase', 'nils');
$socketClient = stream_socket_client('ssl://gateway.push.apple.com:2195', $error,
$errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
$payload = json_encode($body);
print "sending message :" . $payload . "\n";
while($row = mysql_fetch_array($dbquery)) {
$message = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken))
.chr(0) . chr(strlen($payload)) . $payload;
$deviceToken = str_replace(' ', '', $row['deviceToken']);
$message = pack('CnH*', 0, 32, $deviceToken);
$message = $message . pack('n', strlen($payload));
$message = $message . $payload;
fwrite($socketClient, $message);
echo ($row['deviceToken']);
}
fclose($socketClient);
exit();
?>
Would be nice if you can help.
Why is it working with one Device...and not with the others...
have you tried
STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT
?
I use php to send push message to apns , i use "Enhanced notification format" to sent .. but i can not get the return" Codes in error-response packet" anyone can help me ?? here is my code
<?php
header("Content-Type: text/html; charset=UTF-8");
$deviceToken = "123";
$content = "testing";
if(isset($content))
{
$newContent=substr($content,0,30)."...";
$re_content=iconv("GB2312","UTF-8",$newContent);
$pass = 'Ladder';
$body = array("aps" => array("alert" => $re_content, "badge" => 1, "sound" => 'received5.caf'));
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'dev.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
//$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
stream_set_blocking ($fp, 0);
if (!$fp)
{
print "Failed to connect $err $errstrn";
return;
}
else
{
print "Connection OK\n<br/>";
}
$payload = json_encode($body);
$msg =
// new: Command "1"
chr(1)
// new: Identifier "1111"
. chr(1) . chr(1) . chr(1) . chr(1)
// new: Expiry "tomorrow"
. pack('N', time() + 86400)
// old
. chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
//print "sending message :" . $payload . "\n";
fwrite($fp, $msg);
//checkAppleErrorResponse($fp);
echo 'Done\n';
fclose($fp);
echo $apple_error_response = fread($fp, 6);
/* return false;
exit(); */
}
?>
I call this function after fwrite and before close commands
function error_response($fp)
{
$read = array($fp);
$null = null;
$changedStreams = stream_select($read, $null, $null, 0, 1000000);
if ($changedStreams === false)
{
echo ("Error: Unabled to wait for a stream availability");
}
elseif ($changedStreams > 0)
{
$responseBinary = fread($fp, 6);
if ($responseBinary !== false || strlen($responseBinary) == 6)
{
$response = unpack('Ccommand/Cstatus_code/Nidentifier', $responseBinary);
var_dump($response);
}
}
}
It works when I sending a notification in the enhanced format. But doesn't work with notification in the simple format. I don't have idea why... Any clue?