PHP增强苹果推送通知读取错误响应PHP增强苹果推送通知读取错误响应(PHP Apple Enhan

2019-05-13 10:55发布

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

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

以下是我看着: http://developer.apple.com/library/mac/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html 从PHP增强苹果推送通知读取错误 iPhone推送通知-错误响应问题

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

Answer 1:

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

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

  • 苹果不发送任何响应回来,如果一切正常,那么这可能会导致你的脚本暂停,并永远等待FREAD()正在等待未来的数据。 解决方案:需要设置stream_set_blocking为0,这样的fread总是立即返回。 请注意,这导致另一个小问题,它收到一个错误响应之前的fread可以退货,但看到代码的解决方法,这仅仅是暂停了1/2秒后,所有的发送完成,然后检查FREAD一次。

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

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

<?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;
}
?>


Answer 2:

我不知道你们中的内容,但你应该尝试ApnsPHP这是很好的测试运行完美,它能够处理所有可能的异常和错误你。

其他替代品

https://github.com/sebastianborggrewe/PHP-Apple-Push-Notification-Server https://github.com/bortuzar/PHP-Mysql---Apple-Push-Notification-Server

已经测试了2出的3个我的例子,并没有实施和错误管理的问题。

谢谢

:)



文章来源: PHP Apple Enhanced Push Notification read error response