php之Apple 推送通知之PHP之SSL 操作失败,代码为 1

zhujiabin 阅读:59 2025-05-04 20:05:19 评论:0

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

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

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

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

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

发送到 Apple 服务器的通知是逐个发送的,而不是捆绑发送的。但是我们并没有建立太多的联系(可能每天有一千个)。没有排队系统。

所以,简而言之

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

  • 我们试过这些
  • 重新创建证书和 key
  • 重新创建 PEM 文件
  • 将 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 错误吗?任何想法什么和在哪里检查?
    Apple 是否有可以检查 APN 网络当前运行状况的站点?

    任何帮助是极大的赞赏...
    谢谢

    请您参考如下方法:

    查看此代码以发送多条消息

    $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."); 
    } 
    


    标签:PHP
    声明

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    关注我们

    一个IT知识分享的公众号