Messing up the Apple Push Notification Service - php

I have been developing an app that uses push notifications. I have been messing around ALOT trying to fix the stupid provisioning stuff, and I really don't know what's what anymore.
I managed to fix the whole development push notifications. And now, we are close to release. However, the switch to Production notification didn't go as smooth as expected. And I still don't really understand the whole provisioning-thing.
I thought I just had to switch out the .pem file with a new one, generated from a new .cer and .p12 file, aswell as remove the "sandbox" from the url it's trying to connect to. This just resulted in "Failed to connect: 0" in my .php sending the push.
.php
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'dp.pem')
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if(!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
After messing around with the .p12 and .cer and .cert and .pem and .mobileprovision .ipa, I really don't know what to do anymore.. Why do we have to convert to .pem and merge them? Is this REALLY the way Apple intended for us to do this? Or have I been following a pretty redicolus tutorial?
What .cer file do I need? Which profile should the app use? AppID vs provision vs device vs Certificate. What the hell.. Should I have to do anything other than switching to a new .pem file and remove the "sandbox". I have activated and downloaded the "Production Push SSL Certificate" from the portal, and generated my .pem file from that. I have tried reading up on this, but it is reeeally hard and a stupid setup! I'm sure I have done something wrong. But can't figure out what, where and why!

Push notification services - great tutorial, you will find php script + answer for all your questions.

Related

how to retrieve ck.pem file for push notifications php

Hi I'm having trouble sending push notifications from a cron job invoked php script. However the same script works when I invoke the script from the terminal so I know its a problem retrieving the ck.pem. When I hit the script from the terminal I just use the lines
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
to get the ck.pem and it works because the ck.pem file is right on my desktop and local. When I hit the script thats invoked by the cron job it does not have the ck.pem file locally so I uploaded the ck.pem file to the server so the php script invoked from the cron job could access it and this is the code I use to retrieve it
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', file_get_contents("http://www.website.com/Certificates/ck.pem"));
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
however I get the errors
PHP Warning: stream_socket_client(): Failed to enable crypto
PHP Warning: stream_socket_client(): unable to connect to
ssl://gateway.sandbox.push.apple.com:2195 (Unknown error)
PHP Warning: stream_socket_client(): SSL operation failed with code
1. OpenSSL Error messages:
and all these errors happen on the third line of code in the following segment:
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
So like I said Im pretty sure its because of the ck.pem file and I made sure that ports 2195 and 2196 are open so it is not that and I can't figure this out. Any help or suggestions would be greatly greatly appreciated!
Solved this answer with this stack overflow link: iOS push notification does not work when using crontab scheduler
I was retrieving the ck.pem file the wrong way

Unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error)

I have a question about Apples Push Service.
What do following warnings exactly mean?
Warning: stream_socket_client(): Failed to enable crypto in /opt/../xyz.php on line 150
Warning: stream_socket_client(): unable to connect to ssl://gateway.push.apple.com:2195 (Unknown error) in /opt/../xyz.php on line 150
I am using about 5 different php files for sending push (AddFriendPush, ChatMessagePush...) to the iOS Devices and they are working fine. But sometime I get these warnings and I don't know what they mean but push doesn't work when I get these warnings..
I know that they can appear if your pem file is wrong or the port 2195 is blocked. But push works sometimes and sometimes it doesn't. So the pem file has to be right and the port can't be blocked.
I know it is not good to have 5 different scripts for push, I will change it soon.
Do you have any idea what is going on?
My php scripts look like this:
function sendPush($deviceToken, $msg)
{
$deviceToken = $deviceToken;
$passphrase = 'passhrase';
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'Production.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
$fp = stream_socket_client(
'ssl://gateway.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp) {
unset($con);
exit();
}
//do the other stuff
//Close the connection to the server
fclose($fp);
}

'Unable to set private key file' attempting to send push using php

I'm using the Ray Wenderlich push tutorial as a reference to set up push for my app, something I have done dozens of times before, literally dozens, and its always gone smoothly, until now.
When executing the php file to manually test sending the push I'm getting the error:
'Unable to set private key file ... ck.pem'
at the last line:
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
ck.pem is a concatentation of the ssl certificate and private key and I CAN use these sussesfully with the following command:
openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCert.pem -key PushKey.pem
When I execute this I get a big spiel and output regarding SSK handshake reading/writing N bytes which indicates it was sucessful and thus the certificate and key must be valid.
So I don't understand why there is no problem using the certificate and key separately when used as arguments to the openssl command line above but there is when used in the concatenated from in the php file.
After getting the problem initially I deleted everything - I clearned out all the certificates and keys from the keychain, deleted all the provisioning profiles etc. The whole lot and started with a clean slate again to make sure I didn't make a mistake somewhere. Same results - keep getting the 'Unable to set private key file'.
I saw a past posting where somebody had the same problem and they solved it by executing the php file using sudo, but that didn't work for me.
Any suggestions, this is driving me mad, especially as I've done it before dozens of times previously sucessfully.
I had this once, after many hours of frustration I tracked the problem down to the fact that I was using TextEdit to edit the .php file's contents and TextEdit was inserting invisible characters.
Not at the end of the line, actually in the line itself i.e. if the original text in the Ray Wenderlich file is like this:
// Put your private key's passphrase here:
$passphrase = ‘cpushchat';
Then after using TextEdit to change the password it looked like this when you viewed it:
// Put your private key's passphrase here:
$passphrase = ‘mypassword';
But if you viewed it in a hex edited, what TextEdit has actually done was to insert invisible (invisible in the in the text viewer) characters like this:
// Put your private key's passphrase here:
$passphrase = ‘E28098mypassword';
Which resulted in the password being incorrect of course and thus leading to that message.

Correct way to reopen TCP connection with PHP after remote party closes?

I'm having issues reopening a TCP socket connection after its remotely closed. Specifically this is for Apple Push Notification service - when Apple encounters a device token from you that pairs with a device that deleted your application they close the secure TCP socket to their push gateway. I need to immediately reopen this connection (or start a new one) when this issue occurs so I can continue sending notification to other users who still do have the app installed. I have some code using which I try to sort this out but it's freezing my entire Apache server and I have to restart manually to get things running again and I have no idea why. Below is the code with which I attempt to reopen a socket with Apple:
if($error_response == "InvalidToken"){
$results .= "\ntried to restart";
fclose($fp);
usleep(20000);
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck_real.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', '****');
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
}

How to know whether .pem file is correct or not

I have created a .pem file to be used for Production push notification,
and uploaded in server.
But when sending push notification, it is giving error like this.
$fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx); not working, return failed.
what is this error, how to solve it.
Finally, how to know whether the .pem file is correct or not
You could use "certtool" from the GnuTLS binaries to validate the certificate (certtool -i --infile cert.pem). Windows binaries are also available.
I don't have an answer for your stream_socket_client problem. Make sure the context is initialized correctly, an example is shown in the documentation.

Categories