2

for the past 3 days i have been trying to make things work with my php code and apns.

So far i'm able to deliver notifications (i only have one device so i don't know if this is working for multiple devices).

When i try to test sending one notification for 2 devices where the first is an device token invalid (invented by me) and the second is my device token, im unable to deliver the notification to my device... From what i read, when a notification is unreadable or erroneous, apns shuts the connection down and sends an error of 6 bytes long, where the 2nd byte (status_code) is the error type. If no error happens, im still unable to understand if apns send the status_code 0 (No errors encountered) or if it does not send anything at all.

So far i wasn't able to ever find this status_code, despite of following several codes found on internet.

CODE

$ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', '.\certif\ck.pem');
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Create the payload body
    //file_put_contents('logs/debug_not.log', 'body'. "\n", FILE_APPEND);
    $body['aps'] = array(
        'alert' => $message,
        'sound' => 'default'
    );

    // Encode the payload as JSON
    //file_put_contents('logs/debug_not.log', 'json body'. "\n", FILE_APPEND);
    $payload = json_encode($body);
    $open = true;
    foreach ($devices as $device) {
        //file_put_contents('logs/debug_not.log', 'inicio ciclo'. "\n", FILE_APPEND);
        if($open == true){
            //file_put_contents('logs/debug_not.log', 'abrir ligacao'. "\n", FILE_APPEND);
            // 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){
               //file_put_contents('logs/debug_not.log', 'erro abrir ligacao'. "\n", FILE_APPEND);
               throw new \Exception;
            }
        }
        // Build the binary notification
        //file_put_contents('logs/debug_not.log', 'criar payload'. "\n", FILE_APPEND);
        $msg = chr(0) . pack('n', 32) . pack('H*', str_replace(' ', '', $device['token'])) . pack('n', strlen($payload)) . $payload;


        // Send it to the server
        //file_put_contents('logs/debug_not.log', 'enviar payload'. "\n", FILE_APPEND);
        $result = fwrite($fp, $msg, strlen($msg));
        stream_set_blocking ($fp, 0);    

        $errorResponse = @fread($apns, 6);
        //if i var_dump($errorResponse) it gives me null/false all the time, no matter what             

        //this is my workaround for invalid device tokens-- its not working or at least is not send the valid tokens
        if(!$result || !$fp)
        {

            //file_put_contents('logs/debug_not.log', 'erro na not '. chr($data["status_code"]). "\n", FILE_APPEND);
            fclose($fp);
            $open = true;
        } else{
            //file_put_contents('logs/debug_not.log', 'suc na not'. "\n", FILE_APPEND);
            $open = false;
        }
        //file_put_contents('logs/debug_not.log', 'fim ciclo'. "\n", FILE_APPEND);
    }
    // Close the connection to the server
    if($fp){
        //file_put_contents('logs/debug_not.log', 'fechar connection'. "\n", FILE_APPEND);
        fclose($fp);
    }

fread on my connection gives null/false all the time, even when i receive my notification or i'm trying with a wrong token.

My logic for connect after error, seems to be not working.

can please someone help me??? i dont intend to use 3rd classes or code, would like to have a simple basic one working for an array of device tokens, even if there are some that apns gives error.

Thanks everyone.

zx81
  • 41,100
  • 9
  • 89
  • 105
FEST
  • 813
  • 2
  • 14
  • 37
  • 1
    Ok, so it seems that, first... im sending the simple format and that is why i get false on my socket connetion fread all the time (apns does not send error on simple format). I update my form building the message – FEST Aug 23 '13 at 11:16
  • I'm having exact the same issue. Could you please tell me, if changing format solved your problem? And if so, what do you mean by "simple format"? How the other format is named and what is the difference? Some source code would be much appreciated! – Kup Dec 05 '13 at 19:32

2 Answers2

6

You have made your connection as $fp = stream_socket_client ......

and you are trying to $errorResponse = @fread($apns, 6); which will never give you any output as $apns is not defined.

Rather you should do this :

$errorResponse = @fread($fp, 6);

and your code will work fine

bummi
  • 27,123
  • 14
  • 62
  • 101
Pratik Solanki
  • 392
  • 3
  • 9
1

If you receive an error (most likely in your case because your invented device token does not exist on Apple's servers for your app), then an error message is returned just before the connection is closed. If the message is successful, there is no response, but the connection remains open.

Here's how you could handle this:

  1. Send your message.
  2. Read the error with a timeout (or in non-blocking mode). If you get an error response, the message failed. (You'll need a new connection.)
  3. If the read times out (or returns nothing in non-blocking mode), the message may be successful. (Do nothing.)
  4. Send the next message. If the send is successful (still connected), the last message was definitely successful.

Keep track of your last successful message. You could always follow up a series of messages by sending your own device a message just to prevent any false positives.

You might want to check out the source code for EasyAPNS, which is an open source PHP implementation of this. Also, you can read the details in Apple's documentation: Provider Communication with Apple Push Notification Service

Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
  • That was the theory i followed... and i checked EasyAPNS code, they have fread(socket connection) as i do but to me, the result is always false/null. :( – FEST Aug 22 '13 at 21:58
  • @FEST did you ever get anywhere on this at all? Im dealing with the same issue and need to detect the status to see which device tokens are a problem so I can remove them from my database. – tamak Mar 11 '15 at 13:45