Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

EMV NFC Paycard Enrollment CI Coverage Status

Description

Java library used to read and extract public data from NFC EMV credit cards.

Android sample app available on Play store.

Get it on Google Play

Getting started

First you need to create a custom Provider to exchange APDU with an NFC EMV credit card (sample here).

public class YourProvider implements IProvider {

  @Override
  public byte[] transceive(final byte[] pCommand) {
	 // implement this
  }

  @Override
  public byte[] getAt() {
     // implement this to get card ATR (Answer To Reset) or ATS (Answer To Select)
  }

}

After that, create an instance of a parser and read the card.

// Create provider
IProvider provider = new YourProvider();
// Define config
Config config = EmvTemplate.Config()
		.setContactLess(true) // Enable contact less reading (default: true)
		.setReadAllAids(true) // Read all aids in card (default: true)
		.setReadTransactions(true) // Read all transactions (default: true)
		.setReadCplc(false) // Read and extract CPCLC data (default: false)
		.setRemoveDefaultParsers(false) // Remove default parsers for GeldKarte and EmvCard (default: false)
		.setReadAt(true) // Read and extract ATR/ATS and description
		.setReadAllRecords(true) // Read the whole application file, not only up to the card number (default: true)
		.setReadExtendedData(false) // Read the optional GET DATA objects: offline balance, last online ATC (default: false)
		.setTerminalCountryCode(CountryCodeEnum.FR) // Country the terminal pretends to be located in (default: FR)
		; 
// Create Parser
EmvTemplate parser = EmvTemplate.Builder() //
		.setProvider(provider) // Define provider
		.setConfig(config) // Define config
		//.setTerminal(terminal) (optional) you can define a custom terminal implementation to create APDU
		.build();
		
// Read card
EmvCard card = parser.readEmvCard();

card object contains all data read (Aid, card number, expiration date, card type, transactions history)

Data read from the card

On top of the card number, the expiration date and the transaction history, each Application of the card exposes the data objects defined by the EMV specification:

DataTagGetter
Application PAN and sequence number5A, 5F34getPan(), getPanSequenceNumber()
Effective and expiration dates5F25, 5F24getEffectiveDate(), getExpirationDate()
Issuer country5F28, 5F56getIssuerCountryCode()
Application currency and exponent9F42, 9F44getCurrency(), getCurrencyExponent()
Application preferred name9F12getApplicationPreferredName()
Issuer code table index9F11getIssuerCodeTableIndex()
Language preference5F2DgetLanguagePreferences()
Service code5F30getServiceCode()
Issuer URL5F50getIssuerUrl()
Application version number9F08getApplicationVersionNumber()
Application Interchange Profile82getInterchangeProfile()
Application Usage Control9F07getUsageControl()
Cardholder Verification Method list8EgetCvmList(), getCvmAmountX(), getCvmAmountY()
Issuer Action Codes9F0E, 9F0F, 9F0DgetIssuerActionCodeDenial(), getIssuerActionCodeOnline(), getIssuerActionCodeDefault()
Kernel capability data objects9F6C, 9F6E, 9F5DgetCardTransactionQualifiers(), getFormFactorIndicator(), getApplicationCapabilitiesInformation()
Contactless kernel9F2AgetKernel(), getShortKernelId(), isKernelDerived()
Offline data authentication credentials8F, 90, 92, 93, 9F32, 9F46, 9F47, 9F48, 9F4A, 9F4BgetOfflineDataAuthentication()
Contactless mag-stripe profile (Kernel 2)56, 9F60, 9F61, 9F62, 9F63, 9F64, 9F65, 9F66, 9F67, 9F69, 9F6BgetMagStripeData()
Issuer Application Data9F10getIssuerApplicationData()
Issuer Identification Number42getIssuerIdentificationNumber()
Consecutive offline limits9F14, 9F23getLowerConsecutiveOfflineLimit(), getUpperConsecutiveOfflineLimit()
Application reference currencies9F3B, 9F43getReferenceCurrencies(), getReferenceCurrencyExponents()
Application discretionary data9F05getApplicationDiscretionaryData()
Data object lists the card carries8C, 8D, 9F49, 97getCdol1(), getCdol2(), getDdol(), getTdol()
ATC and last online ATC9F36, 9F13getTransactionCounter(), getLastOnlineTransactionCounter()
Offline (electronic cash) balance9F79, 9F50getOfflineBalance() (a BigDecimal, the amount carries up to 12 digits)
Tokenized credential (mobile wallet)9F19, 9F24, 9F25isTokenized(), getPaymentAccountReference(), getLast4DigitsOfPan()

The Application Interchange Profile, the Application Usage Control and the CVM list are decoded into objects, so you can directly ask whether the card supports CDA, whether it may be used abroad or which cardholder verification methods it accepts:

Application app = card.getApplications().get(0);

app.getInterchangeProfile().isCdaSupported();
app.getUsageControl().isInternationalUsageAllowed();
for (CVM cvm : app.getCvmList()) {
	System.out.println(cvm.getMethod() + " - " + cvm.getCondition());
}

The Issuer Action Codes and the kernel capability data objects are exposed raw: the first ones are bitmaps built on the Terminal Verification Results layout (EMV 4.3 Book 3 Annex C5), and the meaning of the tags 9F6C and 9F6E depends on the payment system (Card Transaction Qualifiers and Form Factor Indicator for Visa, Mag Stripe Application Version Number and Third Party Data for MasterCard), so the library does not guess which one a card meant.

Contactless mag-stripe profile

A card personalised for the Mag-stripe Mode of EMV Contactless Book C-2 v2.11 (Kernel 2, the MasterCard applications) carries the bitmaps that tell a reader where to write the dynamic card verification code, the unpredictable number and the application transaction counter inside the discretionary data field of its tracks. getMagStripeData() decodes them into positions:

MagStripeData magStripe = app.getMagStripeData();

magStripe.isMandatoryDataPresent();                        // Table 6.4
magStripe.isConsistent();                                  // S7.22
magStripe.getUnpredictableNumberDigitCount();              // nUN
magStripe.getCvc3Track2Positions();                        // PCVC3(Track2)
magStripe.getApplicationTransactionCounterTrack2Positions();

Two of these tags were assigned twice, and only the kernel tells the readings apart: 9F66 is PUNATC(Track2) for Kernel 2 and the reader sourced Terminal Transaction Qualifiers for Kernel 3, 9F69 is the UDOL for Kernel 2 and the Card Authentication Related Data for Kernel 3. EMV Contactless Book B fixes the kernel before the first GET PROCESSING OPTIONS, from the Kernel Identifier of the payment directory or, when the card expressed no preference, from the AID, so the profile is only read for an application whose kernel is the MasterCard one. An application whose kernel is neither announced nor implied by its AID — a domestic scheme, typically — is left alone rather than read against a dictionary that may not be its own.

The two CVC3 (tags 9F60 and 9F61) are only returned by the COMPUTE CRYPTOGRAPHIC CHECKSUM command, which this library never sends: they are picked up only when a response read for another reason already carried them.

Mag-stripe Mode is gone from Book C-2 v2.12 (May 2026), which implements Specification Bulletin No. 317 "Mag-stripe Mode Implementation Option Deprecated". Cards personalised for it are still in the field, so the library keeps reading them and everything above is sourced to v2.11.

What this library will never do

It reads the public data of a card. It never asks the card to authenticate anything, and never makes it change state. One nuance: the GET PROCESSING OPTIONS command that starts any read does make a contactless card do cryptographic work of its own accord — several recorded traces answer it with an Application Cryptogram (tag 9F26) nobody asked for — but the library never requests one, never sends a GENERATE AC, and discards what it does not need. That boundary is deliberate, and it rules out a large part of the EMV specifications:

Commands that are never sent. GENERATE AC (it increments the Application Transaction Counter and consumes the offline counters), INTERNAL AUTHENTICATE, VERIFY (it decrements the PIN Try Counter and can block an application for good — the remaining tries are read with GET DATA instead), GET CHALLENGE, PIN CHANGE/UNBLOCK, EXTERNAL AUTHENTICATE, APPLICATION BLOCK and CARD BLOCK, EXCHANGE RELAY RESISTANCE DATA, RECOVER AC, COMPUTE CRYPTOGRAPHIC CHECKSUM, PUT DATA, and the issuer scripts. The data objects that only exist to feed those commands — the CDOLs, the DDOL, the mag stripe bitmaps — are read and reported, never executed.

Terminal data that is never invented. The Terminal Verification Results (95), the Transaction Status Information (9B) and the CVM Results (9F34) are produced by a terminal during a transaction; the card never holds them. The all-zero 95 this library answers when a card asks for one in its PDOL is the honest value, not a placeholder.

Decisions that are never taken. Terminal action analysis, terminal risk management (floor limits, random selection, velocity checking), cardholder verification method selection, and the combination selection of the contactless Entry Point. They all end on a verdict about a transaction that is not happening. The library reports the card's own parameters — the Issuer Action Codes, the consecutive offline limits, the CVM list and its amounts — and stops there.

Offline data authentication is reported, not verified. The certificates, the certification authority key index and the key lengths are exposed through getOfflineDataAuthentication(). Verifying a signature needs the certification authority public keys, which the payment systems do not publish, and the dynamic schemes additionally need the card to sign a challenge.

One hard ceiling. A card that protects its data behind the Kernel 8 secure channel cannot be read at all: establishing the channel requires the card to perform a key agreement. That is a limit of any read-only tool, not a missing feature.

Application selection

The library follows the application selection rules of EMV 4.3 Book 1 (sections 12.2 to 12.4) and of EMV Contactless Book B:

  • the Application Priority Indicator (tag 87) is decoded into the priority order (bits 4 to 1) and the cardholder confirmation flag (bit 8); an application without priority is proposed last;
  • a payment directory record that carries a DDF Name (tag 9D) references a sub directory whose records are read too, so the applications it holds are not missed;
  • the Extended Selection (tag 9F29) is appended to the ADF Name in the data field of the SELECT command when the card asks for it, with a fallback on the bare ADF Name if the card refuses it (setExtendedSelectionSupported(false) disables it entirely);
  • the Kernel Identifier (tag 9F2A) is kept on the Application;
  • when the applications are looked up with a partial AID (a RID), the SELECT is repeated with the next occurrence option (P2 = 02) so every application built on that RID is seen;
  • an application answering 6283 (invalidated) or 6A81 (function not supported) to the SELECT is blocked: it is skipped and flagged through Application.isBlocked(). Book 1 asks the terminal to terminate the session on 6A81; this library keeps reading the remaining applications instead, since it only extracts public data.

9F79 is only read on the applications that define it as the Electronic Cash Balance (UnionPay/PBOC); on any other card that tag is the generic Unprotected Data Envelope 5 and reading it as money would report an amount the card never meant.

Values requested through a DOL are padded following EMV 4.3 Book 3 section 5.4: a numeric value is right justified and padded with zeroes on the left, any other format is left justified and padded on the right.

Country specificities

Some cards only answer, or only answer completely, to a terminal that looks domestic. setTerminalCountryCode sets both the terminal country (tag 9F1A) and the transaction currency (tag 5F2A) the library announces, which is what Interac (Canada), girocard (Germany) or UnionPay (China) applications look at:

Config config = EmvTemplate.Config().setTerminalCountryCode(CountryCodeEnum.CA);

Text data objects are decoded with the character set the issuer asks for through the Issuer Code Table Index (tag 9F11), so a card issued in Turkey (ISO/IEC 8859-9), in Russia (ISO/IEC 8859-5) or in Greece (ISO/IEC 8859-7) returns a readable application name instead of mojibake.

EmvCardScheme also knows the AID of the domestic schemes and the country they are operated in:

EmvCardScheme.getCardTypeByAid("D27600002547410100"); // GIROCARD
EmvCardScheme.GIROCARD.getCountry();                  // DE
EmvCardScheme.GIROCARD.isDomestic();                  // true

Supported domestic schemes: CB (France), girocard and GeldKarte (Germany), Interac and The Exchange Network (Canada), Dankort/PBS (Denmark), PagoBANCOMAT (Italy), Bankaxept (Norway), Chipknip (Netherlands), LINK and Midland (United Kingdom), UnionPay (China), JCB (Japan), RuPay (India), Mir and ПРО100 (Russia), Простiр (Ukraine), Troy (Turkey), Elo, Banrisul and Bradesco (Brazil), Verve, InterSwitch and eTranzact (Nigeria), SPAN (Saudi Arabia), Meeza (Egypt).

Android usage

For android, you can create a provider with IsoDep class:

public class Provider implements IProvider {

	private IsoDep mTagCom;

	@Override
	public byte[] transceive(final byte[] pCommand) throws CommunicationException {
		
		byte[] response;
		try {
			// send command to emv card
			response = mTagCom.transceive(pCommand);
		} catch (IOException e) {
			throw new CommunicationException(e.getMessage());
		}

		return response;
	}

	@Override
	public byte[] getAt() {
        // For NFC-A
		return mTagCom.getHistoricalBytes();
		// For NFC-B
        // return mTagCom.getHiLayerResponse();
	}


	public void setmTagCom(final IsoDep mTagCom) {
		this.mTagCom = mTagCom;
	}

}

Screens

Sample demo

Download

Maven

<dependency>
  <groupId>com.github.devnied.emvnfccard</groupId>
  <artifactId>library</artifactId>
  <version>3.2.0</version>
</dependency>

Gradle

dependencies {
	compile 'com.github.devnied.emvnfccard:library:3.2.0'
}

JAR

You can download this library on Maven central or in Github release tab

Dependencies

If you are not using Maven or some other dependency management tool that can understand Maven repositories, the list below is what you need to run EMV-NFC-Paycard-Enrollment.

Build

To build the project launch:

mvn clean install

Bugs

Please report bugs and feature requests to the GitHub issue tracker.
Forks and Pull Requests are also welcome.

Author

Millau Julien

Copyright and license

Copyright 2020-2026 Millau Julien.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

关于 About

A Java library used to read and extract data from NFC EMV credit cards (Android/PCSC).
androidcredit-cardemvjavajava-librarynfctlvtrack2

语言 Languages

Java100.0%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
21
Total Commits
峰值: 13次/周
Less
More

核心贡献者 Contributors