Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make it easier to see EMV tags #328

Merged
merged 2 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions exp/emv/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,134 @@ type Data struct {
UnpredictableNumber *field.String `index:"9F37"`
UpperConsecutiveOfflineLimit *field.String `index:"9F23"`
}

// genearte struct with native go types
type NativeData struct {
AcquirerIdentifier string `index:"9F01"`
AdditionalTerminalCapabilities string `index:"9F40"`
AmountAuthorisedBinary string `index:"81"`
AmountAuthorisedNumeric int64 `index:"9F02"`
AmountOtherBinary string `index:"9F04"`
AmountOtherNumeric int64 `index:"9F03"`
AmountReferenceCurrency string `index:"9F3A"`
ApplicationCryptogram string `index:"9F26"`
ApplicationCurrencyCode string `index:"9F42"`
ApplicationCurrencyExponent string `index:"9F44"`
ApplicationDiscretionaryData string `index:"9F05"`
ApplicationEffectiveDate string `index:"5F25"`
ApplicationExpirationDate string `index:"5F24"`
ApplicationFileLocatorAFL string `index:"94"`
ApplicationIdentifierAIDcard string `index:"4F"`
ApplicationIdentifierAIDterminal string `index:"9F06"`
ApplicationInterchangeProfile string `index:"82"`
ApplicationLabel string `index:"50"`
ApplicationPreferredName string `index:"9F12"`
ApplicationPrimaryAccountNumberPAN string `index:"5A"`
ApplicationPrimaryAccountNumberPANSequenceNumber string `index:"5F34"`
ApplicationPriorityIndicator string `index:"87"`
ApplicationReferenceCurrency string `index:"9F3B"`
ApplicationReferenceCurrencyExponent string `index:"9F43"`
ApplicationSelectionRegisteredProprietaryData string `index:"9F0A"`
ApplicationTemplate string `index:"61"`
ApplicationTransactionCounter int64 `index:"9F36"`
ApplicationUsageControl string `index:"9F07"`
ApplicationVersionNumber string `index:"9F08"`
ApplicationVersionNumberTerminal string `index:"9F09"`
AuthorisationCode string `index:"89"`
AuthorisationResponseCode string `index:"8A"`
BankIdentifierCodeBIC string `index:"5F54"`
CardBITGroupTemplate string `index:"9F31"`
CardRiskManagementDataObjectList1CDOL1 string `index:"8C"`
CardRiskManagementDataObjectList2CDOL2 string `index:"8D"`
CardholderName string `index:"5F20"`
CardholderNameExtended string `index:"9F0B"`
CardholderVerificationMethodCVMList string `index:"8E"`
CardholderVerificationMethodCVMResults string `index:"9F34"`
CertificationAuthorityPublicKeyIndex string `index:"8F"`
CertificationAuthorityPublicKeyIndexTerminal string `index:"9F22"`
CommandTemplate string `index:"83"`
CryptogramInformationData string `index:"9F27"`
DataAuthenticationCode string `index:"9F45"`
DedicatedFileDFName string `index:"84"`
DirectoryDefinitionFileDDFName string `index:"9D"`
DirectoryDiscretionaryTemplate string `index:"73"`
DynamicDataAuthenticationDataObjectListDDOL string `index:"9F49"`
EMVProprietaryTemplate string `index:"70"`
FacialTryCounter string `index:"DF50"`
FileControlInformationFCIIssuerDiscretionaryData string `index:"BF0C"`
FileControlInformationFCIProprietaryTemplate string `index:"A5"`
FileControlInformationFCITemplate string `index:"6F"`
FingerTryCounter string `index:"DF51"`
ICCDynamicNumber string `index:"9F4C"`
IntegratedCircuitCardICCPINEnciphermentPublicKeyCertificate string `index:"9F2D"`
IntegratedCircuitCardICCPINEnciphermentPublicKeyExponent string `index:"9F2E"`
IntegratedCircuitCardICCPINEnciphermentPublicKeyRemainder string `index:"9F2F"`
IntegratedCircuitCardICCPublicKeyCertificate string `index:"9F46"`
IntegratedCircuitCardICCPublicKeyExponent string `index:"9F47"`
IntegratedCircuitCardICCPublicKeyRemainder string `index:"9F48"`
InterfaceDeviceIFDSerialNumber string `index:"9F1E"`
InternationalBankAccountNumberIBAN string `index:"5F53"`
IssuerActionCodeDefault string `index:"9F0D"`
IssuerActionCodeDenial string `index:"9F0E"`
IssuerActionCodeOnline string `index:"9F0F"`
IssuerApplicationData string `index:"9F10"`
IssuerAuthenticationData string `index:"91"`
IssuerCodeTableIndex string `index:"9F11"`
IssuerCountryCode string `index:"5F28"`
IssuerCountryCodealpha2format string `index:"5F55"`
IssuerCountryCodealpha3format string `index:"5F56"`
IssuerIdentificationNumberIIN string `index:"42"`
IssuerIdentificationNumberExtended string `index:"9F0C"`
IssuerPublicKeyCertificate string `index:"90"`
IssuerPublicKeyExponent string `index:"9F32"`
IssuerPublicKeyRemainder string `index:"92"`
IssuerScriptCommand string `index:"86"`
IssuerScriptIdentifier string `index:"9F18"`
IssuerScriptTemplate1 string `index:"71"`
IssuerScriptTemplate2 string `index:"72"`
IssuerURL string `index:"5F50"`
LanguagePreference string `index:"5F2D"`
LastOnlineApplicationTransactionCounterATCRegister string `index:"9F13"`
LogEntry string `index:"9F4D"`
LogFormat string `index:"9F4F"`
LowerConsecutiveOfflineLimit string `index:"9F14"`
MerchantCategoryCode string `index:"9F15"`
MerchantIdentifier string `index:"9F16"`
MerchantNameandLocation string `index:"9F4E"`
PaymentAccountReferencePAR string `index:"9F24"`
PersonalIdentificationNumberPINTryCounter string `index:"9F17"`
PointofServicePOSEntryMode string `index:"9F39"`
ProcessingOptionsDataObjectListPDOL string `index:"9F38"`
ResponseMessageTemplateFormat1 string `index:"80"`
ResponseMessageTemplateFormat2 string `index:"77"`
ServiceCode string `index:"5F30"`
ShortFileIdentifierSFI string `index:"88"`
SignedDynamicApplicationData string `index:"9F4B"`
SignedStaticApplicationData string `index:"93"`
StaticDataAuthenticationTagList string `index:"9F4A"`
TerminalCapabilities string `index:"9F33"`
TerminalCountryCode string `index:"9F1A"`
TerminalFloorLimit string `index:"9F1B"`
TerminalIdentification string `index:"9F1C"`
TerminalRiskManagementData string `index:"9F1D"`
TerminalType string `index:"9F35"`
TerminalVerificationResults string `index:"95"`
TokenRequestorID string `index:"9F19"`
Track1DiscretionaryData string `index:"9F1F"`
Track2DiscretionaryData string `index:"9F20"`
Track2EquivalentData string `index:"57"`
TransactionCertificateTCHashValue string `index:"98"`
TransactionCertificateDataObjectListTDOL string `index:"97"`
TransactionCurrencyCode string `index:"5F2A"`
TransactionCurrencyExponent string `index:"5F36"`
TransactionDate string `index:"9A"`
TransactionPersonalIdentificationNumberPINData string `index:"99"`
TransactionReferenceCurrencyCode string `index:"9F3C"`
TransactionReferenceCurrencyExponent string `index:"9F3D"`
TransactionSequenceCounter string `index:"9F41"`
TransactionStatusInformation string `index:"9B"`
TransactionTime string `index:"9F21"`
TransactionType string `index:"9C"`
UnpredictableNumber string `index:"9F37"`
UpperConsecutiveOfflineLimit string `index:"9F23"`
}
57 changes: 36 additions & 21 deletions exp/emv/emv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,50 @@ package emv

import (
"encoding/hex"
"fmt"
"os"
"testing"

"github.com/moov-io/iso8583/field"
"github.com/moov-io/iso8583"
"github.com/stretchr/testify/require"
)

func TestEmv(t *testing.T) {
exampleICCData := `9F0206000000006300820258009F360200029F2608B9B2B58202D37033840FA000000152301010000100000000009F100801050000000000009F3303E0F0C09F1A020840950500000000009A031711209C01005F2A0208409F370459F58EB1`
rawData, err := hex.DecodeString(exampleICCData)
iccData := `4f07a00000000410105f2a0208405f2d047275656e82021980950500000000009a032410029c01009f02060000000001009f03060000000000009f0607a00000000410109f090200029f1a0208409f1e0834543734353038359f21030909329f33030000e89f34030000009f3501229f360200539f370409bc21069f3901919f4104000000069f530100df81290830f0f00030f0ff00dfee2601d1dfef4c06002700000000dfef4d28fd4b4f392e1278361252d85649e405b430b9cb5e57d5211ba81d00242dbbd987ffe099fbf92b422eff810581ac500a4d6173746572436172648407a00000000410109f6d02000156a1292a353438392a2a2a2a2a2a2a2a313433375e202f5e323330333230312a2a2a2a2a2a2a2a2a2a2a2a2a56c1307004c1af307c59842b4edd3e745d27e783f4fefefb36698568ee921be4b2d6ae066b1a8cac8aba5c29453da922bc7ed89f6ba1135489cccccccc1437d2303201cccccccccccccc9f6bc118c5e921e707dabbfc762d47986509668fd22f9b3dbd10cbd6ff81063cdf812ac11870b80a15602160f54503ce3f5d9116997adb85fcfcd5388edf812bc110e912f0f4c0d82d1075ccc984f9864127df8115060000000000ffffee012cdf300100df31c110ab6c422bbfb95378504cbc6683306641df32c11081592240b4e352d17af39b923ad115caffee120acdcdcd0701453de0000d`
rawData, err := hex.DecodeString(iccData)
require.NoError(t, err)

// we have to add LLL length before rawData to unpack it
lenPrefix := fmt.Sprintf("%03d", len(rawData))
rawData = append([]byte(lenPrefix), rawData...)

emvField := field.NewComposite(Spec)
_, err = emvField.Unpack(rawData)

require.NoError(t, err)

data := &Data{}

err = emvField.Unmarshal(data)
msg := iso8583.NewMessage(MessageSpec)
msg.MTI("0100")
msg.BinaryField(55, rawData)

// this will print the all EMV tags in readable format
iso8583.Describe(msg, os.Stdout)

// like this (note, that first F is not part of the tag, it's just a Filed prefix):
// F55 ICC Data SUBFIELDS:
// -------------------------------------------
// F4F Application Identifier (AID) – card............: A0000000041010
// F5F2A Transaction Currency Code.....................: 0840
// F5F2D Language Preference...........................: 7275656E
// F82 Application Interchange Profile................: 1980
// F95 Terminal Verification Results..................: 0000000000
// F9A Transaction Date...............................: 241002
// F9C Transaction Type...............................: 00
// F9F02 Amount, Authorised (Numeric)..................: 100

// now we can extract values we can use
iccField := msg.GetField(55)
data := &NativeData{}
iccField.Unmarshal(data)

// test our spec and that we can pack and unpack the same
// without errors
packed, _ := msg.Pack()
msg2 := iso8583.NewMessage(MessageSpec)

err = msg2.Unpack(packed)
require.NoError(t, err)

require.Equal(t, int64(6300), data.AmountAuthorisedNumeric.Value())
require.Equal(t, "5800", data.ApplicationInterchangeProfile.Value())
require.Equal(t, int64(2), data.ApplicationTransactionCounter.Value())
require.Equal(t, "B9B2B58202D37033", data.ApplicationCryptogram.Value())

packed2, err := msg2.Pack()
require.Equal(t, packed, packed2)
}
Loading
Loading