IOS6:在你的APP内使用PASSBOOK
前言
这是一篇翻译,感谢Jonathan Tang。
原文地址:iOS 6 Tutorial: Integrating Passbook into Your Applications
另外,看到另一篇很好的教程:iOS 6 Passbook 入门 1/2
正文
什么是Passbook?Passbook是iOS6中提供的一个用于收集和显示票据(passes)的工具,这些票据包括电影票、登机牌、积分卡和礼品卡等。Passbook为开发者提供了一种用于在系统级别保存信息的方式。Passbook还能根据你的位置和日期信息来动态的将某个票据显示出来,并且允许动态的更新各个票据。
这里用虚拟的CapTech Ice Store作为例子,当你走进这家店时,你的iPhone将会自动的弹出这家店的会员卡的图标。当你在这家店里买了某些东西后,服务器将会用推送的方式自动更新你的会员卡中的奖励积分。
截至目前,Passbook还不是具有支付能力的电子钱包,但是移动支付显然是未来必然要实现的功能。
票据(Passes)
当前,一共有5种票据可用:
1. 登机牌(boarding pass)
2. 优惠券(coupon)
3. 活动票据(event ticket)
4. 商店专用赊购卡、奖励卡(store card/rewards card)
5. 普通票据(generic pass)
在开发中,你可以使用JSON文件自定义条形码的类别(二维码或者QR码),显示的文本、背景图像和颜色、图标。票据的生成必须遵循Apple的设计规范。你可以从苹果开发者网站下载票据的例子来获得对于每种类别的更深的认识。
在票据的文件夹中,你可以看到多个.pkpass文件以及一个.raw文件夹。如果你的系统为iOS6.0以上,那么你可以将签名过的票据通过email发送到手机上进行安装。截至2012年9月,Gmail并不会识别pkpass的mimetype,因此你应该尽量避免使用Gmail。
而且你还要注意有一些程序会影响到pkpass的mimitype。比如logmein, airsharing, box, receipts, good reader,这些程序都会影响到pkpass的正确载入。所以在安装票据时,你可能需要先将它们卸载掉,安装完成后再把它们重新安装。
这个教程主要是介绍票据相关信息,如何创建票据,以及在iOS端如何和它们交互。我的另外一篇Passbook的教程将会介绍如何远程生成、传递以及更新票据。
票据里面有什么?
票据文件被打包成后缀名为.pkpass的压缩文件。票据并不包含任何可执行代码,它的文件夹中有如下文件:
1. pass.json: 定义票据的JSON文件
2. 票据图片:
- Logo-logo.png, logo@2x.png
- Icon file-icon.png, icon@2x.png
- Strip image-strip.png, strip@2x.png
3. manifest.json: 一个包含压缩包中每个文件的hash值得文件
4. 签名文件:manifest.json经过PKCS#7签名的文件
如何创建一个票据
再次使用虚构的CapTech Ice Cream Store作为例子,你要为客人生成一个用于积分获得免费甜点的会员卡。通常票据是由服务器端生成的,但是这篇文章主要是讲解如何在你的本地生成。如同前面提到的,另一篇文章将会讲解如何在服务器端使用PassKit。
Store Card
你还可以在本文的最后下载一个票据的原始文件来生成一个奖励卡。
生成票据证书
在苹果开发者网站生成票据的步骤和生成开发、发布证书的步骤类似。
1. 首先登录,点击provisioning,然后点击左边导航栏的Pass Type IDs。
创建票据类型ID
2. 点击New Pass Type ID来生成新的票据id和证书。填写id、描述。
Create Pass Type ID - 2
3. 你可能需要使用钥匙串访问(Keychain Access)生成一个证书签发请求(Certificate Signing Request,CSR)。这个步骤和生成开发、发布证书时的过程类似。
CSR
4. 在生成证书之后,你就可以进行下载、安装,在钥匙串访问中进行确定了。
Download Pass Certificate
Private Key
pass.json中有什么?
让我们看一下pass.json文件。下面是CapTech Ice Cream Store的奖励卡的一级键值。
{
"formatVersion" : 1,
"passTypeIdentifier" : "pass.captech.ventures.blog",
"serialNumber" : "xxxxxxx",
"teamIdentifier" : "xxxxxxx",
“storeCard” : {…}
...
}
formatVersion必须为1,作为当前Passbook的版本。passTypeIdentifier, team identifier, organization name同开发者网站上生成的一致。passTypeIdentifier定义了证书的类别。这个值必须和签名文件一致以生成正确的票据。serial number 是一个用于标识这个票据的唯一值。你需要在你的服务器端生成它。
因为我们不能提供给你证书来为这个票据签名,passTypeIdentifier和team identifier需要你在开发者网站自己生成。这将允许你使用自己的证书来进行票据的签名。
在指定了签名等等之后,你需要指定票据的类型。在这个例子中,你将使用storeCard类型来生成会员卡。剩下的键值是可选的,用于指定票据显示时的头部、前面、后面的信息。对这个例子,你将使用barcode, foreground ,background colors, 以及其他的可选项,如下所示:
"barcode" : {
"message" : "123456789",
"format" : "PKBarcodeFormatPDF417",
"mesageEncoding" : "iso-8859-1"
},
"foregroundColor" : "rgb(255, 255, 255)",
"backgroundColor" : "rgb(78, 74, 50)",
"storeCard" : {
"primaryFields" : [
{
"key" : "rewards",
"label" : "total rewards",
"value" : 25,
}
],
"auxiliaryFields" : [
{
"key" : "level",
"label" : "LEVEL",
"value" : "Gold"
},
],
"backFields" : [
{
"key" : "terms",
"label" : "TERMS AND CONDITIONS",
…
]
在pass.json中还有许多其他字段,例如locations和relevantDate,用来设定票据的位置和日期信息。你可以在PassKit的文档中查看到完整的参数列表,它当前的网址是http://developer.apple.com/passbook/。
签名以及打包.pkpass文件
你需要对票据进行签名并且打包成.pkpass文件。通常这在服务器端收到对于票据的请求时来生成。为了了解签名和打包.pkpass文件的步骤,你可以使用Apple提供的一个程序。在另外的那篇文档中将向你展示如何通过网络远程的生成、更新票据。
在苹果提供的Passbook Session Materials中,找到signpass工程。这个工具将.raw目录转化成.pkpass文件。注意signpass要求钥匙串中具有和票据的passTypeIdentifier字段匹配的证书。请查看前面的步骤来获得这个证书。
在编译完这个工具后,这么调用它:
signpass -p /path/to/MyPass.raw
这个程序将会为你做下面这些事:
1. 验证passTypeIdentifier是否匹配钥匙串中的签名id。
2. 生成manifest文件。
3. 使用票据证书生成签名文件。
4. 压缩文件夹并且重命名为.pkpass。
你可以将这个.pkpass文件传递到手机上。不幸的是,截至这篇文章写作时,仍然没有一种快速的方式来查看生成的票据是什么样的。这意味着你要想测试的话必须将他们安装到设备上。另外也不存在简便的方法用于查看票据的bug,必须将票据安装到手机上,通过控制台推断bug。苹果在模拟器中提供了passbook,但是你需要开发一个程序通过PKPass Framewrok来载入.pkpass。
如何传输票据?
现在你知道了如何生成票据,那么你该如何获得它们呢?一共有三种传输方式:通过email下载,通过网站下载,以及在应用中加载。
如果通过email传输,只需要将.pkpass作为附件发送就可以了。iPhone上的Mail.app客户端将会自动识别出附件是.pkpass类型,允许你将其添加到Passbook里。
如果允许用户从网站上下载票据,将MIME类型设置为application/vnd.apple.pkpass,这样Mobile Safari将会把它作为票据处理。加载一个带有这种MIME类型的网页将会启动安装到Passbook的流程。
你还可以使用PassKit框架开发一个程序来载入票据。下一部分将会向你展示如何使用PassKit在你的机器上载入,访问以及替换票据。
应用程序可以使用票据做什么?
如果你要在程序中加载,访问以及修改票据,你需要使用PassKit框架。这个框架提供了Objective-C的API用于和用户的票据库进行交互。例如,ice cream store的应用可能允许用户在网上预订一份甜点并且将一张票据发送到用户的票据库里,用户可以在店里证明他们的订单,或者根据用户在网上的订单更新用户会员卡中的奖励点数。在本文的最下端你可以找到一个示例程序。
下面的几个部分的内容如下所示:
1. 在你的应用中添加票据授权
2. 验证票据库是否可用
3. 向库中添加票据
4. 访问票据
5. 修改票据
6. 删除票据
在你的应用中添加票据授权
当你的工程中需要使用票据时,你必须记得在target中打开授权。在Tareget中点击Summary选项卡,选中Entitlements。这将会生成一个TargetName.entitlements。使用从在开发者中心中生成的票据类型id,或者手动的添加你想要访问的票据的类型id。
验证票据库是否可用
首先使用isPassLibraryAvailable来判断票据库是否存在以及是否可以访问。确定之后创建一个PKPassLibrary对象。
//check if pass library is available if (![PKPassLibrary isPassLibraryAvailable]) { UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Pass Library Error" message:@"The Pass Library is not available." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } _passLib = [[PKPassLibrary alloc] init];
添加票据
要向库中添加票据:
1. 创建一个PKPass对象,使用票据的数据进行初始化。
2. 使用containsPass:方法检测票据是否在库中,即使并没有授权从库中将票据读出。
3. 如果票据并不存在,并且票据库可访问,使用PKAddPassesViewController向用户请求来添加票据。这个view controller在将票据添加到库之前会将其展示出来。
- (IBAction)addPassButtonPressed:(id)sender { //load StoreCard.pkpass from resource bundle NSString *filePath = [[NSBundle mainBundle] pathForResource:@"StoreCard" ofType:@"pkpass"]; NSData *data = [NSData dataWithContentsOfFile:filePath]; NSError *error; //init a pass object with the data PKPass *pass = [[PKPass alloc] initWithData:data error:&error]; //init a pass library PKPassLibrary* passLib = [[PKPassLibrary alloc] init]; //check if pass library contains this pass already if([passLib containsPass:pass]) { //pass already exists in library, show an error message UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Pass Exists" message:@"The pass you are trying to add to Passbook is already present." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } else { //present view controller to add the pass to the library PKAddPassesViewController *vc = [[PKAddPassesViewController alloc] initWithPass:pass]; [vc setDelegate:(id)self]; [self presentViewController:vc animated:YES completion:nil]; } }
访问票据
要访问票据,应用必须拥有读写指定票据类型id的授权(entitlements)。
1. 通过方法获得用户库中得一个票据列表。只有你的app有授权的票据会被返回。
2. 或者使用passWithPassTypeIdentifier:serialNumber:方法获得一个指定的票据。
3. 使用PKPass类的icon, localizedName,localizedDescription, organizationName属性访问票据中的字段。
4. 要访问票据中的特定字段,使用PKPass类的localizedValueForFieldKey方法获得。
下面的例子和截图展示了从票据中获得数据。
- (IBAction)accessPassButtonPressed:(id)sender { //init a pass library PKPassLibrary* passLib = [[PKPassLibrary alloc] init]; NSArray * passArray = [passLib passes]; NSLog(@"number of passes in library are: %d",[passArray count]); _numberOfPasses.text = [NSString stringWithFormat:@"%d",[passArray count]]; //if more tha one pass in library, just use the first one. if ([passArray count] > 0) { PKPass *onePass = [passArray objectAtIndex:0]; //access general fieldnames _localizedName.text = [onePass localizedName]; _organizationName.text = [onePass organizationName]; //access a specific field name _rewardsBalance.text = [onePass localizedValueForFieldKey:@"rewards"]; } }
注意:没有方法可以用来在你的应用中展示票据,你只能通过方法获得一些票据的信息。这是因为苹果希望票据展示在Passbook应用中而不是在你的应用中。可以通过下面的方法直接在Passbook中展示某个票据:
[sharedApp openURL:[tappedPass passURL]]
修改票据
要修改库里的一个票据,程序必须首先具有写入指定类型id的票据的授权。使用PKPassLibrary类的passWithPassTypeIdentifier:serialNumber: 来获得一个票据。然后,你有两种方式来修改票据:
1. 创建一个新的票据,然后使用PKPassLibrary类的replacePassWithPass: 方法替换旧的的票据。新旧票据的passTypeIdentifier和serialNumber必须一致。新票据将会自动展示给用户,所以你需要监听PKPassLibraryDidChangeNotification事件来提醒用户。
2. 你也可以使用PKPassLibrary类的removePass:方法将票据删除,然后添加一个具有不同serialNumberde的新票据。
你需要记住的一件事是你不能在你的设备上修改和生成新的票据;你必须从别的地方获得它们,例如你的服务器端。
- (IBAction)modifyPassButtonPressed:(id)sender { //load StoreCard2.pkpass from resource bundle NSString *filePath = [[NSBundle mainBundle] pathForResource:@"StoreCard2" ofType:@"pkpass"]; NSData *data = [NSData dataWithContentsOfFile:filePath]; NSError *error; //init a pass object with the data PKPass *newPass = [[PKPass alloc] initWithData:data error:&error]; //init a pass object with the data PKPass *oldPass = [_passLib passWithPassTypeIdentifier:@"pass.captechventures.blog" serialNumber:@"p69f2J"]; //check if pass library contains this pass already if (oldPass) { //replace old pass with new pass [_passLib replacePassWithPass:newPass]; UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Pass has been replaced" message:@"The pass has been successfully replaced." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } }
删除票据
有时你可能需要从Passbook中删除票据。它的代码如下所示:
- (IBAction)removePassButtonPressed:(id)sender { //init a pass object with the data PKPass *pass = [_passLib passWithPassTypeIdentifier:@"pass.captechventures.blog" serialNumber:@"p69f2J"]; //check if pass library contains this pass already if (pass) { [_passLib removePass:pass]; //pass already exists in library, show an error message UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Pass removed" message:@"The pass has been removed from the library." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } }
结束
这里就是在你的App内使用Passbook的结束。如同前面提到的,另一篇叫做“在你的企业系统中支持Passbook”将会在短期内发表,它主要是关于Passbook ecosystem的相关信息。如果你有任何问题,请不要犹豫,直接联系我:jtang@captechconsulting.com。
附件: