Apple推送通知 – PHP – SSL代码1失败

在过去的几天中,当我们使用套接字连接到生产服务器上的APN服务器时,我们遇到了一些奇怪的PHP行为。

在大多数情况下,有效载荷被推送,没有任何错误,客户端收到通知。 但是,在某些情况下,我们开始收到PHP错误(即使我们收到错误,有时会通知被推送)。 当我们开始看到这个错误时,它会持续几个小时然后消失,PHP继续工作,就像什么也没有发生。

另一个奇怪的是,从shell运行相同的PHP代码不会产生任何错误。 从networking(nginx / php-fpm)运行它… PHP在shell和web上运行具有相同的configuration,并共享相同的php.ini。 唯一的区别是web运行在php-fpm上。

另外,在我们的登台服务器上运行相同的代码+证书没有任何错误。 生产服务器是登台服务器的副本,因此每个configuration都是相同的。

我们能够find一些可能导致此错误的答案,包括来自stackoverflow.com的答案,但我们无法find解决scheme或解决它。

通知到苹果服务器是一个接一个发送,而不是一个捆绑。 但是我们并没有build立太多的联系(也许每天有一千个)。 没有队列系统。

所以,总之

  • 我们有时会在发送通知时收到PHP错误,但并非总是如此。
  • 通过相同的PHP从shell发送通知不会产生任何错误
  • 从登台服务器发送通知不会产生任何错误

我们尝试了这些

  • 重新创build证书和密钥
  • 重新创buildPEM文件
  • 将ssl://更改为sslv3://
  • 使用stream_socket_client
  • 使用fsockopen
  • 更改/删除证书密码

错误是:

2012/08/28 12:18:09 [error] 4282#0: *225858 FastCGI sent in stderr: "PHP message: PHP Warning: fwrite() [<a href='function.fwrite'>function.fwrite</a>]: SSL operation failed with code 1. OpenSSL Error messages: error:1409F07F:SSL routines:func(159):reason(127) in /usr/local/nginx/html/play/classes/PushNotification.php on line 283" while reading response header from upstream, client: 94.---.---.---, server: play.--------.com, request: "POST /game_request_random.php HTTP/1.1", upstream: "fastcgi://unix:/var/run/phpfpm.sock:", host: "play.--------.com", referrer: "http://--------.com/" 

从php连接和发送有效载荷的代码实际上是一个类的一部分,这部分是什么使得连接和发送有效载荷:

  private function ConnectAndSend ( $msg = false ) { $ctx = stream_context_create(); stream_context_set_option( $ctx, 'ssl', 'local_cert', $this->certificate ); stream_context_set_option( $ctx, 'ssl', 'passphrase', $this->certificatepass ); // Open a connection to the APNS server $fp = stream_socket_client( APN_SERVER, $err, $errstr, 60, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, $ctx ); if ( !$fp ) { errorlog( "Push notification error : $err $errstr" ); $this->error = "$err $errstr"; return; } // Build the notification if ( !$msg ) { $msg = chr( 0 ) . pack( 'n', 32 ) . pack( 'H*', $this->devicetoken ) . pack( 'n', strlen( $this->payload ) ) . $this->payload; } // Send it to the server if ( !($result = fwrite( $fp, $msg, strlen( $msg ) )) ) { // Could not send $this->error = 'Notification could not be send'; errorlog( "Push notification error : {$this->error}" ); } else { // Notification sent $this->error = false; errorlog( "Push notification sent" ); } fclose($fp); // Reset the content $this->devicetoken = false; $this->message = false; $this->command = false; $this->badge = 0; $this->payload = false; $this->sound = false; } 
  • stream_socket_connection是出现在错误消息中的第283行
  • 我们不使用沙箱(sslv3://gateway.push.apple.com:2195)
  • PHP版本是5.3.15

这是一个我们不知道的PHP或OpenSSL错误? 任何想法什么和在哪里检查? 苹果是否有一个网站可以检查APNnetworking当前的健康状况?

任何帮助非常感谢…谢谢

看看这个代码发送多个消息

 $i = 0; while($res = mysql_fetch_array( $result )) { $deviceTokens[$i] = $res['token']; $i++; } // APNs Push testen auf Token //$deviceToken = $token; // Hier das Device-Token angeben, ist 64-stellig // Payload erstellen und JSON codieren $message = $_POST['message']; $message = utf8_encode($message); $payload['aps'] = array('alert' => 'Neuer Artikel in Aktuelles', 'badge' => +1, 'sound' => 'default'); if (trim($message) != '') { $payload['aps'] = array('alert' => "$message", 'badge' => 1, 'sound' => 'default'); } $payload = json_encode($payload); //Development: $apnsHost = 'gateway.sandbox.push.apple.com'; $apnsHost = 'gateway.push.apple.com'; $apnsPort = 2195; //Development: $apnsCert = 'apsDevBundle.pem'; $apnsCert = 'apns-dev.pem'; // Stream erstellen $streamContext = stream_context_create(); stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert); $apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext); if ($error==0) { for($i = 0; $i<count($deviceTokens); $i++) { // Build the binary notification $apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceTokens[$i])) . chr(0) . chr(strlen($payload)) . $payload; fwrite($apns, $apnsMessage); } // Verbindung schliessen fclose($apns); } else { var_dump($error); var_dump($errorString); die("Fehler aufgetreten."); }