I've set up and APNS Provider Server using PHP. I connect to Apple's APNS Server with no errors, and the script seems to run fine, cycling through all the devices and sending the payload. However, notifications aren't being received on the devices that have subscribed to notifications. Can someone please help me find the error in my code?
$message = $_POST['message'];
echo "Posted Message: $message<br />";
$message = str_replace("'", "\'", $message);
echo "Formatted message: $message<br />";
$title = $_POST['title'];
$title = str_replace("'", "\'", $title);
echo "Formatted Title: $title<br />";
$category = $_POST['category'];
echo "Category: $category<br />";
$alert = array('title' => "$title", 'body' => "$message");
foreach ($alert as $key => $value){
echo "Key: $key Value: $value<br />";
}
ini_set("display_errors",1);
$apnsHost = 'gateway.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns.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 ($error!="" || $errorString!=""){
echo "Error Connecting: $error : $errorString<br />";
}
else{
echo "No Error Connecting<br />";
}
$query = "INSERT INTO notifications (`title`, `message`, `category`) VALUES (\"$title\", \"$message\", \"$category\")";
echo "Insert Query: $query<br />";
$result1 = mysqli_query($connection, $query);
$query = "SELECT * FROM notifications ORDER BY notification_id DESC";
$result931 = mysqli_query($connection, $query);
$row = $result931->fetch_assoc();
$notification_id = $row[notification_id];
$query = "SELECT * FROM category_subscriptions WHERE category_id='$category' ORDER BY device_id";
$result1 = mysqli_query($connection, $query);
echo "Subscriber Query: $query<br />";
while($row = $result1->fetch_assoc()) {
$device_id = $row[device_id];
$query = "SELECT * FROM devices WHERE device_id='$device_id' ORDER BY device_id";
$result = mysqli_query($connection,$query);
while($r = $result->fetch_assoc()) {
$deviceToken = $r[device_token];
$badge = $r[badge_value] + 1;
if ($r[accepts_alerts]==1) {
if ($r[accepts_badges]==1) {
if ($r[accepts_sounds]==1) {
$payload['aps'] = array('alert' => $alert, 'badge' => $badge, 'sound' => 'default');
} else {
$payload['aps'] = array('alert' => $alert, 'badge' => $badge);
}
}
else if ($r[accepts_sounds]==1) {
$payload['aps'] = array('alert' => $alert, 'sound' => 'default');
}
else {
$payload['aps'] = array('alert' => $alert);
}
$payload1 = json_encode($payload);
echo "Payload: $payload1<br />";
echo "<br /> Sending to Device Token: $deviceToken<br />";
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload1)) . $payload1;
echo "APNS Message: $apnsMessage<br />";
fwrite($apns, $apnsMessage);
$query6 = "UPDATE devices SET badge_value = $badge WHERE device_id='$device_id'";
$result6 = mysqli_query($connection,$query6);
$query7 = "INSERT INTO notification_map (`device_id`, `notification_id`, `viewed`) VALUES ($device_id, $notification_id, \"false\")";
$result7 = mysqli_query($connection,$query7);
}
}
}
fclose($apns);
Screenshot:
Perform following steps:
1. Check if pem file is valid or not.
2. check if port 2195 is open on your server or not.
3. if your pem file is of development mode the use "ssl://gateway.sandbox.push.apple.com:2195" to connect to apns otherwise if your pem file is of production mode the use "ssl://gateway.push.apple.com:2195" .
check if passpharas is correct.
check this sample code:
<?php
// Put your device token here (without spaces):
$deviceToken = 'fefb03ba6adcea310cf3f455dae16fec4f63b4ba4d96103c20d594a04efd7c2a';
// Put your private key's passphrase here:
$passphrase = 'Welcome#1';
// Put your alert message here:
$message = 'My first push notification!';
////////////////////////////////////////////////////////////////////////////////
$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',
'title' => 'testing title'
);
// 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);
Upon further reading of the documentation, I believe I have figured out my problem. I had one database table that held the device tokens for both development and production versions of the app. Apparently when trying to send a production notification it was closing the connection after sending a development device token. I'm not sure why the fwrite command wasn't sending errors after the connection closed, but since I deleted the development device tokens from the database table, it appears to be working now.
Related
Push notification badge count not increasing.It shows always 1.I have used php to send the push from server and here is the code following:
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsCert = 'project_dev.pem';
$apnsPort = 2195;
$badgecount=1;
$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){
exit("Failed to connect: $error $errorString" . PHP_EOL);
}else{
$messageHeader = (strlen($message) > 26) ? substr($message,0,26).'...' : $message;
$msgd=explode(':',$message);
$payload['aps'] = array('alert' => $messageHeader,'badge' => $badgecount, 'sound' => 'default','mess'=>$fromUserId.'||'.$userNamee.'||'.$userimage.'||'.$message,'type'=>'reply', 'unread_count'=>$unread_count);
$output = json_encode($payload);
$token = pack('H*', str_replace(' ', '', $token));
$apnsMessage = chr(0) . chr(0) . chr(32) . $token . chr(0) . chr(strlen($output)) . $output;
fwrite($apns, $apnsMessage);
fclose($apns);
}
badgecount always send by server side.it seems you are sending $badgecount=1; always.Update it with other value then check.It definitely reflect on IOS.
In your code you have send your badge always one that's why you getting only $badgecount 1 badge into application side.
you need to use following type to send notification badge.
$query = "SELECT badgecount FROM pushnotifications WHERE device_token = '{$device_token}'";
$query = $this->db->query($query);
$row = $query->row_array();
$updatequery = "update pushnotifications set badgecount=badgecount+1 WHERE device_token ='{$device_token}'";
$updatequery = $this->db->query($updatequery);
$device = $device_token;
$payload['aps'] = array('alert' => $pushmessage, 'badge' =>$row["badgecount"]+1, 'sound' => 'default');
$payload = json_encode($payload);
I think you now more clearify with above code.
I have set up a php file on my own server and used it to send push notifications. I have already tried it with two devices and it works well. The problem is with the feedback method which returns nothing. I have already tried everything and disabled firewall and so on. Note that i tested the feedback like this: I run the app on both devices. They both get the notification. then i delete the app on one of them and try again. Here is the PHP code i used:
<?php
$deviceToken1 = '.....';
$deviceToken2 = '.....';
$tokenArr = array($deviceToken1,$deviceToken2);
$passphrase = '.....';
$message = $_POST['message'];
$newsID = $_POST['newsID'];
$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;
for($i = 0; $i < count($tokenArr); $i++)
{
$body['aps'] = array(
'alert' => $message,
'badge' => 1,
'sound' => 'sound.aiff',
'newsID' => $newsID);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $tokenArr[$i]) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result) {
echo '<br/>'.date("Y-m-d H:i:s").' Message not delivered' . PHP_EOL;
}
else {
echo '<br/>'.date("Y-m-d H:i:s").' Message successfully delivered' . PHP_EOL;
}
}
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
$apns = stream_socket_client('ssl://feedback.sandbox.push.apple.com:2196', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
echo $apns;
if(!$apns)
{
echo '<br/>';
echo "Error $errcode : $errstr\n";
return;
}
else {
echo "APNS feedback results\n";
while ($devcon = fread($fp, 38))
{
$arr = unpack("H*", $devcon);
$rawhex = trim(implode("", $arr));
$feedbackTime = hexdec(substr($rawhex, 0, 8));
$feedbackDate = date('Y-m-d H:i', $feedbackTime);
$feedbackLen = hexdec(substr($rawhex, 8, 4));
$feedbackDeviceToken = substr($rawhex, 12, 64);
echo "TIMESTAMP:" . $feedbackDate . "\n";
echo "DEVICE ID:" . $feedbackDeviceToken. "\n\n";
}
}
?>
I have submit my app to apple store and now I want to send APNS to the users .
I want to send 7000 push messages through this php code from my desktop:
<?php
// Put your private key's passphrase here:
$passphrase = '*****';
// Put your alert message here:
$message = 'text here';
////////////////////////////////////////////////////////////////////////////////
$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</br>' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
////////////////////////////////////////////////////////////////////////
function selectfromdb(){
$x = array();
$con = mysql_connect("localhost","root","root");
mysql_select_db("my_db", $con);
mysql_query("set character_set_server='utf8'");
mysql_query("set names 'utf8'");
$result = mysql_query("SELECT idip FROM id");
$c = 0;
while($r = mysql_fetch_array($result))
{
$x[$c] = $r['idip'];
$c++;
}
return $x;
}
///////////////////////////////////////////////////////////////////////
$y = selectfromdb();
$i = 0;
while ($i < sizeof($y)){
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*',$y[$i]) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered</br>' . PHP_EOL;
else
echo 'Message successfully delivered</br>' . PHP_EOL;
$i++;
}
echo 'end</br>';
// Close the connection to the server
fclose($fp);
?>
but it just sent for 507 , then it says : Message not delivered
for all the rest .
The problem is that apple closes the connection after X messages that were sent to unavailable device-IDs.
Clean up your collection / database of deviceids by consuming the APNS feedback service, then finish the deployment of your APNS messages.
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 am able to connected to the apns and by inserting the values to database for just check i am getting "message delivered" message but it's not showing any notification....can anybody tell me where i am mistaken...
$deviceToken = '**********************';
$payload['aps'] = array('alert' => 'This is the alert text', 'badge'
=> 1, 'sound' => 'default'); $payload = json_encode($payload);
$passphrase = '***';
$apnsHost = 'gateway.sandbox.push.apple.com'; $apnsPort = 2195; $apnsCert = 'ck.pem';
$streamContext = stream_context_create(); stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert); stream_context_set_option($streamContext, 'ssl', 'passphrase',$passphrase );
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns)
{
$check = $errorString; $query = "INSERT INTO tbl_checkData(friend_nickname) VALUES('$check') "; $result=mysql_query($query); } else{
$check = "connected"; $query = "INSERT INTO tbl_checkData(friend_nickname) VALUES('$check') "; $result=mysql_query($query); }
$apnsMessage = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
//chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
$result=fwrite($apns, $apnsMessage);
if (!$result)
{
$check = 'Message not delivered' ; $query = "INSERT INTO tbl_checkData(friend_nickname) VALUES('$check') "; $result=mysql_query($query);
} else { $check = 'Message delivered' ; $query = "INSERT INTO tbl_checkData(friend_nickname) VALUES('$check') "; $result=mysql_query($query);
}
enter code here
fclose($apns);
$apnsHost = 'gateway.sandbox.push.apple.com';
remove sandbox from this url and it will run...
i have tested it...
Make sure that :
1-your app is not running because push notification used only to notify the use when the app is closed.
2-Device token of the device is correct Also make sure that the push notification certificate is also configured for the same device.
3-Make sure that you device is connected to the internet .
You can take a look at this link.
Push Notification