Push-уведомление (iOS) не получено/отправлено с кодом PHP

Я пытаюсь реализовать APNS (Push-уведомление). Я создал сертификаты и т. д., все было создано так, как я делал это много раз. но я не могу получить сообщение об ошибке от сервера Apple APNS, и кажется, что все в порядке, но я все еще не получаю никаких толчков в устройствах. это код PHP, который я использую, чтобы творить чудеса :) Я гарантирую, что ПОРТЫ открыты на хостинге.

в основном я получаю токен пользователя из БД и отправляю push-текст со звуком по умолчанию.

может кто-нибудь посмотреть и сказать мне, видите ли вы какую-либо проблему в этом коде, или дайте мне знать, как я могу получить реальный результат процесса/ответа от сервера APNS?

<?php
    error_reporting(0);
    header("Content-type: application/json; charset=utf-8");
    include "dbconn.php";
    $data = array();
    $json= array();
    $users = array();

    $opponent_id = $_REQUEST['opponent_id'];
    $sender_id = $_REQUEST['sender_id'];
    $message = $_REQUEST['message'];

    $sql = "SELECT * FROM `registration` WHERE `chat_id` ='$opponent_id'";

    $result = mysql_query($sql);

    if (!$result) {
        echo "Could not successfully run query ($sql) from DB: " . mysql_error();
        exit;
    }

    if (mysql_num_rows($result) == 0) {
        echo "No rows found, nothing to print so am exiting";
        exit;
    }

    while ($row = mysql_fetch_assoc($result)) {
            $token = $row['token'];
    }

    echo "\n$token";

    $passphrase = 'certificate_password';

    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
    //stream_context_set_option($ctx, 'ssl', 'local_cert','push/some_prod_certificate.pem');
    stream_context_set_option($ctx, 'ssl', 'local_cert','push/some_dev_certificate.pem');
    stream_context_set_option($ctx, 'ssl', 'cafile', 'push/entrust_root_certification_authority.pem');

    # Open a connection to the APNS server
    $fp = stream_socket_client(//'ssl://gateway.push.apple.com:2195', $err,
                               'ssl://gateway.sandbox.push.apple.com:2195', $err,
                               $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);


     if (!$fp){
        echo "Error: ".$err;
        exit;
    }

    echo "\n".'Connected to APNS Push Notification' . PHP_EOL;

    $body['aps'] = array(
                         'alert' => $message,
                         'sound' => 'default'
                         );

    $payload = json_encode($body);
    echo "\n$payload";

    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;

    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));

    //set blocking
    stream_set_blocking($fp,0);

    //Check response
    checkAppleErrorResponse($fp);

    // Close the connection to the server
    fclose($fp);

    function checkAppleErrorResponse($fp) {

        $apple_error_response = fread($fp, 6); //byte1=always 8, byte2=StatusCode, bytes3,4,5,6=identifier(rowID). Should return nothing if OK.
        //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) {

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

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

        echo "\nPush respnse OK";
        return false;
    }
?>

person Amir Foghel    schedule 22.06.2014    source источник


Ответы (1)


Вы не можете получить ответы об ошибках от Apple, потому что вы используете простой двоичный формат, который не возвращает ответы об ошибках:

$msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;

Если вам нужен формат, который может возвращать ответ об ошибке, вы можете использовать один из расширенных форматов.

Например, формат, начинающийся с 1:

Сообщение будет начинаться с chr(1), за которым следуют 4 байта идентификатора сообщения, 4 байта времени истечения срока действия, а остальная часть сообщения будет такой же, как у вас сейчас pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload

Это должно выглядеть так:

$msg = chr(1) . pack("N", $msg_id) . pack("N", $expiry) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload; 
person Eran    schedule 22.06.2014
comment
Помогли мне получить ошибку и решить мою проблему. Спасибо. - person Amir Foghel; 23.06.2014
comment
Не могли бы вы немного рассказать о $msg_id? Каково его значение? Может ли это быть одно и то же число каждый раз или оно должно меняться? - person Ynhockey; 08.07.2015
comment
@Ynhockey Идея с $msg_id заключается в том, что если вы отправляете push-уведомление с $msg_id == x и это уведомление отклонено Apple (например, из-за недопустимого токена устройства), вы можете прочитать ответ об ошибке от Apple, который будет содержать этот идентификатор x, который позволит вам узнать, какое уведомление было отклонено (и вам придется повторно отправить все уведомления, которые вы отправили по тому же соединению после отклоненного сообщения, поскольку все они были проигнорированы Apple). - person Eran; 08.07.2015