使用PEM文件在PHP中实现推送通知

14
我一直在学习Ray Wenderlich的教程,使用PHP脚本进行推送通知。
参考资料:http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1

http://www.raywenderlich.com/32963/apple-push-notification-services-in-ios-6-tutorial-part-2

我已经做了大量的研究,但在第二部分中,使用ck.pem文件运行push.php文件时遇到了问题。 /Applications/XAMPP/bin/php push.php development 唯一的区别是我使用的是XAMPP而不是MAMP。
我已确认所有扩展都已安装。
我可以通过以下方式在终端中测试我的证书: openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem 它会要求我输入密码。我这样做一切都成功了。
然而,当我运行push.php文件时,我会得到以下错误:
PHP警告:stream_socket_client():SSL操作失败,代码为1。OpenSSL错误消息: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed PHP警告:stream_socket_client():无法启用加密
PHP警告:stream_socket_client():无法连接ssl://gateway.sandbox.push.apple.com:2195(未知错误)位于第140行 php文件中的第140行是:

$this->fp = stream_socket_client('ssl://' . $this->server, $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

我发现了这些:

使用crontab调度程序时,iOS推送通知无法工作

https://devforums.apple.com/message/1054840#1054840

PHP中的推送通知

我已经尝试了所有方法。我知道我的密码短语是正确的。我重新创建了证书、pem文件和密钥。但仍然不起作用。每次这样做时都会出现相同的错误。

我已经超出了困惑的范畴。

有人有任何建议或知道发生了什么吗?

谢谢!

更新 1:

我还尝试设置ck.pem文件的完整路径,但也无法修复错误。


你确定你已经正确地导出了 .p12 文件吗?在从钥匙串中导出它时,请确保取的是私钥而不仅仅是公钥。 - Emilie
@Emilie 我只导出了私钥。因为教程没有告诉我,所以我没有导出公钥。 - Sandy D.
$ctx 的值是什么?它上面设置了哪些选项? - oflannabhra
从Entrust网站下载Entrust.net认证机构(2048)。然后,在OpenSSL命令中使用证书和-CAfileopenssl s_client -connect gateway.sandbox.push.apple.com:2195 -CAfile entrust-ca.pem。您还应该使用TLS 1.0和SNI:openssl s_client -connect gateway.sandbox.push.apple.com:2195 -CAfile entrust-ca.pem -tls1 -servername gateway.sandbox.push.apple.com - jww
@jww 我已经回答过这个问题了。但还是谢谢你。 - Sandy D.
显示剩余3条评论
4个回答

58

好的,我终于搞清楚了!在与此问题工作了两天后。

所以,对于任何遇到这个问题的人:

从以下网址下载entrust_2048_ca.cer证书: https://www.entrust.com/get-support/ssl-certificate-support/root-certificate-downloads/

向下滚动并获取Entrust.net Certificate Authority (2048)

然后,在push.php文件中,在设置密码短语的上下文之后,添加此行: stream_context_set_option($ctx, 'ssl', 'cafile', 'entrust_2048_ca.cer');


1
那真是非常有帮助! - gunjot singh
3
答案中的URL已经失效。目前正确的链接是https://www.entrust.com/get-support/ssl-certificate-support/root-certificate-downloads/,然后向下滚动到**Entrust.net Certificate Authority (2048)**。 - swifthorseman
5
希望我在5小时前就看到了你的帖子!我试过各种方法,都无法解决问题。当我删除URL中的'ssl://'时,我发现脚本可以工作,但我的iPhone上没有收到推送通知。我找到一个人说要添加stream_context_set_option($ctx, 'ssl', 'verify_peer', false);这将取消服务器验证。作为一种故障排除想法,我尝试了一下,神奇地推送成功了。那时,我知道问题出在服务器验证上。早些时候,我下载了entrust证书并将其添加到我的系统密钥链中,但没有帮助。谢谢你!我感激不尽! - One In a Million Apps
2
非常感谢!在MacOS Sierra中,这是解决方案! - Resty
1
如果可以的话,我会给你的答案点赞两次。我被卡了几天,开始拔头发了。非常感谢! - Swapnil Dhanwal
显示剩余3条评论

6

已更新至macOS Sierra 10.12.4


问题在于macOS Sierra中新版本的PHP。他们改变了它与证书配合工作的方式。

我建议对接受的答案进行一些小修改,以明确事情。

在创建流上下文时,您必须设置路径entrust_2048_ca.cer和其他参数。

$streamContext = stream_context_create([
        'ssl' => [
            'verify_peer'      => true,
            'verify_peer_name' => true,
            'cafile'           => '/path/to/bundle/entrust_2048_ca.cer',
        ]
    ]);
这里有完整的解释和链接,关于APNS推送通知在macOS Sierra上的操作。

5

升级到 macOS Sierra 10.12.5

请添加

stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

问题出在macOS Sierra中的新PHP版本。

3

添加

stream_context_set_option($ctx, 'ssl', 'verify_peer', false);

这将取消服务器验证。 感谢@One In a Million Apps在上面的评论中提供的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接