Académique Documents
Professionnel Documents
Culture Documents
Contents
About Passbook 5
At a Glance 5 Passes Exist in a Larger Ecosystem 5 Passes Are Created as a Package 6 Passes Are Updated Using Push Notifications and Your Web Server 6 Your App Can Interact with Passes 6 See Also 6
Contents
The Back of the Pass Provides Additional Space for Text 26 Barcodes Link Passes to Your Records 28 Pass Colors Can Be Customized 29 Images Fill Their Allotted Space 30 Relevance Information Displays Passes on the Lock Screen 30 Passes Support Localization 33 Passes Are Cryptographically Signed and Compressed 35 Passes Are Distributed via Email, the Web, or Your App 36 Debugging Passes 36
Updating a Pass 37
Overview of the Communication 37 Devices Register for Updates 40 Your Server Sends a Push Notification When Something Changes 41 Devices Ask for Changed Serial Numbers 41 Devices Ask for Latest Version of Passes 43 Devices Display Change Messages 43 Best Practices 43
Updating a Pass 37
Figure 4-1 Interaction between the client and your server 38
About Passbook
Passes are a digital representation of information that might otherwise be printed on small pieces of paper or plastic. They let users take an action in the physical world. Passes can contain images and a barcode, and you can update passes using push notifications. The pass library contains the users passes, and users view and manage their passes using the Passbook app.
Server Client
A package format for creating passes. A web service API for updating passes, implemented on your server. An Objective-C API used by your apps to interact with the users pass library.
At a Glance
This document covers the key concepts of the Passbook technology and explains the ways you can use it.
Passes Are Updated Using Push Notifications and Your Web Server
Passes can be updated after you distribute them. Updates use the Apple Push Notification service to inform the device that a new version of the pass is available, and a web service that your server implements to provide the latest version of the pass. Relevant Chapter: Updating a Pass (page 37)
See Also
Local and Push Notification Programming Guide describes how to send push notifications. Passbook Package Format Reference describes the package format for defining passes. Passbook Web Service Reference describes the web service protocol for updating passes. Pass Kit Framework Reference describes the Objective-C API for interacting with the users pass library.
The Passbook support materials are available in the developer downloads area They contain fully-worked example passes, a command-line tool to help you sign passes during development, and a sample implementation of the web service.
In this tutorial, you will download and edit a sample pass, build it, and view it in the iOS Simulator app.
Next, the pass needs to describe the actual offer. This requires three levels of keys, as shown in Listing 1-2. At the top level, find the coupon key which indicates that this pass is a coupon. Its value is a dictionary that describes the coupon. At the second level, find the primaryFields key which shows text on the front of the pass for the offer. Its value is a dictionary that describes the contents of the field. At the third level, the key is a string that uniquely identifies the field within the pass, and the value and label contain text that appears on the pass. Change their values to describe the candy stores offer.
Listing 1-2
{ ... "description" : "Coupon for a free lollipop at Example Candy Store", "logoText" : "Example Candy Store",
"coupon" : { "primaryFields" : [ { "key": "offer", "value": "Free lollipop" "label": "On July 29" } ] }, ...
In the iOS Provisioning Portal, go to the Pass Type IDs section. Click the New Pass Type ID button. Enter the description and pass type identifier, and click Submit.
In the Pass Type IDs section of the iOS Provisioning Portal, click the Configure link next to the pass type identifier. Click the Configure button next to Pass Certificate . Follow the directions that are shown to generate a certificate signing request in Keychain Access, upload it to the iOS Provisioning Portal, and then download the certificate. After you download the certificate, you can delete the certificate signing request.
2. 3.
4.
Open Keychain Access and select your certificate. Select File > Get Info and find the Organizational Unit section under Details. This is your team ID. The pass type identifier appears in the certificate under the User ID section.
You can also find your team ID by visiting the Member Center and looking at your organization profile.
10
Listing 1-3
{
"description" : "Coupon for a free lollipop at Example Candy Store", "logoText" : "Example Candy Store", "coupon" : { "primaryFields" : [ { "key": "offer", "value": "Free lollipop" "label": "On July 29" } ] },
Open the Xcode project in the Passbook Support Materials for the signpass tool and build the project. Right-click on the signpass executable (in the Products folder) and select Show in Finder. Move the signpass executable to the Documents folder.
To sign and compress the pass, use the signpass tool to sign the pass package. In Terminal, run the following commands:
cd ~/Documents ./signpass -p ~/Lollipop.pass
11
This creates a signed and compressed pass named Lollipop.pkpass in the Documents folder. If the pass fails to build, check the pass.json file to make sure the JSON file is well formed. A common error is to misplace commas or braces.
When testing in the iOS Simulator app, errors are logged to the system log, which you can view with the Console app. If the pass doesnt display and add to Passbook, check the log for a description of what went wrong.
12
There are three major parts to the pass life cycle: creation, management, and redemption. Passbook handles the middle; it lets users view and manage their passes and provides lock screen integration. You are responsible for the two ends: creating passes and redeeming passes.
13
14
Dont try to expire or void a pass by pushing an update. Updates are not guaranteed to be delivered: the user may not have a network connection or may have disabled updates for the pass. Instead, update your database to indicate that the pass is invalid, and consult your database when the pass is redeemed. Additionally, your app should not remove expired passes without the users consent.
15
the pass is still valid. Scanning the museum pass doesnt change any state. In contrast, scanning a one-time-use coupon does change state: it voids the coupon. Without network access at the scanner, there is no way to get the latest state of the world before scanning or inform others of a state change after scanning.
16
The files that make up a pass are arranged in a package called the pass package. At the center of the pass is a JSON file named pass.json which defines the pass. The file contains information that identifies the pass, the text that appears on it, and other information about the pass. In addition to this file, you provide images and localization data. Figure 3-1 shows the directory structure for a sample pass that provides a background image an icon and a logo, and is localized in Spanish and Chinese. It has both at Retina and non-Retina sizes of the image assets, and a different version of background for the Chinese localization.
Figure 3-1 Directory structure of a sample pass
Most of your work in creating a pass is done by providing keys and values in the pass.json file.
17
The exact meaning of each pass type identifier is determined by you. You specify what types of pass an app can interact with as part of the apps entitlements. This allows you to have app-specific passes if you are developing multiple apps. A different certificate is used for signing passes with different pass type identifiers. This means that groups in your company that work with different types of passes dont need to share signing infrastructure, certificates, or private keys. The serial number is a string that uniquely identifies the pass within the scope of its pass type. The value for the serialNumber key in the pass specifies the serial number. The serial number is opaque to Passbook; you are free to assign it in whatever way makes sense. A monotonically increasing integer or a UUID are convenient ways to assign the serial number. The combination of pass type identifier and serial number is used throughout Passbook to uniquely identify a pass. Two passes of the same type with the same serial number are understood to be the same pass, even if other information on them differs. For example, when a pass is updated, the new version has the same pass type identifier and serial number as the old version, so the new version replaces the old version. The difference between pass type identifiers and serial numbers is similar to the difference between classes and instances of a class: pass type identifiers designate an abstract kind of thing, and serial numbers identify a specific concrete thing. For example, suppose an airline is creating passes for boarding passes and for its loyalty card program. All of the boarding passes you create have the same pass type identifier because theyre all the same type of pass, but each one has its own serial number. Loyalty cards have a different pass type identifier than boarding passes, because theyre a different type of pass.
18
Pass Design and Creation Pass Style Sets the Overall Visual Appearance
The description lets VoiceOver make your pass accessible to blind and low vision users. The value for the description key in the pass specifies the description. The description should start with a high-level term such as Membership card , Weekly coupon , or Bus ticket followed by one or two small pieces of information such as the coupons offer and the store where its valid. Dont try to summarize the entire contents of the pass, but include enough detail to let users distinguish between passes of the same type.
Boarding passes use the key boardingPass. This pass style is appropriate for passes used with transit systems such as train tickets, airline boarding passes, and other types of transit. Typically each pass corresponds to a single trip with a specific starting and ending point. Coupons use the key coupon. This pass style is appropriate for coupons, special offers, and other discounts. Event tickets use the key eventTicket. This pass style is appropriate for passes used to gain entry to an event like a concert, a movie, a play, or a sporting event. Typically each pass corresponds to a specific event, but you can also use a single pass for several events as in a season ticket. Store cards use the key storeCard. This pass style is appropriate for store loyalty cards, discount cards, points cards, and gift cards. Typically a store identifies an account the user has with your company that can be used to make payments or receive discounts. When the account carries a balance, the current balance should appear on the pass. Generic passes use the key generic. This pass style is appropriate for any pass that doesnt fit into one of the other more specific stylesfor example, gym membership cards, coat check claim tickets, and metro passes that carry a balance.
The value of this key is a dictionary containing the fields that hold the pass content. Listing 3-1 shows a pass that uses the boarding pass style, with a placeholder for the field dictionaries.
Listing 3-1
{
19
Pass Design and Creation Pass Style Sets the Overall Visual Appearance
"description" : "Boarding pass for October 4, San Francisco to London", "formatVersion" : 1, "passTypeIdentifier" : "pass.com.example.boarding-pass", "serialNumber" : "123456", "boardingPass" : { <<field dictionaries>> } }
The pass style controls how fields are laid out and which images can be used. Table 3-1 shows the images supported by each pass style and the number and placement of fields for each pass style. Pass style also affects relevance informationfor details, see Relevance Information Displays Passes On the Lock Screen (page 30).
Table 3-1 Pass style Pass styles, images, and layout Supported images Layout
logo, icon, footer logo, icon, strip logo, icon, strip, background, thumbnail If you specify a strip image, do not specify a background image or a thumbnail.
See Figure 3-2 (page 21) See Figure 3-3 (page 21) See Figure 3-4 (page 22)
Generic
20
Pass Design and Creation Pass Style Sets the Overall Visual Appearance
Pass style
Supported images
Layout
Store card
Figure 3-2
Figure 3-3
Layout of a coupon
21
Pass Design and Creation Pass Style Sets the Overall Visual Appearance
Figure 3-4
Figure 3-5
logo
secondary fields
rectangular barcode
square barcode
22
Pass Design and Creation Fields Contain Text Displayed on the Pass
Figure 3-6
The pass style determines the maximum number of fields that can appear on the front of a pass:
In general, a pass can have up to three header fields, a single primary field, up to four secondary fields, and up to four auxiliary fields. Boarding passes can have up to two primary fields and up to five auxiliary fields. Coupons and store cards can have a total of up to four secondary and auxiliary fields, combined. Event tickets with a background image and generic passes with a square barcode dont support auxiliary fields.
The number of fields displayed on the pass also depends on the length of the text in each field. If there is too much text, some fields may not be displayed.
23
Pass Design and Creation Fields Contain Text Displayed on the Pass
Listing 3-2
{
"description" : "Boarding pass for October 4, San Francisco to London", "formatVersion" : 1, "passTypeIdentifier" : "pass.com.example.boarding-pass", "serialNumber" : "123456", "boardingPass" : { "primaryFields" : [ { "key" : "origin", "label" : "San Francisco", "value" : "SFO" }, { "key" : "destination", "label" : "London", "value" : "LHR" } ], "secondaryFields" : [ { "key" : "boarding-gate", "label" : "Gate", "value" : "F12" } ], "auxiliaryFields" : [ { "key" : "seat", "label" : "Seat", "value" : "7A" }, { "key" : "passenger-name", "label" : "Passenger",
24
The ordering between the lists of fields is not significant, but the ordering of fields within the list is significant. For example, putting the primary fields before or after the secondary fields doesnt change where the primary and secondary fields appear, but putting the seat assignment before or after the passenger name changes the ordering of those two fields on the pass. This is because the key/value pairs in a dictionary arent ordered, but lists are. For a complete list of the keys used in a field dictionary and their possible values, see Field Dictionary Keys in Passbook Package Format Reference .
To set the alignment for a field, specify a value for the alignment key in the field dictionary. To format a date, specify a value for the dateStyle and timeStyle keys in the field dictionary. To format a currency amount or other number, specify a value for the currencyCode or numberStyle key in the field dictionary.
Letting Passbook handle dates, times, and currency amounts ensures the right display formatting based on the users locale. Listing 3-3 shows an example of date and number formatting.
Listing 3-3
{ ...
25
Pass Design and Creation The Back of the Pass Provides Additional Space for Text
"key" : "event-name", "label" : "Event", "value" : "The Hectic Glow in concert" } ], "secondaryFields" : [ { "dateStyle" : "PKDateStyleMedium", "isRelative" : true, "key" : "doors-open", "label" : "Doors open", "timeStyle" : "PKDateStyleShort", "value" : "2013-08-10T19:30-06:00" }, { "key" : "seating-section", "label" : "Seating section", "numberStyle" : "PKNumberStyleSpellOut", "textAlignment" : "PKTextAlignmentRight", "value" : 5 } ] } }
26
Pass Design and Creation The Back of the Pass Provides Additional Space for Text
The back of the pass gives you a place to put information that is too long to fit on the front of the pass, extra information that isnt as important, and general information that may be helpful for your users. Examples of back fields include terms and conditions, the full address of a venue, your customer service phone number, and the URL for your website. Listing 3-4 shows examples of back fields. These go in the same place in the pass file as the rest of the fieldsthis key is a sibling to primaryFields and auxiliaryFields.
Listing 3-4
{ ...
"backFields" : [ { "key" : "frequent-flier-number", "label" : "Frequent flier number", "value" : "1234-5678" }, { "key" : "website", "label" : "Track my checked bags", "value" : "http://www.example.com/track-bags/XYZ123" }, { "key" : "customer-service", "label" : "Customer service", "value" : "(800) 555-0199" }, { "key" : "terms", "label" : "Terms and Conditions", "value" : "O Fortuna velut luna statu variabilis, semper crescis aut decrescis; vita detestabilis nunc obdurat et tunc curat ludo mentis aciem, egestatem, potestatem dissolvit ut glaciem.\n\n Sors immanis et inanis, rota tu volubilis, status malus, vana salus semper dissolubilis, obumbrata et velata michi quoque niteris; nunc per ludum dorsum nudum fero tui sceleris.\n\n Sors salutis et virtutis michi nunc contraria, est affectus et defectus semper in angaria. Hac in hora
27
sine mora corde pulsum tangite; quod per sortem sternit fortem, mecum omnes plangite!" } ] }
The text of the back fields is run through data detectors for URLs and phone numbers, which appear as live links. Users can tap on the URL to launch it in Safari and on phone numbers to dial them. Text on the back of the card can include line breaks, escaped in the JSON file as \n. To provide a link to an app, provide a list of iTunes Store item identifiers (also known as Adam IDs) as the value of the associatedStoreIdentifiers key at the top level of the pass.json file.
"barcode" : { "message" : "ABCD 123 EFGH 456 IJKL 789 MNOP", "format" : "PKBarcodeFormatPDF417", "messageEncoding" : "iso-8859-1" } }
28
Barcode scanners and software typically use the ISO 8859-1 encoding, also known as Latin-1. Unicode in particular is poorly supported by most systems. Passbook itself supports all encodings supported by Foundation. Note: Most laser scanners cant reliably read barcodes displayed on LCD screens. To scan pass barcodes, use an optical barcode scanner. All of the supported barcode formats are two dimensional and are typically read with optical barcode scanners.
The barcode message is just data, theres nothing that limits you from using it to carry additional information. For example, suppose you need to scan passes in a setting without network access, which makes it impossible to communicate with your database. You can sign the data you need with a private key, and use the result as the barcode. When the pass is scanned, validating the signature lets you trust the data in the barcode. Although this approach doesnt let you enforce a one-time-use pass, it could be useful for applications where passes are valid for a predictable period of time. The amount of data that you can include in a barcode depends on the barcode format and the conditions under which the barcode is scanned. The barcode format defines a hard maximum that it supports, but scanning conditions often lower this limit. For example, consider a barcode displayed on a non-Retina device under poor lighting, and scanned by an inexpensive barcode scanner. Test your passes in real-world conditions on a variety of devices to ensure that the barcode can be scanned reliably.
The background color is used for the background of the front and back of the pass. If you provide a background image, any background color is ignored. The key for the background color is backgroundColor. The foreground color is used for the values of fields shown on the front of the pass. The key for the foreground color is foregroundColor. The label color is used for the labels of fields shown on the front of the pass. The key for the label color is labelColor.
29
The background image (background.png) is displayed behind the entire front of the pass. The expected dimensions are 180x220 points. The image is cropped slightly on all sides and blurred. Depending on the image, you can often provide an image at a smaller size and let it be scaled up, because the blur effect hides details. This lets you to reduce the file size without a noticeable difference in the pass. The footer image (footer.png) is displayed near the barcode. The allotted space is 286x15 points. The icon (icon.png) is displayed when a pass is shown on the lock screen and by apps such as Mail when showing a pass attached to an email. The expected dimensions are the same as a small icon, as described in Custom Icon and Image Creation Guidelines in iOS Human Interface Guidelines . A shine effect is automatically applied to the icon for you. The logo image (logo.png) is displayed in the top left corner of the pass, next to the logo text. The allotted space is 160x50 points; in most cases it should be narrower. To engrave the logo so that it matches the logo text, add a black drop shadow with a 1 pixel y offset, a 1 pixel blur, and a 35% opacity. The strip image (strip.png) is displayed behind the primary fields. The allotted space is 312x84 points for event tickets, 312x110 points for other pass styles with a square barcode, and 312x123 in all other cases. A shine effect is automatically applied to the strip image; to suppress it use the suppressStripShine key. The thumbnail image (thumbnail.png) displayed next to the fields on the front of the pass. The allotted space is 90x90 points. The aspect ratio should be in the range of 2:3 to 3:2, otherwise the image is cropped.
Note: The dimensions given here are all in points. On Retina displays, there are 2 pixels per point; on non-Retina displays, there is 1 pixel per point. Provide both Retina and non-Retina assets in your passes.
30
Pass Design and Creation Relevance Information Displays Passes on the Lock Screen
You provide a point in time and points in space in the pass. Passbook determines the appropriate duration of time and radius in space around these points that the pass appears on the lock screen. Dont try to manipulate the time and place that pass appears on the lock screen by providing inaccurate relevance information. Relevance information is passive: it helps users find passes when they need them by putting relevant passes right on the lock screen. It doesnt present alerts or post notifications. This is in contrast to the notification posted when a pass updates, as described in Updating a Pass (page 37). To provide a relevant date, add the relevantDate key at the top level of the pass. Its value is a W3C timestamp, either a complete date plus hours and minutes or a complete date plus hours minutes and seconds. For more information about the timestamp format, see Time and Date Formats on the W3C website. To provide relevant locations, add the locations key at the top level of the pass. Its value is an array of dictionaries with longitude, latitude, and optional altitude information. Listing 3-6 shows part of an example pass which provides both a relative date and three relevant locations. A pass can have up to ten relevant locations. In many cases, you have more than ten relevant locations so you have to pick the best ten. There are a variety of ways to do this. For example, you could have settings in your account management system to let customers add their favorite stores or the stores that they frequently visit. Like other data in the pass, relevance data can be changed when the pass is updated. A pass could initially have very generic relevance information which is replaced over time with relevant locations tailored by the user.
Listing 3-6
{ ...
"description" : "Example pass showing relevance information", "locations" : [ {"latitude" : 37.3229, "longitude" : -122.0323}, {"latitude" : 37.3286, "longitude" : -122.0143}, { "altitude" : 10.0, "latitude" : 37.331, "longitude" : -122.029, "relevantText" : "Store nearby on 3rd and Main." } ], "relevantDate" : "2012-12-05T09:00-08"
31
Pass Design and Creation Relevance Information Displays Passes on the Lock Screen
Depending on the pass style, the relevance information is interpreted in slightly different ways, as listed in Table 3-2. When the location is interpreted with a small radius, the current location must be on the order of a hundred meters or closer; with a large radius, on the order of a thousand meters or closer. In both cases, the exact relevance radius is an implementation detail and may change.
Table 3-2 Pass style Pass style and relevance information Relevant Date Relevant Locations Relevance
Boarding pass
Optional
Relevant if the time or any location matches. Without a relevant time, relevant if any location matches.
Coupon
Not supported
Event ticket
Relevant if the time and any location matches. Without a relevant time, relevant if any location matches.
Generic
Relevant if the time and any location matches. Without a relevant time, relevant if any location matches. Relevant if any location matches.
Store card
Not supported
The system provides the relevant text for passes that have time-based relevance. For passes with relevant locations, you provide a description of why the pass is relevant at a given location. This can be as simple as Store nearby or include a brief description of how to find the relevant location, such as cross streets or landmarks. Dont include your organization name in the relevant text, and dont include instructions to the user such as Redeem this pass at XYZ .
32
Note: Test relevance information on a device; the iOS Simulator app doesnt support relevance information.
"primaryFields" : [ { "key" : "origin", "label" : "Seville", "value" : "SVQ" }, { "key" : "destination", "label" : "London", "value" : "LHR" } ] }
33
"primaryFields" : [ { "key" : "origin", "label" : "origin_SVQ", "value" : "SVQ" }, { "key" : "destination", "label" : "destination_LHR", "value" : "LHR" } ] }
The field values are no longer the text to be displaynow they indicate which entry in the strings file should be used.
2.
Create an es.lproj directory in the pass package. Create a strings file named pass.strings containing the Spanish strings:
"origin_SVQ" = "Sevilla"; "destination_LHR" = "Londres";
3.
Create an en.lproj directory in the pass package. Create a strings file named pass.strings containing the English strings:
"origin_SVQ" = "Seville"; "destination_LHR" = "London";
34
Pass Design and Creation Passes Are Cryptographically Signed and Compressed
Note: In this example, the strings files contains only ASCII characters. Save strings files that contain non-ASCII characters using the UTF-16 encoding.
If there is more than one localization, each localization needs its own .lproj directory, as shown earlier in Figure 3-1 (page 17). If the text in the pass were left in English and Spanish text were provided in a strings file, the pass would display in Spanish only. For more information about strings files, see Localizing String Resources in Internationalization Programming Topics . Images that need to be localized appear in the .lproj directories for their respective languages. Images that dont need localization appear at the top level of the pass. Dont include an image at the top level and inside a .lproj directory. For more information about localizing images, see Localized Resources in Bundles in Bundle Programming Guide .
To create the manifest file, recursively list the files in the package (except the manifest file and signature), calculate the SHA-1 hash of the contents of those files, and store the data in a dictionary. The keys are relative paths to the file from the pass package. The values are the SHA-1 hash (hex encoded) of the data at that path. Write this to the file manifest.json at the top level of the pass package. To create the signature file, make a PKCS #7 detached signature of the manifest file, using the private key associated with your signing certificate. Include the WWDR intermediate certificate as part of the signature; you can download this certificate from Apples website. Write the signature to the file signature at the top level of the pass package. To compress the pass, create a ZIP archive of the contents of the pass package. This ZIP archive is what you distribute to users.
35
Pass Design and Creation Passes Are Distributed via Email, the Web, or Your App
Using your own app to install passes is appropriate when your app provides a richer experience by integrating with your systems and business. For information about how your app can interact with passes, see Interacting With Passes in Your App (page 44).
Debugging Passes
If the pass doesnt display and add to Passbook, check the log for a description of what went wrong. When testing in the iOS Simulator app, errors are logged to the system log, which you can view with the Console app. When testing on a device, errors are logged to the devices console which you can view from the Xcode organizer window. Common errors include malformed JSON files, misspelled keys or values, pass type identifiers that dont match your certificate, and signatures that omit the WWDR intermediate certificate.
36
Updating a Pass
Passes allow the user to take real-world actions, and they reflect real-world state. When something in the real world changes, such as a delay to a departure, you can update the pass. Another reason to update a pass is when the pass represents multiple real world actions. For example, a season ticket gains access to every game of the season, and is updated before each game.
A pass that supports updates is installed and the users device registers with your server to get updates. Some change triggers an update and your server sends a push notification. The users device receives the notification and it queries your server to get a list of changes.
37
4.
The users device asks your server for the latest version of each pass that has changed.
Figure 4-1
APNs
Tells Passbook how to contact your web server Together, uniquely identify the pass
Device defines
38
Information
Source
Purpose
Authorizes requests Allows the server to send push notifications to the device Describes state
Update tag
Your server implements a specific web service API which allows this communication to happen. This is different from most uses of push notifications where you provide an app that is free to communicate with your server however you prefer. In this case, you only provide a pass, so Passbook needs a standardized way to communicate with your server. The web service URL tells Passbook how to contact your server during the update process. It must include the protocol, and it can include an optional port number. Passbook requires an HTTPS connection to your server for all communication. During development, you can use the developer settings to allow plain HTTP connections. Before responding to a request, you server always checks that the request is authorized. There are two shared secrets that are used to authorize requests. For more information about shared secrets, see Security Overview . The device library identifier is a Passbook-specific shared secret between the users device and your web server. It is not related to the device identifier (UDID). The device identifies itself with a different ID to different servers and it may change its ID at any time. Its purpose is to allow efficient communication between the device and your server, not to let your server keep a list of of what passes are currently installed on a device. The device library identifier uniquely identifies a device and indicates that the entity making the request is authorized to make such a request. The authentication token is a shared secret between the users device and your server. It shows that the request for an update to a pass is actually coming from the user who has the pass, and not from a third party. Your server needs to remember contain information between requests. There are two entitiesdevices and passesand one relationship, registrations. Assuming your server stores data in a traditional relational database, it needs to maintain the following tables: Devices table A device is identified by its device library identifier; it also has a push token. Passes table A pass is identified by pass type ID and serial number. This table includes a last-update tag (such as a time stamp) for when the pass was last updated, and typically includes whatever data you need to generate the actual pass.
39
Registrations table A registration is a relationship between a device and a pass. You need to be able to look up information in both directions: to find the passes that a given device has registered for, and to find the devices that have registered for a given pass. Registration is a many-to-many relationship: a single device can register for updates to multiple passes, and a single pass can be registered by multiple devices. Note: Test updates on a device; the iOS Simulator app doesnt register for push notifications.
Device library identifier (in the URL) Push token (in JSON payload) Pass type ID (in the URL) Serial number (in the URL) Authentication token (in the header)
Verify that the authentication token is correct. If it doesnt match, immediately return the HTTP status 401 Unauthorized and disregard the request. Store the mapping between the device library identifier and the push token in the devices table. Store the mapping between the pass (by pass type identifier and serial number) and the device library identifier in the registrations table.
2. 3.
When a device removes a registration, it uses the same endpoint and sends the same data. The difference is that the device sends a DELETE request instead of a POST request, and your server removes (or invalidates) data from its tables instead of adding it. When a device removes a registration, you can immediately remove the entry from the registrations table. When there are no entries for a device in the registrations table, you can remove the entry for the device from the devices table.
40
Updating a Pass Your Server Sends a Push Notification When Something Changes
The pass type identifier (in the certificate) The push token (in the communication to the Apple Push Notification service)
Update the passes table with the new pass information and get the pass type identifier and serial number for the pass that changed. Consult the registrations table and get the list of devices that registered for updates for that pass. Consult the devices table and get the push token for each device. Send a push notification with an empty JSON dictionary as its payload to each push token.
2. 3. 4.
You may wonder why your server doesnt include more information in the push notification. The reason is twofold: push notifications are not guaranteed to be delivered, and multiple push notifications from the same source are coalesced into a single notification. If more information were included it could be lost. The push notification just indicates that some passes with a given pass type identifier changed, so no information is lost if they are coalesced. Note: The Apple Push Notification service (APNs) provides feedback to your server which may require specific actions. For example, if APNs tells you that a push token is invalid, remove that device and its registrations from your server.
You use the same certificate and private key for sending push notifications as for signing passes. For more information about push notifications, see Local and Push Notification Programming Guide .
41
The device ID (in the URL) The pass type ID from the push notification (in the URL) The latest update tag that its seen from this pass type ID (as an optional query)
Authorization tokens are specified by each pass, so there is no appropriate token in this case. The device identifier is sufficient to prove that the request is valid. Your server determines which passes have changed since that update tag. It returns the serial numbers of those passes, and a new update tag to store. To send the list of serial numbers, do the following:
1. 2.
Look at the registrations table and determine which passes the device is registered for. Look at the passes table and determine which passes have changed since the given tag. Dont include serial numbers of passes that the device didnt register for. If no update tag is provided, return all the passes that the device is registered for. For example, this happens the very first time a device communicates with your server. Compare the update tags for each pass that has changed and determine which one is the latest. This is the update tag that will be returned to the device. Respond with this list of serial numbers and the latest update tag in a JSON payloadfor example:
{ "serialNumbers" : [001, 020, 3019], "lastUpdated" : "1351981923" }
3.
4.
Update tags are just an opaque piece of data, as far as Passbook is concerned. Your server must be able to compare any two tags to determine which one comes before the other, and the later tag must also be later than every earlier tag. The tag system is similar to the standard HTTP If-Modified-Since mechanism, but different in an important way. The standard HTTP mechanism is for a single monolithic resource; if the resource has changed, the entire resource is returned. The tag system used here is for a collection of passes; only the passes that have changed are returned, not the entire collection.
42
Pass type identifier (in the URL) Serial number (in the URL) Authentication token (in the header)
Your server returns the pass data or the HTTP status 304 Not Modified if the pass hasnt changed. Support the If-Modified-Since or ETag caching mechanism on this endpoint.
Best Practices
As you implement your web service, keep the following best practices in mind:
Always make a backup of your private key and certificate and keep them in a secure place. Avoid storing your private keys on your web server, because web servers typically have a larger attack surface. A more secure approach is to have a different server handle creating and signing passes, and push the finished passes to your web server. The serial number, pass type identifier, and last-update tag all get included in a URL when talking to your web service. Making them excessively long could cause problems with systems that impose a restriction on the length of a URL. Dont change the authentication token in an update. Passes are not guaranteed to be updated, so there could still be devices with the old pass and the old authentication token. Your server would have to check the authentication token against the list of every token that has ever been valid.
43
There are two main reasons apps interact with passes: to provide an integrated user experience or to serve as a conduit for passes. An event venues app is an example of an integrated user experience. This app could show the performance schedule, play short video clips, and let users buy tickets. After buying a ticket, it could add a pass for that ticket to Passbook and create an event in the users calendar. It could also include UI for managing the tickets that users have purchased. An email or instant messaging client is an example of an app serving as a conduit. Just as it supports attachments such as images, it could also support passes attached to a message like Mail does. The app could display UI that indicated that the message has a pass attached and allow users to add the pass to their library. Supporting passes in your app should add value for the user; avoid trying to duplicate functionality of the Passbook app. Your app needs the appropriate entitlement to read, update, or delete passes. Adding a pass requires explicit user interaction, so it doesnt require an entitlement. The Pass Kit framework provides model-level access to pass data. The PKPassLibrary class represents the pass library, and the PKPass class represents individual passes. The framework also provides a view controller, the PKAddPassesViewController class, which displays a pass and lets users add it to their pass library. Your app is responsible for the views it needs to display passes. If you need to present a pass, use the passURL property of a pass and open that to show it in Passbook as follows:
[[UIApplication sharedApplication] openURL:[pass passURL]]
Note: A pass should not depend on your app to be useful. Passes need to be self contained and useful by themselves, even if your app is not installed.
44
Interacting with Passes in Your App Checking Whether a Pass Is in the Library
Create an instance of the PKPass class for the pass. Create an instance of the PKPassLibrary class. Call the containsPass: method of the PKPassLibrary class with the pass you just created.
Getting Passes
Use the passes method of the PKPassLibrary class to get all passes that your app is entitled to access. Passes are returned in an arbitrary order. If your app displays a list of passes, it should sort them in some meaningful way such as by date. To receive notifications when the pass library changes, register for the PKPassLibraryDidChangeNotification notification. Pass the instance of PKPassLibrary as the object. The pass library isnt a singleton; each instance sends its own notifications, and you want the notifications from this particular instance. Use the addObserverForName:object:queue:usingBlock: method to specify that you want to respond on the main queue and provide a block to handle the notification. The user info dictionary of the notification describes what changed. Alternately, use the dispatch_async and dispatch_get_main_queue functions to respond on the main thread.
Reading a Pass
Use the passWithPassTypeIdentifier:serialNumber: method of the PKPassLibrary class to read a particular pass from the pass library. You can access certain common bits of data, such as the organization name and description, using the properties of the PKPass class. You can access the description using the localizedDescription method. These are useful if your app is acting as a conduit passes that you didnt create, so you dont know their fields keys. You can access specific fields of a pass using the their key with the localizedValueForFieldKey: method. This is useful if you created the pass, because then you know the keys for specific fields.PKPass properties.
45
Create an instance of the PKPass class for the pass, initializing it with the passs data. Use the containsPass: method of the PKPassLibrary class to check whether the pass is in the library. Your app can use this method to detect the presence of a pass, even if it doesnt have the entitlements to read passes in the library. If the pass isnt in the library, use an instance of the PKAddPassesViewController class to let the user add it. Present the add passes view controller modally, with animation.
3.
Changing a Pass
Passes cannot be changed directly on the device. Changing the contents of a pass would invalidate its signature. An updated pass needs to be signed using your private key, and distributing your private key as part of your app would be a particularly poor security practice. To change a pass, coordinate with your server:
1.
Your app connects to your server. It identifies the pass by serial number and pass type identifier and describes the change to your server. Your server updates your business records as needed, creates a new version of the pass, and signs it. Your app downloads the new pass from your server and uses the replacePassWithPass: method of the PKPassLibrary class to install it.
2. 3.
After creating a new version of the pass, your server should also send a push notification so that other devices with this pass installed will get the latest copy.
Removing a Pass
Use the removePass: method of the PKPassLibrary class to remove a pass. Remember that passes belong to the user, not to your app. Pass removal should be done only in response to a direct user action. Never remove a pass without the users consent, even if the pass is expired or outdated.
46
Notes New document that explains how to create passes, update them, and interact with them from your app.
47
Apple Inc. 2012 Apple Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Inc., with the following exceptions: Any person is hereby authorized to store documentation on a single computer for personal use only and to print copies of documentation for personal use provided that the documentation contains Apples copyright notice. No licenses, express or implied, are granted with respect to any of the technology described in this document. Apple retains all intellectual property rights associated with the technology described in this document. This document is intended to assist application developers to develop applications only for Apple-labeled computers. Apple Inc. 1 Infinite Loop Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, Finder, iTunes, Keychain, Numbers, Objective-C, OS X, Passbook, Safari, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. Retina is a trademark of Apple Inc. iCloud and iTunes Store are service marks of Apple Inc., registered in the U.S. and other countries. iOS is a trademark or registered trademark of Cisco in the U.S. and other countries and is used under license.
Even though Apple has reviewed this document, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS DOCUMENT, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS DOCUMENT IS PROVIDED AS IS, AND YOU, THE READER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS DOCUMENT, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state.