PHP: отправка Push-уведомлений в ios

я отправляю push-уведомления с php на ios. Он работает нормально, и вот мой код:

$passphrase = '';
$badge = 1;
$path = base_path('path/to/certificate.pem');
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $path);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client(
    'ssl://gateway.sandbox.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx
);

if (!$fp) {
    self::SavePush($device_token, $message, $device_id, $device_type, $user_id, "pending", "normal", null);
}

//echo 'Connected to APNS' . PHP_EOL;
$body['aps'] = array(
    'alert' => $message,
    'badge' => $badge,
    'sound' => 'default'
);
$payload = json_encode($body);
$msg = chr(0) . pack('n', 32) . pack('H*', $device_token) . pack('n', strlen($payload)) . $payload;
$result = fwrite($fp, $msg, strlen($msg));

//print_r($result);exit;

if (!$result) {
    self::SavePush($device_token, $message, $device_id, $device_type, $user_id, "pending", "normal", null, $result);
} else {
    self::SavePush($device_token, $message, $device_id, $device_type, $user_id, "sent", "normal", null, $result);
}

fclose($fp);

Теперь проблема, с которой я сталкиваюсь, я не могу определить, если уведомление не удается как $result содержится целое число в каждом случае, успех или неудача. Я передал случайную цифру как токен, и она возвращает целое число, такое как 115 или 65, и она меняется каждый раз. Так что !$result не будет работать. Как узнать, если уведомление не удается?

3 ответов


вызов fwrite() вернет количество успешно отправленных байтов или вернет FALSE, если произошла ошибка отправки. Ваш результат $изменяется, потому что он изменяется с размером отправляемого сообщения. Зная это, вы можете предположить, что если $result===FALSE, то произошла ошибка и уведомление не удалось. Если $ результат!= = FALSE, затем уведомление было успешно отправлено. Это только подтверждает, что сообщение было отправлено по сети. Он не проверяет, что структура сообщения или действительность токенов или что-то в этом роде.

теперь, если вы пытаетесь выяснить, действительно ли само сообщение push-уведомления и что apple приняла и обрабатывает его, то вы, вероятно, хотите свернуться и HTTP/2 для этого. Делать быстрый поиск Google, я наткнулся на этот сайт, который показывает демо, как это сделать. Я не тестировал этот сайт http://coding.tabasoft.it/ios/sending-push-notification-with-http2-and-php/ так не могу сказать вы, если демо правильно или нет. Это был просто быстрый поиск, но, возможно, вы на правильном пути.


после того, как вы отправите что-то в APNS с fwrite вам понадобится fread (или stream_get_contents ;)) ответ. Лучший способ-использовать неблокирующее соединение (stream_set_blocking($fp, 0);) и ждать ответа в простом ограниченном по времени цикле:

$read = '';
$to = time() + 2;  // max 2 seconds wait...
while (!feof($fp)) // ...or end of connection
{
    $r = stream_get_contents($fp);
    if (strlen($r) > 0)
        $read .= $r;
    if (time() >= $to)
        break;
    usleep(100000);
}

после этого, в $read у вас будет либо что-то, либо ничего. Что-то (ровно с 6 байтами) означает ошибку ($error = unpack('Ccommand/Cstatus/Nident', $read);). Ничто (или содержимое короче/длиннее 6 байт) не означает успешно отправленное сообщение.


мои два цента, чтобы прояснить важный момент: как заявляет Apple, "нет гарантии доставки", поскольку push работает таким образом.

таким образом, вы можете, конечно, проверить на сетевые ошибки, как предложили другие ребята, но у вас нет гарантии, что уведомление не было получено. Чтобы получить так, единственное (long..) способ-вызвать запрос URL в устройстве iOS, когда он получает толчок. Этот запрос URL обновит вашу БД.