Техника PHP для запроса сервера обратной связи APNs

Может ли кто-нибудь прояснить, чего хочет APN (Apple Push Notification) в том, как вы его запрашиваете?

В документах говорится, что он начинает отправку, как только установлено соединение. Означает ли это, что я не делаю fread() на нем?

Вот мой текущий код, чтобы попробовать его прочитать. Я НЕ помещал fread() в цикл, так как я не знаю, какой ответ указывает на то, что «записей для чтения больше нет», и мне не нужен бесконечный цикл на моем сервере.

<?php
$apnsCert = 'HOHRO-prod.pem';

$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'verify_peer', false);

$apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);

echo 'error=' . $error;
echo 'errorString=' . $errorString;


$result = fread($apns, 38);
echo 'result=' . $result;


fclose($apns);
?>

Пока все, что я получаю, - это нулевой ответ. Ошибок нет, значит подключается.

Я не знаю, означает ли нулевой ответ отсутствие данных или мой fread() неправильный способ сделать это.

Спасибо


person Community    schedule 14.08.2009    source источник
comment
Даже у меня есть похожий код, и я тоже получаю null от fread. Не уверен, действительно ли мой код работает, и APNS отправляет ответ NULL или что-то отсутствует. Я уверен, что мое подключение к APNS прошло успешно. Я установил свое приложение на несколько 5-10 устройств и отправил пару предупреждений, а затем удалил приложение с нескольких и снова начал отправлять предупреждения, чтобы сервер обратной связи APNS сообщил нам, что он не доставляется на нескольких устройствах. У меня нет ничего, кроме пустого в fread () :-( Если вы сделали что-то другое и все заработало, дайте мне знать.   -  person Anish    schedule 17.08.2009
comment
Вы использовали pushutil? Как только вы это выясните, это более быстрый способ проверить сервер обратной связи. Это утилита для Mac OS X, которую вы компилируете, а затем запускаете из командной строки Unix. Google Erica Sadun - это на ее сайте в разделе Push.   -  person    schedule 17.08.2009
comment
По-прежнему не получаю ответа от сервера обратной связи, даже когда я отправил 76 push-уведомлений - некоторые из них должны были быть неудачными. То же самое происходит, когда я использую утилиту командной строки pushutil Эрики Садун - push проходит нормально, затем я удаляю приложение и снова нажимаю, и ВСЕ ЕЩЕ ничего не появляется на сервере обратной связи. И это с приложением Эрики, поэтому я знаю, что оно должно работать. Думаю, проблема в сертификате. Я использую тот же сертификат push-production, что и для push. Нет отдельного сертификата обратной связи?   -  person    schedule 08.09.2009
comment
Сегодня я обнаружил, что fread () не будет работать, потому что обратная связь APN отправляет мусорные данные до фактической обратной связи. Это приводит к сбою fread, потому что он читает нулевые / пустые данные. Как упоминается ниже в gw1921, вы должны выполнять цикл от feof () до strlen (fread ($ apns, 38)). С этого момента у вас будет действительная обратная связь. Затем распакуйте данные, как предложил Ник Б. (Еще одна неприятная проблема: удаленное приложение не будет генерировать обратную связь, если у вас нет другого приложения на устройстве с той же aps-средой. Поэтому вам нужно 2 приложения-песочницы с поддержкой push на вашем устройстве, чтобы удаленное приложение отправило отзыв.)   -  person brack    schedule 18.05.2010


Ответы (5)


Вот большая проблема, которая смутила меня, когда я впервые попытался подключиться: серверы обратной связи APNS возвращают только токены устройств, срок действия которых истек с момента вашего последнего запроса обратной связи. Это означает, что в большинстве случаев вы получите ответ NULL, если вы уже не имеете дело с большим количеством пользователей вашего приложения.

Поэтому убедитесь, что вы сохранили токены с истекшим сроком действия на диск или в базу данных, потому что после вашего запроса обратной связи они исчезли навсегда. Это делает тестирование, мягко говоря, болью!

Вот полная функция для получения токенов устройств с серверов обратной связи APNS (большое спасибо приведенным выше ответам за то, что помогли мне собрать все вместе):

function send_feedback_request() {
    //connect to the APNS feedback servers
    //make sure you're using the right dev/production server & cert combo!
    $stream_context = stream_context_create();
    stream_context_set_option($stream_context, 'ssl', 'local_cert', '/path/to/my/cert.pem');
    $apns = stream_socket_client('ssl://feedback.push.apple.com:2196', $errcode, $errstr, 60, STREAM_CLIENT_CONNECT, $stream_context);
    if(!$apns) {
        echo "ERROR $errcode: $errstr\n";
        return;
    }


    $feedback_tokens = array();
    //and read the data on the connection:
    while(!feof($apns)) {
        $data = fread($apns, 38);
        if(strlen($data)) {
            $feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data);
        }
    }
    fclose($apns);
    return $feedback_tokens;
}

Если все в порядке, возвращаемые значения из этой функции будут выглядеть примерно так (через print_r ()):

Array
(
    Array
    (
        [timestamp] => 1266604759
        [length] => 32
        [devtoken] => abc1234..............etcetc
    ),
    Array
    (
        [timestamp] => 1266604922
        [length] => 32
        [devtoken] => def56789..............etcetc
    ),
)
person Nick Baicoianu    schedule 19.02.2010
comment
Спасибо за это элегантное решение. Теперь мне просто нужно знать, как сравнить метку времени, возвращаемую приведенным выше кодом обратной связи, с меткой времени, которую я сохранил в своей базе данных, которая, конечно же, представляет собой последнее время, когда устройство отправило мне токен. Я просто выполняю прямое целочисленное сравнение? Или мне нужно преобразовать метки времени для правильного порядка байтов или что-то в этом роде? - person ; 20.02.2010
comment
Этот ответ должен быть принятым решением, ИМО. В основном это то, что я делаю, и это отлично работает. Если вы по-прежнему не видите данные обратной связи с помощью этого метода, убедитесь, что у вас есть другое приложение на устройстве с включенной функцией push, которое отправляет отчеты в ту же среду APS, что и удаленное приложение. Джонни: что касается метки времени, после того, как вы распаковываете ее, как в сообщении Ника, вы можете провести целочисленное сравнение. - person brack; 18.05.2010
comment
В каком случае я не получу ответ от сервера обратной связи? Мои уведомления проходят нормально (как я могу судить по журналам), но по какой-то причине я никогда не получаю никаких уведомлений на устройстве! - person lostInTransit; 19.05.2011
comment
серверы обратной связи APNS возвращают только токены устройств, срок действия которых истек с момента вашего последнего запроса обратной связи. ой, я действительно должен прочитать документацию, я думаю; ( - person Daniel Magnusson; 11.04.2012
comment
Я пробовал использовать эту функцию. Я действительно уверен, что использую правильную комбинацию сертификатов / серверов. Я всегда использую .sandbox. Я отправляю два push-уведомления на устройства разработки, одно устройство получает сообщение, а массив обратной связи пуст. - person Julian F. Weinert; 30.10.2012
comment
Вместо того, чтобы проверять метку времени, я могу просто проверить все возвращенные токены и удалить их из своей базы данных? - person Andy Ibanez; 16.11.2013
comment
Абсолютно. Это то, что мы делаем в нашей реализации - данные временных меток не представляют для нас ценности, поэтому мы их игнорируем. - person Nick Baicoianu; 17.11.2013
comment
@NickBaicoianu - это код, который вы разместили здесь, и который вы в настоящее время используете для обнаружения недействительных токенов устройства? Я потратил неделю, наконец, на то, чтобы мои push-уведомления работали ИДЕАЛЬНО, за исключением того факта, что при отправке соединение с apns разрывается, как только будет обнаружен / предпринят старый / недопустимый токен устройства. Я попытался использовать здесь ваш код, подставив свой сертификат и массив токенов, но ничего не получил. - person tamak; 11.03.2015
comment
Да, мы все еще используем этот код в наших производственных приложениях. Он выполняется как ежечасное задание cron, отдельно от нашего основного APNS-соединения. - person Nick Baicoianu; 14.08.2015
comment
теперь код возвращает все токены устройств, а отметки времени нет. - person Vaibhav Saran; 22.05.2019

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

 while (!feof($apns)) {
        $devcon = fread($apns, 38);
 }

Однако моя проблема - это фактическая распаковка данных. Кто-нибудь знает, как распаковать двоичные данные, которые вы только что прочитали, чтобы получить фактический идентификатор устройства (в виде строки) вместе с меткой времени и т. Д.?

person strange    schedule 14.10.2009
comment
Думаю, это правильная идея - $ array = unpack (NnH32, $ result); $ feedbackTime = $ row [0]; $ feedbackLen = $ row [1]; $ feedbackUDID = $ row [2]; Это распаковывает 38 байтов, отправленных сервером обратной связи. Однако 32-битное значение даты находится в сетевом порядке или с прямым порядком байтов. Если кто-то может предоставить функцию PHP, которая переведет эти 4 байта в порядок Intel (с прямым порядком байтов), я думаю, у нас есть решение. ПРИМЕЧАНИЕ: фактический UDID представляет собой символьную строку, и ее НЕ нужно менять местами. - person ; 15.10.2009
comment
Это хорошо? --------- / * Преобразование числа с плавающей запятой из HostOrder в сетевой заказ / function FToN ($ val) {$ a = unpack (I, pack (f, $ val)); вернуть пакет (N, $ a [1]); } / Преобразование числа с плавающей запятой из сетевого порядка в HostOrder * / function NToF ($ val) {$ a = unpack (N, $ val); $ b = распаковать (f, pack (I, $ a [1])); вернуть $ b [1]; } - person strange; 15.10.2009

Я получил решение от яблочного форума, и оно предназначено для разработки. Попробуйте это также для производства.

"Ну, как бы глупо это ни звучало, я нашел решение:

Создайте фиктивный идентификатор приложения на программном портале, включите для него push-уведомления разработки. Создайте и загрузите связанный профиль обеспечения. Создайте новый проект xcode и вызовите метод registerForRemoteNotificationTypes при запуске. Установите фиктивное приложение на свое устройство. На этом этапе на вашем устройстве должны быть запущены два приложения РАЗРАБОТКА: исходное приложение и фиктивное приложение. Оба должны быть зарегистрированы для получения push-уведомлений. Удалите исходное приложение и попробуйте отправить ему push-уведомление. Вызовите службу обратной связи, и вы получите данные обратно ».

person Community    schedule 05.10.2009

Это наконец сработало для меня.

$arr = unpack("H*", $devconts); 
$rawhex = trim(implode("", $arr));

$feedbackTime = hexdec(substr($rawhex, 0, 8)); 
$feedbackDate = date('Y-m-d H:i', $feedbackTime); 
$feedbackLen = hexdec(substr($rawhex, 8, 4)); 
$feedbackDeviceToken = substr($rawhex, 12, 64);

А затем вы просто проверяете токен устройства по отметке времени!

person strange    schedule 15.10.2009
comment
Это отлично работает, gw1921. Сейчас я храню $ feedbackDate в столбце SQL. Какого типа данные должны быть в столбце? Я установил для него значение Integer, и это дает мне 2009 год. Остальные 2 столбца, длина и токен, работают ОТЛИЧНО !! Спасибо - person ; 31.10.2009

Только начал использовать эту библиотеку - у меня отлично работает!

https://github.com/mac-cain13/notificato

person Steven M    schedule 19.02.2016