ApnsPHP: Push notifications working in development but not in production
Asked Answered
Z

1

4

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.

Zoophyte answered 26/9, 2013 at 15:4 Comment(0)
Z
8

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.

Zoophyte answered 26/9, 2013 at 15:4 Comment(3)
Are you exporting a .p12 of the CERTIFICATE itself or the KEY for the certificate? Is that what you mean they shouldn't be handled similarly?Masera
My phrasing was kind of clumsy here - probably both certificates could be installed in the same way. In this last variant certificate is first installed in keychain (OSX) and then exported combined together with the key. Much less to go wrong this way.Zoophyte
HA! Thanks so much for this straightforward approach! For anyone struggling, just forget about the tutorials online and think the process out for a few minutes. If you're here, your problem is obviously just the creation of the .PEM file, and all the tutorials make it seem like this has to involve multiple files and commands. Simply import the Distribution Push aps_production.cer into Keychain Access, find it in Keychain Access and expand it so you see the private key, select both, "Export 2 items" as a .p12 file. Upload to server, SSH in & run openssl command above on it - DONE! Beautiful.Longhand

© 2022 - 2024 — McMap. All rights reserved.