ProximityReader 是一个面向 Apple ProximityReader 框架的 iOS 开发技能,用于在 iPhone 上构建非接触式支付、会员卡和身份证件验证功能,无需额外 NFC 硬件。
适用场景
该技能适用于以下开发任务:集成 Tap to Pay on iPhone(非接触式支付受理);从 Apple Wallet 读取会员卡 / VAS 通行证;实现离线支付场景的 Store and Forward;使用 Verifier API 构建证件验证(移动驾照、国家身份证);通过 ProximityReaderDiscovery 展示商户教育 UI;调试 PaymentCardReaderError 或 MobileDocumentReaderError。
框架概览
ProximityReader 支持 iOS 15.4+、iPadOS 15.4+、Mac Catalyst 15.4+,让 iPhone 充当非接触式读卡器,覆盖以下领域:
- 支付(Payments):PaymentCardReader、PaymentCardReaderSession,最低 iOS 15.4
- 会员卡(Loyalty / VAS):VASRequest、VASReadResult,最低 iOS 15.4
- 存储与转发(Store & Forward):StoreAndForwardPaymentCardReaderSession、PaymentCardReaderStore,iOS 17.0+
- 证件验证(ID Verification):MobileDocumentReader、MobileDocumentReaderSession,iOS 17.0+
- 商户发现(Merchant Discovery):ProximityReaderDiscovery,iOS 18.0+
架构上,应用层包含支付流程、会员卡(VAS)、存储与转发、证件验证等模块,其下为 ProximityReader 框架,最底层为安全元件 / NFC 硬件。
前置条件与授权
编写代码前需确保:
- 授权(Entitlement):需通过开发者账号向 Apple 申请 Tap to Pay on iPhone 授权,否则框架无法工作。
- 支付服务提供商(PSP):必须与 Level 3 认证的 PSP(如 Stripe、Adyen、Square、Windcave)协作。PSP 提供初始化读卡器所需的 reader token(JWT)。
- 设备:iPhone XS 或更新机型,无需额外 NFC 硬件。
- Xcode:在应用的 entitlements 文件中添加 com.apple.developer.proximity-reader.payment.acceptance 授权。
对于 Verifier API(证件读取),需要单独的授权以及服务端生成 reader token,详见 references/verifier-api.md。
常见使用模式
技能文档给出多种常见代码模式:
-
支付卡读取(Tap to Pay):创建并配置 PaymentCardReader;从 PSP 获取 token;首次使用时关联商户账号(linkAccount);创建 PaymentCardReaderSession 并调用 prepare();通过 PaymentCardTransactionRequest 发起读取,将结果中的 paymentCardData 发送给 PSP 处理。
-
会员卡(VAS)读取:可通过 VASRequest 单独读取,也可与支付读取组合;读取支付卡时传入 vasRequest,结果中的 vasReadResult 包含会员标识数据。
-
存储与转发(离线):使用 StoreAndForwardPaymentCardReaderSession 在本地存储交易;联网后通过 PaymentCardReaderStore 获取批次(allBatches),将 batch.data 发送给 PSP,成功后使用 deletionToken 删除批次。
-
移动证件 / ID 读取(Verifier API):使用 MobileDocumentReader,从服务端获取 reader token;创建 MobileDocumentReaderSession 并 prepare();通过 MobileDriversLicenseDisplayRequest 或 MobileDriversLicenseDataRequest 请求证件展示或数据。
-
商户发现 UI:iOS 18+ 可使用 ProximityReaderDiscovery 展示 Apple 提供的商户教育界面。
错误处理
所有 ProximityReader 调用应使用 do-catch 包裹。主要错误类型包括:
- PaymentCardReaderError:如 notAllowed(缺少授权或未授权)、unsupported(设备不支持 Tap to Pay)、networkError(连接问题)、invalidReaderToken(PSP 令牌无效或过期)、readerBusy(已有读取会话进行中)、backgrounded(读取期间应用进入后台,需重新调用 prepare())等。
- PaymentCardReaderSession.ReadError:如 cancelled(顾客取消)、invalidAmount(金额为负或为零)、notReady(未调用 prepare())等。
- Verifier API:需处理 MobileDocumentReaderError。
关键实现注意事项
- 应用回到前台后必须重新调用 prepare()。读卡器会话在进入后台时失效,可安全多次调用。
- 每次交易后调用 prepare() 以重置内部状态,供下一次交易使用。
- reader token(JWT)来自 PSP,而非直接来自 Apple。每个 PSP 有自己的令牌生成流程。
- iOS 16.4+ 支持对需要 PIN 的非接触式卡进行 PIN 输入。
- 测试:可使用 ProximityReaderStub 进行模拟器测试;真实 NFC 读取需要物理设备。
- 线程安全:ProximityReader 使用 Swift 并发(async/await),所有调用应在 main actor 或适当的 actor 上下文中进行。
- 存储与转发:批次持久保存在设备上,成功处理后务必删除,避免数据堆积。
代码生成准则
生成 ProximityReader 代码时应:始终 import ProximityReader;使用 Swift 并发(async/await),整个 API 均为异步;将所有读卡器操作包裹在带具体错误处理的 do-catch 中;在回到前台后和每次交易后包含 prepare() 调用;绝不硬编码 PSP 令牌,始终从服务端 / PSP SDK 获取;SwiftUI 中使用 .task {} 修饰符或 @MainActor 视图模型;在尝试使用读卡器前始终检查设备能力;遵循 Apple HIG,点击支付表单由系统提供,不要自行重建。
深入参考文档
技能包含以下参考文件:references/api-reference.md(完整类 / 结构体 / 枚举列表及属性与方法)、references/verifier-api.md(Verifier API 完整设置,含服务端令牌生成)、references/integration-patterns.md(PSP 集成模式、SwiftUI 模式、MVVM 架构)、references/troubleshooting.md(常见错误、调试技巧、设备兼容性)。