手机扫护照混合 App — 开发计划
-工程代号 passport-nfc-app。目标:用手机 NFC 读取带芯片的电子护照(eMRTD),读出 MRZ、基本信息、芯片头像并做真伪验证。本文档为立项与分阶段实施计划。最后更新 2026-11-10。
-一句话:用 Capacitor + Angular 做壳,护照芯片读取由自定义原生插件完成(iOS 用 NFCPassportReader,Android 用 jMRTD)。双端、全深度(MRZ + DG1 + DG2 头像 + PA 验真),先做独立 Demo,暂不接后端。
-
-
-1. 已确认的决策
-
-
-
-
-
-| 决策项 | 结论 | 理由 |
|---|---|---|
| 技术栈 | Capacitor + Angular | 贴合现有 AML_Frontend / justsolutionsWeb 的 Angular 技术栈,H5 可复用,NFC 走原生插件 |
| 目标平台 | iOS + Android | 两端都要覆盖;实施上 Android 优先 |
| 读取深度 | MRZ + DG1 + DG2 头像 + PA 被动认证 | KYC 防伪必须验签(PA) |
| 后端集成 | 先做独立 Demo | 先验证可行性,后续再接 ScanCertificateV2 |
2. 技术约束与现实(必须先知道)
-
-
-
--
-
- 网页读不了护照芯片。Web NFC(
NDEFReader)只支持 NDEF、仅安卓 Chrome,不暴露 APDU;护照需要 ISO-DEP / APDU + BAC/PACE,只能走原生。所以本项目重心在原生插件,不在 H5。
- - iOS NFC 门槛高。需要 付费 Apple 开发者账号才能开 NFC entitlement(
com.apple.developer.nfc.readersession.iso7816,AID 需含 eMRTDA0000002471001);NFC 不能在模拟器跑,必须 iPhone 7+ / iOS 13+ 真机。
- - Android 需真机。需带 NFC 的真机,模拟器无 NFC。 -
- 测试需要实体护照。每个阶段验证都要一本带芯片的护照 + 对应 MRZ。 -
- 必须先有 MRZ。MRZ 的「护照号 + 出生日期 + 有效期」是开芯片 BAC/PACE 的钥匙,缺它读不了芯片。 -
3. 架构总览
-┌─────────────────────────────────────────────┐ -│ Angular (WebView) —— 界面层 │ -│ 输入/OCR MRZ → 调插件 → 展示字段/头像/验真结果 │ -└───────────────┬─────────────────────────────┘ - │ Capacitor Bridge (JS ↔ Native) -┌───────────────┴─────────────────────────────┐ -│ 自定义插件 PassportNfc.readPassport(mrzKey) │ -│ ├─ iOS : Swift + NFCPassportReader │ -│ └─ Android: Kotlin + jMRTD + SpongyCastle │ -│ BAC/PACE → 读 DG1/DG2 → PA 验签 │ -└──────────────────────────────────────────────┘- -
4. 关键原生库选型
-均为业界事实标准,避免自己实现密码学与协议栈。
-
-
-
-
-
-| 平台 | 库 | 语言 / 许可 | 能力 |
|---|---|---|---|
| iOS | NFCPassportReader(AndyQ) | Swift / MIT | BAC + PACE、DG1/DG2、PA(可带 CSCA masterlist)、AA |
| Android | jMRTD + SCUBA + SpongyCastle | Java/Kotlin / LGPL | BAC + PACE、全数据组、PA、AA |
| MRZ OCR(P4) | ML Kit Text Recognition 或 Tesseract | — | 摄像头识别 MRZ 两行,替代手输 |
5. App 核心流程
--
-
- 输入或摄像头扫描 MRZ → 得到
护照号 + 出生日期 + 有效期
- - 点「贴卡读取」→ 调
PassportNfc.readPassport({ mrzKey })
- - 原生层:13.56MHz 供电 → BAC/PACE 开安全通道 → 读 DG1(文本)、DG2(头像)、EF.SOD -
- PA 被动认证:SOD → DSC → CSCA 证书链校验 -
- 回传 JSON + 头像 base64 + 验真结论 → Angular 展示 -
6. 建议工程结构
-passport-nfc-app/ -├── docs/ 本计划等文档 -├── src/ Angular 界面(MRZ 输入页、读取页、结果页) -├── capacitor.config.ts -├── android/ cap add android 后生成 -├── ios/ cap add ios 后生成 -└── plugins/passport-nfc/ 自定义 Capacitor 插件 - ├── src/ TS 接口 definitions / web 桩 - ├── android/ Kotlin + jMRTD 实现 - └── ios/ Swift + NFCPassportReader 实现- -
7. 分阶段路线图
-
-
-
-
-
-| 阶段 | 内容 | 产出 / 验收 | 工具链前置 |
|---|---|---|---|
| P0 | 搭 Capacitor + Angular 骨架 + 插件 TS 接口与 web 桩 | Web 壳能跑;插件接口定义完成 | Node(已就绪) |
| P1 | Android 优先:Kotlin 插件接 jMRTD,手输 MRZ,读 DG1/DG2 | 安卓真机扫出芯片文本 + 头像 | JDK + Android Studio + 安卓真机 |
| P2 | PA 被动认证 + 头像展示 + 错误/超时处理 + UI 打磨 | 安卓完整 Demo,含验真结论 | 同上 + CSCA masterlist |
| P3 | iOS:Swift 插件接 NFCPassportReader,配 entitlement | iPhone 真机双端打通 | Xcode + CocoaPods + iPhone + 付费账号 |
| P4 | MRZ 摄像头 OCR,替代手输;体验完善 | 扫 MRZ 自动填充 | ML Kit / Tesseract |
| P5 | (可选)接 AML 后端 ScanCertificateV2,与柜台扫描仪统一口径 | 读取结果入 KYC 流程 | 后端联调 |
8. 本机工具链现状
-
-
-
-
-
-| 工具 | 状态 | 用途 | 动作 |
|---|---|---|---|
| Node 24 / npm 11 | 已就绪 | Capacitor + Angular | — |
| JDK | 未装 | Android 构建 | P1 前装(Android Studio 自带) |
| Android SDK / Studio | 未装 | Android 构建 / 真机部署 | P1 前装 |
| Xcode | 未装 | iOS 构建 | P3 前装 |
| CocoaPods | 未装 | iOS 依赖 | P3 前装 |
| 付费 Apple 开发者账号 | 待确认 | iOS NFC entitlement | P3 前准备 |
9. 风险与合规
-
-
-
--
-
- 隐私:护照芯片含姓名、证件号、头像等敏感个人信息。Demo 阶段不落盘、不上传,仅内存展示;接后端时按现有 KYC 的数据口径与脱敏要求处理。 -
- PA 验签依赖 CSCA masterlist:完整被动认证需各签发国 CSCA 证书(来源 ICAO PKD)。Demo 可先做 SOD 哈希一致性 + DSC 签名校验,masterlist 到位后再补全证书链。 -
- iOS 政策风险:NFC entitlement 需付费账号并审批;若账号/设备不具备,P3 会被阻塞,但不影响 P0–P2 的 Android 路线。 -
- 库许可:jMRTD/SCUBA 为 LGPL,注意引用方式与分发合规。 -
- 兼容性:不同国家/版本护照数据组与安全机制(BAC vs PACE)不一,需多本护照回归测试。 -
10. 验收标准(Demo Done)
--
-
- 安卓真机:输入 MRZ → 贴卡 → 读出 DG1 文本字段 + DG2 头像,PA 给出通过/失败结论 -
- iOS 真机:同等能力打通 -
- 读取失败(MRZ 错、芯片读不到、验签失败)有明确提示,不崩溃 -
- 全程不持久化敏感数据 -
11. 下一步
-
-P0 立即可做(无需原生工具链):初始化
-之后进入 P1 需先安装 JDK + Android Studio 并准备一台带 NFC 的安卓真机 + 一本实体护照。 -
-
-
-
-passport-nfc-app 的 Capacitor + Angular 骨架,定义 PassportNfc 插件接口与 web 桩,搭好 MRZ 输入 / 结果展示两个页面。-之后进入 P1 需先安装 JDK + Android Studio 并准备一台带 NFC 的安卓真机 + 一本实体护照。 -