Coding Passbook: Lessons Learned

We recently released BillGuard for Passbook, being among the first few to integrate with Passbook. For us, adding Passbook support to our product was a bit of a whim and we deployed our first version 48 hours after starting to work on it.

For the sake of those of you that decided to join in on the Passbook party and create your own passes we present here some of the pitfalls we ran into. As with every new and fangled thing, Passbook is still rough around the edges and surely you’d rather work on actual features and reduce the time spent on just getting the damn thing to work, right?

Without further ado, let’s dive in to the nitty gritty gotchas!

Technical Gotchas

Signing correctly

First of all, you’ll need to request a certificate for your pass type identifier through the Apple Developer Portal. For that certificate, export a p12 file from Keychain Access. Then, you’ll need to turn the p12 into a pem file. This script does that and some more and really helped us getting started.

It is not enough to sign the passes with the certificate you get from Apple’s site. The signing should also include the WWDR intermediate certificate. You can get the WWDR certificate here, and then convert it to a pem file (e.g. using KeyChain). Equipped with that you can now easily sign your passes. For example:
If you fail to sign correctly, you will get the “Add does nothing” situation described below, with the error “Manifest signature did not verify successfully” in the console.

Tapping “Add” when opening the pass on your iPhone does nothing?

First, connect your iPhone to a mac with a USB cable. Then open the phone’s console using Xcode (open Xcode, shift+command+2, pick your phone, console). Now when you click on “Add” you should see an error in the console that’ll hopefully help you understand the problem.

“Manifest didn’t parse” errors on the device’s console?

Funny enough, we encountered this because some hand crafted JSON contained single-quote strings instead of double-quote ones. Although that works pretty much everywhere, it’s against the JSON standard and the iPhone just balks at these.

Passes won’t work with invalid webServiceUrls

The webServiceUrl isn’t mandatory, but if you specify it then make sure it’s a valid one. For example, “TODO TODO TODO” won’t work and you won’t be able to add the pass to your device (learned that the hard way). Also, unless you enable it (from the Developer section under Settings app), you won’t be able to add a pass with a webServiceUrl scheme that’s “http://” and not “https://”. If the URL is not a valid URL, the pass attachment won’t even appear as a pass in Mail.app and won’t have an option to be opened with Passbook. In case the scheme is “http://” the pass would open but tapping on “Add” fails with the error “Invalid data error reading card passTypeIdentifier. scheme of webServiceURL ‘http://example.com’ needs to be an https rather than http” in the console.

Updating Passes and Push Notifications

We took to updating passes in several releases:

Not updating passes at all

As already mentioned, our first release of BillGuard for Passbook was after 2 days of work. Having a tight schedule, we decided to first release the passes without any updates. We just made sure that the passes contained a valid webServiceUrl that we can later update to actually work. In retrospect this wasn’t such a good decision as it made us lose the ability to update several of the early passes later on. Even if you don’t care at all about updates at this point, it might be a good idea to implement the following endpoints:

  • Register, so you can communicate with the device later on
  • Unregister, to keep your registration info up-to-date
  • Log. Devices will send debug information to this endpoint for your convenience. Forwarding these logs to your application log can be very useful later on for debugging, and sometimes reveal issues that are missing from the documentation

Enabling pull-to-refresh updates

Users can manually update a pass by turning to its back side and pulling-to-refresh. All you need to do in order to support this is respond to the update endpointwith the updated pkpass file.

Sending updates as they come using Push Notifications

Implementing the full update mechanism is pretty straight-forward. One aspect that may be a bit confusing is the use of push notifications to send an update to a device. What’s important to understand is that the push notifications used here are simply a means of communication to a device, signaling it to check for updates. Passbook push notifications, unlike regular ones, do not contain any data about changes. In fact, the notification causes the device to refetch all updated passes as a whole, and checks what changed in them by itself.

A useful way of making sure you’re using the right certificate, is opening it in Keychain Access and validating it contains your Pass type ID as its common name. That’s how Apple knows this push notification is for passbook-updating purposes, and which pass type needs an update.

Passbook Certificate

Using the java-apns library, here’s our code for sending push notifications:

The example above uses a p12 file (which combines your pass type identifier certificate and private key). Other frameworks may take in the certificate and private key files separately.

Once the push notification arrives at the device, the device should contact the get-changed-passes-of-device endpoint, which returns the list of passes that have changed since the previous request to the same endpoint. After that, the device updates each of these passes using the previously mentioned update endpoint, easy!

Layout and Appearance

Even though the format for passes seems limiting, there are many little tricks that can be leveraged to create great looking passes.

When testing your pass, do not rely on the rendering of OSX when clicking on a pass as it tends to mess up with some layouts, where an actual device or the simulator would render them just fine.

Front of the card

  • The pass type that you choose will appear in the email of the pass, so be aware of that in case you’re contemplating (ab)using the wrong pass-type for better layout options:
  • When you do chose a card type, make sure to carefully look at what is the set of fields and images supported by this specific card type.
    A good resource for that is the visual specification from the Apple doc
  • Passes automatically add a white border around the thumbnail.png image for Generic type passes. We couldn’t find any way around this.

Back of the card

The back of the card is pretty much text only but there are a few tricks to make the most of it:

  • Urls and phone numbers turn into links
  • Even though it is not specified in Apple’s documentation, you can use add tabs in the text with two ‘t’.
  • From our experiments, it seems that the font size for each area is calculated separately based on its longest line.
  • When rendering a table with dynamic content, it is helpful to have a line with the maximum number of characters you want to allow for, that way the rendering engine will be forced to calculate
    the font size consistently based on this line. In our case, we took advantage of long URLs to serve this purpose.

Links to Helpful Resources

  • The best non-Apple article about pass structure we found: link
  • Apple documentation: link
  • The “Introducing Passbook” session from WWDC 2012: link

Leave a Comment