B4A Library TapCard - scan your NFC enabled Bank Card with your NFC enable device (EMV)

A wrap for this Github project. Scan your NFC enabled Bank Card with your NFC enable device.

Enable NFC on your Nfc enable device before trying to scan a card. I have not added any code to check if you have NFC enabled or not. Browse the forum to figure out how you can do it programmatically.

Attached the following
1. B4A sample project
2. B4A (wrapper) library files - extract them from attached B4ATapCardLibFiles.zip (jar and xml) and copy them to your additional libs folder.
3. Java Code - use and amend it to your liking (I am not going to modify any further or maintain it)

You also need to download the following two jar and add them to your additional library folder:
1. http://www.java2s.com/example/jar/r/download-rxjava1017jar-file.html
2. http://www.java2s.com/example/jar/r/download-rxjava202jar-file.html

I cannot guarantee that it will read all cards - I have wrapped whatever is in the Github project.

Sure you will figure out how to use it. The B4A code is very well commented to make sense of how it works.

Top UI - a Label with basic Info from the card
Middle (EditText1) - Command / Response comms between the card and the device (scroll the EditText up/down with your finger to view the complete conversation)
Bottom (EditText2) - the tag names, tags, tag lengths, and tag values read from the card.

Enjoy!

??




Sample Code:

B4A Code:
#Region  Project Attributes
    #ApplicationLabel: b4aTapCard
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
                                                                         'MAKE SURE YOU ENABLE NFC ON YOUR DEVICE BEFORE SCANNING A CARD. THE APP WILL NOT PROMPT YOU TO ENABLE NFC CAPABILITY. YOU CAN ADD IT YOURSELF.
    Dim tapcard As TapCard                                               'declare TapCard
    Dim prevIntent As Intent                                             'see "If si.IsInitialized = False Or si = prevIntent Then Return"......
    Dim ips As InputStream                                               'declare InputStream
    Private Label1 As Label                                              'declare Label1 - it will display the infor returned in event "ips_scan_result(cardNumber As String, cardType As String, expireDate As String, cardHolderLastname As String, cardHolderFirstname As String, isNfcLocked As Boolean)"
    Dim mbm As Bitmap                                                    'declare bitmap that indicates to scan the card. It will be displayed when app is started and also if you click on Label1 after a scan
                                                                         'you can at any time scan a new card after you have scanned a card - no need to click on Lable1 to show the bitmap
    Private ImageView1 As ImageView                                      'imageview that will display the bitmap
    Private EditText1, EditText2 As EditText                                        'used to display the command / response between the card and the device - it is scrollable so that you can voew the entire comms between the card and the device

    Dim tgname As List                                                   'a list to hold the tagnames
    Dim tg As List                                                       'a list to hold the tags
    Dim tglength As List                                                 'a list to hold the tag lengths
    Dim tgvalue As List                                                  'a list to hold the tag values
 

End Sub

Sub Activity_Create(FirstTime As Boolean)
 
    tgname.Initialize                                                     'initialize an empty list for the tagnames
    tg.Initialize                                                         'initialise an empty list for the tags
    tglength.Initialize                                                   'initilaize an empty list for the tag lengths
    tgvalue.Initialize                                                    'initialize an empty list for the tag values
 
    Activity.LoadLayout("Layout")
    Label1.Visible = False
    EditText1.Color = Colors.LightGray
    EditText2.Color = Colors.Cyan
 
    tapcard.Initialize("ips")                                             'initialize TapCard
    ips = File.OpenInput(File.DirAssets,"smartcard_list.txt")             'Load the lookup list as an inputstream for various cards from smartcard_list.txt in the asset folder
    mbm.Initialize(File.DirAssets, "tapimage.png")                        'load the bitmap into mbm
    ImageView1.Bitmap = mbm                                               'set the bitmap to be dispalyes by Imageview1
    ImageView1.Visible = True                                             'show the bitmap
    Label1.Visible = False                                                'hide the label
    EditText1.Visible = False                                             'hide the scrollable edittext
    EditText2.Visible = False
 
    tapcard.IPS = ips                                                     'pass the InputStream to the library - the library needs the inputstream from the text file.                                               '
 
End Sub

Sub Activity_Resume

    tgname.Clear                                                        'clear the list that holds the tag names
    tg.Clear                                                            'clear the list that holds the tags
    tglength.clear                                                      'clear the list that holds the tag lengths
    tgvalue.clear                                                       'clear the list that holds the tag values
 
    EditText1.Text = "YOU CAN SCROLL ME UP/DOWN TO VIEW ALL COMMANDS/RESPONSES" & CRLF & CRLF
    EditText2.Text = "YOU CAN SCROLL ME UP/DOWN TO VIEW ALL TAG INFO" & CRLF & CRLF
'    EditText1.Text = ""                                                   'a new scan occurred or app started - set edittext1.text to nothing
    Dim si As Intent = Activity.GetStartingIntent
    'check that the intent is a new intent
    If si.IsInitialized = False Or si = prevIntent Then Return            'no intent received or intent is the same as previous intent
    prevIntent = si                                                       'set previntent to the starting intent
    If si.Action.EndsWith("TECH_DISCOVERED") Or si.Action.EndsWith("NDEF_DISCOVERED") Or si.Action.EndsWith("TAG_DISCOVERED") Then   'check what action is available in the intent received
        If si.Action.EndsWith("TECH_DISCOVERED") Then                     'show a toast message of the action available in the intent received.        
            ToastMessageShow("TECH_DISCOVERED", False)
        Else If si.Action.EndsWith("NDEF_DISCOVERED") Then
            ToastMessageShow("NDEF_DISCOVERED", False)
        Else If si.Action.EndsWith("TAG_DISCOVERED") Then
            ToastMessageShow("TAG_DISCOVERED", False)
        Else
            ToastMessageShow("NOTHING_DISCOVERED", False)    
        End If
        Label1.Visible = True                                            'make label1 visible
        ImageView1.Visible = False                                       'hide imageview1
        EditText1.Visible = False                                        'hide edittext1
    End If

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

'Event that will be raised when a card has been scanned - it brings back the CardNumber, CardType, CardExpityDate, CardHolderLastName, CardHolderFirstName, if the card is NFC locked
Sub ips_scan_result(cardNumber As String, cardType As String, expireDate As String, cardHolderLastname As String, cardHolderFirstname As String, isNfcLocked As Boolean)
    Label1.Text = ""                         'set the text in label1.text to nothing
    ImageView1.Visible = False               'hide imageview1
    Label1.Visible = True                    'make labe11 visible

    'set the text of label1 to the values receive from the event
    Label1.Text = "CardNumber: " & cardNumber & CRLF & "cardType: " & cardType & CRLF & "expireDate: " & expireDate & CRLF  _
                  & "Card Holder Last Name: " & cardHolderLastname & CRLF & "Card Holder First Name : " & cardHolderFirstname _
                  & CRLF & "isNfcLocked : " & isNfcLocked
    EditText1.Visible = True       'make edittext1 visible.
 
End Sub

'the commands and responses between the card and the device - it will be dispalyed in EditText1 (it is scrollable so that you can view all commands/responses
Sub ips_command_response(command As String, response As String)
    Log("COMMAND = " & command)                       'log command from device to the card in the B4A log
    Log("RESPONSE = " & response)                     'log response from the card to the device in the B4A log
 
    'set the command / response comms in edittext1
    'note that there are numerous commands sent / responses received from a single card scan - the code below just adds to the empty string so that you can see the entire conversation
    'EditeText1 will be "reset" to "" when a new scan occurs so that a new command/response string can be built.
    EditText1.Text = EditText1.Text & "COMMAND: " & CRLF & command & CRLF & "RESPONSE: " & response & CRLF & CRLF
    Log(" ")
 
 
End Sub

'this event bring back tagName, the Tag itself (HEX), the Tag length (HEX), and the Tag values (HEX) to the B4A project (from the library)
Sub ips_tag_data (tagname As String, tags As String, taglengths As String, tagvalues As String)

    EditText2.Visible = True                 'make edittext2 visible
    tgname.Add(tagname)                      'add a tag name
    tg.Add(tags)                             'add the tag
    tglength.Add(taglengths)                 'add the tag length
    tgvalue.Add(tagvalues)                   'add the tag value
 
End Sub

'this event will be raised once the card has been read - i.e all comms between the card and the device have been completed
Sub ips_scan_completed
 
    Log("In B4A and scan completed")                      'the card scan is completed
 
    For i = 0 To tgname.Size - 1                          'going to log all the tag names, tags, tag lengths, tag values
        EditText2.Text = EditText2.Text & CRLF &"TagName: " &tgname.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "Tag: " & tg.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "TagLength: " & tglength.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "TagValue: " & tgvalue.Get(i) & CRLF
    Next
 
 
End Sub

'these are hooks to the wrapper as the wrapper uses for eg onNewIntent, onResume, onPause and dont want to extend the wrapper with Activity
#If Java

    public void _onnewintent (android.content.Intent intent) {

    }
 
    public void _onresume () {

    }
 
    public void _onpause () {

    }

#End If

Private Sub Label1_Click
 
    Label1.Visible = False                                              'hide label1
    ImageView1.Visible = True                                           'show imageview1
    EditText1.Visible = False                                           'hide edittext1
    EditText1.Text = ""                                                 'set edittext1.text to nothing
 
    EditText2.Visible = False                                           'hide edittext2
    EditText2.Text = ""                                                 'set edittext2.text to nothing
 
    tgname.Clear                                                        'clear the list that holds the tag names
    tg.Clear                                                            'clear the list that holds the tags
    tglength.clear                                                      'clear the list that holds the tag lengths
    tgvalue.clear                                                       'clear the list that holds the tag values
 
End Sub
 

Attachments

  • b4aTapCard.zip
    166.3 KB · Views: 461
  • B4ATapCardLibFiles.zip
    127.5 KB · Views: 415
  • JavaCode.zip
    109.9 KB · Views: 409
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Version 1.01 attached (you still need to download the jars from the below links and copy them to your additional library folder) :
1. http://www.java2s.com/example/jar/r/download-rxjava1017jar-file.html
2. http://www.java2s.com/example/jar/r/download-rxjava202jar-file.html

You also need to download attached jar and xml and copy them to your additional library folder.

Updated B4A project attached.

Take note of the below image (label). The RED rectangle is where a scan of your card should report the ATR of your card - should most probably be different to mine. The green rectangle indicates the possible banks/institutions that issued this card. In my case the ATR was reported in the B4A log (and in label1) as:
ATR in B4A log (also in label1 of the UI):
ATR = 3B8B80010031C0640844037600900036

If your Bank/institution is not listed in the GREEN rectangle then you can edit "smatcard_list.txt" in the /Files folder of the attached B4A project and add your bank/institution card details. For eg - my card reported the ATR as 3B8B80010031C0640844037600900036. I searched for it in "smartcard_list.txt" using (add spaces between every 2 chars)
3B 8B 80 01 00 31 C0 64 08 44 03 76 00 90 00 36
and added my bank card details to the list....

smarcard_list.txt:
3B 8B 80 01 00 31 C0 64 08 44 03 76 00 90 00 36
    American Express Blue Card (Germany) (Bank)
    Mastercard issued by OTP Bank (Hungary) (Bank)
    ABSA Visa Gold Credit Card issued by ABSA Bank (South Africa) (Bank)
    https://www.otpbank.hu/portal/en/Retail/Bankcards

See lines 6320 to 6324 of "smatcard_list.txt" in the /Files folder of the attached B4A project where I have added my ABSA credit card.

So, seems like some cards in different/same countries and different/same banks could "share" the same ATR.




Sample Code:

B4A sample code:
#Region  Project Attributes
    #ApplicationLabel: b4aTapCard
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Private xui As XUI
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
                                                                         'MAKE SURE YOU ENABLE NFC ON YOUR DEVICE BEFORE SCANNING A CARD. THE APP WILL NOT PROMPT YOU TO ENABLE NFC CAPABILITY. YOU CAN ADD IT YOURSELF.
    Dim tapcard As TapCard                                               'declare TapCard
    Dim prevIntent As Intent                                             'see "If si.IsInitialized = False Or si = prevIntent Then Return"......
    Dim ips As InputStream                                               'declare InputStream
    Private Label1 As Label                                              'declare Label1 - it will display the infor returned in event "ips_scan_result(cardNumber As String, cardType As String, expireDate As String, cardHolderLastname As String, cardHolderFirstname As String, isNfcLocked As Boolean)"
    Dim mbm As Bitmap                                                    'declare bitmap that indicates to scan the card. It will be displayed when app is started and also if you click on Label1 after a scan
                                                                         'you can at any time scan a new card after you have scanned a card - no need to click on Lable1 to show the bitmap
    Private ImageView1 As ImageView                                      'imageview that will display the bitmap
    Private EditText1, EditText2 As EditText                                        'used to display the command / response between the card and the device - it is scrollable so that you can voew the entire comms between the card and the device

    Dim tgname As List                                                   'a list to hold the tagnames
    Dim tg As List                                                       'a list to hold the tags
    Dim tglength As List                                                 'a list to hold the tag lengths
    Dim tgvalue As List                                                  'a list to hold the tag values
  

End Sub

Sub Activity_Create(FirstTime As Boolean)
  
    tgname.Initialize                                                     'initialize an empty list for the tagnames
    tg.Initialize                                                         'initialise an empty list for the tags
    tglength.Initialize                                                   'initilaize an empty list for the tag lengths
    tgvalue.Initialize                                                    'initialize an empty list for the tag values
  
    Activity.LoadLayout("Layout")
    Label1.Visible = False
    EditText1.Color = Colors.LightGray
    EditText2.Color = Colors.Cyan
  
    tapcard.Initialize("ips")                                             'initialize TapCard
    ips = File.OpenInput(File.DirAssets,"smartcard_list.txt")             'Load the lookup list as an inputstream for various cards from smartcard_list.txt in the asset folder
    mbm.Initialize(File.DirAssets, "tapimage.png")                        'load the bitmap into mbm
    ImageView1.Bitmap = mbm                                               'set the bitmap to be dispalyes by Imageview1
    ImageView1.Visible = True                                             'show the bitmap
    Label1.Visible = False                                                'hide the label
    EditText1.Visible = False                                             'hide the scrollable edittext
    EditText2.Visible = False
  
    tapcard.IPS = ips                                                     'pass the InputStream to the library - the library needs the inputstream from the text file.                                               '
  
End Sub

Sub Activity_Resume

    tgname.Clear                                                        'clear the list that holds the tag names
    tg.Clear                                                            'clear the list that holds the tags
    tglength.clear                                                      'clear the list that holds the tag lengths
    tgvalue.clear                                                       'clear the list that holds the tag values
  
    EditText1.Text = "YOU CAN SCROLL ME UP/DOWN TO VIEW ALL COMMANDS/RESPONSES" & CRLF & CRLF
    EditText2.Text = "YOU CAN SCROLL ME UP/DOWN TO VIEW ALL TAG INFO" & CRLF & CRLF

    Dim si As Intent = Activity.GetStartingIntent
    'check that the intent is a new intent
    If si.IsInitialized = False Or si = prevIntent Then Return            'no intent received or intent is the same as previous intent
    prevIntent = si                                                       'set previntent to the starting intent
    If si.Action.EndsWith("TECH_DISCOVERED") Or si.Action.EndsWith("NDEF_DISCOVERED") Or si.Action.EndsWith("TAG_DISCOVERED") Then   'check what action is available in the intent received
        If si.Action.EndsWith("TECH_DISCOVERED") Then                     'show a toast message of the action available in the intent received.         
            ToastMessageShow("TECH_DISCOVERED", False)
        Else If si.Action.EndsWith("NDEF_DISCOVERED") Then
            ToastMessageShow("NDEF_DISCOVERED", False)
        Else If si.Action.EndsWith("TAG_DISCOVERED") Then
            ToastMessageShow("TAG_DISCOVERED", False)
        Else
            ToastMessageShow("NOTHING_DISCOVERED", False)     
        End If
        Label1.Visible = True                                            'make label1 visible
        ImageView1.Visible = False                                       'hide imageview1
        EditText1.Visible = False                                        'hide edittext1
        EditText2.Visible = False
    End If

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

'Event that will be raised when a card has been scanned - it brings back the CardNumber, CardType, CardExpityDate, CardHolderLastName, CardHolderFirstName, if the card is NFC locked
Sub ips_scan_result(cardNumber As String, cardType As String, expireDate As String, cardHolderLastname As String, cardHolderFirstname As String, isNfcLocked As Boolean)
    Label1.Text = ""                         'set the text in label1.text to nothing
    ImageView1.Visible = False               'hide imageview1
    Label1.Visible = True                    'make labe11 visible

    'set the text of label1 to the values receive from the event
    Label1.Text = "CardNumber: " & cardNumber & CRLF & "cardType: " & cardType & CRLF & "expireDate: " & expireDate & CRLF  _
                  & "Card Holder Last Name: " & cardHolderLastname & CRLF & "Card Holder First Name : " & cardHolderFirstname _
                  & CRLF & "isNfcLocked : " & isNfcLocked
    EditText1.Visible = True       'make edittext1 visible.
    EditText2.Visible = True       'make edittext1 visible.
  
End Sub

'the commands and responses between the card and the device - it will be dispalyed in EditText1 (it is scrollable so that you can view all commands/responses
Sub ips_command_response(command As String, response As String)
    Log("COMMAND = " & command)                       'log command from device to the card in the B4A log
    Log("RESPONSE = " & response)                     'log response from the card to the device in the B4A log
  
    'set the command / response comms in edittext1
    'note that there are numerous commands sent / responses received from a single card scan - the code below just adds to the empty string so that you can see the entire conversation
    'EditeText1 will be "reset" to "" when a new scan occurs so that a new command/response string can be built.
    EditText1.Text = EditText1.Text & "COMMAND: " & CRLF & command & CRLF & "RESPONSE: " & response & CRLF & CRLF
    Log(" ")
  
  
End Sub

'this event bring back tagName, the Tag itself (HEX), the Tag length (HEX), and the Tag values (HEX) to the B4A project (from the library)
Sub ips_tag_data (tagname As String, tags As String, taglengths As String, tagvalues As String)

    EditText2.Visible = True                 'make edittext2 visible
    tgname.Add(tagname)                      'add a tag name
    tg.Add(tags)                             'add the tag
    tglength.Add(taglengths)                 'add the tag length
    tgvalue.Add(tagvalues)                   'add the tag value
  
End Sub

'this event will be raised once the card has been read - i.e all comms between the card and the device have been completed
Sub ips_scan_completed
  
    Log("In B4A and scan completed")                                                 'the card scan is completed
    Log("ATR = " & tapcard.CardATRValue)
    Log("Possible Banks = " & tapcard.PossibleBankInfo)
    'late arrivals that are added to the end of Label1 - late = only available in the wrapper once the card has been scanned and comms between
    'the card and the device are completed.
    Label1.Text = Label1.Text & CRLF & "ATR: " & tapcard.CardATRValue & CRLF & _     'get the ATR and add it to Label1
                                "Possible Banks: " & tapcard.PossibleBankInfo         'get possible Banks and add it to Label1
  
  
    For i = 0 To tgname.Size - 1                          'going to display all the tag names, tags, tag lengths, tag values in EditText2
        EditText2.Text = EditText2.Text & CRLF &"TagName: " &tgname.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "Tag: " & tg.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "TagLength: " & tglength.Get(i)
        EditText2.Text = EditText2.Text & CRLF & "TagValue: " & tgvalue.Get(i) & CRLF
    Next
  
  
End Sub

'these are hooks to the wrapper as the wrapper uses for eg onNewIntent, onResume, onPause and dont want to extend the wrapper with Activity
#If Java

    public void _onnewintent (android.content.Intent intent) {

    }
  
    public void _onresume () {

    } 
  
    public void _onpause () {

    } 

#End If

Private Sub Label1_Click
  
    Label1.Visible = False                                              'hide label1
    ImageView1.Visible = True                                           'show imageview1
    EditText1.Visible = False                                           'hide edittext1
    EditText1.Text = ""                                                 'set edittext1.text to nothing
  
    EditText2.Visible = False                                           'hide edittext2
    EditText2.Text = ""                                                 'set edittext2.text to nothing
  
    tgname.Clear                                                        'clear the list that holds the tag names
    tg.Clear                                                            'clear the list that holds the tags
    tglength.clear                                                      'clear the list that holds the tag lengths
    tgvalue.clear                                                       'clear the list that holds the tag values
  
End Sub

'ATR from Johan's Card
'ATR = 3B 8B 80 01 00 31 C0 64 08 44 03 76 00 90 00 36


'ATR from Belinda's card
'ATR = 3B 8B 80 01 00 31 C1 64 08 60 32 06 00 90 00 52
 

Attachments

  • Tapcard.jar
    137 KB · Views: 329
  • TapCard.xml
    2.4 KB · Views: 325
  • b4aTapCard.zip
    166.6 KB · Views: 378
Last edited:

yaqoob

Active Member
Licensed User
Longtime User
Hi johan,

Thank you for the example and library. Great job. I tried the application to read the ID card. I got the below logs. My question can the application reads EMV Id card?

Thank you.

Reading card....
** Activity (main) Resume **
COMMAND = 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
RESPONSE =
6A 82 -- File not found

COMMAND = 00 A4 04 00 05 A0 00 00 00 03 00
RESPONSE =
6A 82 -- File not found

COMMAND = 00 A4 04 00 07 A0 00 00 00 03 10 10 00
RESPONSE =
6A 82 -- File not found

COMMAND = 00 A4 04 00 07 A0 00 00 00 98 08 48 00
RESPONSE =
6A 82 -- File not found

COMMAND = 00 A4 04 00 05 A0 00 00 00 04 00
RESPONSE =
69 82 -- Security condition not satisfied

COMMAND = 00 A4 04 00 05 A0 00 00 00 05 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 00 25 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 00 42 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 00 29 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 00 65 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 07 A0 00 00 01 21 10 10 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 07 A0 00 00 01 41 00 01 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 07 A0 00 00 01 52 30 10 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 01 54 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 02 28 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 02 77 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 03 24 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 03 33 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 03 59 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 03 71 00
RESPONSE =
69 99 -- RFU

COMMAND = 00 A4 04 00 05 A0 00 00 04 39 00
RESPONSE =
69 99 -- RFU

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String io.github.tapcard.emvnfccard.model.EmvCard.getCardNumber()' on a null object reference
at tapcardwrapper.tapcardWrapper.showCardInfo(tapcardWrapper.java:137)
at tapcardwrapper.tapcardWrapper.access$100(tapcardWrapper.java:68)
at tapcardwrapper.tapcardWrapper$1.onPostExecute(tapcardWrapper.java:171)
at tapcardwrapper.tapcardWrapper$1.onPostExecute(tapcardWrapper.java:153)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.access$600(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7073)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

 

Johan Schoeman

Expert
Licensed User
Longtime User
Only (some) EMV bank cards. Not NFC ID cards. The comms protocol will be different between NFC ID cards and EMV bank cards
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
My question can the application reads EMV Id card?
emv cards are payment cards, not id cards. you requested the application id for a payment/money card. the application id for an id card (eg, passport, national identity card, driver's license, etc) is something quite different. what you used is a sort of generic select command for a payment/money card that conforms to the visa international standard (not only for visa). if it's a non-conforming payment card or some other kind of card (eg, id), you need to know the specific select command used by that card, and you might find that, without appropriate security keys, the data you manage to extract is little more than what you can see by looking at the card with your eyes. while it is technically possible to apply a brute force method to derive the aid, card issuers are aware of such tactics and have taken countermeasures.
 

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
Hi Johan,
I'm back to this...
Is there a way to activate your Lib as an internal part of my app?

I mean to read nfc card upon a button press and get the results
Without a separate intent that will go throu activity_resume?

And to make it read only from my app activated button and not independent at any time as it does now

Thanks...
 

Johan Schoeman

Expert
Licensed User
Longtime User
Final update is here...

 

Hamied Abou Hulaikah

Well-Known Member
Licensed User
Longtime User
I got partial card info, then i got error and crash!
Why I got this error:
B4X:
java.lang.Exception: Sub ips_scan_result signature does not match expected signature.
public static anywheresoftware.b4a.pc.RemoteObject jhs.tapcard.main_subs_0._ips_scan_result(anywheresoftware.b4a.pc.RemoteObject,anywheresoftware.b4a.pc.RemoteObject,anywheresoftware.b4a.pc.RemoteObject,anywheresoftware.b4a.pc.RemoteObject,anywheresoftware.b4a.pc.RemoteObject,anywheresoftware.b4a.pc.RemoteObject) throws java.lang.Exception
class anywheresoftware.b4a.pc.RemoteObject,
 

Johan Schoeman

Expert
Licensed User
Longtime User
 

Hamied Abou Hulaikah

Well-Known Member
Licensed User
Longtime User
Thank you very much worked fine.
Why you don't update the library and example here, It confusing us

Another thing: Can we got CVV number?
 

Johan Schoeman

Expert
Licensed User
Longtime User
Thank you very much worked fine.
Why you don't update the library and example here, It confusing us

Another thing: Can we got CVV number?
I don't think the CVV number is available in the scan of the card
 

Zeev Goldstein

Well-Known Member
Licensed User
Longtime User
Thank you very much worked fine.
Why you don't update the library and example here, It confusing us

Another thing: Can we got CVV number?
the CVV2 is NOT a part of the EMV data pack sent by the NFC reader and is not stored in the chip
it is also not relevant for EMV proximity or chip & pin transaction - it is relevant only for MOTO or Online

note: the data you get from the great job Johan did is NOT a proximity transaction as it doesn't contain Field55 (especially not the 2 encrypted flags) so the only thing you can do is use this for CNP (Card Not Present (MOTO & Online) with the benefit of ease of use and data entry errors

there are commercial packs for that (proximity) and even free ones provided by MasterCard but this needs to be wrapped to suit B4A
if you take a commercial pack make sure it is valid for your country / region and certified with your local acquirers

should you need any further info you're welcome to contact me

i would like to once again to thank Johan for his great job and contribution and patience to me as i was the pest starting this all
i hope you managed to restore your lost laptop...

@Johan Schoeman
 

rbirago

Active Member
Licensed User
Longtime User
Hi Johan, best compliments for the good job.
I have tried to read both VISA than Mastercard cards and the result is perfect.
When I tried to read an American Express card (I am shure it is active because I have used it in a shop) I had no success.
The complicate log is this:

B4X:
Logger connesso a:  Telpo M1K
--------- beginning of main
Copying updated assets files (1)
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
Killing previous instance (main).
** Activity (main) Create  **
Reading card....
** Activity (main) Resume **
COMMAND = 00 A4 04 00 07 A0 00 00 05 24 10 10 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 04 54 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 80 A8 00 00 02 83 00 00
RESPONSE =
69 85 -- Conditions of use not satisfied
 
COMMAND = 00 A4 04 00 07 A0 00 00 01 52 30 10 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 29 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 07 A0 00 00 03 71 00 01 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 80 A8 00 00 02 83 00 00
RESPONSE =
69 85 -- Conditions of use not satisfied
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 25 00
RESPONSE =
6F 39 -- File Control Information (FCI) Template
      84 08 -- Dedicated File (DF) Name
            A0 00 00 00 25 01 08 01 (BINARY)
      A5 2D -- File Control Information (FCI) Proprietary Template
            50 10 -- Application Label
                  41 4D 45 52 49 43 41 4E 20 45 58 50 52 45 53 53 (=AMERICAN EXPRESS)
            9F 38 06 -- Processing Options Data Object List (PDOL)
                     9F 35 01 -- Terminal Type
                     9F 6E 04 -- Visa Low-Value Payment (VLP) Issuer Authorisation Code
            87 01 -- Application Priority Indicator
                  01 (BINARY)
            5F 2D 02 -- Language Preference
                     69 74 (=it)
            BF 0C 07 -- File Control Information (FCI) Issuer Discretionary Data
                     9F 0A 04 -- [UNKNOWN TAG]
                              00 01 01 02 (BINARY)
90 00 -- Command successfully executed (OK)
 
COMMAND = 00 A4 04 00 07 A0 00 00 01 21 10 10 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 03 71 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 09 D2 76 00 00 25 45 50 01 00 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 06 A0 00 00 00 24 01 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 05 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 03 00
RESPONSE =
6F 10 -- File Control Information (FCI) Template
      84 08 -- Dedicated File (DF) Name
            A0 00 00 00 03 00 00 00 (BINARY)
      A5 04 -- File Control Information (FCI) Proprietary Template
            9F 65 01 -- Track 2 bit map for CVC3
                     FF (BINARY)
90 00 -- Command successfully executed (OK)
 
COMMAND = 00 A4 04 00 05 A0 00 00 03 33 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 07 A0 00 00 01 21 10 10 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 80 A8 00 00 02 83 00 00
RESPONSE =
6D 00 -- Instruction code not supported or invalid
 
COMMAND = 00 A4 04 00 07 F0 00 00 00 03 00 01 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 08 A0 00 00 00 25 01 08 01 00
RESPONSE =
6F 39 -- File Control Information (FCI) Template
      84 08 -- Dedicated File (DF) Name
            A0 00 00 00 25 01 08 01 (BINARY)
      A5 2D -- File Control Information (FCI) Proprietary Template
            50 10 -- Application Label
                  41 4D 45 52 49 43 41 4E 20 45 58 50 52 45 53 53 (=AMERICAN EXPRESS)
            9F 38 06 -- Processing Options Data Object List (PDOL)
                     9F 35 01 -- Terminal Type
                     9F 6E 04 -- Visa Low-Value Payment (VLP) Issuer Authorisation Code
            87 01 -- Application Priority Indicator
                  01 (BINARY)
            5F 2D 02 -- Language Preference
                     69 74 (=it)
            BF 0C 07 -- File Control Information (FCI) Issuer Discretionary Data
                     9F 0A 04 -- [UNKNOWN TAG]
                              00 01 01 02 (BINARY)
90 00 -- Command successfully executed (OK)
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 65 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 07 A0 00 00 00 98 08 48 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 42 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 01 54 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 03 59 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 00 04 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 06 A0 00 00 04 76 6C 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 02 77 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 80 A8 00 00 07 83 05 22 00 00 00 00 00
RESPONSE =
69 85 -- Conditions of use not satisfied
 
COMMAND = 00 A4 04 00 07 D5 78 00 00 02 10 10 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 09 A0 00 00 00 25 01 08 01 04 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 04 39 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 07 A0 00 00 01 41 00 01 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
RESPONSE =
6F 41 -- File Control Information (FCI) Template
      84 0E -- Dedicated File (DF) Name
            32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 (BINARY)
      A5 2F -- File Control Information (FCI) Proprietary Template
            BF 0C 2C -- File Control Information (FCI) Issuer Discretionary Data
                     61 2A -- Application Template
                           4F 08 -- Application Identifier (AID) - card
                                 A0 00 00 00 25 01 08 01 (BINARY)
                           50 10 -- Application Label
                                 41 4D 45 52 49 43 41 4E 20 45 58 50 52 45 53 53 (=AMERICAN EXPRESS)
                           87 01 -- Application Priority Indicator
                                 01 (BINARY)
                           9F 0A 04 -- [UNKNOWN TAG]
                                    00 01 01 02 (BINARY)
                           9F 2A 01 -- The value to be appended to the ADF Name in the data field of the SELECT command, if the Extended Selection Support flag is present and set to 1
                                    04 (BINARY)
90 00 -- Command successfully executed (OK)
 
COMMAND = 80 A8 00 00 07 83 05 22 00 00 00 00 00
RESPONSE =
69 85 -- Conditions of use not satisfied
 
COMMAND = 00 A4 04 00 05 A0 00 00 02 28 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 05 A0 00 00 03 24 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 00 A4 04 00 07 A0 00 00 00 03 10 10 00
RESPONSE =
6A 82 -- File not found
 
COMMAND = 80 A8 00 00 02 83 00 00
RESPONSE =
6D 00 -- Instruction code not supported or invalid

Have you an idea where is the trick?
Where can I find a documentation to understand the meaning of the Commands/Responses to understand the dialog path?

thank you
Roberto
 

Johan Schoeman

Expert
Licensed User
Longtime User
You should perhaps ask @Zeev Goldstein or @drgottjr. They are far more knowledgeable than what I am when it comes to EMV cards. But from your log above it does seem as if the card does not recognize the command issued by the App.
 

drgottjr

Expert
Licensed User
Longtime User
APDU commands are easy to find. just google "apdu commands".

without having your card at hand, it's difficult to know exactly what the
problem is, but i can tell you that:
COMMAND = 00 A4 04 00 07 A0 00 00 05 24 10 10 00
is not the correct select aid for an amex card. the card is supposed
to tell you its application id; you don't just tell it a random aid.
i don't understand how an amex card would give you the application
id that you posted.

and other commands that you show, such as:
COMMAND = 80 A8 00 00 02 83 00 00
are too short to be acceptable (even though, technically, they
may have followed proper formatting).

i get the impression from your post that you are feeding commands
in no particular order. the basic process to reading an emv contactless
card is relatively uncomplicated. if followed correctly, the card will tell
you what it's allowed to tell you. more and more, however, cards are
giving up less and less. in many cases, what you can derive from scanning
the card will provide less information than simply looking at the card with the
naked eye (eg, some cards cannot tell you the name of the cardholder,
something which is plainly visible on the card. the terminal has to get online
to the issuing bank to learn the cardholder's name).

as to the information that it will tell you, the app shows what the various
tags mean. whether or not you understand their meaning is another
matter. every card provider has thick volumes of standards and documentation,
much of it available online. regrettably, a lot more documentation is
proprietary and/or only available in exchange for a lot of money.

for obvious reasons, banks and card-issuing companies don't
want you to read their cards. they want that to be done by
licensed terminals in the hands of paying merchants. the
people who developed the terminals spent a lot of time and
money producing those machines and their controlling software.
whether it's worth your time to learn all that is necessary to
extract a very small handful of (relatively harmless) data from an
emv card is your choice.
 

rbirago

Active Member
Licensed User
Longtime User
Thanks all for the replies and suggestions.
From your comments I understand that probably the various banks have a different policies than the good old magnetic band. At that times they did want to keep simple to users to use their cards, now perhaps they have a different target.
Actually I tried to apply "as is" the TapCard app hoping in a transparent mind of the bank cards. At this point I think that if I really want to manage NFC bank cards reading I have to retrieve APDU commands documentation and, using the samples seen in TapCard to understand the various specs used by Amex or other "exotic" issuers.
Thank you all
Roberto
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…