Send Push Notifications to Windows Phone 7 from PHP
I couldn’t find a library for sending Push Notifications to Windows Phone 7 from PHP. Most samples were using an ASP.NET web service. For those of us who would like to run Push Notifications from cheaper PHP and cURL enabled hosting, I’ve created a little helper class: (The XML may be break below, so here is the Text Version)
class WindowsPhonePushPriority { const TileImmediately = 1; const ToastImmediately = 2; const RawImmediately = 3; const TileWait450 = 11; const ToastWait450 = 12; const RawWait450 = 13; const TileWait900 = 21; const ToastWait900 = 22; const RawWait900 = 23; } class WindowsPhonePushClient { private $device_url = ''; private $debug_mode = false; function __construct($device_url) { $this->device_url = $device_url; } public function send_raw_update($msg, $priority = WindowsPhonePushPriority::RawImmediately) { return $this->_send_push(array('X-NotificationClass: ' . $priority), $msg); } public function send_tile_update($image_url, $count, $title, $priority = WindowsPhonePushPriority::TileImmediately) { $msg = "< ?xml version=\"1.0\" encoding=\"utf-8\"?>" . "<wp :Notification xmlns:wp=\"WPNotification\">" . "</wp><wp :Tile>". "</wp><wp :BackgroundImage>" . $image_url . "</wp>" . "<wp :Count>" . $count . "</wp>" . "<wp :Title>" . $title . "</wp>" . " " . ""; return $this->_send_push(array( 'X-WindowsPhone-Target: token', 'X-NotificationClass: ' . $priority, ), $msg); } private function send_toast($title, $message, $priority = WindowsPhonePushPriority::ToastImmediately) { $msg = "< ?xml version=\"1.0\" encoding=\"utf-8\"?>" . "<wp :Notification xmlns:wp=\"WPNotification\">" . "</wp><wp :Toast>" . "</wp><wp :Text1>" . $title . "</wp>" . "<wp :Text2>" . $message . "</wp>" . "" . ""; return $this->_send_push($url, array( 'X-WindowsPhone-Target: toast', 'X-NotificationClass: ' . $priority, ), $msg); } private function _send_push($headers, $msg) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->device_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, // Add these headers to all requests $headers + array( 'Content-Type: text/xml', 'Accept: application/*' ) ); curl_setopt($ch, CURLOPT_POSTFIELDS, $msg); if ($this->debug_mode) { curl_setopt($ch, CURLOPT_VERBOSE, $this->debug_mode); curl_setopt($ch, CURLOPT_STDERR, fopen('debug.log','w')); } $output = curl_exec($ch); curl_close($ch); return array( 'X-SubscriptionStatus' => $this->_get_header_value($output, 'X-SubscriptionStatus'), 'X-NotificationStatus' => $this->_get_header_value($output, 'X-NotificationStatus'), 'X-DeviceConnectionStatus' => $this->_get_header_value($output, 'X-DeviceConnectionStatus') ); } private function _get_header_value($content, $header) { return preg_match_all("/$header: (.*)/i", $content, $match) ? $match[1][0] : ""; } }
This code supports sending all three types of push notifications, Tile, Toast and Raw.
To use the class, simply include the file and call the constructor with the Device URL, which has already been uploaded to your server from the devices themselves.
Comments
17 Comments on Send Push Notifications to Windows Phone 7 from PHP
-
olivier on
Thu, 25th Nov 2010 11:23 AM
-
Ram on
Tue, 14th Dec 2010 10:46 AM
-
Dave on
Tue, 11th Jan 2011 3:36 PM
-
Jeff on
Tue, 11th Jan 2011 4:46 PM
-
Dave on
Tue, 11th Jan 2011 4:59 PM
-
Jeff on
Tue, 11th Jan 2011 5:02 PM
-
Jeff on
Tue, 11th Jan 2011 5:06 PM
-
Dave on
Tue, 11th Jan 2011 5:08 PM
-
Jeff on
Tue, 11th Jan 2011 7:05 PM
-
Jeff on
Tue, 11th Jan 2011 8:07 PM
-
Dave on
Tue, 11th Jan 2011 8:10 PM
-
Jeff on
Tue, 11th Jan 2011 9:01 PM
-
Dave on
Tue, 11th Jan 2011 9:03 PM
-
olivier on
Thu, 13th Jan 2011 9:51 AM
-
billy riantono on
Fri, 25th Mar 2011 2:55 AM
-
cubed on
Thu, 16th Feb 2012 7:44 AM
-
Ken on
Mon, 20th Feb 2012 9:35 PM
Hy,
Thank you for your code, I have been looking for a while for a php solution to send push.
But, I have a problem with your code, I receive the notification but can’t read id.
I have an exception at : “string notificationText = reader.ReadString();”
Got raw notification:
‘taskhost.exe’ (Managé) : ‘System.SR.dll’ chargé
Une exception de première chance de type ‘System.IO.EndOfStreamException’ s’est produite dans mscorlib.dll
System.IO.EndOfStreamException: Unable to read beyond the end of the stream.
à System.IO.__Error.EndOfFile()
à System.IO.BinaryReader.ReadString()
I can’t find where it come from.
I home you can help me :)
Thanks — excellent starting point. I had to fix a few minor things to make it work:
1) send_toast needs to be changed to “public”
2) the call to the private function _send_push from send_toast needed to have the extra parameter removed
3) the XML needed to be fixed (I think Microsoft may have changed the specification since this was published) — the specs for the correct XML are at http://msdn.microsoft.com/en-us/library/ff402545%28VS.92%29.aspx
@Ram -
I’ve updated the code, but I didn’t need to change the XML. This code is live and working great, can you be more specific about what wasn’t working?
Dave, is there any chance you can include code in an example form? So taking your script and actually showing how you call it? I posted your code above and even though I didn’t get any errors, I didn’t get a notification on my phone either…
Thanks!
@Jeff –
Examine the response code from the method that sends the notification.
$cli = new WindowsPhonePushClient(‘http://sb1.live.net….’);
var_dump($cli->send_toast(‘title’,'message text’);
There really isn’t much to it. Make sure you have the right URL for your device.
@Dave –
array(3) { ["X-SubscriptionStatus"]=> string(7) “Expired” ["X-NotificationStatus"]=> string(7) “Dropped” ["X-DeviceConnectionStatus"]=> string(12) “Disconnected” } var_dump
What does this mean?
@Dave –
I tried again after I changed the following in my app:
myChannel = HttpNotificationChannel.Find(“OilChangeAppNotify”);
After putting in the new URI I got this:
array(3) { ["X-SubscriptionStatus"]=> string(6) “Active” ["X-NotificationStatus"]=> string(10) “Suppressed” ["X-DeviceConnectionStatus"]=> string(9) “Connected” } var_dump
@Jeff -
Check out this page for the meaning behind those response codes: http://msdn.microsoft.com/en-us/library/ff941100(VS.92).aspx
It looks like you have not called BindToShellToast.
After your Find call, you’ll want something like this:
if (!_channel.IsShellToastBound) _channel.BindToShellToast();
I suggest you grab the sample projects from MSDN for push notifications, they have some good code that sets up the channel properly.
@Dave – That looks to be the issue. I have successfully received a Toast message in the emulator using your script! That is awesome!
Thanks!
@Dave – Quick question… Is there a way to send a notification to a specific phone? I have the ANID…
Thanks!
@Jeff – the only way to send a notification to a phone i via the URL provided when opening a notification channel. I don’t believe it is possible to send a notification by knowing only the ANID.
Does the app generate a unique URI for every install?
Yes, each channel subscription, on each device, has a unique URL.
Thanks for the update :)
I’ll try it soon.
Thanks this code work perfectly for me :)
Super Sache, funktioniert sehr gut! Vielen Dank dafür! Hat mir echt eine Menge Kopfzerbrechen erspart!!
Have you thought of adding support for https so that you are not limited to the 500 per day? I’ve tried without luck to get php code that can send a certificate to the servers in a manner that they would accept it.
