我正在尝试将 Apple 推送通知发送到我的应用程序。我正在关注 APNS 流程的本教程。网址:http ://www.raywenderlich.com/3525/apple-push-notification-services-tutorial-part-2 。
我在 MAMP、PHP 中几乎完成了工作,并且我在 pus_config.php 文件中提到了我的 .pem 文件以进行 APNS 连接。我已经用 simplepush.php 文件测试了我的 .pem 文件,并向我的设备发送了通知。现在正在尝试使用从上述教程中获取的 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;
}
}
我的 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 文件没有问题。