Skip to content

Instantly share code, notes, and snippets.

@samvermette
Created December 30, 2010 07:40
Show Gist options
  • Star 50 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save samvermette/759564 to your computer and use it in GitHub Desktop.
Save samvermette/759564 to your computer and use it in GitHub Desktop.
Quickly send an Apple Push Notification using PHP
<?php
$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsCert = 'apns-dev.pem';
$apnsPort = 2195;
$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
$payload['aps'] = array('alert' => 'Oh hai!', 'badge' => 1, 'sound' => 'default');
$output = json_encode($payload);
$token = pack('H*', str_replace(' ', '', $token))
$apnsMessage = chr(0) . chr(0) . chr(32) . $token . chr(0) . chr(strlen($output)) . $output;
fwrite($apns, $apnsMessage);
socket_close($apns);
fclose($apns);
@daanlemmen
Copy link

I got these errors:

Warning: stream_socket_client() [function.stream-socket-client]: SSL operation failed with code 1. OpenSSL Error messages: error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown in /home/daanle1q/public_html/Push/push.php on line 9

Warning: stream_socket_client() [function.stream-socket-client]: Failed to enable crypto in /home/daanle1q/public_html/Push/push.php on line 9

Warning: stream_socket_client() [function.stream-socket-client]: unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Unknown error) in /home/daanle1q/public_html/Push/push.php on line 9

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/daanle1q/public_html/Push/push.php on line 15

Warning: socket_close() expects parameter 1 to be resource, boolean given in /home/daanle1q/public_html/Push/push.php on line 17

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/daanle1q/public_html/Push/push.php on line 18

What am I doing wrong?

@slowbrewedmacchiato
Copy link

@daanlemmen

It seems that the certificate you provided could not be found. Have you obtained a Push Certificate from apple? What name did you give to it? Where is it stored and what's its path relative to your code? Once you've got all of those resolved, replace line 2 by the path and actual name of your certificate. This code should work without an issue. Also, as @OskarStark did point out, do not forget the semicolon at the end of line 13.

Good luck!

@vasuj
Copy link

vasuj commented Sep 16, 2013

Same issue facing @janporu-san as above mentioned added semicolon and renamed the push notification certificate also but issue is not resolved what could be the cause for it

@hswong3i
Copy link

hswong3i commented Sep 9, 2014

My updated version, tested with PHP5.5 + Cordova PushPlugin:

<?php

$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsCert = 'ck.pem';
$apnsPort = 2195;
$apnsPass = '<PASSWORD_GOES_HERE>';
$token = '<DEVICE_TOKEN_GOES_HERE>';

$payload['aps'] = array('alert' => 'Oh hai!', 'badge' => 1, 'sound' => 'default');
$output = json_encode($payload);
$token = pack('H*', str_replace(' ', '', $token));
$apnsMessage = chr(0).chr(0).chr(32).$token.chr(0).chr(strlen($output)).$output;

$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);
stream_context_set_option($streamContext, 'ssl', 'passphrase', $apnsPass);

$apns = stream_socket_client('ssl://'.$apnsHost.':'.$apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);
fwrite($apns, $apnsMessage);
fclose($apns);

@samayananthan
Copy link

this code i am using but not work please help me

function pushnotification()
{
echo "sucess";
$deviceToken='974eb97d262c6a74e22ee7a632b1444d109956f7e48b44255aff1681bbc1d741';
$message="moadmin";
$payload= '{
"apps" :
{
"alert":"'.$message.'"
"badge":1,
"sound":"bingbong.aiff"
}

        }';
   $ctx=stream_context_create();

// stream_context_set_option($ctx, 'ssl', 'local_cert', './certs/ck.pem');
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
//stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
// $fb=stream_context_set_option($ctx,'ssl','passphrase','1234');
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
// $fp=stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195',$err,$errstr,60,STREAM_CLIENT_CONNECT,$ctx);
if ($fb) {
print "Failed to connect $err $errstr";
return;
}
else
{
print "Notification sent";
}

   $devarray=array();
   $devarray=$deviceToken;
   foreach ($devarray as $deviceToken) {
    $msg=chr(0).pack("n",32).pack('H*',str_replace('','',$deviceToken)).pack("n",strlen($payload)).$payload;
       print"$sending message :".$payload."n";
      fwrite($fp,$msg);


   }
  fclose($fp);

}
}

@KushThakkar
Copy link

$apnsCert = 'ck.pem';

change this line with below line:

$apnsCert = dirname(FILE).'/abc.pem';

@shramee
Copy link

shramee commented Jun 13, 2017

Will this work from localhost?

@andreszs
Copy link

This code is obsolete, for the Legacy APNS interface.

@shayo
Copy link

shayo commented Jul 25, 2017

@andreszs , is there a solution for non legacy interface?

@hfarhanahmed
Copy link

How can we test if the push is successfully sent, I am using this code, the code runs without any error but the push is not received on ios device.

@andreszs
Copy link

andreszs commented Jun 20, 2018

The previous code has serious flaws with the packaging of bytes, Try this instead:
http://www.kubilayerdogan.net/sample-apple-push-notification-php-script/

Or just update the existing sample with this code, which works just fine:

/* original code until line 8 goes here */

// Better payload with title and body; for silent push omit 'alert' and 'sound'
$payload['aps'] = array(
	'alert' => array(
		'title' => 'Sample push number ' . mt_rand(100, 999),
		'body' => 'Sample push body goes here'
	),
	'badge' => 9,
	'sound' => 'default',
	'my_value_1' => 'more data',
	'my_value_2' => 'even more data'
);

// JSON-encode payload
$output = json_encode($payload, JSON_NUMERIC_CHECK);

// Cancel if payload too long
if(strlen($output) > 2048){
	die('Payload too long ('.strlen($output).'): Aborted');
}

// Build the binary notification (correctly)
$token = pack('H*', str_replace(' ', '', $token)); /* str_replace useless since token does not appear to have spaces? */
$apnsMessage = chr(0).pack('n', 32).$token.pack('n', strlen($output)).$output;

// Send it to the server
$result = fwrite($apns, $apnsMessage, strlen($apnsMessage));

// Result returns number of bytes sent on success, false otherwise
if(intval($result) > 0){
	// Push sent
	$response = $result.' bytes sent. $payload size is: '.strlen($output).' (payload limit is 2048 bytes)';
	fclose($apns);
}else{
	// Push failed
	$error = error_get_last();
	$response = (is_array($error) ? $error['message'] : 'undefined error');
}

// Show result
die($response);

@imhsgoraya
Copy link

@andreszs, i m getting "undefined error" can you help what is the issue ?

@bhavin-chauhan
Copy link

bhavin-chauhan commented Mar 12, 2019

got some errors
Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection timed out) in /customers/d/b/3/server.com/httpd.www/app/apn-server.php on line 18 Warning: fwrite() expects parameter 1 to be resource, boolean given in /customers/d/b/3/server.com/httpd.www/app/apn-server.php on line 19 Warning: fclose() expects parameter 1 to be resource, boolean given in /customers/d/b/3/server.com/httpd.www/app/apn-server.php on line 20
Can anyone suggest what's wrong with this server.
If there is any restrictions from server then let me know what should I do.

@Harithareddykuram
Copy link

i am getting fwrite(): send of 92 bytes failed with errno=10053 An established connection was aborted by the software in your host machine. this error please help me.

@MOBitooT
Copy link

I am getting same errors as you @bhavin-chauhan. Did you manage to get this issue fixed?

Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection refused) in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 17
Warning: pack(): Type H: illegal hex digit h in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 34

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 35

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 42

Warning: Cannot modify header information - headers already sent by (output started at /home/mandin/public_html/vadmin2/send_broadcast_dev.php:42) in /home/mandin/public_html/vadmin2/common.php on line 977

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 35

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 42

Can anyone help please???

@bhavin-chauhan
Copy link

I am getting same errors as you @bhavin-chauhan. Did you manage to get this issue fixed?

Warning: stream_socket_client(): unable to connect to ssl://gateway.sandbox.push.apple.com:2195 (Connection refused) in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 17
Warning: pack(): Type H: illegal hex digit h in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 34

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 35

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 42

Warning: Cannot modify header information - headers already sent by (output started at /home/mandin/public_html/vadmin2/send_broadcast_dev.php:42) in /home/mandin/public_html/vadmin2/common.php on line 977

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 35

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/mandin/public_html/vadmin2/send_broadcast_dev.php on line 42

Can anyone help please???

My Server not allow me to open APN Port number, So Finally I've Used Firebase service for that task. It's easy to use and both android, iOS token can easily work now. Let me know if you need any help from my side.
Thanks!
Bhavin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment