Я настроил службу пересылки / отправки, которая содержит открытое соединение с APN, как указано / рекомендовано Apple, чтобы предотвратить обнаружение DoS и сертификат работает …
Я успешно подключен, и сообщения отправляются успешно, но сообщения не принимаются на устройстве iOS (iPhone) … (?!?) Количество отправленных байт равно количеству (байтов) возвратов fwrite.
Наконец, сообщения могут содержать специфичные для страны символы. Как APN обрабатывают это? и как эти символы должны быть отправлены на сервер APN?
Я пробовал как с, так и без службы пересылки, но без везения. 🙁
Все вызовы журнала удаляются в фрагментах кода, чтобы избежать путаницы. Это означает, что вложенные сообщения журнала не могут отображаться непосредственно в фрагменты кода, но должно быть возможно «угадать», откуда приходят сообщения журнала.
Пожалуйста, помогите мне в решении этих вопросов. заранее спасибо
Соединение выполняется таким образом:
$ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', $certPath); stream_context_set_option($ctx, 'ssl', 'passphrase', $passPhrase); $this->apn_link = stream_socket_client($url, $err, $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx); /* ... */
Внутри цикла, который прослушивает сокет в службе пересылки:
foreach ($changed as $changed_socket) { while(isset($changed_socket) && socket_recv($changed_socket, $buf, 1024, 0) >= 1) { $buf = trim($buf); if ($buf != '') { $this->msg2apn($buf); } } } /* ... */
Далее я отправляю сообщения таким образом:
public function msg2apn($msg) { if (isset($this->apn_link)) { while(!$result = fwrite($this->apn_link, $msg, strlen($msg))) { usleep(400000); //400 msec } if ($result) { fflush($this->apn_link); return True; } } }
Сообщения, отправленные в экспедиторскую службу:
private function send_pn_iosproxy($msg) { $address = IOS_APNPROXY_HOST; $port = IOS_APNPROXY_PORT; $fp = fsockopen($address,$port); if (!$fp) { elog("Connection to [".$address.":".$port."] could not be established"); return False; } $result = fwrite($fp, $msg, strlen($msg)); if (isset($fp)) fflush($fp); if (isset($fp)) fclose($fp); return True; }
Для каждого токена устройства сообщение генерируется следующим образом:
$payload = '{"aps":{"alert":"'.$message['message'].'","badge" : "1","sound":"default"}}'; foreach($deviceTokens as $deviceToken) { // Build the binary notification $msg = chr(0) . pack('n', 32) . base64_decode($deviceToken) . pack('n', strlen($payload)) . $payload; // see function above $result = $this->send_pn_iosproxy($msg); if ($result) { ilog("Message delivered"); dlog("DeviceToken[$deviceToken], Payload[$payload]"); } else { wlog("Message not properly delivered"); dlog("Msg[$msg]"); dlog("DeviceToken[$deviceToken], Payload[$payload]"); } }
Журнальные сообщения из logdisp находятся в службе пересылки, а сообщения журнала из журнала – с веб-сервера. Веб-сервер подключается к службе пересылки с использованием 127.0.0.1/localhost, поэтому веб-сервер и сервер пересылки размещаются на одном физическом компьютере.
[2015-08-27 11:19:03] log.DEBUG: pn::send_pn_ios() [] [] [2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy() [] [] [2015-08-27 11:19:03] log.INFO: Message delivered [] [] [2015-08-27 11:19:03] logdisp.DEBUG: Client [127.0.0.1] connected [] [] [2015-08-27 11:19:03] log.DEBUG: DeviceToken[djYBbJepT8NOPKgLd5FoGOog9jxY8LcpQhCGaXAkqy0=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}] [] [] [2015-08-27 11:19:03] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1] [] [] [2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy() [] [] [2015-08-27 11:19:03] logdisp.DEBUG: dispatcher::msg2apn() [] [] [2015-08-27 11:19:03] log.INFO: Message delivered [] [] [2015-08-27 11:19:03] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] [] [2015-08-27 11:19:03] log.DEBUG: DeviceToken[7FH3vRMfmb3qRBOaKY30GT/+82jU/6kx7RhBJq2Ihw8=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}] [] [] [2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy() [] [] [2015-08-27 11:19:03] log.INFO: Message delivered [] [] [2015-08-27 11:19:03] log.DEBUG: DeviceToken[b+20wASQBp9lD08l1+EY3CHJjcCl1UBWNmSeI1c9ouQ=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}] [] [] [2015-08-27 11:19:03] log.DEBUG: pn::send_pn_iosproxy() [] [] [2015-08-27 11:19:03] log.INFO: Message delivered [] [] [2015-08-27 11:19:03] log.DEBUG: DeviceToken[Yya0lH080lz6fL2B/1UexOenBLyAJIp3zgSGgV9F5ms=], Payload[{"aps":{"alert":"message","badge" : "1","sound":"default"}}] [] [] [2015-08-27 11:19:04] logdisp.DEBUG: Client [127.0.0.1] connected [] [] [2015-08-27 11:19:04] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1] [] [] [2015-08-27 11:19:04] logdisp.DEBUG: dispatcher::msg2apn() [] [] [2015-08-27 11:19:04] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] [] [2015-08-27 11:19:05] logdisp.DEBUG: Client [127.0.0.1] connected [] [] [2015-08-27 11:19:05] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1] [] [] [2015-08-27 11:19:05] logdisp.DEBUG: dispatcher::msg2apn() [] [] [2015-08-27 11:19:05] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] [] [2015-08-27 11:19:07] logdisp.DEBUG: Client [127.0.0.1] connected [] [] [2015-08-27 11:19:07] logdisp.DEBUG: Message buf[...{"aps":{"alert":"message","badge" : "1","sound":"default"}}] from ip[127.0.0.1] [] [] [2015-08-27 11:19:07] logdisp.DEBUG: dispatcher::msg2apn() [] [] [2015-08-27 11:19:07] logdisp.DEBUG: SUCCESS msg2apn, written[107], sent[107] [] []
Я попытался отправить два вида полезной нагрузки:
{"aps" : {"alert" : "message","badge" : "1","sound" : "default"}} {"aps" : { "alert" : { "title" : "My Title", "body" : "My Message" }, "badge" : 2, "sound" : "default" } }
После восстановления сертификатов теперь я получаю следующие ошибки при подключении:
[vagrant@server backend-src]$ php -f dispatcher.php Log path: [/srv/backend/log/log.txt], Log level: [0], Binding info: address[127.0.0.1], port[6060] Connecting to [ssl://gateway.push.apple.com:2195], using certificate [/srv/backend/htdocs/ios_distribution.pem] and passphrase[?] PHP Warning: stream_socket_client(): Failed to enable crypto in /vagrant/backend-src/dispatcher.php on line 182 PHP Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /vagrant/backend-src/dispatcher.php on line 182 Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /vagrant/backend-src/dispatcher.php on line 182 Connect failed error[0 ] to url [ssl://gateway.push.apple.com:2195] with certicate [/srv/backend/htdocs/ios_distribution.pem]
Теперь я могу подключиться! Причина здесь была простой. Путь к сертификатам был неправильным. Однако push-уведомления по-прежнему не принимаются на устройствах с новым сертификатом.
Должно ли приложение быть опубликовано / выпущено с новым сертификатом, прежде чем он будет работать? Ни по разработке, ни по производству не поступают сообщения на устройстве ???
Наконец, ему удалось получить сообщения как для песочницы, так и для производственных / рекламных токенов.
// 64 chars token // Sandbox and productions tokens have the same length and // they cannot be distinguished $deviceToken='1234567890123456789012345678901234567890123456789012345678901234'; $body['aps'] = array('alert' => 'Sample message', 'sound' => 'default'); $payload = json_encode($body); $deviceToken = str_replace(' ', '', $deviceToken); $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload; fwrite($apn_link, $msg, strlen($msg)); fflush($apn_link);
НЕ смешивайте маркеры из песочницы и продуктового устройства на производстве!
Производственная среда APN не позволяет использовать маркеры песочницы, и она молча перестает доставлять сообщения в токены производства, когда используется токен песочницы.
// 64 chars token // Sandbox and productions tokens have the same length and // they cannot be distinguished $deviceToken='1234567890123456789012345678901234567890123456789012345678901234'; $body['aps'] = array('alert' => 'Sample message', 'sound' => 'default'); $payload = json_encode($body); $deviceToken = str_replace(' ', '', $deviceToken); $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload; fwrite($apn_link, $msg, strlen($msg)); fflush($apn_link);
НЕ смешивайте маркеры для песочницы и устройства для производства на производстве!
Производственная среда APN не позволяет использовать маркеры песочницы, и она молча перестает доставлять сообщения в токены производства, когда используется токен песочницы.
Apple немного изменила ситуацию: в то время как она по-прежнему позволяет создавать сертификаты только для песочницы, производственные сертификаты могут использоваться как в песочнице, так и в производственных средах.