I am trying to use push notification using Api and I am not getting any error message neither I am getting any response.
I have checked Apple Push Notification Service with PHP Script
and applied changes in my code accordingly but still not working.
I am not able to get how to get serverId that I have to use in
$device = 'fbb5a9c71066794d57fee33b4005a89f1bb8941a68660fd6e91f466be1299ab6'; // My iphone deviceToken
$payload['aps'] = array(
'alert' => 'This is the alert text',
'badge' => 1,
'sound' => 'default'
);
$payload['server'] = array(
'serverId' => 1,
'name' => 'keyss.in'
);
$payload = json_encode($payload);
$apnsCert = 'apple_push_notification_production.pem';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
//socket_close($apns); seems to be wrong here ...
fclose($apns);
Getting the errors:
Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out)
Warning: fwrite() expects parameter 1 to be resource, boolean given
Warning: fclose() expects parameter 1 to be resource, boolean given
You are not getting any response because you are using the old binary notification format :
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $device)) . chr(0) . chr(strlen($payload)) . $payload;
In order to get responses (responses are returned only in case of an error), use the enhanced format :
$apnsMessage = pack("C", 1) . pack("N", $apple_identifier) . pack("N", $apple_expiry) . pack("n", 32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n", strlen($payload)) . $payload;
You can see sample code here.
Related
I am trying to send a push notification to IOS using php and Yii framework. I created a function as follows to get data and send notification. $data is an array which contains a message and an array inside to keep registration IDs (device tokens). I ran it on my localhost but notification is not sent to my device. By the way, the output of my function is an integer value and I cannot recognize if the message has been sent or what!?
Is there anything wrong in my code?
private function _pushIOS($data)
{
// Create a connection
$apnsHost = $this->_notificationUrl;
$apnsPort = 2195;
$apnsCert = Yii::app()->controller->createUrl('/').'/my_certificate_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);
if (!$apns)
exit("Failed to connect: $error $errorString" . PHP_EOL);
foreach($data['registration_ids'] as $deviceToken) {
$body = array();
$body['aps'] = array(
'alert' => $data['data']['message'],
'badge' => 1,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($apns, $apnsMessage, strlen($apnsMessage));
}
// Close the socket and connection to the server
#socket_close($apns);
fclose($apns);
return json_decode($result);
}
Finally, I got the answer. The problem was with the pem file path. Absolute path must be passed to the function to work. The following line should be replaced:
$apnsCert = Yii::app()->controller->createUrl('/').'/my_certificate_dev.pem';
Correct path:
$apnsCert = dirname(Yii::app()->request->scriptFile).'/my_certificate_dev.pem';
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 am using Push Notification in my app and a PHP server that manages database with tokens and sending payload to Apple servers. Sending messages to a small number of devices (I have tried with 2) works well but when I want to send a message to entire database ( over 20.000 devices ) it doesn't work. Connection with Apple server is made ( i get no errors of connection ) but the two devices I have ( that are also in database ) do not received the message.
The PHP code is:
$apnsHost = 'gateway.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'path/to/my/certificate.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);
while($row = mysql_fetch_array($result))
{
$deviceToken=$row['token'];
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
if ($error==0)
{
echo "Notification was sent successfully to ".$row['token']."<br/>";
}
else
{
echo "Notification failure to ".$row['token']."<br/>";
}
}
socket_close($apns);
fclose($apns);
As a result I am getting "Notification was sent successfully" for all the records in database but it seems like it doesn't send the message because I don't see it on my devices. When I am using the same code to send message to 2 tokens it works well. What could be the problem? Is there an upper limit for number of devices I can send to with one connection?
Not sure if there is a limit, but I'm sure it won't be low as I have successfully sent notifications to thousands of devices at a time in the past (although currently I'm shooting them about 250-500 at a time).
Try replacing this:
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
With this:
$apnsMessage = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n", strlen($payload)) . $payload;
Also, you might be interested in trying this out: http://code.google.com/p/apns-php/
i am working on a project in PHP which requires me to push an alert notification on APNS server. I have used enhanced push notification format. but I am not receiving response as specified by the APNS docs. I am getting response in three digits usually 133, 132, 154, 138, etc. Which I concluded to be Status signs, eg. 133 is 1, 3, 3. but now I have also received 139. so I doubt that my interpretation of response is wrong. But I am not getting where it is wrong. And important thing is though I am receiving these responses Alert is getting pushed and I am receiving notification on my iPhone as well as on iPad.
My code is as follows:
$payload['aps'] = array('alert' => $message, 'badge' => 1, 'sound' => 'default');
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195; // default port
$apnsCert = 'apns-dev.pem'; // APNS crtificate.
$passPhrase = '';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', $passPhrase);
try{
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns) {
print "Failed to connect {$error} {$errorString}\n";
}
else {
// Sending the payload
$apnsMessage = chr(0) . pack('n', 1) . pack('n', $nid) . pack('n', time() + 604800) . pack('n', 32) . pack('H*', str_replace(' ', '', $alert_device_token)) . pack('n', strlen($payload)) . $payload;
echo 'APNS Message: ' . $apnsMessage;
$fwrite = fwrite($apns, $apnsMessage);
echo 'APNS response: ' . $fwrite;
And when this get executed i got the following response printed on the browser:
APNS Message: ��=ŸÂ� òc6–U:õŸŠ ¸Þ ÷ćÚ0ßqšÊzÂífÕnZ�`{"aps":{"alert":"Your EUR\/USD SELL alert price has been reached!","badge":1,"sound":"default"}}APNS response: 139
Can anyone please tell me what does this 139 means here. am doing anything wrong here.
The echoed "139" is the return value of fwrite(). It's the number of bytes written by fwrite()
See: PHP: fwrite
When I try to send Push Notifications I get this error: "Connection refused", but I don't know why... I've uploaded my apns-dev.pem in the same directory as well in the root-directory but that won't work either.
<?php
$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-dev.pem';
$apnsPass = 'secret';
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', $apnsPass);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
if (!$apns) {
echo "Error: $errorString ($error)";
}
// Do this for each
$deviceToken = '00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000';
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);
// End do
socket_close($apns);
fclose($apns);
?>
Does anyone know what I'm doing wrong? When I remove the passphrase and don't send it it doesn't work either...
Make sure the outgoing port 2195 is open.This would be in your firewall config.
You don't want a passphrase unless your .pem file requires one. The connection requires peer verification (option verify_peer) turned on. Also, make sure $apnsCert is the valid path to the certificate, you can use an absolute path as a sanity check.
Lastly, this shouldn't effect your ability to connect, but your device token needs to be valid.
I've know fixed that error by adding this: STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT
Know I'm not getting any errors, but I don't receive any notification. I think the Dev-token is not valid know, so, this is how it look like
numbers numbers numbers numbers numbers numbers numbers numbers.
The spaces are removed in this line:
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
Edit: I founded the problem:
My server is refusing the outgoing port, just sent a mail, hoping they can activate it...