Песочница APNS Ошибка подключения «0» в php-файле?

Я пытаюсь отправить уведомления Apple Push в мое приложение. Следуйте этому руководству для процесса APNS. URL: http://www.raywenderlich.com/3525/apple-push-notification-services-tutorial-part-2 .

Я почти работал в MAMP, PHP, и я упомянул мой файл .pem в файле pus_config.php для подключения APNS. Я протестировал мой файл .pem с файлом simplepush.php и отправил уведомления на свое устройство. Теперь я пытаюсь с файлом push.php, который был взят из вышеупомянутого учебника.

Это мой файл push_config.php,

<?php // Configuration file for push.php $config = array( // These are the settings for development mode 'development' => array( // The APNS server that we will use 'server' => 'gateway.sandbox.push.apple.com:2195', // The SSL certificate that allows us to connect to the APNS servers 'certificate' => 'GopiAPNSCert.pem', 'passphrase' => 'gopi', // Configuration of the MySQL database 'db' => array( 'host' => 'localhost', 'dbname' => 'gopipush', 'username' => 'gopipush', 'password' => 'uH4q9xQGNAuFW', ), // Name and path of our log file 'logfile' => '/Users/gopi/Desktop/PushChatServer/log/push_development.log', ), // These are the settings for production mode 'production' => array( // The APNS server that we will use 'server' => 'gateway.push.apple.com:2195', // The SSL certificate that allows us to connect to the APNS servers 'certificate' => 'ck.pem', 'passphrase' => 'secret', // Configuration of the MySQL database 'db' => array( 'host' => 'localhost', 'dbname' => 'pushchat', 'username' => 'pushchat', 'password' => '1233}jfdoie', ), // Name and path of our log file 'logfile' => '/Users/gopi/Desktop/PushChatServer/log/push_development.log', ), ); 

Вышеуказанное имя сертификата и кодовая фраза проверяются и проверяются корректно с помощью файла simplepush.php.

Вот мой файл push.php,

 <?php try { require_once('push_config.php'); ini_set('display_errors', 'off'); if ($argc != 2 || ($argv[1] != 'development' && $argv[1] != 'production')) exit("Usage: php push.php development|production". PHP_EOL); $mode = $argv[1]; $config = $config[$mode]; writeToLog("Push script started ($mode mode)"); $obj = new APNS_Push($config); $obj->start(); } catch (Exception $e) { fatalError($e); } //////////////////////////////////////////////////////////////////////////////// function writeToLog($message) { global $config; if ($fp = fopen($config['logfile'], 'at')) { fwrite($fp, date('c') . ' ' . $message . PHP_EOL); fclose($fp); } } function fatalError($message) { writeToLog('Exiting with fatal error: ' . $message); exit; } //////////////////////////////////////////////////////////////////////////////// class APNS_Push { private $fp = NULL; private $server; private $certificate; private $passphrase; function __construct($config) { $this->server = $config['server']; $this->certificate = $config['certificate']; $this->passphrase = $config['passphrase']; // Create a connection to the database. $this->pdo = new PDO( 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['dbname'], $config['db']['username'], $config['db']['password'], array()); // If there is an error executing database queries, we want PDO to // throw an exception. $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // We want the database to handle all strings as UTF-8. $this->pdo->query('SET NAMES utf8'); } // This is the main loop for this script. It polls the database for new // messages, sends them to APNS, sleeps for a few seconds, and repeats this // forever (or until a fatal error occurs and the script exits). function start() { writeToLog('Connecting to ' . $this->server); if (!$this->connectToAPNS()) { exit; } while (true) { writeToLog('Getting PushQueue'); $stmt = $this->pdo->prepare('SELECT * FROM push_queue WHERE time_sent IS NULL LIMIT 20'); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($messages as $message) { if ($this->sendNotification($message->message_id, $message->device_token, $message->payload)) { $stmt = $this->pdo->prepare('UPDATE push_queue SET time_sent = NOW() WHERE message_id = ?'); $stmt->execute(array($message->message_id)); } else // failed to deliver { $this->reconnectToAPNS(); } } unset($messages); sleep(5); } } // Opens an SSL/TLS connection to Apple's Push Notification Service (APNS). // Returns TRUE on success, FALSE on failure. function connectToAPNS() { $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certificate); stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase); $this->fp = stream_socket_client( 'ssl://' . $this->server, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); if (!$this->fp) { writeToLog('Failed APNS Connection'); writeToLog("Failed to connect: $err $errstr"); return FALSE; } writeToLog('Connection OK'); return TRUE; } // Drops the connection to the APNS server. function disconnectFromAPNS() { fclose($this->fp); $this->fp = NULL; } // Attempts to reconnect to Apple's Push Notification Service. Exits with // an error if the connection cannot be re-established after 3 attempts. function reconnectToAPNS() { writeToLog('ReconnectToAPNS'); $this->disconnectFromAPNS(); $attempt = 1; while (true) { writeToLog('Reconnecting to ' . $this->server . ", attempt $attempt"); if ($this->connectToAPNS()) return; if ($attempt++ > 3) fatalError('Could not reconnect after 3 attempts'); sleep(60); } } // Sends a notification to the APNS server. Returns FALSE if the connection // appears to be broken, TRUE otherwise. function sendNotification($messageId, $deviceToken, $payload) { if (strlen($deviceToken) != 64) { writeToLog("Message $messageId has invalid device token"); return TRUE; } if (strlen($payload) < 10) { writeToLog("Message $messageId has invalid payload"); return TRUE; } writeToLog("Sending message $messageId to '$deviceToken', payload: '$payload'"); if (!$this->fp) { writeToLog('No connection to APNS'); return FALSE; } // The simple format $msg = chr(0) // command (1 byte) . pack('n', 32) // token length (2 bytes) . pack('H*', $deviceToken) // device token (32 bytes) . pack('n', strlen($payload)) // payload length (2 bytes) . $payload; // the JSON payload /* // The enhanced notification format $msg = chr(1) // command (1 byte) . pack('N', $messageId) // identifier (4 bytes) . pack('N', time() + 86400) // expire after 1 day (4 bytes) . pack('n', 32) // token length (2 bytes) . pack('H*', $deviceToken) // device token (32 bytes) . pack('n', strlen($payload)) // payload length (2 bytes) . $payload; // the JSON payload */ $result = @fwrite($this->fp, $msg, strlen($msg)); if (!$result) { writeToLog('Message not delivered'); return FALSE; } writeToLog('Message successfully delivered'); return TRUE; } } эта <?php try { require_once('push_config.php'); ini_set('display_errors', 'off'); if ($argc != 2 || ($argv[1] != 'development' && $argv[1] != 'production')) exit("Usage: php push.php development|production". PHP_EOL); $mode = $argv[1]; $config = $config[$mode]; writeToLog("Push script started ($mode mode)"); $obj = new APNS_Push($config); $obj->start(); } catch (Exception $e) { fatalError($e); } //////////////////////////////////////////////////////////////////////////////// function writeToLog($message) { global $config; if ($fp = fopen($config['logfile'], 'at')) { fwrite($fp, date('c') . ' ' . $message . PHP_EOL); fclose($fp); } } function fatalError($message) { writeToLog('Exiting with fatal error: ' . $message); exit; } //////////////////////////////////////////////////////////////////////////////// class APNS_Push { private $fp = NULL; private $server; private $certificate; private $passphrase; function __construct($config) { $this->server = $config['server']; $this->certificate = $config['certificate']; $this->passphrase = $config['passphrase']; // Create a connection to the database. $this->pdo = new PDO( 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['dbname'], $config['db']['username'], $config['db']['password'], array()); // If there is an error executing database queries, we want PDO to // throw an exception. $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // We want the database to handle all strings as UTF-8. $this->pdo->query('SET NAMES utf8'); } // This is the main loop for this script. It polls the database for new // messages, sends them to APNS, sleeps for a few seconds, and repeats this // forever (or until a fatal error occurs and the script exits). function start() { writeToLog('Connecting to ' . $this->server); if (!$this->connectToAPNS()) { exit; } while (true) { writeToLog('Getting PushQueue'); $stmt = $this->pdo->prepare('SELECT * FROM push_queue WHERE time_sent IS NULL LIMIT 20'); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($messages as $message) { if ($this->sendNotification($message->message_id, $message->device_token, $message->payload)) { $stmt = $this->pdo->prepare('UPDATE push_queue SET time_sent = NOW() WHERE message_id = ?'); $stmt->execute(array($message->message_id)); } else // failed to deliver { $this->reconnectToAPNS(); } } unset($messages); sleep(5); } } // Opens an SSL/TLS connection to Apple's Push Notification Service (APNS). // Returns TRUE on success, FALSE on failure. function connectToAPNS() { $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certificate); stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase); $this->fp = stream_socket_client( 'ssl://' . $this->server, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); if (!$this->fp) { writeToLog('Failed APNS Connection'); writeToLog("Failed to connect: $err $errstr"); return FALSE; } writeToLog('Connection OK'); return TRUE; } // Drops the connection to the APNS server. function disconnectFromAPNS() { fclose($this->fp); $this->fp = NULL; } // Attempts to reconnect to Apple's Push Notification Service. Exits with // an error if the connection cannot be re-established after 3 attempts. function reconnectToAPNS() { writeToLog('ReconnectToAPNS'); $this->disconnectFromAPNS(); $attempt = 1; while (true) { writeToLog('Reconnecting to ' . $this->server . ", attempt $attempt"); if ($this->connectToAPNS()) return; if ($attempt++ > 3) fatalError('Could not reconnect after 3 attempts'); sleep(60); } } // Sends a notification to the APNS server. Returns FALSE if the connection // appears to be broken, TRUE otherwise. function sendNotification($messageId, $deviceToken, $payload) { if (strlen($deviceToken) != 64) { writeToLog("Message $messageId has invalid device token"); return TRUE; } if (strlen($payload) < 10) { writeToLog("Message $messageId has invalid payload"); return TRUE; } writeToLog("Sending message $messageId to '$deviceToken', payload: '$payload'"); if (!$this->fp) { writeToLog('No connection to APNS'); return FALSE; } // The simple format $msg = chr(0) // command (1 byte) . pack('n', 32) // token length (2 bytes) . pack('H*', $deviceToken) // device token (32 bytes) . pack('n', strlen($payload)) // payload length (2 bytes) . $payload; // the JSON payload /* // The enhanced notification format $msg = chr(1) // command (1 byte) . pack('N', $messageId) // identifier (4 bytes) . pack('N', time() + 86400) // expire after 1 day (4 bytes) . pack('n', 32) // token length (2 bytes) . pack('H*', $deviceToken) // device token (32 bytes) . pack('n', strlen($payload)) // payload length (2 bytes) . $payload; // the JSON payload */ $result = @fwrite($this->fp, $msg, strlen($msg)); if (!$result) { writeToLog('Message not delivered'); return FALSE; } writeToLog('Message successfully delivered'); return TRUE; } } не <?php try { require_once('push_config.php'); ini_set('display_errors', 'off'); if ($argc != 2 || ($argv[1] != 'development' && $argv[1] != 'production')) exit("Usage: php push.php development|production". PHP_EOL); $mode = $argv[1]; $config = $config[$mode]; writeToLog("Push script started ($mode mode)"); $obj = new APNS_Push($config); $obj->start(); } catch (Exception $e) { fatalError($e); } //////////////////////////////////////////////////////////////////////////////// function writeToLog($message) { global $config; if ($fp = fopen($config['logfile'], 'at')) { fwrite($fp, date('c') . ' ' . $message . PHP_EOL); fclose($fp); } } function fatalError($message) { writeToLog('Exiting with fatal error: ' . $message); exit; } //////////////////////////////////////////////////////////////////////////////// class APNS_Push { private $fp = NULL; private $server; private $certificate; private $passphrase; function __construct($config) { $this->server = $config['server']; $this->certificate = $config['certificate']; $this->passphrase = $config['passphrase']; // Create a connection to the database. $this->pdo = new PDO( 'mysql:host=' . $config['db']['host'] . ';dbname=' . $config['db']['dbname'], $config['db']['username'], $config['db']['password'], array()); // If there is an error executing database queries, we want PDO to // throw an exception. $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // We want the database to handle all strings as UTF-8. $this->pdo->query('SET NAMES utf8'); } // This is the main loop for this script. It polls the database for new // messages, sends them to APNS, sleeps for a few seconds, and repeats this // forever (or until a fatal error occurs and the script exits). function start() { writeToLog('Connecting to ' . $this->server); if (!$this->connectToAPNS()) { exit; } while (true) { writeToLog('Getting PushQueue'); $stmt = $this->pdo->prepare('SELECT * FROM push_queue WHERE time_sent IS NULL LIMIT 20'); $stmt->execute(); $messages = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($messages as $message) { if ($this->sendNotification($message->message_id, $message->device_token, $message->payload)) { $stmt = $this->pdo->prepare('UPDATE push_queue SET time_sent = NOW() WHERE message_id = ?'); $stmt->execute(array($message->message_id)); } else // failed to deliver { $this->reconnectToAPNS(); } } unset($messages); sleep(5); } } // Opens an SSL/TLS connection to Apple's Push Notification Service (APNS). // Returns TRUE on success, FALSE on failure. function connectToAPNS() { $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', $this->certificate); stream_context_set_option($ctx, 'ssl', 'passphrase', $this->passphrase); $this->fp = stream_socket_client( 'ssl://' . $this->server, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); if (!$this->fp) { writeToLog('Failed APNS Connection'); writeToLog("Failed to connect: $err $errstr"); return FALSE; } writeToLog('Connection OK'); return TRUE; } // Drops the connection to the APNS server. function disconnectFromAPNS() { fclose($this->fp); $this->fp = NULL; } // Attempts to reconnect to Apple's Push Notification Service. Exits with // an error if the connection cannot be re-established after 3 attempts. function reconnectToAPNS() { writeToLog('ReconnectToAPNS'); $this->disconnectFromAPNS(); $attempt = 1; while (true) { writeToLog('Reconnecting to ' . $this->server . ", attempt $attempt"); if ($this->connectToAPNS()) return; if ($attempt++ > 3) fatalError('Could not reconnect after 3 attempts'); sleep(60); } } // Sends a notification to the APNS server. Returns FALSE if the connection // appears to be broken, TRUE otherwise. function sendNotification($messageId, $deviceToken, $payload) { if (strlen($deviceToken) != 64) { writeToLog("Message $messageId has invalid device token"); return TRUE; } if (strlen($payload) < 10) { writeToLog("Message $messageId has invalid payload"); return TRUE; } writeToLog("Sending message $messageId to '$deviceToken', payload: '$payload'"); if (!$this->fp) { writeToLog('No connection to APNS'); return FALSE; } // The simple format $msg = chr(0) // command (1 byte) . pack('n', 32) // token length (2 bytes) . pack('H*', $deviceToken) // device token (32 bytes) . pack('n', strlen($payload)) // payload length (2 bytes) . $payload; // the JSON payload /* // The enhanced notification format $msg = chr(1) // command (1 byte) . pack('N', $messageId) // identifier (4 bytes) . pack('N', time() + 86400) // expire after 1 day (4 bytes) . pack('n', 32) // token length (2 bytes) . pack('H*', $deviceToken) // device token (32 bytes) . pack('n', strlen($payload)) // payload length (2 bytes) . $payload; // the JSON payload */ $result = @fwrite($this->fp, $msg, strlen($msg)); if (!$result) { writeToLog('Message not delivered'); return FALSE; } writeToLog('Message successfully delivered'); return TRUE; } } 

Я получаю эту ошибку в файле push_development.log.

 2012-05-14T18:04:28+05:30 Push script started (development mode) 2012-05-14T18:04:28+05:30 Connecting to gateway.sandbox.push.apple.com:2195 2012-05-14T18:04:29+05:30 Failed to connect: 0 

Я не могу найти то, что я сделал неправильно? И что я должен изменить в моем файле push.php. Я тестировал свои сетевые подключения и файлы .pem. Не могли бы вы помочь мне решить эту ошибку и получить уведомления на моем устройстве? Заранее спасибо.

РЕДАКТИРОВАТЬ

 unknownc42c032e8297:~ name$ cd /Users/name/Desktop/PushChatServer unknownc42c032e8297: PushChatServer name$ telnet gateway.sandbox.push.apple.com 2195 Trying 17.149.34.66... Connected to gateway.sandbox.push-apple.com.akadns.net. Escape character is '^]'. ^C Connection closed by foreign host. unknownc42c032e8297: PushChatServer name$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert NameAPNCert.pem -key GopiAPNSCert .pem Enter pass phrase for NameAPNKey.pem: CONNECTED(00000003) depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C verify error:num=20:unable to get local issuer certificate verify return:0 --- Certificate chain 0 s:/C=US/ST=California/L=Cupertino/O=Apple Inc/OU=Internet Services/CN=gateway.sandbox.push.apple.com  i:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C 1 s:/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C  i:/O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048) --- Server certificate -----BEGIN CERTIFICATE----- MIIEZTCCA02gAwIBAgIESyDhfjANBgkqhkiG9w0BAQUFADCBsTELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 Lm5ldC9ycGEgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW KGMpIDIwMDkgRW50cnVzdCwgSW5jLjEuMCwGA1UEAxMlRW50cnVzdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eSAtIEwxQzAeFw0xMDA0MTMyMzM0MzNaFw0xMjA1MzEw MDA0MjdaMIGPMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAG A1UEBxMJQ3VwZXJ0aW5vMRIwEAYDVQQKEwlBcHBsZSBJbmMxGjAYBgNVBAsTEUlu dGVybmV0IFNlcnZpY2VzMScwJQYDVQQDEx5nYXRld2F5LnNhbmRib3gucHVzaC5h cHBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM5NngiDMFpGBMmb 8tG2MRhLEdsx553Xjq+5C/c0mtildwhnC1X0LWKUexWdQsMchniac+WnHFSs3YMJ JJ55kQSB6wqK/WNcxsUn8pMkMsvk3YZFM7TsaKQvFOeieiXCSJVlR3grm3+dilv1 Br+SUqv8JrgU3ijmoQO63vkb8B/hAgMBAAGjggEnMIIBIzALBgNVHQ8EBAMCBaAw HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMDMGA1UdHwQsMCowKKAmoCSG Imh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvbGV2ZWwxYy5jcmwwMwYIKwYBBQUHAQEE JzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5ldDBABgNVHSAE OTA3MDUGCSqGSIb2fQdLAjAoMCYGCCsGAQUFBwIBFhpodHRwOi8vd3d3LmVudHJ1 c3QubmV0L3JwYTAfBgNVHSMEGDAWgBQe8auJBvhJDwEzd+4Ueu4ZfJMoTTAdBgNV HQ4EFgQUNyg/64Sjw/+b4YOwC8E/c+jemRgwCQYDVR0TBAIwADANBgkqhkiG9w0B AQUFAAOCAQEAk9Ij+NCp+323+4vBqbA0fT9ZCROptPqNIshY5uEvaWUaW5hsoLUm fsMJMueqzDaoj4yPD8iCCZq1Mp8tM8WB2mG1zIxTLshlhRgDDUF11IbUUBHv/ZhU RzXewQD6pazQmsBPuR0vP3mmWbKqmZOiv2yWSGlQmWGW4m6RQwjYYj8UqqFEdinV g1+qY6/muTpaCiygDjJZBlv9P6bwwP9FB8OJf5tGECvvxXad3PK/oiI77aLTYSVr SA0oisXCiqcgTKQq5BV5M3fQQ4ZS73aBKLI0wPYc0AASD5WdtPTGTvmEbhO4KeaU 0SL85Prf8uSsDOLvn3656awLz/H/yzrf/g== -----END CERTIFICATE----- subject=/C=US/ST=California/L=Cupertino/O=Apple Inc/OU=Internet Services/CN=gateway.sandbox.push.apple.com issuer=/C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C --- No client certificate CA names sent --- SSL handshake has read 2549 bytes and written 2017 bytes --- New, TLSv1/SSLv3, Cipher is AES256-SHA Server public key is 1024 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session:  Protocol  : TLSv1  Cipher   : AES256-SHA  Session-ID:  Session-ID-ctx:  Master-Key: 729CC0899B36143DAC78D40B2C31ECB71C81A3BD8DC5CFD6D71AC7885DD2E63DCD47096E97A1B3AF032A8D7D48BF73DA  Key-Arg  : None  Start Time: 1336636910  Timeout  : 300 (sec)  Verify return code: 0 (ok) --- name closed unknownc42c032e8297: PushChatServer name$ php simplepush.php Connected to APNS Message successfully delivered 

Здесь я могу соединиться с apns и отправлять уведомления. Поэтому не думайте о проблемах с файлами .pem.

[EDIT] Не могли бы вы попытаться установить общий путь к файлу сертификата в config?

Вы можете проверить это, чтобы решить проблему проверки сверстников.

Установите сертификат http://code.google.com/p/apns-php/wiki/CertificateCreation#Verify_peer_using_Entrust_Root_Certification_Authority

Использовать здесь

 stream_context_set_option($ctx, 'ssl', 'cafile', 'entrust_2048_ca.cer'); 

Примечание. Отключить проверку также работает.

Что-то, что сработало для меня, – это обновление разрешений на файле ck.pem, чтобы PHP-скрипт мог правильно его прочитать. После этого я смог без проблем подключиться к APNS.