能否将 Android 手机的 NFC 用作 EMV Payment POS 终端?
结论
Android 手机的 NFC 在技术上可以与非接触式 EMV 卡通信,但普通手机不能仅靠应用读取卡片数据,再将其发送给 payment gateway,就变成可商用的银行卡 POS。
实际项目应采用 SoftPOS / Tap to Phone / Tap on Phone 方案,并满足收单机构、银行卡组织、EMVCo 和 PCI SSC 的认证要求。认证对象通常是完整的“支付受理解决方案”,而不只是 APK。手机属于 COTS(Commercial Off-The-Shelf)设备,也要符合方案对设备型号、Android 版本、安全能力和完整性的要求。
因此:
- NFC/EMV 技术验证是可行的。
- 自行实现完整 EMV kernel 并直接上线收款,理论上可行,但商业成本和认证难度都很高。
- 与收单机构合作并使用已认证的 SoftPOS SDK,通常是更合适的路径。
- 仅通过 PCI DSS,不能让应用成为合规的 POS 产品。
为什么不能只是读取卡片再提交网关
一次 EMV 非接触交易并不是简单地“读取卡号,然后扣款”。终端需要完成一整套状态机和密码学交互,包括:
- 选择支付环境和银行卡应用。
- 读取卡片支持的应用及能力。
- 根据终端、卡片和交易参数执行处理限制。
- 完成终端风险管理和 CVM(Cardholder Verification Method)判断。
- 生成 ARQC 等动态交易数据。
- 将 EMV 数据元素组装成授权请求。
- 由收单机构将请求送入对应的银行卡组织网络。
- 正确处理批准、拒绝、重试、反转和异常中断。
Payment gateway 还必须明确支持 card-present EMV contactless 交易。普通在线支付 API 往往只接收 PAN、有效期和 CVC。如果用这类 API 提交通过 NFC 读取的数据,交易可能被识别为 card-not-present,既不合规,也无法获得 EMV 交易对应的责任转移和风控待遇。
读到的银行卡数据也不能通过自定义接口随意上传。虽然 EMV 卡上的部分数据可以通过 APDU 读取,但这些数据的存储、日志记录和传输仍受 PCI DSS、隐私保护要求及收单规则约束。
Android 能提供什么能力
Android 提供 NFC Reader Mode,可用于发现 ISO-DEP 卡片,并通过 IsoDep.transceive() 收发 ISO 7816-4 APDU。
常见入口包括:
NfcAdapter.enableReaderMode()TagIsoDep- ISO/IEC 14443 Type A、Type B
- ISO/IEC 7816-4 APDU
这些 API 只提供底层通信通道,不包含经过认证的 EMV contactless kernel。应用仍要处理交易状态、TLV 编解码、超时、卡片移除、冲突检测、异常恢复和安全控制。
下面的代码只演示如何检测 ISO-DEP 卡并选择 PPSE,适合实验和学习,不构成完整的支付实现:
import android.app.Activity
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.IsoDep
import android.os.Bundle
import android.util.Log
class MainActivity : Activity(), NfcAdapter.ReaderCallback {
private var nfcAdapter: NfcAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
nfcAdapter = NfcAdapter.getDefaultAdapter(this)
}
override fun onResume() {
super.onResume()
val flags =
NfcAdapter.FLAG_READER_NFC_A or
NfcAdapter.FLAG_READER_NFC_B or
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK
nfcAdapter?.enableReaderMode(this, this, flags, null)
}
override fun onPause() {
nfcAdapter?.disableReaderMode(this)
super.onPause()
}
override fun onTagDiscovered(tag: Tag) {
val isoDep = IsoDep.get(tag) ?: return
try {
isoDep.connect()
isoDep.timeout = 5000
// SELECT "2PAY.SYS.DDF01" (PPSE)
val selectPpse = hexToBytes(
"00A404000E325041592E5359532E444446303100"
)
val response = isoDep.transceive(selectPpse)
// 支付应用中不要记录完整 APDU、PAN 或其他敏感数据。
Log.d("NFC", "Response length=${response.size}")
} catch (e: Exception) {
Log.e("NFC", "ISO-DEP communication failed", e)
} finally {
try {
isoDep.close()
} catch (_: Exception) {
}
}
}
private fun hexToBytes(value: String): ByteArray {
require(value.length % 2 == 0)
return ByteArray(value.length / 2) { index ->
value.substring(index * 2, index * 2 + 2).toInt(16).toByte()
}
}
}
生产环境不能停留在 APDU 通信层。SELECT PPSE 之后还有应用选择、GPO、AFL、记录读取、CVM、GENERATE AC 等流程,而且各支付网络的 contactless kernel 和规则并不完全相同。
商用方案需要哪些认证
具体认证范围取决于产品架构、收单地区、支持的支付网络以及是否接受 PIN,通常涉及以下几层。
EMVCo 和支付网络认证
POS 受理方案一般需要考虑:
- EMVCo Contactless Level 1:射频、模拟和数字通信层。
- EMVCo Contactless Level 2:支付 kernel 和交易逻辑。
- 对应支付网络的 kernel、终端和端到端认证。
- 收单机构或处理机构的 host certification。
- ISO 8583 或收单方定义的 API 等交易消息格式。
Android 提供 NFC API,并不代表手机已经取得这些支付受理认证。
PCI 要求
以下几个概念需要分别理解:
- PCI DSS:用于保护持卡人数据相关的系统、服务端、网络和运营环境。
- PCI Software Security Framework:适用于特定支付软件场景的软件安全要求。
- PCI CPoC:面向商用现成移动设备的非接触支付受理。
- PCI MPoC:覆盖范围更完整的移动支付受理方案,可以包含 PIN 等能力。
- 其他 PIN、密钥管理或点对点加密要求:是否适用,要看具体方案设计。
PCI DSS 合规不能代替 EMV 和银行卡组织认证,EMV 认证也不能代替 PCI DSS。
手机是否需要单独认证
售票应用开发者通常不需要为每台手机单独申请一张“PCI 证书”,但这也不意味着所有支持 NFC 的 Android 手机都能使用。
经过评估的 SoftPOS 方案一般会规定:
- 支持的设备型号或最低硬件能力。
- Android 版本及安全补丁级别。
- NFC 控制器和固件要求。
- 硬件支持的密钥保护或可信执行环境。
- Bootloader、root、调试和屏幕覆盖检测。
- 应用签名与运行时完整性验证。
- 设备证明、远程监控和撤销机制。
- 禁止或限制使用的设备状态。
认证对象通常是由应用、SDK、后端服务、安全监控机制和受支持设备条件共同组成的完整 solution。某台设备是否符合要求,应以解决方案提供方、实验室、收单机构和支付网络的规定为准。
推荐的实施步骤
1. 先确定交易和地区范围
至少需要明确:
- 接受实体非接触银行卡,还是同时接受 Apple Pay、Google Pay 等钱包。
- 支持哪些银行卡组织。
- 单笔金额和累计金额限制。
- 是否需要输入 PIN。
- 是否只做在线授权。
- 网络中断时是否允许交易。
- 由谁处理退款、撤销、冲正和对账。
是否支持 PIN 会明显影响技术架构和认证范围。由普通应用自行绘制 PIN 输入界面不符合合规要求。
2. 联系收单机构,而不是先找普通网关 API
应向收单机构确认是否提供:
- SoftPOS 或 Tap to Phone 产品。
- 已认证的 Android SDK。
- 支持的国家、币种和银行卡组织。
- 设备兼容列表。
- 测试卡、测试环境和认证流程。
- 交易、撤销、退款、对账及电子凭证接口。
如果现有 gateway 只支持电商交易,就需要另行接入支持 EMV card-present 的处理通道。
3. 集成已认证的 SoftPOS SDK
大多数项目没有必要自行编写 EMV kernel。已认证的 SDK 通常会封装:
- NFC 交互和 EMV kernel。
- 设备完整性检测。
- 敏感数据保护。
- 终端参数和公钥管理。
- 在线授权请求。
- PIN 或 CDCVM 相关流程。
- 交易生命周期、反转和审计日志。
完成 SDK 集成后,项目仍可能需要通过应用级、收单端或端到端认证。SDK 已获认证,不等于整个产品自动获得认证。
4. 设计正确的交易生命周期
火车售票场景至少要处理以下流程:
- 售票员输入票价并确认交易。
- 应用锁定交易金额,避免在读卡过程中被修改。
- 提示乘客将卡片或钱包贴近手机的 NFC 区域。
- SDK 执行 contactless transaction。
- 将授权请求发送到收单端。
- 明确显示批准、拒绝或未知状态。
- 对超时和断网交易进行状态查询或反转。
- 生成脱敏凭证。
- 乘客明确提供或确认邮箱后,再发送电子收据。
- 通过幂等机制关联支付结果和车票订单。
客户端没有收到成功响应,不能直接视为支付失败,因为授权可能已经在服务端完成。
开发时应重点阅读的资料
可以按以下顺序了解相关资料:
- Android NFC Reader Mode、
Tag和IsoDep文档。 - ISO/IEC 14443 和 ISO/IEC 7816-4。
- EMVCo Contactless Specifications。
- 各银行卡组织的 contactless acceptance 规则。
- PCI SSC 的 CPoC、MPoC、PCI DSS 及相关 FAQ。
- 目标收单机构的 SoftPOS SDK 和 host certification 文档。
部分完整规范、测试工具或银行卡组织资料,可能要在注册、获得授权或签署协议后才能获取。
重要注意事项
- 不要在日志、崩溃报告、分析平台或电子邮件中保存完整 PAN、Track 2 Equivalent Data、密钥或原始 APDU。
- 电子收据只应展示脱敏卡号、金额、时间、商户和交易参考号等必要信息。
- 不能读取或保存磁条等效数据,再将其用于后续交易。
- 除非整个方案已经按照适用标准完成评估,否则不要自行实现 PIN 输入。
- 消费级手机的 NFC 天线位置、射频性能和厂商固件各不相同,必须在方案支持的设备范围内测试。
- 手机存在 root、bootloader 解锁、安全补丁过旧或完整性校验失败等情况时,方案通常应拒绝受理交易。
- 交易成功页面、电子邮件和支付网关响应,都不能单独代替服务端账务状态。
- 如果交通场景要求快速过闸、离线受理或聚合扣款,其复杂度会高于人工售票 SoftPOS,可能仍需使用专用 validator。
更现实的起点是先确定目标地区和收单机构,再选择其认可的 PCI CPoC/MPoC SoftPOS 方案,而不是自行实现完整的 EMV 协议。Android NFC 提供的是通信能力。经过认证的 kernel、安全架构、收单连接和运营体系,才让手机具备 POS 受理能力。
备注:内容仅供参考。
