I am sending push message to iPhone devices Through steam_socket using php.It's working fine but i want to send a 1000 records at time in that case i get only 50 messages then i get Warning: stream_set_timeout():
how could i increase stream socket time is there any way to handle this type problem can any one please guide me.
here is my code
for($i=0;$i<100;$i++)
{
$gstr="3f3dad52b4fb50001cb223253a3d995542209d354eXXXXXXXXXXXXXXXX";
pushMessage($gstr,$_REQUEST['msg'].$i,"Thinkingofyou");
}
function pushMessage($deviceToken,$message,$app) {
echo "Sending iPhone Push Notifications to " . $deviceToken . "<br /><br />";
echo "Your Message: " . $message . "<br />";
$time = time();
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'aps-toyPush.pem';
$streamContext = stream_context_create();
stream_set_timeout($streamContext, 3600);
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) {
$payload = array();
$payload['aps'] = array('alert' => $message, 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
} else {
echo "Connection Failed - iPhone Push Notifications Server";
echo $errorString."<br />";
echo $error."<br />";
}
// socket_close($apns);
fclose($apns);
}
Thanks for advance.
Taken from a user's post in the PHP manual:
<?php
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec'=>$sec, 'usec'=>$usec));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec'=>$sec, 'usec'=>$usec));
?>
Related
I'm trying to push notification to APNS to update my pass in Apple Wallet app. According to this document, we only need to send the pass type identifier and the push token to APNs. Then they will take care of the rest.
$apnsHost = 'gateway.push.apple.com';
$apnsPort = 2195;
$apnsCert = base_path('app/config/passbook/certificates.pem');
$payload = ['aps' => []];
$payload = json_encode($payload);
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', 'xxxxxx');
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
if(!$apns) {
Logger::logError(1, "Passbook push notification error", ['serial_number' => $serialNumber, 'pass_type_id' => $passIdentify]);
return "Failed to connect (stream_socket_client): $error $errorString";
} else {
foreach($push_tokens as $idx => $push_token) {
$msg = chr(0) . pack('n', 32) . pack('H*', $push_token) . pack('n', strlen($payload)) . $payload;
fwrite($apns, $msg);
}
}
#socket_close($apns);
fclose($apns);
There is no error returned but it seem doesn't work. What do I do wrong? Please help.
This is the code working on my project
$errors = [];
$apnsHost = 'gateway.push.apple.com';
$apnsPort = 2195;
$apnsCert = base_path('app/config/passbook/certificates.pem');
$payload = ['aps' => []];
$payload = json_encode($payload);
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', 'xxxxxxxxx');
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
stream_set_blocking ($apns, 0);
if( ! $apns) {
return "Failed to connect (stream_socket_client): $error $errorString";
} else {
foreach($push_tokens as $idx => $push_token) {
$msg = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $push_token)) . chr(0) . chr(mb_strlen($payload)) . $payload;
$success = fwrite($apns, $msg);
if ($success === strlen($msg)) { // log success
Logger::logPassbook('Push success', ['push_token' => $push_token]);
} else {
Logger::logPassbook('Push failed', ['push_token' => $push_token]);
}
}
}
#socket_close($apns);
fclose($apns);
return $errors;
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.
I am following a tutorial https://blog.serverdensity.com/how-to-build-an-apple-push-notification-provider-server-tutorial/ to implement connectivity with apple APNS server. The tutorial provided a php code for this:
// Open the connection
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-dev.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);
// Send the payload
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
// Close Resources
socket_close($apns);
fclose($apns);
I want to write this in Perl. What is the best equivalent of PHP's stream_context_create(). I tried something like the below, but didnt work.
use IO::Socket::SSL;
my $client = IO::Socket::SSL->new(
# where to connect
PeerHost => "gateway.sandbox.push.apple.com",
PeerPort => "2195",
SSL_cert_file =>'localcert.pem',
) or die "failed connect or ssl handshake: $!,$SSL_ERROR";
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 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