PHP增强苹果推送通知读取错误响应 [英] PHP Apple Enhanced Push Notification read error response

查看:211
本文介绍了PHP增强苹果推送通知读取错误响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在PHP,你怎么用FREAD(),以检查是否有当发送增强的推送通知的错误响应?

In PHP, how do you use fread() to check if there is an error response when sending enhanced push notifications?

我已经在这里所以读苹果文档,一对夫妇的模糊帖子直通谷歌,和一对夫妇的问题/答案,但这里还是很混乱。

I have read the Apple docs, a couple vague posts thru Google, and a couple questions/answers here on SO but this was still very confusing.

下面是我看了看:
<一href=\"http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html\">http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html
http://stackoverflow.com/questions/6665921/reading-error-from-apple-enhanced-push-notification-with-php
<一href=\"http://stackoverflow.com/questions/4034926/iphone-push-notification-error-response-problem\">iPhone推送通知 - 错误响应的问题

我要回答以下我自己的问题,基于这样一个事实:(1)我发现这是一个非常令人困惑的话题,(2)我不得不用大量的试验和错误得到它拼凑的信息工作,和(3)本博客文章,指出它鼓励:<一href=\"http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/\">http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/

I am going to answer my own question below, based on the fact that: (1) I found this a very confusing topic, and (2) I had to piece the information together with lots of trial and error to get it to work, and (3) this blog post that says it is encouraged: http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/

推荐答案

当您发送推送通知,有几个问题:

When you send a push notification, there are several problems:


  • 如果有问题,苹果将断开你,但你不知道它。当您使用基本的通知也没有办法知道,如果他们全部送到与否。的解决方法:的这是一个使用增强的通知,然后检查是否有错误响应的整点。请注意,我们会在数据库查询中使用ORDER BY ID,然后使用id作为我们在发送通知的标识符。这样一来,如果有问题,我们知道哪些行的分贝引起问题(因此我们知道当苹果断开我们并停止发送通知)。然后,我们可以继续发送推送通知导致问题的行之后的所有行,而不必重新发送到我们​​已经送到的。

  • If there is a problem, Apple will disconnect you but you don't know about it. When you use basic notifications there is no way to know if they were all sent or not. SOLUTION: This is the whole point of using an enhanced notification and then checking for an error response. Note that we will use "ORDER BY id" in database query and then use the id as the identifier that we send in notification. This way, if there is a problem, we know exactly which row in the db caused the problem (and therefore we know when Apple disconnected us and stopped sending the notifications). We can then continue sending Push notifications to all the rows after the row that caused the problem, without having to resend to the ones we already sent to.

苹果不发送任何响应回来,如果一切正常,那么这可能会导致你的脚本暂停,永远等待FREAD()在等待一个不来的数据。的解决方法:的需要设置stream_set_blocking为0,这样的fread总是返回的时候了。请注意,这导致另一个小问题,它收到一个错误响应之前的fread可以退货,但看到在code中的解决方法,这仅仅是暂停1/2第二毕竟你的发送完成,然后检查FREAD一个更多的时间。

Apple does NOT send any response back if everything is ok, so this can cause your script to pause and wait forever while fread() is waiting for data that is not coming. SOLUTION: Need to set stream_set_blocking to 0 so that fread always returns right away. Note that this causes another minor issue that fread can return before it receives an error response, but see the workaround in the code, which is just to pause for 1/2 a second AFTER all your sending is done and then check fread one more time.

您可以发送多个推送通知的速度远远超过它需要一个错误响应要回你。的解决方案:的再次,这是上面提到的相同的解决方法......暂停1/2秒后,所有的发送完成,然后检查FREAD一次

You can send multiple push notifications much faster than it takes an error response to get back to you. SOLUTION: Again this is the same workaround mentioned above... pause for 1/2 a second AFTER all your sending is done and then check fread one more time.

下面是我的解决方案使用PHP,这解决了我所有的问题,我遇到过。它的pretty基本的,但能够完成任务。我曾与在同一时间发送一些通知,以及在同一时间发送12万进行了测试。

Here is my solution using PHP, which addresses all my problems that I encountered. Its pretty basic but gets the job done. I have tested it with sending a few notifications at a time as well as sending out 120,000 at one time.

<?php
/*
 * Read Error Response when sending Apple Enhanced Push Notification
 *
 * This assumes your iOS devices have the proper code to add their device tokens
 * to the db and also the proper code to receive push notifications when sent.
 *
 */

//database
$host = "localhost";
$user = "my_db_username";
$pass = "my_db_password";
$dbname = "my_db_name";
$con = mysql_connect($host, $user, $pass);
if (!$con) {
    die('Could not connect to database: ' . mysql_error());
} else {
    mysql_select_db($dbname, $con);
}

// IMPORTANT: make sure you ORDER BY id column
$result = mysql_query("SELECT id,token FROM `device_tokens` ORDER BY id");

//Setup notification message
$body = array();
$body['aps'] = array('alert' => 'My push notification message!');
$body['aps']['notifurl'] = 'http://www.myexampledomain.com';
$body['aps']['badge'] = 1;

//Setup stream (connect to Apple Push Server)
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'passphrase', 'password_for_apns.pem_file');
stream_context_set_option($ctx, 'ssl', 'local_cert', 'apns.pem');
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
stream_set_blocking ($fp, 0); //This allows fread() to return right away when there are no errors. But it can also miss errors during last seconds of sending, as there is a delay before error is returned. Workaround is to pause briefly AFTER sending last notification, and then do one more fread() to see if anything else is there.

if (!$fp) {
    //ERROR
    echo "Failed to connect (stream_socket_client): $err $errstrn";
} else {
    $apple_expiry = time() + (90 * 24 * 60 * 60); //Keep push alive (waiting for delivery) for 90 days

    //Loop thru tokens from database
    while($row = mysql_fetch_array($result)) {
        $apple_identifier = $row["id"];
        $deviceToken = $row["token"];
        $payload = json_encode($body);
        //Enhanced Notification
        $msg = pack("C", 1) . pack("N", $apple_identifier) . pack("N", $apple_expiry) . pack("n", 32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n", strlen($payload)) . $payload;
        //SEND PUSH
        fwrite($fp, $msg); 
        //We can check if an error has been returned while we are sending, but we also need to check once more after we are done sending in case there was a delay with error response.
        checkAppleErrorResponse($fp);
    }

    //Workaround to check if there were any errors during the last seconds of sending.
    usleep(500000); //Pause for half a second. Note I tested this with up to a 5 minute pause, and the error message was still available to be retrieved

    checkAppleErrorResponse($fp);

    echo 'DONE!';

    mysql_close($con);
    fclose($fp);
}

//FUNCTION to check if there is an error response from Apple
//         Returns TRUE if there was and FALSE if there was not
function checkAppleErrorResponse($fp) {

   //byte1=always 8, byte2=StatusCode, bytes3,4,5,6=identifier(rowID). Should return nothing if OK.
   $apple_error_response = fread($fp, 6);
   //NOTE: Make sure you set stream_set_blocking($fp, 0) or else fread will pause your script and wait forever when there is no response to be sent.

   if ($apple_error_response) {
        //unpack the error response (first byte 'command" should always be 8)
        $error_response = unpack('Ccommand/Cstatus_code/Nidentifier', $apple_error_response);

        if ($error_response['status_code'] == '0') {
            $error_response['status_code'] = '0-No errors encountered';
        } else if ($error_response['status_code'] == '1') {
            $error_response['status_code'] = '1-Processing error';
        } else if ($error_response['status_code'] == '2') {
            $error_response['status_code'] = '2-Missing device token';
        } else if ($error_response['status_code'] == '3') {
            $error_response['status_code'] = '3-Missing topic';
        } else if ($error_response['status_code'] == '4') {
            $error_response['status_code'] = '4-Missing payload';
        } else if ($error_response['status_code'] == '5') {
            $error_response['status_code'] = '5-Invalid token size';
        } else if ($error_response['status_code'] == '6') {
            $error_response['status_code'] = '6-Invalid topic size';
        } else if ($error_response['status_code'] == '7') {
            $error_response['status_code'] = '7-Invalid payload size';
        } else if ($error_response['status_code'] == '8') {
            $error_response['status_code'] = '8-Invalid token';
        } else if ($error_response['status_code'] == '255') {
            $error_response['status_code'] = '255-None (unknown)';
        } else {
            $error_response['status_code'] = $error_response['status_code'] . '-Not listed';
        }

        echo '<br><b>+ + + + + + ERROR</b> Response Command:<b>' . $error_response['command'] . '</b>&nbsp;&nbsp;&nbsp;Identifier:<b>' . $error_response['identifier'] . '</b>&nbsp;&nbsp;&nbsp;Status:<b>' . $error_response['status_code'] . '</b><br>';
        echo 'Identifier is the rowID (index) in the database that caused the problem, and Apple will disconnect you from server. To continue sending Push Notifications, just start at the next rowID after this Identifier.<br>';

        return true;
   }
   return false;
}
?>

这篇关于PHP增强苹果推送通知读取错误响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆