Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP technique to query the APNs Feedback Server

Here's a big gotcha which confused me when I first tried connecting: the APNS feedback servers only return the device tokens that have "expired" since your last feedback request. Which means most of the time you'll get a NULL response unless you're already dealing with a high volume of users of your app.

So make sure you store the expired device tokens to disk or db, because after your feedback query they're gone for good. This makes testing a pain to say the least!

Here's a complete function to fetch the device tokens from the APNS feedback servers (many thanks to the answers above for helping me put it all together):

function send_feedback_request() {
    //connect to the APNS feedback servers
    //make sure you're using the right dev/production server & cert combo!
    $stream_context = stream_context_create();
    stream_context_set_option($stream_context, 'ssl', 'local_cert', '/path/to/my/cert.pem');
    $apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $stream_context);
    if(!$apns) {
        echo "ERROR $errcode: $errstr\n";
        return;
    }


    $feedback_tokens = array();
    //and read the data on the connection:
    while(!feof($apns)) {
        $data = fread($apns, 38);
        if(strlen($data)) {
            $feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data);
        }
    }
    fclose($apns);
    return $feedback_tokens;
}

If all is well, the return values from this function will look something like this (via print_r()):

Array
(
    Array
    (
        [timestamp] => 1266604759
        [length] => 32
        [devtoken] => abc1234..............etcetc
    ),
    Array
    (
        [timestamp] => 1266604922
        [length] => 32
        [devtoken] => def56789..............etcetc
    ),
)

That code looks right however you need to loop and check for end of stream in order to read all the device codes.

 while (!feof($apns)) {
        $devcon = fread($apns, 38);
 }

However my problem is the actual unpacking of the data. Does anyone know how to unpack the binary data which you've just read to get the actual device ID (as string) along with the timestamp etc?


I got the solution from apple forum and it is for development. Try this for production also.

"Well, as dumb as it sounds, I found a solution:

Create a dummy app id in the program portal, enable development push notifications on it Create and download the associated provisioning profile Create a new xcode project, and invoke the registerForRemoteNotificationTypes method on start. Install the dummy app on your device. At this point, you should have two DEVELOPMENT apps running on your device: the original app and the dummy app. Both should be registered to receive push notifications. Uninstall the original app, and try to send a push notification to that app. Invoke the feedback service, and you should receive data back."