Apple Push notification script not working - notifications

I am using this php script but its producing output Message successfully delivered but not sending notification. i have already check device id and certificates they are perfect and working fine with another script.
<?php
// Put your device token here (without spaces):
$deviceToken = 'fbf04bf4ace2f1e823016082da3a798cf3ab666ae99a395b65e364eb4c6d6d4a';
// Put your private key's passphrase here:
$passphrase = '123';
// Put your alert message here:
$message = 'A push notification has been sent!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'key.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' . PHP_EOL;
// Create the payload body
$body['aps'] = array('alert' => array('body' => $message, 'action-loc-key' => 'Look', ), 'badge' => 2, 'sound' => 'oven.caf', );
// 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));
echo "<pre>Result : ";
print_r($result);
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
?>
Can any one help me to getting out of this.?
Thanks in advance

I encounter similar problem when i first start iOS push notifications
There Will be possibility that you are doing a development push rather than a production push
Change the server to ssl://gateway.sandbox.push.apple.com:2195 and use your development push notification key to give a try.
That solves my problem

I think you have to change port number
You code: ssl://gateway.push.apple.com:2195. 2195 use for sandbox and 2196 use for live.
Can you please change it and try.
Hope this work.

Related

PHP Sockets with SSL / TLS - no suitable shared cipher could be used

I am attempting to create a server and client using PHP Sockets with SSL / TLS. However, when sending data to the server, I receive the following error:
PHP Warning: stream_socket_accept(): SSL_R_NO_SHARED_CIPHER: no
suitable shared cipher could be used. This could be because the
server is missing an SSL certificate (local_cert context option) in
server.php on line 32
I've looked at other examples and tried various changes to no avail. Any help could be much appreciated.
client.php
<?php
$host = '192.168.10.10';
$port = 8080;
$timeout = 30;
$cert = 'assets/cert.pem';
$context = stream_context_create(
[ 'ssl'=> [ 'local_cert'=> $cert, "crypto_method" => STREAM_CRYPTO_METHOD_TLS_CLIENT ] ]
);
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);
stream_context_set_option($context, 'ssl', 'verify_peer_name', false);
if ($socket = stream_socket_client( 'tls://'.$host.':'.$port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context) ) {
$meta = stream_get_meta_data($socket);
print_r( $meta );
fwrite($socket, "Hello, World!\n");
echo stream_socket_recvfrom($socket,8192);
fclose($socket);
} else {
echo "ERROR: $errno - $errstr\n";
}
server.php
<?php
// Set the ip and port we will listen on
$address = '192.168.10.10';
$port = 8080;
$cert = 'assets/cert.pem';
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'local_cert', $cert);
stream_context_set_option($context, 'ssl', 'crypto_method', STREAM_CRYPTO_METHOD_TLS_SERVER);
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', false);
stream_context_set_option($context, 'ssl', 'verify_peer_name', false);
$server = stream_socket_server('tls://'.$address.':'.$port, $errno, $errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
// Display server start time
echo "PHP Socket Server started at " . $address . " " . $port . ", at ". date( 'Y-m-d H:i:s' ) ."\n";
// loop and listen
while (true) {
/* Accept incoming requests and handle them as child processes */
$client = stream_socket_accept($server);
$ip = stream_socket_get_name( $client, true );
echo "New connection from " . $ip;
stream_set_blocking($client, true); // block the connection until SSL is done
stream_socket_enable_crypto($client, true, STREAM_CRYPTO_METHOD_TLS_SERVER);
// Read the input from the client – 1024 bytes
$input = fread($client, 1024);
// unblock connection
stream_set_blocking($client, false);
// Strip all white spaces from input
$output = preg_replace("[ \t\n\r]", "", $input) . "\0";
$new = $input;
// Display Date, IP and Msg received
echo date( 'Y-m-d H:i:s' ) . " | " . $ip . ": \033[0;32m" . $input . "\033[0m" . PHP_EOL;
fclose($client);
}
// Close the master sockets
socket_close($sock);
It turns out that the issue was related to OpenSSL and the transport streams available. The issue was resolved by:
Updating OpenSSL to the latest version (1.0.2k, to support TLS v1.2)
Recompiling PHP to enable tlsv1.2 transport stream
Updating the code to use tlsv1.2:// as the protocol on both the server and the client, e.g.
$server = stream_socket_server('tlsv1.2://'.$address.':'.$port, $errno,
$errstr, STREAM_SERVER_BIND|STREAM_SERVER_LISTEN, $context);
and
$socket = stream_socket_client( 'tlsv1.2://'.$host.':'.$port, $errno,
$errstr, 30, STREAM_CLIENT_CONNECT, $context)
Once the transport stream was updated to TLSv1.2, there was no need for the cipher option, and the scripts successfully negotiated a TLS connection.
I experienced similar problems. However my certificate and private key were in seperate files. According to the PHP documentation you should be able to load the private key seperately:
stream_context_set_option($context, 'ssl', 'local_cert', '/etc/apache2/ssl/public_crt.cert');
stream_context_set_option($context, 'ssl', 'local_pk', '/etc/apache2/ssl/private_key.pem');
Turns out this did not work for me resulting in the same error message in the original post. Combining the certificate and key in one file did the trick:
cat public_crt.cert private_key.pem > combined_cert.pem
And setting the new combo cert in PHP, made the thing work:
stream_context_set_option($context, 'ssl', 'local_cert', '/etc/apache2/ssl/combined_cert.pem');
PHP has pathetic problems with SSL. At worse they are OS dependent, most fixes are for REHL. I am supplying you sample full code and other guides. They will possibly help you. To avoid those errors, this library is commonly used. That is not always practical.
Line 32 should be this :
stream_set_blocking($client, true); // block the connection until SSL is done
Here is stream blocking doc on PHP manual, also read this. Here is a good guide on using SSL with PHP, here is example of client-server. Cipher can be added in this fashion :
$context = stream_context_create(
[
'ssl' => [
'ciphers' => 'DHE-RSA-AES256-SHA:LONG-CIPHER',
],
]
);

QuickBlox Unauthorized using CURL PHP

Have been using a PHP script to read custom objects for weeks. Today I started to get {"errors":["Unauthorized"]} replies. I can still log-on using the web-portal and the same credentials. Android app still works well using the same QuickBlox App. Have been scratching my head.. Can someone please help?
Code:
<?php
// Application credentials - change to yours (found in QB Dashboard)
DEFINE('APPLICATION_ID', 99999);
DEFINE('AUTH_KEY', "AbCd...");
DEFINE('AUTH_SECRET', "ZxYvW...");
// User credentials
DEFINE('USER_LOGIN', "user#domain.com");
DEFINE('USER_PASSWORD', "password");
// Quickblox endpoints
DEFINE('QB_API_ENDPOINT', "https://api.quickblox.com");
DEFINE('QB_PATH_SESSION', "session.json");
// Generate signature
$nonce = rand();
$timestamp = time(); // time() method must return current timestamp in UTC but seems like hi is return timestamp in current time zone
$signature_string = "application_id=".APPLICATION_ID."&auth_key=".AUTH_KEY."&nonce=".$nonce."&timestamp=".$timestamp."&user[login]=".USER_LOGIN."&user[password]=".USER_PASSWORD;
echo "stringForSignature: " . $signature_string . "<br><br>";
$signature = hash_hmac('sha1', $signature_string , AUTH_SECRET);
// Build post body
$post_body = http_build_query(array(
'application_id' => APPLICATION_ID,
'auth_key' => AUTH_KEY,
'timestamp' => $timestamp,
'nonce' => $nonce,
'signature' => $signature,
'user[login]' => USER_LOGIN,
'user[password]' => USER_PASSWORD
));
echo "postBody: " . $post_body . "<br><br>";
// Configure cURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, QB_API_ENDPOINT . '/' . QB_PATH_SESSION); // Full path is - https://api.quickblox.com/session.json
curl_setopt($curl, CURLOPT_POST, true); // Use POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_body); // Setup post body
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Receive server response
// Execute request and read response
$response = curl_exec($curl);
// Check errors
if ($response) {
echo $response . "\n";
} else {
$error = curl_error($curl). '(' .curl_errno($curl). ')';
echo $error . "\n";
}
$jsonResponse = json_decode($response,true);
$qbToken = $jsonResponse['session']['token'];
1.First you need to check the credential for quickblox which you pass in the script like appId,authKey
2.Then need to check that user registered in the same quickblox account or not .
3.One more thing you need to know that in php the password of quick account should be more then 8 char.

didReceiveRemoteNotification not getting invoked

I am creating app in iOS/android. When a remote notification is received in the device, didReceiveRemoteNotification should get called. But it is not happening. My server side code for sending msg through APNS is as under:
$deviceToken = $obj_listener->ref_id;
// Put your private key's passphrase here:
$passphrase = 'blahblah';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', '/var/www/mobileapp/TestAppCK.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){
$this->log->debug("Failed to connect: $err $errstr" . PHP_EOL);
exit("Failed to connect: $err $errstr" . PHP_EOL);
}
$badge_count = $obj_listener->badge_count + 1;
// Create the payload body
$body['aps'] = array(
//'alert' => 'Message received',
'sound' => 'default',
'badge' => $badge_count,
'msg_id' => $this->msg_id,
//'user_key' => $obj_listener->ref_id,
'email' => $obj_listener->to_email_id
);
// 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));
// Close the connection to the server
fclose($fp);
My objective-c side code is as under:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
//UIWebView *NewWebView = NULL;
NSLog(#"didReceiveRemoteNotification function");
return;
}
I have checked for the device token in the server side code. It is correct for the device.
Why is the above function not getting called. Thanks in advance.
If you don't register for notifications at your app start, they will never be received.
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound)];
Now, about your server side, I suggest you run your code in debug mode and see if Apple's gateway is being properly reached through SSL. A simple bad cert or lack of it can take you away days of work. Personal experience.
If Application is not in background you should use following code
//-------------- check notification when app is come to foreground after apllication get terminated ----------------//
UILocalNotification *localNotif =
[launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (localNotif) {
[self handleRemotNotification:[launchOptions valueForKey:#"UIApplicationLaunchOptionsRemoteNotificationKey"]]; // private method
}

Apple Push Notification from Server

I have followed :
Apple Push Notification Services Tutorial.
And it worked for me locally.
Next, i want to send push notifications from my server?
I have uploaded simplepush.php and ck.pem to my server. When i check http://www.myserver/simplepush.php it gives me error:
*Warning: stream_socket_client() [function.stream-socket-client]: unable to connect to ssl://gateway.sandbox.push.apple.com:2195
(Connection timed out) in /home/cherry/public_html/simplepush.php on
line 21 Failed to connect: 110 Connection timed out*
Could you please help me?
PHP Code:
<?php
// Put your device token here (without spaces):
$deviceToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// Put your private key's passphrase here:
$passphrase = 'xxxxxxxxxx';
// 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'
);
// 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);
Is the PHP compiled with SSL? And is it the same version as your local version?
Or maybe the firewall of some kind blocks connection to 2195 port from your server?
Can you log in to this server (to a shell of some kind) and check if you can connect via telnet to this server and port:
$ telnet gateway.sandbox.push.apple.com 2195

Send Push Notifications to all users

So, I have an App. This app, send a Push Notification using this PHP code:
<?php
$deviceToken = '4bc9b8e71b9......235095a22d';
// Put your private key's passphrase here:
$passphrase = '12345';
// Put your alert message here:
$message = 'My Message 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.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'
);
// 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);
My question is: If I have more than one users in my app, and I run this PHP code in Terminal, the Push Notification will be send only to this Device (4bc9b8e71b9...), or it'll be send to all of my users? If this will be sent only to this Device, how can I send the Push to all my users?
PS: I followed this tutorial, and it worked as well, except because i dont know if the Push will be send to all my users.
Sorry for the bad english, and thanks a lot!!
The usual approach is to store tokens in the database and once you need to send them - just select the tokens from the DB and loop through them.
the code might look like that
$pdo = new PDO(
"mysql:host=$db_host;port=$db_port;dbname=$db_name",
$db_user,
$db_pass
);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$select_tokens_sql = 'SELECT * FROM tokens';
$select_tokens_statement = $pdo->prepare($select_tokens_sql);
// 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'
);
// Encode the payload as JSON
$payload = json_encode($body);
$select_tokens_statement->execute();
$tokens = $select_tokens_statement->fetchAll();
//loop through the tokens
foreach($tokens as $token) {
// 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));
if (!$result)
echo 'Message to the device ' . $token . ' not delivered' . PHP_EOL;
else
echo 'Message to the device ' . $token . ' successfully delivered' . PHP_EOL;
}
// Close the connection to the server
fclose($fp);
It might also be a good idea to listen to apple feedback service just after you have finished sending push notifications. It will tell you if on some devices your app is not present anymore so you can safely remove corresponding tokens from the database.
You'll have to loop over all of your device tokens and write them to the gateway with fwrite()