这是一个深夜。我只是花了10个小时在google / stackoverflow搜索和实验。似乎我讨厌Apple推送通知。我非常沮丧,并会感激任何帮助。
谢谢。
用于发送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/...
它停止在两个单独的服务器上工作,这些服务器使用单独的脚本发送APN。
服务器:带有PHP 5.4.32的CentOS 6.5和带有PHP 5.5.9的Ubuntu 14.04.3
APN:在生产模式
证书:使用700多个推送通知进行测试。
其中一台服务器在localhost上使用https://github.com/immobiliare/ApnsPHP,其他 - https://github.com/antongorodezkiy/wp-apn,我在不使用任何第三方代码的情况下测试了简单文件。
对于以下所有情况,我使用了相同的有效设备令牌和相同的生产PEM证书。
但是,即使这个简单的代码在服务器和localhost上都不起作用,并返回与上面相同的错误:
$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()
选项,包括entrust_2048_ca.cer
等,甚至是this article中的一些选项。虽然提供的代码在2015年8月之前没有任何修改。
连接工作:
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 )
。
连接工作:
-sh-4.1$ telnet gateway.push.apple.com 2195
Trying 17.172.233.150...
Connected to gateway.push.apple.com.
它没有发送推送通知。我只是尝试使用sample code的改编版,但得到了错误Invalid token
。令牌是活动的,我在任何地方使用过相同的令牌,也用于休斯顿和Ruby。
与Houston合作
apn push "0346a53f...231d9d6abe11" -c /absolute/path/to/apn_prod.pem -m "Hello from the command line!" -e "production"
我不是Ruby程序员(至少还是),但在休斯顿取得成功之后,我发现并修改了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"
stream_socket_client()
如何实现。答案 0 :(得分:5)
我发现了问题并修复了它。
问题位于.pem证书中。不知何故,在一个文件中有两个证书用于生产和开发.pem文件。具有两个证书的相同.pem文件在回购中很长一段时间,但APN仅在几个月前停止工作。也许在Apple的一方升级/改变了一些东西。
我认为Ruby代码以某种方式删除了证书重复,或者它只需要第一个证书,所以它在Ruby中工作。
但是,解决方案是从.pem文件中删除第二个证书。之后,APN开始工作,他们现在工作(我昨天收到了一些)。
答案 1 :(得分:0)
如果您只是重复使用旧的证书签名请求(CSR),请确保在导出新证书和私钥作为p12文件之前从钥匙串中删除过期/旧的APN证书。如果您不这样做,您从导出的p12生成的PEM文件仍将包含过期/旧证书,该证书与Apple的推送提供程序不兼容。因此导致unable to connect to ssl...
。