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

标签 php ios apple-push-notifications

在过去的几天里,当使用套接字连接到生产服务器上的 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 - Apple 推送通知 - PHP - SSL 操作失败,代码为 1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12156976/

    相关文章:

    ios - 我可以将我的应用程序转换为任何语言吗?

    c++ - 您可以将 C++ Linux 目标应用程序链接到 Objective-C 静态库吗?

    ios - Firebase iOS 设置 - nil senderID

    iOS 如何理解符号错误

    ios - 如何检测发送到其他应用程序的推送通知?

    php - MySql : can i query "WHERE ' $str' LIKE %table. col%"?

    php - 从 print_r 或对象中排除私有(private)属性(property)?

    php - PHP 中有 "nullsafe operator"吗?

    php - 使用 PDO 调用 mysql 过程出现一般错误

    iOS日历访问权限对话框,强制显示?