为什么我的HCE应用程序重置了物理POS设备



我在华为手机(Android 10(上玩基于主机的卡仿真(HCE(。我的第一个目标是让我的手机知道销售点(POS(正在与它通话。到目前为止,我不需要用它付款。由于我不知道如何在家里可靠地测试我的应用程序,我麻烦了当地的面包店(在法国,每天去一次面包店并不罕见(。

不幸的是,今天早上,当我在实际的面包店POS上测试我的应用程序时,POS重置为0.00,尽管我的应用processCommandApdu功能没有触发。我试着第二次接近我的手机(面包师重新输入金额后(,POS再次重置,我的应用程序侧没有显示任何消息(谷歌支付也没有显示,因为它没有被设置为NFC的默认应用程序(。我没有第三次尝试(因为在场的其他客户(,而是用我的NFC信用卡付款。

请注意,我的手机NFC设置如下:NFC已启用,默认应用程序为我的应用程序,并使用当前运行的应用程序。

我遵循了本指南以及HCE上的Android文档。所以我的apduservice.xml注册了维基百科上显示的所有Visa卡AID,看起来像:

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/servicedesc"
android:requireDeviceUnlock="false">
<aid-group
android:category="payment"
android:description="@string/aiddescription">
<aid-filter android:name="A0000000031010"/>
<aid-filter android:name="A0000000032010"/>
<aid-filter android:name="A0000000032020"/>
<aid-filter android:name="A0000000038010"/>
</aid-group>
</host-apdu-service>

HCE服务类似

class HostCardEmulatorService : HostApduService() {
companion object {
val TAG = "Host Card Emulator"
val STATUS_SUCCESS = "9000"
val STATUS_FAILED = "6F00"

}
/**
* The function always returns success as this is just a test
*/
override fun processCommandApdu(commandApdu: ByteArray?, extras: Bundle?): ByteArray {
Toast.makeText(this, "ProcessCommandApdu called with n $commandApdu", Toast.LENGTH_SHORT).show()
println("ProcessCommandApdu called!")
return Utils.hexStringToByteArray(STATUS_SUCCESS)

}
/**
* The `onDeactiveted` method will be called when the a different AID has been selected or the NFC connection has been lost.
*/
override fun onDeactivated(reason: Int) {
Toast.makeText(this, "Connection lost because of $reason!", Toast.LENGTH_SHORT).show()
}
}

清单文件需要NFC权限并要求NFC服务:

<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-permission android:name="android.permission.NFC_TRANSACTION_EVENT" />
... (standard ANdroid project)
<service
android:name=".HostCardEmulatorService"
android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
</intent-filter>
<meta-data
android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/apduservice" />
</service>

MainActivity启动/停止HCE服务:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//...
val hceService: HostCardEmulatorService = HostCardEmulatorService()
val hceIntent = Intent(applicationContext, HostCardEmulatorService::class.java)
binding.mainButton.setOnClickListener {
when (serviceEnabled) {
false -> {
applicationContext.startService(hceIntent)
if (isServiceRunning(HostCardEmulatorService::class.java)) {
binding.output.setText("Service enabled!")
// Changing state
serviceEnabled = true;
}
}
true -> {
applicationContext.stopService(hceIntent)
binding.output.setText("Service disabled!")
// Changing state
serviceEnabled = false;
}
}
}
}

现在我想知道为什么我的应用程序processCommandApdu功能没有触发,而POS显然到达了我手机上的某个地方?

此外,我能否通过NFC阅读器应用程序,用另一部支持NFC的手机可靠地测试我的第一个目标(检测到POS正在与我的应用程序通话(,这样我就不会每天用我的极客测试来打扰面包师了?我的意思是,在另一部手机上运行的NFC阅读器应用程序是否足以像实际的POS一样触发我的应用程序processCommandApdu

最后(如果可以回答的话(将实际POS重置为0.00,并且没有保留该金额;成功命令";在processCommandApdu函数中(在这种情况下,这意味着函数运行了,但toast消息没有出现,或者我错过了它(?

感谢任何帮助:-(

因此,由于这个较老的So问题,我关于processCommandApdu函数不触发的第一个问题可以得到回答。事实上,它没有触发,因为它没有期望EMV POS发送的应用程序ID。该AID对应于PPSE(接近支付系统环境(,PPSE请求智能卡支持的所有AID的列表。

apduservice.xml中使用该PPSE AID使HCE服务按预期工作

<aid-filter android:name="325041592E5359532E4444463031"/>

关于我的应用程序的测试,使用NFC读卡器不起作用,因为他们不像EMV POS那样发送PPSE AID。编写我自己的应用程序发送这个特殊的AID应该可以工作。

就EMV POS显示的金额重置而言,这可能是由Sim卡NFC芯片或移动NFC天线以某种POS没有预料到的方式反应引起的。

最新更新