Beginning Passbook in iOS 6: Part 1/2
Note from Ray: This is the second iOS 6 tutorial in the iOS 6 Feast! This tutorial is an abbreviated version of one of the chapters from our new book iOS 6 By Tutorials. Marin Todorov wrote this chapter – the same guy who wrote most of the “bonus” chapters in iOS 5 by Tutorials. […] By Marin Todorov.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Beginning Passbook in iOS 6: Part 1/2
45 mins
- Part 1: Understanding and building Passes
- Passes are everything in your pocket
- What makes a pass, a pass
- Do I board with this pass, or do I get a free coffee?
- The guts of the pass
- Let’s write some JSON!
- Get me the certificate!
- Passes come in style this year!
- Time to make it beautiful, baby!
- The pass manifest
- Can I have your signature, please?
- Show me or I don’t believe it!
- Where to go from here?
The guts of the pass
This section will introduce the building blocks for a pass. A pass comes to the user as a file with a .pkpass extension. (“pkpass” standing for PassKit Pass – totally makes sense, right?)
The .pkpass file is just an ordinary .zip file with a custom extension. If you rename one to ZIP and extract it, you’ll find several files. Here are the contents of the Free Hug Pass you saw earlier:
- pass.json – the description of the pass information fields, their content, and meta information.
- manifest.json – the file that describes the list of files inside the pass and the SHA1 checksums of each of those files.
- signature – a detached DER signature of manifest.json, generated using an Apple-provided certificate.
- background.png – the image to show on the front of the pass.
- background@2x.png – the retina-sized image for the front of the pass.
- logo.png – the logo to show in the pass header. Apple recommends a solid one-color logo. The image size is up to you, but the height shouldn’t be more than 50px in order to fit inside the header.
- logo@2x.png – the retina counterpart of logo.png.
- icon.png – a small icon for the pass, used when the pass comes as an attachment in Mail. As of the time of writing, there is still no documentation about the icon’s size, but it looks to be 29×29 pixels (bigger size icons are scaled down, so they look fine as well).
- icon@2x.png – the retina icon file.
- strip.png and strip@2x.png – the image strip, used as background behind the primary fields; used only for the coupon and store card passes.
And that’s all!
As you can see, the main file of the pass is the JSON file pass.json. Inside it you declare all the contents of the front and back of the pass. Along with this JSON file, you provide all images the pass should display (in the case of a coupon, you can supply only background.png and its retina counterpart). Finally, you need a manifest file, which states the original SHA1 checksums of all those files above, and a detached signature signed by you, so that Passbook can verify that the pass hasn’t been amended since you created it.
Let’s write some JSON!
You’re at the point where you can write some code. Let’s see if you can reproduce the Free Hug coupon!
But wait! JSON isn’t Objective-C. It’s not even a programming language of any sort. It’s just a markup language used to describe data structures… So, how do you write JSON? Actually, you can use any text editor – Xcode, TextMate, Coda or even TextEdit. In this chapter, you’re going to use Xcode.
From Xcode’s menu choose File/New/File… and then choose iOS/Other/Empty for the file type. Name the new file pass.json and save it in a folder of your choice. Note you probably want to create a new folder to store the pass in, because you’ll be putting a lot of pass-related files in the same folder and it will be nice to keep it all together.
You should now be looking at a tragically empty window, like this one:
But’s that’s OK – no worries!
For those of you not familiar with JSON notation – it’s pretty easy. You can use numbers, strings, arrays, and dictionaries. The information is written out like this:
14.37457 – for numbers
“Some text here!” – for strings
[object1, object2, object3, …] – for arrays
And:
{“key1”: object1, “key2”: object2, “key3”: object3, …} – for dictionaries
Object1, object2, object3 and so forth can be any of the four types of objects above – i.e. you can have arrays of dictionaries, dictionaries that hold arrays, strings, numbers, and so on.
You can read more on JSON here: http://en.wikipedia.org/wiki/JSON
Note: You might notice that Apple’s proprietary plist file format stores the same types of primitive data that JSON stores – arrays, dictionaries, numbers, and the like. You might wonder why Apple chose to use JSON instead of the plist file format we all know and love.
Well, passes are most likely to be generated in an environment that is not iOS or OS X – most likely, passes will be generated on a web server in response to a request from a user. Therefore Apple wanted to make it easier for you to generate passes in all possible web-scripting languages, and since JSON is well-supported in PHP, .NET, Ruby, Python and so forth, in the end JSON probably seemed like the best choice.
Note: You might notice that Apple’s proprietary plist file format stores the same types of primitive data that JSON stores – arrays, dictionaries, numbers, and the like. You might wonder why Apple chose to use JSON instead of the plist file format we all know and love.
Well, passes are most likely to be generated in an environment that is not iOS or OS X – most likely, passes will be generated on a web server in response to a request from a user. Therefore Apple wanted to make it easier for you to generate passes in all possible web-scripting languages, and since JSON is well-supported in PHP, .NET, Ruby, Python and so forth, in the end JSON probably seemed like the best choice.
Let’s start with the barebones of the Free Hug coupon! Copy this code into your pass.json file:
{
"formatVersion" : 1,
"passTypeIdentifier" : "pass.com.yourdomain.couponfreehug",
"serialNumber" : "001",
"teamIdentifier" : "<YOUR TEAM IDENTIFIER>",
"organizationName" : "Free Hugs LLC",
"description" : "Coupon for 1 Free Hug"
}
This is the bare minimum of meta-information you need to provide:
- formatVersion – the file format version, and since this is a brand-new file format, you’re using 1 (note that 1 is a number; if you provide a string for the value, the file won’t validate).
- passTypeIdentifier – this is the identifier of the Pass. It’s pretty similar to the bundle identifier in an iOS app. More will be said about this identifier in a minute.
- serialNumber – this is the serial number of the pass. You generate this number any way you like – it can be numeric, like “00193” (note that it still needs to be written out as a string value), or a combination of letters and numbers, like the serial numbers you’ve seen on airplane boarding passes (for example, “XS83A”).
- teamIdentifier – this is the unique 10-character identifier Apple assigns to you as an iOS developer. If you’ve been creating your own iOS apps, you should already be familiar with it. To find your team identifier, log onto the iOS Member Center and click the name of your organization. You will find it there next to a label titled “Company/Organization ID”. I’ll show you another way to find it later on as well.
- organizationName – the name of the issuing entity.
- description – a short description of the pass.
This is a lot of information, so let’s see how is it useful to Apple.
Since the passes are not necessarily connected to an iOS app, there’s no automatic way for Apple to connect a pass to a given iOS developer account (which it needs to do to validate the pass contents). Passes might arrive to the user’s device independent from an app, via mail or web download (or another way). This is why the teamIdentifier is included in the meta information inside the pass – to connect the pass instance to an iOS developer.
Once Apple knows the identity of the developer who created the pass, they take the passTypeIdentifier to figure out which type of pass it is (of all the ones defined by a given developer account). Every pass type has its own certificate, so Apple can use this certificate and validate the signature included in the pass bundle – i.e., make sure nobody tampered with the pass contents.
Finally, the serial number is used to identify the unique instance issued for the given pass type.
To recap, consider an example:
- Joe’s Café has an iOS developer account with Apple. Thus, they use their team identifier on all their passes.
- They have store cards with preloaded store credit, which users can use to order yummy coffees in the shop. Store cards have passTypeIdentifier “pass.com.joescafe.storeCard”.
- They also have discount coupons that have a different passTypeIdentifier – “pass.com.joescafe.discountCoupon”.
- A given user can own more than one store card (for example, they bought one and a friend gave them one as a present), so the serial number is used to distinguish between two store cards of the same pass type (for example, “0134” and “0274”).
- Passes from the same passTypeIdentifier will be grouped together inside Passbook. When the user is at Joe’s Café, they’ll tap the stack of Joe’s Café store cards in Passbook, and choose the one they want to use – probably the one that still has credit on it!
By now you should understand pretty well how pass identification works. So “pass” this section and move on to the next, where you’ll create your first pass type.