I have the following PHP code to send Apple Push Notifications to my app:
<?php
$body = '{"aps":{"alert":{"title":"test title","subtitle":"","body":"test body"},"badge":0,"sound":"default","additional_data":"test additional_data"}}';
$context = stream_context_create();
stream_context_set_option($context, "ssl", "local_cert", "certificate.pem");
stream_context_set_option($context, "ssl", "passphrase", "HERE_COMES_THE_PASSWORD_OF_THE_certificate.pem_FILE");
$socket = stream_socket_client("ssl://gateway.sandbox.push.apple.com:2195", $error, $errstr, 30, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $context);
$msg = chr(0) . chr(0) . chr(32) . pack("H*", "HERE_COMES_MY_APPLE_PUSH_TOKEN") . pack("n", strlen($body)) . $body;
$result = fwrite($socket, $msg, strlen($msg));
fclose($socket);
?>
This code is stored on my server together with the certificate file called certificate.pem
.
I'm using this code unchanged since month without any problems. Today, I noticed, that I'm not getting push notifications any more.
The PHP error log shows the following:
[23-Mar-2022 11:39:45 UTC] PHP Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out) in /home2/kd37875/public_html/test/index.php on line 7
[23-Mar-2022 11:39:45 UTC] PHP Warning: fwrite() expects parameter 1 to be resource, bool given in /home2/kd37875/public_html/test/index.php on line 9
[23-Mar-2022 11:39:45 UTC] PHP Warning: fclose() expects parameter 1 to be resource, bool given in /home2/kd37875/public_html/test/index.php on line 10
First, I thought, there's something wrong with the certificate file. Then, I found this: https://www.pushtry.com website. If I insert the Device Token, upload the certificate.pem file, insert the Bundle ID and a message, I'm successfully receiving a push message in my app. (There's a field for password on the website but it's also working if I don't insert it. No idea, why.) So this says me, that the certificate.pem must be okay.
Do you have any idea what I'm doing wrong? Why doesn't it work any more? Did Apple change something?
I finally solved my problem. Apple made a change to this about a year ago. No idea why it affected me only today.
This is the working code:
<?php
function sendHTTP2Push($http2_server, $apple_cert, $app_bundle_id, $message, $token) {
if(!defined('CURL_HTTP_VERSION_2_0')) {
define('CURL_HTTP_VERSION_2_0', 3);
}
$http2ch = curl_init();
curl_setopt($http2ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt_array($http2ch, array(
CURLOPT_URL => "{$http2_server}/3/device/{$token}",
CURLOPT_PORT => 443,
CURLOPT_HTTPHEADER => array("apns-topic: {$app_bundle_id}"),
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => $message,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSLCERT => realpath($apple_cert),
CURLOPT_HEADER => 1
));
$result = curl_exec($http2ch);
if($result === FALSE) {
throw new Exception('Curl failed with error: ' . curl_error($http2ch));
}
$status = curl_getinfo($http2ch, CURLINFO_HTTP_CODE);
return $status;
curl_close($http2ch);
}
$status = sendHTTP2Push('https://api.development.push.apple.com', 'certificate.pem', 'HERE_COMES_THE_APPS_BUNDLE_ID', '{"aps":{"alert":{"title":"test title","subtitle":"","body":"test body"},"badge":0,"sound":"default","additional_data":"test additional_data"}}', 'HERE_COMES_MY_APPLE_PUSH_TOKEN');
echo "Response code: ".$status;
?>
Source: https://gist.github.com/valfer/18e1052bd4b160fed86e6cbb426bb9fc