2012年10月11日

用Asp.net生成Passbook的方法

作者 非鱼

iOS6已经正式上线了,而且破天荒的覆盖到已经超过三年的机型3GS。对于3GS来说,升级到iOS6能够得到的唯一好处,就是苹果的新功能Passbook了。所以iOS6对3GS的支持,恐怕是苹果为了推广Passbook不得不做出的妥协,也因此,iPhone5没有添加NFC功能,所以从3GS到iPhone5的四代机型上面,Passbook的体验是一致的,无论对于用户、开发人员还是最终使用的商户来说,这种统一性带来的好处都是巨大的。剩下的工作,可能就是苹果推出一个官方的Android上的Passbook解决方案了。

而对于像31会议网这样的网站报名管理和现场签到管理平台来说,在本来就已经在使用二维码作为会场电子签到的情况下,Passbook无疑是一个极好的补充,完全不影响现有的架构,又极大的方便和用户,提升了体验。所以,没理由放着这么好的功能不用啊。

要把你的门票放进用户的Passbook程序里,有三种方式,1、提供一个链接,让用户用Safari打开。2、直接将Passbook文件以邮件附件的方式发到用户邮箱,让用户在手机上打开。3、开发一个App,在App里将这个门票直接写到系统的Passbook程序里去。对于在网站上匿名报名的用户来说,第三种方式无法实现,前两种都可以。最方便的当然是第一种。

解决方案很简单,使用这个开源库:https://github.com/tomasmcguinness/dotnet-passbook

这个库提供了生成passbook门票文件所需的一切方法,自动打包生成zip文件并完成签名,可以使用流的方式直接返回给浏览器,用户在手机上用safari打开一个链接,就可以完成passbook文件的下载,然后点击添加,就可以将这张门票添加进Passbook程序了。不过这个库的使用过程可不是一帆风顺,折腾了整整一天才搞定。一开始是safari直接提示文件无法下载,但是在windows下可以看到生成的zip什么问题也没有,里面的文件也是全的,跟demo也几乎是一样,你完全无法知道是哪里的错误,只能一个参数一个参数的试。后来safari终于能打开显示出门票信息了,但是点击添加的时候,不显示添加的动画,而是门票直接消失,然后进入Passbook程序还是空白,什么也没有。这个时候你就更不知道文件里到底有什么错误导致的了。唉,想想就郁闷。

首先,这个项目是VS2012写的,没有提供低版本的项目文件。无奈,下载VS2012,安装,打开项目,编译。还算顺利,结果把生成的dll引用到自己的项目以后,随便写了一个引用测试,编译就出错了。因为这个项目默认编译是for .net framework 4.5的,而我的网站项目还是.net 3.5的,不向下兼容。然后修改这个项目的属性,编译目标改成.net 3.5 dll,再编译,报一堆错误。其中引用的两个System级别的类是.net 4.5新增的,一个是Thread里面的Tasks类,一个是压缩类。删了这两个类的引用和using以后,第一个貌似代码中没有实际使用到,没有影响,第二个是生成zip文件的关键类,不能用了。没办法,添加了ICSharpCode.SharpZipLib.dll引用以后,手动修改生成zip文件的地方,改成FastZip类来生成zip文件。然后重新添加了.net 3.5下面的Newtonsoft.Json.dll,重新编译,成功。

第二个问题是证书,你需要在你的IIS所在的windows server里安装苹果的证书才能对生成的passbook门票签名。上面的gitbug项目说明文件里有一个简单的说明,不过有误导作用。正确的作法是:

1、去http://www.apple.com/certificateauthority/下载WWDR证书,也就是这个页面里的倒数第四个证书(一开始我以为是第一个证书)。这是个cer文件。在windows里进入证书管理(开始-运行-mmc-添加管理单元-证书-本地计算机),左边进入“中级证书颁发机构”下面的证书,右键-导入,选中这个cer文件,就可以导入了。

2、获取Passbook证书。如果你有苹果系统:登录你的苹果开发者中心,证书和Provision管理的地方,左边多了一个Pass Type IDs的菜单,进去新建一个ID,跟程序的App ID是一样的。然后进入这个ID的configure设置证书,申请过程也跟以前的申请certificate一样的,完成后下载cer证书双击导入你的钥匙串管理。然后在证书中找到它,右键,导出成p12文件。然后进入前面的windows的证书管理,在左边进入“个人”下面的证书,右键,导入,选中这个p12文件,成功就对了。然后右击这个证书,高级里有个管理证书,添加一个IIS能访问它的权限。

如果你没有苹果系统(不太可能吧?),上面的github的说明里有篇作者的博客,说明了在windows系统下如何申请获取这个证书,效果是一样的,获取完它会自动出现在“个人”证书下。

然后按照上面的项目里面的Web示例项目里面的代码来生成自己的passbook就行了。这个代码里有几个值是需要注意的:

request.Identifier是你的pass type id的定义,就是pass.com.yourdomain.xxx的样式。

request.TeamIdentifier是你上面的pass type id生成后的前缀,类似于FE93CED9这样的,通常是系统生成给你的。

request.CertThumbprint是你的windows里面的pass证书的指纹。获取方式:在windows证书管理里“个人”的证书下面双击这个pass的证书,在属性页面,所有的属性里,拉到最下面,把指纹的值复制出来,删掉里面的空格,一堆数字加字母的串就是了。大小写不敏感。

request.SerialNumber全局不能重复,也就是同一个Identifier下不允许出现重复的SerialNumber。

request.FormatVersion = 1; 这个值的定义在Web项目的示例代码里居然没有,但是少了这个safari会提示无法下载该文件。

所有的图片都是必填的,因为这个生成代码里没有判断图片为空的情况,所以必须保证Icon, Logo, Background都有。

其它没什么关键的了,如果一切顺利,你用safari打开这个页面的链接,就应该能弹出这个门票了,点击添加,它也应该能进入你的Passbook应用程序了。

另外对这个项目的源码做的修改还有:修改时间字段的序列化方式,默认是2012-10-30T08:00Z,这样会认为时区为0,进入passbook以后会显示成下午4点。把源码里格式改成2012-10-30T08:00+08:00就好了。

如果你的网站是.net 4.5的,就用项目里的代码自己编译一下就行了,如果你的项目也是3.5的,那可以直接下载我这儿生成的dll文件