Sample Apple Push Notification PHP Script

This is an old script that I used to use for sending notifications. I don’t remember the source, on the other hand, it has been modified a couple of times already.

Even though I could manage to send notifications with this script, the Apple server was rejecting the connection after the amount reaches more than 50. It was usually getting cut off around 70. So it needs to get some management for not sending in a loop, like threading or whatever.

<?php

// set time limit to zero in order to avoid timeout
set_time_limit(0);

// charset header for output
header('content-type: text/html; charset: utf-8');

// this is the pass phrase you defined when creating the key
$passphrase = 'my_secret_pass';

// you can post a variable to this string or edit the message here
if (!isset($_POST['msg'])) {
$_POST['msg'] = "Notification message here!";
}

// tr_to_utf function needed to fix the Turkish characters
$message = tr_to_utf($_POST['msg']);

// load your device ids to an array
$deviceIds = array(
'lh142lk3h1o2141p2y412d3yp1234y1p4y1d3j4u12p43131p4y1d3j4u12p4313',
'y1p4y1d3j4u12p43131p4y1d3j4u12p4313lh142lk3h1o2141p2y412d3yp1234'
);

// this is where you can customize your notification
$payload = '{"aps":{"alert":"' . $message . '","sound":"default"}}';

$result = 'Start' . '<br />';

////////////////////////////////////////////////////////////////////////////////
// start to create connection
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'MyAppGenerated.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

echo count($deviceIds) . ' devices will receive notifications.<br />';

foreach ($deviceIds as $item) {
	// wait for some time
	sleep(1);
	
	// Open a connection to the APNS server
	$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" . '<br />');
	} else {
		echo 'Apple service is online. ' . '<br />';
	}

	// Build the binary notification
	$msg = chr(0) . pack('n', 32) . pack('H*', $item) . pack('n', strlen($payload)) . $payload;
	
	// Send it to the server
	$result = fwrite($fp, $msg, strlen($msg));
	
	if (!$result) {
		echo 'Undelivered message count: ' . $item . '<br />';
	} else {
		echo 'Delivered message count: ' . $item . '<br />';
	}

	if ($fp) {
		fclose($fp);
		echo 'The connection has been closed by the client' . '<br />';
	}
}

echo count($deviceIds) . ' devices have received notifications.<br />';

// function for fixing Turkish characters
function tr_to_utf($text) {
	$text = trim($text);
	$search = array('Ü', 'Þ', 'Ð', 'Ç', 'Ý', 'Ö', 'ü', 'þ', 'ð', 'ç', 'ý', 'ö');
	$replace = array('Ãœ', 'Åž', '&#286;ž', 'Ç', 'Ä°', 'Ö', 'ü', 'ÅŸ', 'ÄŸ', 'ç', 'ı', 'ö');
	$new_text = str_replace($search, $replace, $text);
	return $new_text;
}

// set time limit back to a normal value
set_time_limit(30);
?>
  • mutkan

    slm bu yontemi apple kabul etmiyo sanirim, yani socket ac, socket kapa. DDOS olarak algiliyor diyolar.

    Keep your connections with APNs open across multiple notifications; don’t repeatedly open and close connections. APNs treats rapid connection and disconnection as a denial-of-service attack. You should leave a connection open unless you know it will be idle for an extended period of time—for example, if you only send notifications to your users once a day it is ok to use a new connection each day.

    https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html#//apple_ref/doc/uid/TP40008194-CH101-SW6

    • http://kubilayerdogan.net kubilay e.

      Merhaba,

      Bilgi için teşekkürler. 2 sene kadar önce kullandığım bir kod, yazıda da belirttiğim gibi bir süre sonra Apple sunucusu bağlantıyı otomatik olarak kapatıyordu. Gene de o süre zarfında 50-70 arası notification gönderilebiliyordu. Makalenin güncellenme tarihinin 2014 olduğu göz önüne alınırsa artık bu da pek mümkün değil sanırım.

      • mutkan

        Evt, ben dun denedim, direk 50 kisiden sonra gondermiyor, nette de bununla ilgili detayli bir kaynak bulamadim dogrusu, apple da birsey soylemiyor. Ben simdi 10000 kisiye nasil push gonderecegim?

        • http://kubilayerdogan.net kubilay e.

          Evet, bu noktada kaynak sıkıntısı büyük. Elimde bir model bulunmasa da bildiğim kadarıyla veritabanına notification gönderilecek idleri yazarak ve notification gönderildikçe bu tablodan kayıtları gönderildi olarak işaretleyerek yapanlar mevcut.

          Tabii cron job kullanarak bu işi yapan PHP scriptini düzenli olarak çağırmak gerekli.

          Tüm bunlardan kurtulmak için Parse gibi hazır bir servis de kullanılabilir.

          • mutkan

            Parse sdk ini kurmam gerekecek uyg. ve gunceleme cikmam lazim, yani uzun is ve de masrafli.

            Nette buldugum diger arkadasta, seni reddeden kullanicilara gondermeye calisiyosan o anda apple baglantini kesiyor diyor.

            http://www.yasinturkoglu.com/ios-da-uzaktan-bildirimler-nam-i-diger-apns-apple-push-notification-service-remote-notifications/#comment-7001

          • http://kubilayerdogan.net kubilay e.

            Ilginc bir iddia, uygun oldugumda deneyecegim. Fakat daha ilginc olan eger sadece bu durumda baglanti kopuyorsa benim her 70. kullanicim bildirimleri reddediyor, tuhaf bir istatistik. :)

            Bana kalirsa reddedenleri cikarsaniz bile 1000 kullaniciya duzenli notification gondermeye Apple’in izin verecegini sanmiyorum. Bir diger husus, device tokenini register eventinda alabiliyorsunuz, kullanici uygulama acilinca bildirimlere izin vermezse zaten token alamazsiniz, basta izin verip de sonradan gidip bildirimleri kapatacak kullanici da pek yoktur cunku siz daha bildirim gondermediniz ki bundan rahatsizlik duyup gidip kapatsinlar. Acilista izin verip sonra bildirim merkezinden kapatmak gibi bir hobileri varsa bilemeyiz. :)

            Bence zamanlanmis bir gorevle notification gonderilmemis tokenlara baglanti kopana kadar gonderip bu kayitlari gonderildi olarak isaretlemek en uygun cozum. Eger yukarida bahsi gecen iddia dogru degilse o an notification gonderemediginiz bir cihazi reddetti olarak isaretleyeceksiniz ve o kullanici gercekte reddetmedigi icin bir kullanicidan olacaksiniz.

  • gurnam

    Thanx buddy for this code.

  • GURPRITSINGH SAINI

    It worked like a charm and helped me to save so much time.

  • aaryan

    i m getting error “Failed to connect ” 0 please tell me what to do with this code