Building secure contactless payments with Android NFC
NFC lets two nearby devices exchange data over a short radio link. Android can use it to read a card, respond as a card through host card emulation, or hand a payment target to an authorised SDK. A successful tap therefore involves credentials, cryptography and network approval; detecting the radio signal alone does not complete a purchase.
Most Android payment work should use an SDK supplied by a bank, wallet or payment service provider because the provider controls provisioning and scheme approval. Raw NFC APIs remain useful for selecting an NFC target, passing it to that SDK and confirming that the device supports the required hardware.
Consumer checkout and merchant acceptance require different designs. A consumer app asks an issuer-backed SDK to provision a token and run each transaction. A merchant app needs a certified point-of-sale terminal or certified reader that captures the card interaction and sends it to the acquiring bank. An ordinary phone should not be treated as a general-purpose reader that extracts bank-card numbers.
Australian shoppers now expect a quick tap at Woolworths and Coles supermarkets, independent cafés, pharmacies and many counters, usually while the final amount is shown in Australian dollars. Contactless journeys also extend beyond retail: compatible bank cards and phones can be tapped at Opal readers in Sydney, while contactless bank cards can serve as Myki in Melbourne. Many Android users add eligible cards to Google Wallet, but that convenience does not remove an app developer’s obligations under the Privacy Act 1988, the Australian Privacy Principles or applicable payment-card security rules.
| Approach | Android mechanism | Best suited to | Important constraint |
|---|---|---|---|
| Reader mode | enableReaderMode |
Identifying a nearby NFC object during a controlled foreground task | It cannot provision or approve a payment |
| Intent or foreground dispatch | TAG_DISCOVERED and enableForegroundDispatch |
Delivering a selected card or tag to a checkout flow | The app must manage timing and duplicate events |
| Host card emulation | HostApduService |
Responding as a contactless smart card | Payment applications require scheme approval and controlled key provisioning |
| Provider-managed SDK | Wallet, issuer or acquirer APIs combined with NFC | Tokenised checkout or merchant acceptance | Onboarding, test credentials and production approval are mandatory |
Understand the transaction path
A payment tap normally activates a token provisioned for that card and wallet. The phone creates transaction-specific data, often including a dynamic cryptogram, and sends it to the terminal. The terminal forwards that encrypted payload through the acquiring bank to the issuing bank, which checks the credential and returns an approval or decline.
NFC defines the short-range radio exchange; it does not make the underlying payment secure by itself. Tokenisation limits the usefulness of intercepted card data, while cryptography and network checks prevent a copied transaction from being reused. The phone must also follow the payment network’s rules for transaction amounts, unpredictability and offline or online authorisation.
The contactless application and kernel must pass relevant EMV testing, and merchants must follow PCI DSS requirements where cardholder data enters their environment. An Android app that operates outside the certified provider SDK should not attempt to reproduce the scheme’s cryptographic protocol.
Choose the right payment integration
For a consumer wallet, select an SDK that supports Android, Australian issuers, AUD settlement and the cards your users hold. The provider should handle token provisioning, secure storage, network authorisation and lifecycle events such as card removal or device credential changes. A wallet such as Google Wallet can hold eligible Australian cards, but consumer wallet availability does not automatically provide merchant-acceptance functionality.
Merchant acceptance is different. A retail checkout app normally communicates with a certified terminal supplied by its acquiring provider, including the tap, receipt, settlement and refund processes. Trying to turn the handset’s reader mode into a bank-certified acceptance device would create security, certification and operational problems.
Host card emulation is also restricted in practice. A HostApduService can emulate a smart card, but registering a payment application identifier requires approval and controlled provisioning from the relevant scheme. Ordinary applications cannot simply claim a Visa or Mastercard application identifier and become usable payment cards.
Configure NFC discovery in the project
Add the NFC permission and declare whether the hardware is mandatory. If the checkout depends entirely on NFC, requiring it prevents installation on unsupported devices. If online or cash payment remains available, marking the feature as optional allows a broader device base.
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
Intent dispatch can be advertised with the TAG_DISCOVERED action and a technology filter. This approach is useful when the payment SDK expects the activity to receive the selected tag, but it should not be combined with another foreground dispatch implementation without checking the provider’s documentation.
<resources>
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
</tech-list>
</resources>
Before starting discovery, check NfcAdapter.getDefaultAdapter() and confirm that the adapter is enabled. An activity must also verify that a checkout session and expected amount are active, preventing an unsolicited tag from triggering a payment or replaying a previous transaction.
Pass the NFC target to the SDK
Reader mode provides a direct callback while the checkout screen is active. The callback runs on a background executor, so the selected tag should be passed to the provider’s thread-safe API rather than processed as application data.
private lateinit var nfcAdapter: NfcAdapter
private val executor = Executors.newSingleThreadExecutor()
private fun listen(onTag: (Tag) -> Unit) {
val adapter = NfcAdapter.getDefaultAdapter(this) ?: return
nfcAdapter = adapter
adapter.enableReaderMode(
this,
{ tag -> onTag(tag) },
NfcAdapter.FLAG_READER_NFC_A or
NfcAdapter.FLAG_READER_NFC_B or
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK,
executor
)
}
A tag identifier may identify a radio target, but it is not a payment token and may be randomly generated. Do not attempt to parse track data, recover a primary account number or infer approval from the identifier. The provider SDK owns the sensitive exchange, token operation and cryptogram generation.
Foreground dispatch is often preferable for consumer checkout because the activity receives a pending intent and can reject duplicate tag events. Reader mode should be used only when the chosen provider supports it. Whichever mechanism is selected, release resources when the activity stops and ensure that cancellation, rotation and repeated taps cannot create two transactions from one checkout session.
Test and harden the checkout
Use physical Android devices for definitive testing because emulators and simulators may not reproduce real NFC timing or payment-card responses. Test supported card types, different Android versions, screen locks, cancelled taps, declined payments, interrupted connections and rapid repeated scans. Verify that every terminal response maps to a distinct user state such as waiting, approved, declined or cancelled.
Retail and transport integrations should remain separate. A payment certified for a Woolworths checkout cannot automatically be used at an Opal reader in Sydney or as Myki in Melbourne; each transport operator defines its own acceptance rules and backend services. During development, use provider test cards and a sandbox environment rather than placing real payments into the test workflow.
Never log tag bytes, tokens, cryptograms or sensitive card data, and obtain the final amount from a trusted server before displaying it. Secure the app-to-provider connection, minimise personal information, document retention periods and complete the provider’s certification before production credentials are enabled. A release-ready implementation can provide a fast NFC checkout while keeping card credentials and transaction approval inside the certified payment stack.