4

I've been working on the app where I need to implement tap & pay. I am able to connect the HCE service with NFC terminal.

Now my question is what are the next steps, for making actual payment with it?

I've searched everywhere but I could not find a decent document for it. Please help me.

Below is the code I have written to connect HCE service to NFC terminal.

Android Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.nfcemulator">

    <uses-permission android:name="android.permission.NFC" />

    <uses-feature android:name="android.hardware.nfc.hce"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.NFCEmulator">

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".service.HCEService"
            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>

    </application>

</manifest>

HCE Service

class HCEService: HostApduService() {

    companion object {
        val TAG = "Host Card Emulator"
        val STATUS_SUCCESS = "9000"
        val STATUS_FAILED = "6F00"
        val CLA_NOT_SUPPORTED = "6E00"
        val INS_NOT_SUPPORTED = "6D00"
        val AID = "A0000002471001"
        val SELECT_INS = "A4"
        val DEFAULT_CLA = "00"
        val MIN_APDU_LENGTH = 12
    }

    override fun onDeactivated(reason: Int) {
        Log.d(TAG, "Deactivated: " + reason)
    }

    override fun processCommandApdu(commandApdu: ByteArray?, extras: Bundle?): ByteArray {

        if (commandApdu == null) {
            return Utils.hexStringToByteArray(STATUS_FAILED)
        }

        val hexCommandApdu = Utils.toHex(commandApdu)
        if (hexCommandApdu.length < MIN_APDU_LENGTH) {
            return Utils.hexStringToByteArray(STATUS_FAILED)
        }

        if (hexCommandApdu.substring(0, 2) != DEFAULT_CLA) {
            return Utils.hexStringToByteArray(CLA_NOT_SUPPORTED)
        }

        if (hexCommandApdu.substring(2, 4) != SELECT_INS) {
            return Utils.hexStringToByteArray(INS_NOT_SUPPORTED)
        }

        if (hexCommandApdu.substring(10, 24) == AID)  {
            return Utils.hexStringToByteArray(STATUS_SUCCESS)
        } else {
            return Utils.hexStringToByteArray(STATUS_FAILED)
        }

    }

}

apduservices.xml

<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/hce_service"
    android:requireDeviceUnlock="false">
    <aid-group android:description="@string/aid_groups"
        android:category="other">
        <aid-filter android:name="325041592E5359532E4444463031"/>
    </aid-group>
</host-apdu-service>
Jay
  • 497
  • 6
  • 17
  • `What are the next steps, for making actual payment with it?` sounds like you are trying to build your own tap-to-pay system, which is a rather broad topic. I hope you are aware of the various issues when this tech was introduced: https://www.securetechalliance.org/wp-content/uploads/HCE-101-WP-FINAL-081114-clean.pdf – Morrison Chang Dec 20 '21 at 05:45
  • yes, that's correct. – Jay Dec 20 '21 at 06:29
  • For future visitors, it may help to watch: [ByteByteGo - How Does Apple/Google Pay Work?](https://youtu.be/cHv8LqkbPHk) to understand the backend interaction outside of the mobile device. – Morrison Chang Oct 29 '22 at 23:23

1 Answers1

0

I think you have approached this feature at a low level, which is unnecessary given that this functionality is offered when using Google Pay (it supports NFC payments as well as online purchases).

All you need to know about Google Pay if you’re a developer

The Flutter pay plugin is the quickest method to add payment capabilities for your Android app.

Google Pay introduces a Flutter plugin for payments

Pay plugin 1.0.6

ahaghdan
  • 178
  • 7
  • I am trying to create own payment app, is there any way to send the selected card's information to NFC reader and it can use it to make transaction, without needing to use google pay? @ahaghdan – Jay Dec 27 '21 at 10:07