I have been working with Apple’s Push Notification service recently and decided to make a library to send notifications with Haskell. It is very simple and has a few helpers to make notifications with an alert, sound, etc,.

ApplePush Hackage

ApplePush Documentation

When using the library, you must use an SSL tunnel, because Haskell’s SSL support is incomplete. I use stunnel4, which works great, and offloads the SSL processing as well. Here are some basic instructions on getting started with the library.

Stunnel setup

Download your certificate from Apple. If you are using a Mac, export the certificate (.cer) into a directory. Also, export your private key as a .p12 file. Stunnel needs the certificate/key in one file, in the following format:

-----BEGIN RSA PRIVATE KEY-----
YOUR KEY
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
YOUR CERTIFICATE
-----END CERTIFICATE-----

Run the following commands to convert and concatenate your certificate/private key.

openssl x509 -in cert.cer -inform DER -outform PEM -out cert.pem
openssl pkcs12 -in key.p12 -out key.pem -nodes
cat key.pem cert.pem > certs.pem

Create a file called tun.conf, which will configure stunnel.

client=yes
debug=5
foreground=no
pid=tun.pid
[service]
accept=2195
connect=gateway.sandbox.push.apple.com:2195
cert=certs.pem

This will bind stunnel to the local port 2195, and tunnel traffic via SSL to gateway.sandbox.push.apple.com:2195.

Next run the following command to start stunnel.

stunnel tun.conf

ApplePush Haskell Library

Let's update our cabal packages, and then install.

cabal update
cabal install ApplePush

In addition to the library, an application, called applepushtest, is also installed so that you can test the library and your SSL tunnel setup. Let's try it out.

c10k:~ chris$ ~/.cabal/bin/applepushtest 
Apple Push Test, Version 0.1
usage: applepushtest device_token(hex)

You must pass a parameter, device_token, to the application. This tells the library which device to send the notification to. This token must be retrieved in your client application using registerForRemoteNotificationTypes:. Once you have your token, run the following command.

c10k:~ chris$ ~/.cabal/bin/applepushtest (yourtoken)
Device Token: (yourtoken)
Message> hey
Message> whats up?
Message> test!!
Message> 

To use the library in your application, check out Main.hs for an example.