Skip to main content

Android NFC Integration Guide (with ARQC Validation)

This guide covers adding NFC tap scanning to a Dyscan Protect Android integration. On Dyscan Protect, NFC taps can optionally go through cryptogram validation against the card network, providing strong evidence that a physical card was present at tap time.

Overview: NFC tap with ARQC validation

  1. Call DyScan.dynetiNFC.enableScanning with enableCryptogram = true
  2. The DynetiNFCCard result exposes a cryptogramValidated boolean you can use client-side, and a scanId.
  3. Your backend can request /api/v1/<scan-id>/cryptogram to check the results.

Add the Dyneti Maven repository to your project

In your project-level build.gradle add the Dyneti Maven repository (credentials provided during integration):

allprojects {
repositories {
// Other repositories are here
maven {
credentials {
username = "nexusUsername"
password = "nexusPassword"
}
url "https://nexus.dyneti.com/repository/maven-releases/"
authentication {
basic(BasicAuthentication)
}
}
}
}
info

If you would rather integrate without using our Nexus repository, see Integrating as a library.

Add the Dyneti and NFC library dependencies

Include both the DyScan SDK and the NFC SDK. Both should be the same version, and at or above the version that ships ARQC cryptogram support.

implementation("com.dyneti.android.dyscan:dyscan-fraud:${dyscanVersion}")
implementation("com.dyneti.android.nfc:dyneti-nfc:${dyscanVersion}")

Initialize DyScan

In your Application class add the following line to initialize DyScan.

public class DyScanApplication extends Application {

//...

@Override
public void onCreate() {
super.onCreate();
//...
DyScan.init(this, "{YOUR_API_KEY}");
//...
}
}

Requirements and runtime behavior

  • Internet connectivity is required during the tap. The SDK communicates with Dyneti before returning a result.
  • Cryptogram validation is opt-in. Pass the cryptogram flag to DyScan.dynetiNFC.enableScanning.

Required Android permissions

Add the following to your app's AndroidManifest.xml:

<uses-permission android:name="android.permission.NFC"/>
  • android.permission.NFC: required for NFC tap scanning.

Check if the device supports NFC scanning

You can use the method DyScan.hasNfcFeature() to confirm that the device your app is running on is able to scan cards using NFC. It will return true if the device is supported and dynetiNFC has loaded. It will return false if the device is not supported or the NFC SDK could not be found.

Enable and Disable NFC scanning in your activity

In the activity you would like to perform the scan, enable the scanner during your onResume method and disable the scanner in your onPause method.

    override fun onResume() {
super.onResume()
if (DyScan.hasNfcFeature()) {
DyScan.dynetiNFC.enableScanning(this, enableCryptogram = true);
}
}

override fun onPause() {
if (DyScan.hasNfcFeature()) {
DyScan.dynetiNFC.disableScanning(this);
}
super.onPause()
}

Read the result of the NFC Scan

In your activity, listen for the result intent using the onNewIntent method. The success callback receives a DynetiNFCCard with the card data and a cryptogramValidated boolean. When cryptogram validation is enabled, cryptogramValidated will be true if it was successful. When cryptogram validation is disabled via the enableScanning flag, cryptogramValidated will be false.

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (DyScan.hasNfcFeature()) {
DyScan.dynetiNFC.handleIntent(
intent,
{ result: com.dyneti.shared_interfaces.DynetiNFCCard ->
val card = result
runOnUiThread {
findViewById<TextView>(R.id.cardNumber).setText(card.cardNumber);
findViewById<TextView>(R.id.expirationMonth).setText(card.expirationMonth);
findViewById<TextView>(R.id.expirationYear).setText(card.expirationYear);
findViewById<TextView>(R.id.errorText).setText("")
if (!card.cryptogramValidated) {
// Reached only when cryptogram validation is disabled in enableScanning.
}
}
},
{ error: String? ->
Log.d("NFC", "error: $error")
runOnUiThread {
findViewById<TextView>(R.id.errorText).setText(error)
}
})
}
}