PassKit -- Wallet开发

一、简介

根据目前系统钱包中的能够添加的卡,大致可分为三类

  • 银行卡/交通卡
  • 电子卡(例如:京东闪付)
  • 消费凭证 (电影票/机票/优惠券)

消费凭证

消费凭证,大致分为五类,具体请看下图,对于每种凭证的包含信息,入口

二、 制作凭证并添加到Wallet

1. 创建pass包

  1. 苹果创建Pass导航
  2. 创建一个pass包
    首先要明白 Pasees 是以 Pass 包 形式创建的,Pass 包里面包含一个 pass.json 文件,一些图片资源(像 icon, logo 等)
    创建一个 Pass 包:
    (1)在 Finder 的 Desktop 处创建一个 名为 Lollipop.pass 的文件夹
    (2)下载苹果提供的资源文件(包括一些 Pass 包例子, 一个签名工具, 一个测试服务器)
    下载资源: developer downloads area
    (3)在苹果资源处将 Event.pass 文件夹中的所有内容拷贝到 Lollipop.pass 文件夹中。
  3. 设置 Pass Type Identifier 和 Team ID
    每一个 pass 都有和开发者账号相关连的 Pass Type Identifier
    官方文档:

按照苹果的意思在自己的开发账号内生成一个 Pass Type ID, 然后在 pass.json 文件内替换生成的Pass Type ID, Team ID 同理,开发者账号内找到并且在 pass.json 文件内替换。

步骤如下:

  • 在 Certificates, Identifiers & Profiles, 选择 Identifiers
  • 在 Identifiers 下,选择 Pass Type IDs.
  • 选择你已经创建好的 pass type identifier, 点击编辑。
  • 如果已经存在证书文件,直接点击下载即可。如果没有,点击创建,按照提示创建一个(与创建 APNs 推送证书基本一样)。
    创建Pass Type IDs
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

下载证书
下载之后,双击安装到电脑。

  1. 修改pass.json文件的ID
  • 查看Team Id
    到开发者账号下,会员详细信息
    在这里插入图片描述

  • 添加 PassTypeID 和 Team ID 到 pass.json
    打开 Lollipop.pass 文件夹下的 pass.json , 将 PassTypeID 和 Team ID 替换为自己开发者账号下的。

{
...
"passTypeIdentifier" : "your pass type identifier",
"teamIdentifier" : "your Team ID",
...
}
  1. 生成 .pkpass 后缀的压缩文件
  • 找到之前下载的文件,WalletCompanionFiles/signpass/signpass.xcodeproj
    使用Xcode运行
  • 选中 Xcode 中 Products ->Show Build Folder in Finder。
    在这里插入图片描述
  • 拷贝signpass,到Lollipop.pass同级目录
  • 控制台执行以下语句:
cd ~/Desktop
./signpass -p Lollipop.pass

三、创建Xcode 项目 添加凭证到Wallet

添加pass代码如下:

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let pkAddBtn = PKAddPassButton.init(addPassButtonStyle: .black)
        pkAddBtn.titleLabel?.font = .systemFont(ofSize: 15)
        pkAddBtn.frame = CGRect(x: 100, y: 100, width: 220, height: 40)
        view.addSubview(pkAddBtn)
        
        pkAddBtn.addTarget(self, action: #selector(pkAddBtnClick(_:)), for: .touchUpInside)
    }
    
    @objc private func pkAddBtnClick(_ sender: PKAddPassButton) {
        guard let passPath = Bundle.main.path(forResource: "Lollipop", ofType: "pkpass")
        else { return }
        let url = URL(filePath: passPath)
        guard let passData = try? Data.init(contentsOf: url) else {
            return
        }
        guard let pass = try? PKPass.init(data: passData) else {
            print("创建pass 过程中发生错误");
            return
        }
        guard let vc = PKAddPassesViewController.init(pass: pass) else {
            return
        }
        vc.delegate = self
        self.present(vc, animated: true)
    }
    extension ViewController: PKAddPassesViewControllerDelegate {
    func addPassesViewControllerDidFinish(_ controller: PKAddPassesViewController) {
        print("add pass finished")
        self.dismiss(animated: true)
    }
}

修改凭证信息

{
  "formatVersion" : 1,
  "passTypeIdentifier" : "pass.com.test.passkitTestDemo",
  "serialNumber" : "nmyuxofgna",
  "teamIdentifier" : "YourTestTeamID",
  "webServiceURL" : "https://example.com/passes/",
  "authenticationToken" : "vxwxd7J8AlNNFPS8k0a0FfUFtq0ewzFdc",
  "relevantDate" : "2011-12-08T13:00-08:00",
  "associatedStoreIdentifiers" : [728326385],
  "appLaunchURL" : "http://www.xingshulin.com",
  "locations" : [
    {
      "longitude" : -122.3748889,
      "latitude" : 37.6189722
    },
    {
      "longitude" : -122.03118,
      "latitude" : 37.33182
    }
  ],
  "barcode" : {
    "altText" : "订单号:123456",
    "message" : "123456789",
    "format" : "PKBarcodeFormatQR",
    "messageEncoding" : "iso-8859-1"
  },
  "organizationName" : "Apple Inc.",
  "description" : "Apple Event Ticket",
  "foregroundColor" : "rgb(255, 255, 255)",
  "backgroundColor" : "rgb(60, 65, 76)",
  "headerFields" : [
    {
      "key" : "filmName",
      "label" : "影片",
      "value" : "流浪地球",
      "textAlignment" : "PKTextAlignmentNatural"
    }
  ],
  "eventTicket" : {
    "primaryFields" : [
      {
        "key" : "filmName",
        "label" : "影片",
        "value" : "test1111111",
        "textAlignment" : "PKTextAlignmentNatural"
      }
    ],
  "secondaryFields" : [
      {
        "key" : "orderNumber",
        "label" : "订单号",
        "value" : "test2",
        "textAlignment" : "PKTextAlignmentLeft"
      },
      {
        "key" : "verificationNumber",
        "label" : "验证码",
        "value" : "test222",
        "textAlignment" : "PKTextAlignmentRight"
      }
    ],
  "auxiliaryFields" : [
      {
        "key" : "site",
        "label" : "影院",
        "value" : "test333",
        "textAlignment" : "PKTextAlignmentLeft"
      },
      {
        "key" : "order",
        "label" : "场次",
        "value" : "test3",
        "textAlignment" : "PKTextAlignmentCenter"
      },
      {
        "key" : "seat",
        "label" : "座位",
        "value" : "test333333",
        "textAlignment" : "PKTextAlignmentRight"
      }
    ],
    "backFields" : [
      {
        "numberStyle" : "PKNumberStyleSpellOut",
        "label" : "spelled out",
        "key" : "numberStyle",
        "value" : 200
      },
      {
        "label" : "in Reals",
        "key" : "currency",
        "value" : 200,
        "currencyCode" : "BRL"
      },
      {
        "dateStyle" : "PKDateStyleFull",
        "label" : "full date",
        "key" : "dateFull",
        "value" : "1980-05-07T10:00-05:00"
      },
      {
        "label" : "full time",
        "key" : "timeFull",
        "value" : "1980-05-07T10:00-05:00",
        "timeStyle" : "PKDateStyleFull"
      },
      {
        "dateStyle" : "PKDateStyleShort",
        "label" : "short date and time",
        "key" : "dateTime",
        "value" : "1980-05-07T10:00-05:00"
      },
      {
        "dateStyle" : "PKDateStyleShort",
        "label" : "relative date",
        "key" : "relStyle",
        "value" : "2013-04-24T10:00-05:00",
        "isRelative" : true
      }
    ]
  }
}

更新好后重新运行生成Lollipop.pkpass, 替换项目中的文件。

pass.json 官方说明

更新凭证信息

流程图
请添加图片描述

  • pass 被设置为支持更新和安装,并且用户设备注册到你的服务器获取更新。
  • 如果有变更,则触发更新,你的服务器发送推送通知。
  • 用户收到推送后,从你的服务器查询更新的列表。
  • 用户从你的服务器获取每个 pass 的最新版本到自己的设备。

四、京东闪付卡/美团闪付卡/银行卡

这一类的卡,是通过公司接入银联支付产生的,具体可参考银联官网,并可直接电话联系咨询,京东和美团的闪付卡都是接入银联中的一个手机闪付业务做成闪付卡,然后添加到系统钱包。
iOS Developer Wallet中,也介绍到,使用PKAddPaymentPassViewController可以添加这类卡,苹果官方描述如下:

Adding payment passes requires a special entitlement issued by Apple. Your app must include this entitlement before this class can be instantiated. For more information on requesting this entitlement, see the Card Issuers section at[ developer.apple.com/apple-pay/](https://developer.apple.com/apple-pay/).

五、如何做一个凭证,从钱包跳回App


In your pass.json file you can include a key to define an associated app:

"associatedStoreIdentifiers" : [Adam ID],

where Adam ID can be obtained from the link to the app in the app store:

[https://itunes.apple.com/app/id](https://itunes.apple.com/app/id)<Adam ID> ..

e.g. to get the Facebook App, go to:

[https://itunes.apple.com/us/app/facebook/id284882215](https://itunes.apple.com/us/app/facebook/id284882215)

To include it in a Pass, add this to pass.json:

"associatedStoreIdentifiers" : [284882215],

步骤如下:

拿到你的App 上架的时候的App ID

在制作凭证的.json文件中 设置该ID 为associatedStoreIdentifiers的value值,即:
“associatedStoreIdentifiers” : [1395841695]

官方文档说明如下:

在这里插入图片描述

六、passKit 库用到的API

PKAddPassButton: 添加钱包按钮,主要有两种类型,PKAddPassButtonStyleBlack 、 PKAddPassButtonStyleBlackOutline
创建方法
init(addPassButtonStyle style: PKAddPassButtonStyle)

PKPass 该类集成自 PKObject
PKPassType:枚举类型,
PKPassTypeBarcode:条码
PKPassTypePayment:支付
PKPassTypeAny:其它类型

构造方法:
init(data: Data) throws

PKPassLibrary 提供用户传递库

检测PKPassLibrary 是否可用
class func isPassLibraryAvailable() -> Bool

根据passtypeID 和serialNumber 返回pass
open func pass(withPassTypeIdentifier identifier: String, serialNumber: String) -> PKPass?

根据passType返回pass
open func passes(of passType: PKPassType) -> [PKPass]

移除pass
open func removePass(_ pass: PKPass)

判断是否包含pass
open func containsPass(_ pass: PKPass) -> Bool

替换一个pass
open func replacePass(with pass: PKPass) -> Bool

添加pass
open func addPasses(_ passes: [PKPass], withCompletionHandler completion: ((PKPassLibraryAddPassesStatus) -> Void)? = nil)

PKPaymentPass 继承自 PKPass

PKPaymentPassActivationState 枚举类型,
PKPaymentPassActivationStateActivated,(已激活)
PKPaymentPassActivationStateRequiresActivation,(需要被激活)
PKPaymentPassActivationStateActivating,(正在激活)
PKPaymentPassActivationStateSuspended, (挂起)
PKPaymentPassActivationStateDeactivated (停用)

PKAddPaymentPassRequestConfiguration

该类包含初始化一个新的PKAddPaymentPassViewController实例的配置数据。加密机制,持卡人姓名,卡号后四位需要被提供。配置信息仅用来设置和显示。它不包含任何的敏感信息

重要说明:
添加Payment Pass支付卡需要一个特殊的由苹果发行的授权。在使用这个类之前app中必须包括这个授权
public init?(encryptionScheme: PKEncryptionScheme)
emcryptionScheme 用于该请求的加密机制。所有可能的值可以查看Encryption Schemes.
返回值:一个新的实例化的配置对象。
当实例化一个配置对象之后,在使用它创建一个PKAddPaymentPassViewController实例之前,也必须设置cardholderNameprimaryAccountSuffix属性

cardholderName:显示在卡上面的姓名
encryptionScheme:用于该请求的加密机制
localizedDescription:对卡片简短的描述。
paymentNetwork:支付系统,默认为nil。该属性判断哪些卡片可以展示在PKAddPaymentPassViewController类的实例中并显示到屏幕上。PKAddPaymentPassViewController展示卡片区域的所有支持的系统。为了指定一个单一的系统,可指派给该属性一个常量。可查看PKPyamentRequest类的Payment Networks的介绍。
primaryAccountSuffix:后四位或五位卡号
primaryAccountIdentifier:卡号账户的标识,筛选卡库Filtering Pass Libraries 筛选卡库(来自不同的设备 iPhone,iPhone Watch) Constants 常量

Encryption Schemes加密体制

NSString * const PKEncryptionSchemeECC_V2

PKAddPaymentPassViewController

使用提供的配置和代理,返回一个初始化的添加支付的视图控制器实例

/* This controller should be presented with -[UIViewController presentViewController:animated:completion:].
     */
    public init?(requestConfiguration configuration: PKAddPaymentPassRequestConfiguration, delegate: PKAddPaymentPassViewControllerDelegate?)

configuration 配置实例:定义视图控制器的外观
delegate 添加支付视图控制器的代理
返回值:一个新的添加支付的视图控制器

添加Payment Pass支付卡需要一个特殊的由苹果发行的授权。如果app中不包括这个授权,该方法返回值为nil

PKAddPaymentPassViewControllerDelegate 代理

PKAddPaymentPassViewController类的代理必须遵守该协议。该协议定义了两个必需实现的方法。这些方法使系统提示添加支付请求和当请求失败或成功的时候法通知app。

func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, generateRequestWithCertificateChain certificates: [Data], nonce: Data, nonceSignature: Data, completionHandler handler: @escaping (PKAddPaymentPassRequest) -> Void)

controller 添加支付请求的视图控制器
certificates NSData对象的数组。每个对象包括一个DER编码的证书。必须下载根目录CA验证整个链。
nonce 苹果服务器生成的一次性随机值,该随机值必须被包含在添加支付请求的加密数据中。
nonceSignature 有特定设备的签名的随机值。该签名必须被包含在添加支付请求的加密数据中。
handler 完工的处理者。当创建支付请求之后回调该Block。Block中的参数:request 一个新创建的添加支付请求,必须20秒之内传送该请求实例给处理者否则该请求将失败,系统将为用户显示一个错误信息。

该方法提供需要创建一个添加支付请求的书。通过证书束缚在发行者服务器上。该服务器返回一个包含卡数据的加密的JSON文件。当收到加密数据之后,创建一个添加支付请求并回调处理者。
更多关于加密卡数据的信息,可以查看PKPaymentRequest类里的encryptedPassData属性。

func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, didFinishAdding pass: PKPaymentPass?, error: Error?)

controller 添加支付请求的视图控制器
pass 完成的卡,如果有错误,返回nil
error如果请求失败,该参数包含错误对象(PKPassKitErrorDomamin域错误) 。更多可能的错误代码,可查看枚举PKAddPaymentPassError。
当请求成功地添加卡片到Apple Pay或者失败时,调用该方法。

//----苹果支付-----
PKPaymentRequest 订单请求对象
PKPaymentSummaryItem 商品订单信息对象

配置商品价格,送货方式等

-(instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount;
- (instancetype)summaryItemWithLabel:(NSString *)label amount:(NSDecimalNumber *)amount type:(PKPaymentSummaryItemType)type API_AVAILABLE(ios(9.0), watchos(3.0));
PKPaymentAuthorizationViewController 苹果支付请求控制器
初始化方法
- (nullable instancetype)initWithPaymentRequest:(PKPaymentRequest *)request NS_DESIGNATED_INITIALIZER;
PKPaymentAuthorizationViewControllerDelegate 代理方法

//支付银行卡回调,如果需要根据不同的银行调整付费金额,可以实现该代理
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectPaymentMethod:(PKPaymentMethod *)paymentMethod completion:(void (^)(NSArray<PKPaymentSummaryItem *> * _Nonnull))completion

//支付凭据,发给服务端进行验证支付是否真实有效
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus status))completion

//支付完成
- (void) paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值