ApnsPHP:在开发中工作但不在生产中的推送通知

Posted

技术标签:

【中文标题】ApnsPHP:在开发中工作但不在生产中的推送通知【英文标题】:ApnsPHP: Push notifications working in development but not in production 【发布时间】:2013-09-26 15:04:16 【问题描述】:

是的:这个问题有很多重复,但没有一个答案有帮助。

我正在关注这个伟大的tutorial by Ali Hafizji on using APNS service for push notifications。

开发模式下测试APNS:

下载aps_development.cer 导出证书的私钥 (aps_development_key.p12)

然后我使用以下命令(使用终端)将两者结合起来:

openssl x509 -in aps_development.cer -inform der -out aps_development.pem
openssl pkcs12 -nocerts -out aps_development_key.pem -in aps_development.p12
cat aps_development.pem aps_development_key.pem > final_aps_development.pem

并且(在服务器上使用 Apnsphp)我可以使用此配置成功发送推送通知:

...
$push = new ApnsPHP_Push(ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,'final_aps_development.pem');
$push->setRootCertificationAuthority('entrust_root_certification_authority.pem');
$push->setProviderCertificatePassphrase('mypassword');
...

旁注:我从https://github.com/jonathanrcarter/push2press 获取了 entrust_root_certification_authority.pem, 寻找它的正确地址可能是https://www.entrust.net/downloads/binary/entrust_2048_ca.cer (无论如何它们都是一样的)。

在这种情况下,应用程序在调试模式下运行(在设备上,从 XCode 运行)并且一切正常。

生产模式下测试 APNS:

为了在生产模式下测试 APNS,我将应用程序存档以进行 AdHoc 分发并将其安装在设备上并使用 iPhone Configuration Utility。

我按照与aps_production.cer 相同的程序制作final_aps_production.pem

Bang,用于发送推送通知的 php 脚本返回 html 状态码 500。

$push 一代当然已针对生产模式进行了修改:

...
$push = new ApnsPHP_Push(ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION,'final_aps_production.pem');
$push->setRootCertificationAuthority('entrust_root_certification_authority.pem');
$push->setProviderCertificatePassphrase('mypassword');
...

快速查看/var/log/apache2/error.log 表明问题所在:

PHP Fatal error:  Uncaught exception 'ApnsPHP_Exception' with message 'Unable to connect to 'ssl://gateway.push.apple.com:2195':  (0)' in /var/www/gettapro/mobile/ApnsPHP/Abstract.php:398\nStack trace:\n#0 /var/www/gettapro/mobile/ApnsPHP/Abstract.php(334): ApnsPHP_Abstract->_connect()\n#1  ....

谷歌搜索(有很多人遇到这个问题)被证明是徒劳的。

许多不同的建议,例如将持有证书的目录的文件权限更改为 775...

我也在ApnsPHP/Abstract.php(这里建议:https://github.com/duccio/ApnsPHP/issues/29)中尝试过这种更改,但没有成功。

$streamContext = stream_context_create(array('ssl' => array(
             //'verify_peer' => isset($this->_sRootCertificationAuthorityFile),
            'cafile' => $this->_sRootCertificationAuthorityFile,
            'local_cert' => $this->_sProviderCertificateFile
        ))); 

那个讨厌的ApnsPHP_Exception 并没有消失。

当然,我还确保在测试生产模式时使用正确的设备 APNS 令牌 - 调试和生产模式下的设备 APNS 令牌不一样 - 已使用。

无论如何:令牌不是问题,因为我的通知发送脚本甚至无法连接到ssl://gateway.push.apple.com:2195

尝试通过telnet 连接ssl://gateway.push.apple.com:2195 只是为了确保:连接正常。

很明显:这是一个证书问题。

【问题讨论】:

【参考方案1】:

看来aps_production.cer 的处理方式不应该和aps_development.cer 一样

RTM moment 来了。

在钥匙串中下载并安装证书(双击aps_production.cer

从 Keychain Access 导出 .p12 版本的 aps_production 证书(您还在这里设置了密码)。

使用此命令将其转换为.pem 格式(您必须在此处输入密码):

openssl pkcs12 -in aps_production.p12 -out final_aps_production.pem -nodes

- 一切都开始了,我又是一个快乐的露营者了。

Jeremy 提供了关于如何导出证书和密钥 here on SO 的类似教程的精彩说明。

【讨论】:

您是在导出证书本身的 .p12 文件还是证书的密钥?这就是你的意思他们不应该被类似处理吗? 我的措辞在这里有点笨拙 - 可能两个证书都可以以相同的方式安装。在最后一个变体中,证书首先安装在钥匙串 (OSX) 中,然后与密钥一起导出。这样就不会出错了。 哈!非常感谢这种直截了当的方法!对于任何苦苦挣扎的人,只需忘记在线教程并思考几分钟即可。如果您在这里,您的问题显然只是 .PEM 文件的创建,并且所有教程都使它看起来必须涉及多个文件和命令。只需将 Distribution Push aps_production.cer 导入 Keychain Access,在 Keychain Access 中找到它并展开它,以便看到私钥,同时选择“Export 2 items”作为 .p12 文件。上传到服务器,SSH 并在上面运行 openssl 命令 - 完成!漂亮。

以上是关于ApnsPHP:在开发中工作但不在生产中的推送通知的主要内容,如果未能解决你的问题,请参考以下文章

NuxtJS:在开发中工作但在生产中工作的路由(netlify)

推送通知在开发中工作正常,但设备在生产中没有收到通知

如何使推送通知在 iOS 的生产环境中工作?

获取在 HTML 页面中工作但不在 JS 中工作 [重复]

请求在CURL中工作但不在Ajax中工作

CoreLocation 应用程序在模拟器中工作但不在设备上