ApnsPHP: Push notifications working in development

2020-02-01 08:39发布

问题:

Yes: there are many duplicates to this question, but none of the answers helped.

I am following this great tutorial by Ali Hafizji on using APNS service for push notifications.

Testing APNS in development mode:

  • download aps_development.cer
  • export the private key for the certificate (aps_development_key.p12)

Then I combined the two using following commands (using terminal):

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

And (using ApnsPHP on server) I could successfully send a push-notification with this configuration:

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

A sidenote: i took the entrust_root_certification_authority.pem from https://github.com/jonathanrcarter/push2press, the correct address to look for it would probably be https://www.entrust.net/downloads/binary/entrust_2048_ca.cer (they are the same thing anyway).

In this case application was running in debug mode (on device, run from XCode) and everything was working fine.

Testing APNS in production mode:

To test APNS in production mode i archived the app for AdHoc distribution and installed it on device with iPhone Configuration Utility.

I followed the same procedure with aps_production.cer to make final_aps_production.pem.

Bang, the php script that is called to send push-notifications returned HTML Status Code 500.

The $push generation was of-course modified for production mode:

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

A quick look to /var/log/apache2/error.log indicated the problem:

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  ....

Googling around (there are many people having this problem) proved fruitless.

Many different advices, such even so bizzare as to change the file permissions of the directory holding the certificates to 775... none of the suggestions worked for me.

I have also tried this change in ApnsPHP/Abstract.php (suggested here: https://github.com/duccio/ApnsPHP/issues/29) but with no success.

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

That pesky ApnsPHP_Exception did not go away.

Of course i also made sure that when i was testing the production mode the correct device APNS token - device APNS tokens in debugging and production mode are not the same - was used.

Anyway: tokens can not be a problem since my notification sending script can't even connect to ssl://gateway.push.apple.com:2195.

Tried to connect ssl://gateway.push.apple.com:2195 via telnet just to make sure: connection was fine.

It became obvious: it is a certificate problem.

回答1:

It seems that aps_production.cer shouldn't be handeled the same way as aps_development.cer

Here comes the RTM moment.

Download and install certificate in the keychain (double clicking aps_production.cer)

Export a .p12 version of aps_production certificate (you also set a password here) from the Keychain Access.

Convert it to .pem format using this command (you will have to enter password here):

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

And voilà - everything started working and i am a happy camper again.

There are great tutorial-like instructions by Jeremy on how to export certificate & key here on SO.