donglong9745 2014-05-14 12:31
浏览 82
已采纳

Apple推送服务器无法正常工作,由单个令牌引起

I created a push notification server for my apps. This server works fine on test and production. I created an API which can recieve a serialized array of device tokens. This API is created in PHP, and the call to the API is PHP as well. This is the array:

  'devices' => serialize(array(
        //'aaaaaa',
        'bbbbb',
        'ccccc'
   )),

The real tokens are replaced by placeholders for security reasons, ofcourse. I got one token that screws up the push notifications for the other tokens. When I disable this token in the array (aaaaa in this case), the other 2 devices receive the token. When I enable the aaaa token, no push notification is delivered at all.

The API side to send the actual push:

 foreach($devices as $device) {
      $msg = chr(0) . pack('n', 32) . pack('H*', $device) . pack('n', strlen($payload)) . $payload;
      $result = fwrite($fp, $msg, strlen($msg));
 }

Ofcourse there is some variable explaination missing in the code above, but this works fine in the case without token aaa, so that shouldnt be the problem.

Anyone knows why one faulty token can screw up pushes for valid tokens?


EDIT: I now use the enhanced method for APNS, using this code:

$error = false;
foreach($devices as $deviceToken) {
    $msg = pack("C", 1) . pack("N", $deviceToken) . pack("N",  time() + 86400) . pack("n", 32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n", strlen($payload)) . $payload;
    fwrite($fp, $msg);
    $error = $this->checkAppleErrorResponse($fp);

    debug($error);
}

And the checkAppleErrorResponse function:

function checkAppleErrorResponse($fp) {

    $apple_error_response = fread($fp, 6);

    if ($apple_error_response) {

        $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 '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;
}

Sending only the valid token, $numchanged is 0. Sending the invalid token and then the valid token, $numchanged is 1 for both cases.

  • 写回答

2条回答 默认 最新

  • douyan6871 2014-05-14 14:33
    关注

    You are using the simple binary format for sending push notifications to Apple (starts with a 0 byte). With this format, Apple never return any responses, but when the APNS server encounters a bad notification (often caused by invalid device token, but there are other error types, such as payload too long), it closes the connection. Any messages that were sent after the faulty one won't be processed by Apple. In that case you have to open a new connection and resend the other messages.

    If you switch to the more advanced formats (that start with a 1 byte or a 2 byte), Apple will send you an error response before closing the connection, and if you manage to read that response, you'll know the type of the error (for example 8 means invalid token) and the identifier of the faulty message. This lets you know which message was faulty, and therefore tells you which messages need to be resent (all the ones following the faulty message).

    Read more about it here and here.

    When you use the enhanced format, make sure to give a unique message ID to each notification you send. That's the ID you'll get back from Apple in an error response, so it must be unique for you to be able to identify the invalid notification.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测