深夜です。google/stackoverflow の検索と実験に 10 時間費やしました。そして、私は Apple プッシュ通知が嫌いなようです。私は完全にイライラしており、助けていただければ幸いです。
ありがとうございました。
問題:
2 週間前に正常に機能していた Apple プッシュ通知を送信するための PHP コードが、現在は機能しなくなり、次のエラーがスローされます。
PHP Warning: stream_socket_client(): Failed to enable crypto in /home/...
PHP Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /home/...
APNs 送信用に別々のスクリプトを使用している 2 つの別々のサーバーで動作しなくなりました。
環境:
サーバー: PHP 5.4.32 を使用する CentOS 6.5 および PHP 5.5.9 を使用する Ubuntu 14.04.3
APN: 本番モード
証明書: 700 以上のプッシュ通知でテスト済み。
サーバーの 1 つはhttps://github.com/immobiliare/ApnsPHP、その他 - https://github.com/antongorodezkiy/wp-apn、ローカルホストで使用しています。サードパーティのコードを使用せずに単純なファイルをテストしました。
調査:
以下のすべてのケースで、同じアクティブなデバイス トークンと同じ運用 PEM 証明書を使用しました。
php
ただし、この単純なコードでさえ、サーバーとローカルホストの両方で機能せず、上記と同じエラーを返します。
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', '/absolute/path/to/apn_prod.pem');
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
stream_context_set_option()
また、オプション、 includeentrust_2048_ca.cer
など、さらにはこの記事のいくつかのオプションで遊んでみました。提供されたコードは、2015 年 8 月までは変更なしで機能しましたが。
openssl
接続はopensslで機能しました(リンク):
openssl s_client -connect gateway.push.apple.com:2195 -cert /absolute/path/to/apn_prod.pem -debug -showcerts -CAfile /absolute/path/to/server-ca-cert.pem
そして と を得ましCONNECTED(00000003)
たVerify return code: 0 ( ok )
。
telnet
接続はtelnetで機能しました:
-sh-4.1$ telnet gateway.push.apple.com 2195
Trying 17.172.233.150...
Connected to gateway.push.apple.com.
ペクルapn
プッシュ通知を送信しませんでした。サンプル コードの適応を使用しようとしましたが、エラーが発生しましInvalid token
た。トークンはアクティブで、どこでも、ヒューストンとルビーにも使用したのと同じトークンです。
ヒューストン
ヒューストンで働いた
apn push "0346a53f...231d9d6abe11" -c /absolute/path/to/apn_prod.pem -m "Hello from the command line!" -e "production"
ルビー
私は (少なくとも) Ruby プログラマーではありませんが、Houston で成功した後、Houston に依存しない Ruby コードを見つけて適応させました。
そしてそれは働いた:
#!/usr/bin/env ruby
require 'openssl'
require 'socket'
require 'json'
token = "0346a53f...231d9d6abe11"
cert = File.read("/absolute/path/to/apn_prod.pem")
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new(cert, '') #set passphrase here, if any
ctx.cert = OpenSSL::X509::Certificate.new(cert)
sock = TCPSocket.new('gateway.push.apple.com', 2195) #development gateway
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.connect
payload = {"aps" => {"alert" => "Oh hai!", "badge" => 1, "sound" => 'default'}}
json = payload.to_json()
token = [token.delete(' ')].pack('H*') #something like 2c0cad 01d1465 346786a9 3a07613f2 b03f0b94b6 8dde3993 d9017224 ad068d36
apnsMessage = "\0\0 #{token}\0#{json.length.chr}#{json}"
ssl.write(apnsMessage)
ssl.close
sock.close
puts "End"
質問:
- PHPの何が問題になっていますか?この問題に関連するバグはありますか? (バグレポートは見つかりませんでした)
- この問題を解決する方法はありますか?
- PHP と Ruby の場合の違いは何ですか (Python や Perl も問題なく動作すると思います)。PHP のソースを読もうとさえしましたが、
stream_socket_client()
実装方法を理解することはできませんでした。