opening stream_socket_client for APNS push notifications

Hi,

I am trying to build a elgg plugin to push notifications to mobile devices. I have this already configured for GCM push notifications, which works as expected. However, now I am trying to configure it for APNS and it is really difficult to get it working. After a lot of trial and error, I now know for sure that my php functionality is correct and that my certificates work. In order to validate this I tried my implementation of the push notifications in a seperate php script. When I use the exact same code and certificate in the elgg plugin, the script refuses to open the stream_socket_client I use to send the notifications to the APNS server. This is the code I use:

 

function sendAPNSmessage($devicetokens, $type, $body) {

     $deviceToken = 'XXXXXXXXXXX';
     $passphrase = 'xxxx';
     $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);

     xdebug_break();
     // 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);
}

When I debug the plugin locally, the $fp stream remains null while the $err is 0 and the $errstr also remains null. Does anybody know why this is the behaviour I see. As this is a copy paste of the functionality that worked outside of the plugin, I think it has something to do with rights/permission/configuration?

Thanks in advance!

Consec

  • are you running the same script on the same server to test?  There's no reason it should function any differently inside a plugin, if you're not testing on the same server I would suggest doing so to rule out server config issues.

  • After a lot of trial and error I finally figured out what was wrong. In a normal php webservice you can just give the filename of the .pem certificate and it will look at the place where the script is. For an Elgg plugin this was not the case, so when you use the code like I did, he just won't find the certificate. 

    In order to fix this I had to give an absolute path like this:

    "certificate" => dirname(__FILE__).'/ck.pem',

    This solved my issue. Thanks for the help.

  • That makes sense, thanks for posting your solution!

  • Nice plugin concept...I had searched the community site and have been surprised not to find any that supports GCM and/or APNS!

Beginning Developers

Beginning Developers

This space is for newcomers, who wish to build a new plugin or to customize an existing one to their liking