Getting Payment Card Information with NFC

ibrahimertanylmz
Huawei Developers
Published in
4 min readOct 25, 2023
High Tech Internet GIF By Matthew Butler

Introduction

Hi everyone! 👋 This article is based on Getting Payment Card Information using NFC for an Android Application in Kotlin. There is a helper library named “EMV NFC Paycard Enrollment” Java library used to read and extract public data from NFC EMV credit cards. We will get basic credit card data like card numbers and expiration date with NFC. Let’s check out more about NFC and develop our sample application!

What is NFC?

NFC

NFC (Near-field communication) is a set of communication protocols that enables communication between two electronic devices over a distance of 4 cm or less. NFC offers a low-speed connection through a simple setup that can be used to bootstrap more capable wireless connections.

If you want to learn more about Android Development with NFC, you can check out NFC Basics and Advanced NFC from the links.

Development Process

Let’s start the development part. Firstly add the necessary permissions to the AndroidManifest file. Add the following NFC and Vibrate Permissions.

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

Then add EMV NFC Paycard Enrollment library implementation to app level build gradle.

implementation 'com.github.devnied.emvnfccard:library:3.0.1'

Then you need to create a custom Provider to exchange APDU with an NFC EMV credit card and for android, you can create a provider with IsoDep class:

class PcscProvider : IProvider {

private lateinit var mTagCom: IsoDep

@Throws(CommunicationException::class)
override fun transceive(pCommand: ByteArray?): ByteArray? {
var response: ByteArray? = null
try {
// send command to emv card
if (mTagCom.isConnected) {
response = mTagCom.transceive(pCommand)
}
} catch (e: IOException) {
throw CommunicationException(e.message)
}
return response
}

override fun getAt(): ByteArray {
var result: ByteArray?
result = mTagCom.historicalBytes // for tags using NFC-B
if (result == null) {
result = mTagCom.hiLayerResponse // for tags using NFC-B
}
return result
}

fun setmTagCom(mTagCom: IsoDep) {
this.mTagCom = mTagCom
}
}

Now let’s create an NFC adapter and initialize it in onCreate method. Also the Activity should implement ReaderCallBack to override onTagDiscovered method.

class MainActivity : AppCompatActivity(), ReaderCallback {
private var mNfcAdapter: NfcAdapter? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mNfcAdapter = NfcAdapter.getDefaultAdapter(this)
}
...

Then inside onResume function presence delay and reader mode for NfcAdapter should be set. Enable ReaderMode for all types of card and disable platform sounds.

override fun onResume() {
super.onResume()
if (mNfcAdapter != null) {
val options = Bundle()
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250)

mNfcAdapter!!.enableReaderMode(
this,
this,
NfcAdapter.FLAG_READER_NFC_A or
NfcAdapter.FLAG_READER_NFC_B or
NfcAdapter.FLAG_READER_NFC_F or
NfcAdapter.FLAG_READER_NFC_V or
NfcAdapter.FLAG_READER_NFC_BARCODE or
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
options
)
}
}

Then override the onTagDiscovered method to get the content of the tag, configure and parse it with the emvNfcCard library we implemented. Also on the parser part the PcscProvider we have created will be set as our provider. Then we can read EmvCard and check our results. The process is inside a try-catch block to check if there is a transceive’s IOException.

override fun onTagDiscovered(tag: Tag?) {
val isoDep: IsoDep?
try {
isoDep = IsoDep.get(tag)
if (isoDep != null) {
(getSystemService(VIBRATOR_SERVICE) as Vibrator).vibrate(
VibrationEffect.createOneShot(
150,
10
)
)
}
isoDep.connect()
val provider = PcscProvider()
provider.setmTagCom(isoDep)
val config = EmvTemplate.Config()
.setContactLess(true)
.setReadAllAids(true)
.setReadTransactions(true)
.setRemoveDefaultParsers(false)
.setReadAt(true)
val parser = EmvTemplate.Builder()
.setProvider(provider)
.setConfig(config)
.build()
val card = parser.readEmvCard()
val cardNumber = card.cardNumber
Log.d("PaymentResultCardNumber: ", cardNumber)

val expireDate = card.expireDate
var date = LocalDate.of(1999, 12, 31)
if (expireDate != null) {
date = expireDate.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate()
}
Log.d("PaymentResultDate: ", date.toString())
try {
isoDep.close()
} catch (e: IOException) {
e.printStackTrace()
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
}
}

Then run the code on your android device and check it with a Credit Card to see the results for card number and expiration date. Don’t forget to activate NFC on your device. Here are the results on logs! 🎉:

That’s all for the development part!

Conclusion

The article explained creating a project to get payment card information with NFC using the EMV NFC Paycard Enrollment library in Android. After development, the information comes from NFC tags like card numbers and expiration dates are logged. Since there is no Kotlin example for getting payment card information with NFC on github, I hope this article helps!

I hope, you found this article helpful and if you have any comments or questions, please let me know in the comments below.

References

--

--

ibrahimertanylmz
Huawei Developers

Android Developer @Huawei 💻, ESOGU Computer Engineering Graduate 🎓, Proactive Self-Starter, Quick Learner, Team Player 👨‍👦‍👦