...
Agnos - along with AgnosDB - provides a set of EMV core primitives which support EMV transaction flow. These primitives are used by:
CT payment applications (see emvco.c as example)
CL card processing applications (alias CL kernels)
C Structures
tTransactionalContext (agnos.h)
See emvco.c for an example using that structure (CT transaction flow only).
...
API _Version _Revision | Description |
---|
_Agnos _version 3.5.20 _revision 23770 | Agnos Interface is an abstraction of EMVCo Book I, II, and III. It relies on 3 components: An EMV tags database to store all tags involved in a card processing A set of EMV application selection routines An EMV engine implementing EMV steps and EMV primitives to access internal states and structures
Image Added Pre-contions setup Use tTransactionContext C structure to initialize Agnos → see emvco.c, an example used to implement EMVCo test app required for EMVCo CT L2 TA Use agnSetEMVTag() calls to initialize Agnos
Code Block |
---|
| gpiMemSet(gEMVCoCtx.mTransactionalContext,0x00,sizeof(tTransactionalContext));
// Set now default parameters for transactional context and using proprietary tags
gEMVCoCtx.mTransactionalContext->mForceTRM = bTRUE; // Always bTRUE for L2 TA. If AIP is missing then do TRM depending on DF12, DF13, DF14
gEMVCoCtx.mTransactionalContext->mSkipTACIACDefault = bTRUE; // DF11. If online only terminal and unable to go online then ARC = Z3 + AAC at 2nd GenAC
gEMVCoCtx.mTransactionalContext->mVelocityChecking = bTRUE; // DF12
gEMVCoCtx.mTransactionalContext->mRandomTransactionSelection = bTRUE; // DF13
gEMVCoCtx.mTransactionalContext->mFloorLimitChecking = bTRUE; // DF14
gEMVCoCtx.mTransactionalContext->mTAC = bTRUE; // DF15
gEMVCoCtx.mTransactionalContext->mPinTimeOut = 10; // DF27
gpiMemCpy(gEMVCoCtx.mTransactionalContext->mTransactionDate,payCtx->mTransactionDate,sizeof(gEMVCoCtx.mTransactionalContext->mTransactionDate));
gpiMemCpy(gEMVCoCtx.mTransactionalContext->mTransactionTime,payCtx->mTransactionTime,sizeof(gEMVCoCtx.mTransactionalContext->mTransactionTime));
agnosError = agnOpenSession("","",(const tString)"EMVCO CT Example",(const tTransactionalContext*)gEMVCoCtx.mTransactionalContext,
bTRUE /*DirectExecution -> reach GenAC - no granular calls*/,
bFALSE /*setEMVTag calls are performed by L3*/,
&payCtx->mSession,
bFALSE /*clipping*/,
bFALSE /*sred*/);
agnSetEMVTag(payCtx->mSession,0x9C,1,(uint8_t*)"\x00"); // Transaction type: depends on Transaction Related Data (TRD)
agnSetEMVTag(payCtx->mSession,0x9F1A,2,(uint8_t*)"\x00\x00"); // Terminal Country Code: depends on merchant context
agnSetEMVTag(payCtx->mSession,0x9F33,3,(uint8_t*)"\x00\x00\x00"); // Terminal Capabilities: depends on ICS
agnSetEMVTag(payCtx->mSession,0x9F35,1,(uint8_t*)"\x00"); // Terminal Type: depends on TRD
agnSetEMVTag(payCtx->mSession,0x9F40,5,uint8_t*)"\x00\x00\x00\x00\x00"); // Additional Terminal Capabilities: depends on TRD
agnSetEMVTag(payCtx->mSession,0x9F39,1,"\x05"); // POS Entry Mode |
Important: L3 must initialize CAKeys to enable ODA Application Selection shall be performed ahead to map AID selection with corresponding EMV tags. This depends on merchant context and acquirer configuration (PROCESSING)
Execution There are 3 ways to execute an EMVCo CT transaction. However, they follow the same pattern initiate/complete Code Block |
---|
| agnosError = agnInitiateEMVTransaction( payCtx->mSession,payCtx->mAmount,payCtx->mCashBack,
gEMVCoCtx.mMutualList.mList[gEMVCoCtx.mCandidate].mADFName,gEMVCoCtx.mMutualList.mList[gEMVCoCtx.mCandidate].mADFLen,
&payCtx->mCID);
if (agnTXN_ONLINE == agnosError)
{
return OLA_GO_ONLINE;
}
else if (agnTXN_ACCEPTED == agnosError)
{
return OLA_OFFLINE_ACCEPTED;
}
else if (agnTXN_REJECTED == agnosError)
{
return OLA_OFFLINE_DECLINED;
}
else if (agnSERVICE_NOT_ALLOWED == agnosError)
{
return OLA_NOT_ACCEPTED;
}
else if (agnPROCEED_TO_NEW_SELECTION == agnosError)
{
return OLA_CONTACT_NEW_SELECTION;
}
else if (agnSELECTION_ERROR == agnosError)
{
return OLA_CONTACT_SELECTION_ERROR;
}
else if (agnINTERRUPTED == agnosError)
{
return OLA_CANCEL;
}
else // Including agnSYSTEM_ERROR
{
return OLA_ERROR;
}
// ...
agnosError = agnCompleteEMVTransaction( payCtx->mSession,payCtx->mARC,&payCtx->mCID,
payCtx->mDataExchange.mIssuerResponse.mStream,payCtx->mDataExchange.mIssuerResponse.mLength,
payCtx->mUnableToGoOnline); |
Documentation under development… Documentation under development… Post-conditions setup Use different primitives such as agnGetEMVTag() to fetch any EMV information |
EMV Engine |
---|
See agnos..h |
#include
| Code Block |
---|
| #include "agnoserrors.h"
//---- Agnos Framework Headers ----
#include "agnosdatabase.h"
//---- Global Headers ----
#include "gpi_agnos_framework_globals.h" |
| -- |
tTransactionalContext
| Code Block |
---|
| typedef struct {
/** If bTRUE, TAC/IAC default processing is skipped if unable to go online*/
tBoolean |
|
...
mSkipTACIACDefault;
/** If bTRUE, TAC processing is performed*/
tBoolean |
|
...
mTAC;
/** If bTRUE, Floor Limit Checking is performed*/
tBoolean |
|
...
mFloorLimitChecking;
/** If bTRUE, RTS is performed*/
tBoolean |
|
...
mRandomTransactionSelection;
/** If bTRUE, Velocity Checking is performed*/
tBoolean |
|
...
mVelocityChecking;
/** If bTRUE, Default TDOL is supported*/
tBoolean |
|
...
mDefaultTDOL;
/** TDOL length*/
tByte |
|
...
mDefaultTDOLLen;
/**Tag 0x97*/
tByte |
|
...
mDefaultTDOLValue[TDOL_MAX_LENGTH];
/** If bTRUE, Default DDOL is supported*/
tBoolean |
|
...
mDefaultDDOL;
/** DDOL length*/
tByte |
|
...
mDefaultDDOLLen;
/**Tag 0x9F49 or 0x9F69 (UDOL for contactless)*/
tByte |
|
...
mDefaultDDOLValue[DDOL_MAX_LENGTH];
/**Terminal Action Code - Denial*/
tTVR mTACDenial;
/**Terminal Action Code - Online*/
tTVR mTACOnline;
/**Terminal Action Code - Default*/
tTVR mTACDefault;
/**Tag 0x9F1B*/
tAmount mTerminalFloorLimit;
/**See EMV Book III, TRM section - Random Transaction Selection*/
tPercentage mTargetPercentage;
/**See EMV Book III, TRM section - Random Transaction Selection. Same transaction currency exponent as 0x9F02*/
tAmount mThresholdValue;
/**See EMV Book III, TRM section - Random Transaction Selection*/
tPercentage mMaxTargetPercentage;
/**if bTRUE, pin may be bypassed when requested*/
tBoolean |
|
...
mPINByPass;
/**bTRUE when merchant manually requested transaction to go online*/
tBoolean |
|
...
mForcedOnline;
/**Tag 0x9A*/
tNumericDate |
|
...
mTransactionDate[3];
/**Tag 0x9F21*/
tNumericDate |
|
...
mTransactionTime[3];
/**Tag 0x9F35*/
tTerminalType |
|
...
mTerminalType;
/** Transaction language*/
tByte |
|
...
mLanguage;
/** PIN entry delay in second*/
tCounter |
|
...
mPinTimeOut;
/** CDAMode1, CDAMode2 and CDAMode3 only*/
tCDAType |
|
...
mCDAType;
/**if bTRUE, Terminal Risk Management is performed even if ICC doesn't request it*/
tBoolean |
|
...
mForceTRM;
/**Tag 0x5F57*/
tByte |
|
...
mAccountType;
/**Tag 0x9F39*/
tByte |
|
...
mPOSEntryMode;
/**Tag 0x9F41*/
tCounter |
|
...
mTransactionSequenceCounter;
/**Tag 0x9F1D*/
tByte |
|
...
mTerminalRiskManagementData[8];
/**Tag 0x9F3A*/
tAmount |
|
...
mAmountReferenceCurrency;
/**Tag 0x9F3C*/
tByte |
|
...
mTransactionReferenceCurrencyCode[2];
/**Tag 0x9F3D*/
tByte |
|
...
mTransactionReferenceCurrencyExponent;
/**Tag 0x9F1A*/
tByte mTerminalCountryCode[2];
/**Tag 0x5F2A*/
tByte |
|
...
mTransactionCurrencyCode[2];
/**Tag 0x5F36*/
tByte |
|
...
mTransactionCurrencyExponent;
/**Tag 0x9F33*/
tByte |
|
...
mTerminalCapabilities[3];
/**Tag 0x9F40*/
tByte |
|
...
mAdditionalTerminalCapabilities[5];
/**Tag 0x9F09*/
tByte mApplicationVersionNumber[2];
/**Tag 0x9C*/
tByte |
|
...
mTxnType;
/**Tag 0x9F1C*/
tByte |
|
...
mTerminalIdentification[8];
/**Tag 0x9F1E*/
tByte |
|
...
mIFDSerialNumber[8];
/**Tag 0x9F01*/
tByte |
|
...
mAcquirerIdentifier[6];
} tTransactionalContext; |
| |
agnGetVersionNumber
| Code Block |
---|
| DLLEXPORT tString agnGetVersionNumber(void); |
| Get EMV core engine version. |
agnOpenSession
| Code Block |
---|
| DLLEXPORT tAgnosError agnOpenSession(
const tString smartcardReaderName,
const tString pinPadName,
const tString applicationId,
const tTransactionalContext *txnContext,
tBoolean DirectExecution,
tBoolean setEMVTag,
tSessionId *session,
tBoolean clipping,
tBoolean sred
); |
| Open a CT session to initiate an EMV transaction flow. |
agnInitiateEMVTransaction
| Code Block |
---|
| DLLEXPORT tAgnosError agnInitiateEMVTransaction (
tSessionId session,
const tAmount *amount,
const tAmount *cashBack,
const tByte *AID,
tByte AIDLen,
tByte *CID
); |
| Initiate/Resume an EMV transaction |
agnCompleteEMVTransaction
| Code Block |
---|
| DLLEXPORT tAgnosError agnCompleteEMVTransaction (
tSessionId session,
tARC ARC,
tByte *CID,
const tByte *issuerResponse,
tWord issuerResponseLen,
tBoolean unableToGoOnline
); |
| Complete a transaction as per EMVCo definition |
agnGetDatabase
| Code Block |
---|
| DLLEXPORT tTagDataBase* agnGetDatabase(const tSessionId session); |
| |
agnIsEMVTagKnown
| Code Block |
---|
| DLLEXPORT tBoolean agnIsEMVTagKnown(
tWord tag // In: Tag to search in db storing referenced tags
); |
| Return bTRUE is tag statically known. |
agnIsEMVTagPresent
| Code Block |
---|
| DLLEXPORT tBoolean agnIsEMVTagPresent(
tSessionId session, // In: Kernel's session
tWord tag // In: Tag to search in current session
); |
| Return bTRUE if tag is present whatever its length. |
agnIsEMVTagEmpty
| Code Block |
---|
| DLLEXPORT tBoolean agnIsEMVTagEmpty(
tSessionId session, // In: Kernel's session
tWord tag // In: Tag to assess length
); |
| Return bTRUE if tag’s length is 0. |
agnIsEMVTagNotEmpty
| Code Block |
---|
| DLLEXPORT tBoolean agnIsEMVTagNotEmpty(
tSessionId session, // In: Kernel's session
tWord tag // In: Tag to assess length
); |
| Return bTRUE if tag’s length is not 0. |
agnGetEMVTag
| Code Block |
---|
| DLLEXPORT tAgnosError agnGetEMVTag(
tSessionId session, // In: Kernel's session
tWord tag, // In: See agnostypes.h. Tags values are word values (unsigned short)
tByte *length, // Out: Tag's length
tByte *value // Out: Value shall be allocated by calling application
) |
| Get a specific tag from Agnos database. |
agnSetEMVTag
| Code Block |
---|
| DLLEXPORT tAgnosError agnSetEMVTag(
tSessionId session, // In: Kernel's session
tWord tag, // In: See agnostypes.h. Tags values are word values (unsigned short)
tByte length, // In: Length of tag's value
const tByte *value // In: Tag's length
); |
| Add a tag into Agnos database without checking tag’s update condition. |
agnOverwriteEMVTag
| Code Block |
---|
| DLLEXPORT tAgnosError agnOverwriteEMVTag(
tSessionId session, // In: Kernel's session
tWord tag, // In: See agnostypes.h. Tags values are word values (unsigned short)
tByte length, // In: Length of tag's value
const tByte *value // In: Tag's length
); |
| Overwrite an existing tag. If it doesn’t exist, create it (no garbage collection if sizes don’t match). |
agnRemoveEMVTag
| Code Block |
---|
DLLEXPORT tAgnosError agnRemoveEMVTag(
tSessionId session, // In: Kernel's session
tWord tag // In: See agnostypes.h. Tags values are word values (unsigned short)
); |
| Remove a tag from Agnos database (no garbage collection). |
agnORTVR
| Code Block |
---|
DLLEXPORT tAgnosError agnORTVR(
tSessionId session, // In: Kernel's session
tByte TVRPosition, // In: 0 based position
tByte value // In: Value to OR
); |
| OR a specific TVR’s bit to 1. |
agnORAgnosTVR
| Code Block |
---|
| DLLEXPORT tAgnosError agnORAgnosTVR(
tSessionId session, // In: Kernel's session
tByte AgnosTVRPosition, // In: 0 based position
tByte value // In: Value to OR
) |
| OR a specific Agnos TVR’s bit to 1. |
agnSetAgnosTVR
| Code Block |
---|
| DLLEXPORT tAgnosError agnSetAgnosTVR(
tSessionId session, // In: Kernel's session
tByte AgnosTVRPosition, // In: 0 based position
tByte value // In: Value to Set
); |
| Set a specific Agnos TVR byte value. |
agnOpenSessionCL
| Code Block |
---|
| DLLEXPORT tAgnosError agnOpenSessionCL(
const tString smartcardReaderName, // In: Smartcard device name
const tString pinPadName, // In: Secured PIN entry device name
const tString applicationId, // In: Application Id
const tTransactionalContext |
|
...
tADFList (selection.h)
...
*txnContext, // In: Context provided by the payment application
tBoolean setEMVTag, // In: set EMV data in kernel database (from transacitonal context)
tSessionId *session, // Out: Session returned by the kernel to be used when primitives are called
tBoolean clipping, // In: activate software clipping into Agnos
tBoolean sred // In: activate low level clipping
); |
| Open a CL session to initiate an EMV transaction flow |
agnCloseSession
| Code Block |
---|
| DLLEXPORT tAgnosError agnCloseSession (
tSessionId session
); |
| Close a transaction flow. |
agnSetAgnosDatabase | | Add a series of tags. Each tag is statically indexed and ruled by an update condition. Use an appropriate update condition to store tags directly into Agnos database |
agnSetKernelStatus | | Set core engine to a specific state. Use this primitive to skip a state in State Machine mode |
agnGetAllTags | | Get all tags from Agnos database |
Application Selection Routines |
---|
See selection..h |
#include
| Code Block |
---|
| #include "agnoserrors.h"
//---- Global Headers ----
#include "gpi_agnos_framework_globals.h" |
| -- |
tADFList
| Code Block |
---|
| typedef struct {
|
|
...
...
tADF mList[MAX_SUPPORTED_ADF];
|
|
...
tBoolean mEliminatedADF[MAX_SUPPORTED_ADF];
|
|
...
...
tBoolean mAnyBlockedApplication;
|
|
...
...
mSelectionIndex;
} tADFList; |
| |
tADF
|
...
...
...
...
...
mADFName[MAX_AID_LENGTH]; //0x4F
|
|
...
...
...
...
mLabel[MAX_AID_LENGTH]; //0x50
|
|
...
...
...
...
mPreferredName[MAX_AID_LENGTH]; //0x9F12
|
|
...
...
...
...
mPriorityIndicator; //0x87
|
|
...
...
mLangagePreference[8]; //0x5F2D
|
|
...
...
...
...
mIssuerCodeTableIndex; //0x9F11
|
|
...
...
...
MAX_REMAINING_FCI_LENGTH]; //0xBF0C. May contain Issuer Country Code 5F56 AND/OR Application Selection Flag DF62
|
|
...
...
...
...
...
...
mCorrespondingAIDOrderNumber; // Order of the ADF in the AID list (application supported by terminal)
|
|
...
// Extension to support PPSE
|
|
...
tByte mKernelIdentifier[8]; //0x9F2A
|
|
...
tByte mKernelIdentifierLen;
|
|
...
tByte mRequestedKernelId;
|
|
...
tByte mExtendedSelection[MAX_AID_LENGTH]; //0x9F29
|
|
...
tByte mExtendedSelectionLen;
} tADF; |
| |
tPSE
|
...
...
...
...
...
mPSEName[MAX_AID_LENGTH]; //0x84
|
|
...
...
...
...
...
...
mLangagePreference[8]; //0x5F2D
|
|
...
...
...
...
mIssuerCodeTableIndex; //0x9F11
|
|
...
...
mRemainingFCI[MAX_REMAINING_FCI_LENGTH]; //0xBF0C. May contain Issuer Country Code 5F56 AND/OR Application Selection Flag DF62
|
|
...
...
mRemainingFCILen;
} tPSE; |
|
Primitives
...
Names
...
Comments
...
Initialization
...
agnGetVersionNumber
...
Provide EMV core engine version
...
agnOpenSession
...
Open a CT session to initiate an EMV transaction flow
...
agnOpenSessionCL
...
Open a CL session to initiate an EMV transaction flow
...
agnInititateEMVTransaction
...
Initiate/Resume an EMV transaction
...
agnCompleteEMVTransaction
...
Complete a transaction as per EMVCo definition
...
agnCloseSession
...
Close a transaction flow
...
Setters and Getters
...
agnSetAgnosDatabase
...
agnSetKernelStatus
...
agnSetEMVTag
...
agnOverwriteTag
...
agnRemoveTag
...
agnGetEMVTag
...
agnGetAllTags
...
agnGetDatabase
...
agnIsEMVTagKnown
...
agnIsEMVTagPresent
...
agnIsEMVTagEmpty
...
agnIsEMVTagNotEmpty
...
agnORTVR
...
OR a specific TVR’s bit to 1
...
agnORAgnosTVR
...
OR a specific Agnos TVR’s bit to 1
...
agnSetAgnosTVR
...
Set a specific Agnos TVR byte value
...
AgnosDB
...
adbGetVersionNumber
...
Provide Agnos database version
...
adbResetDataBase
...
adbAddTag
...
adbAddUnknownTag
...
adbGetUnknowTags
...
adbGetUnknownTagsLength
...
adbGetUnknownTagsCount
...
adbGetAllTLV
C Example
...
|
---|
See emvtag.h, agnosdatabase.h |
| | -- |
adbGetVersionNumber | | Provide Agnos database version. Get all pointers on shared RAM spaces provided by SAL/HAL and set adbAddTag strategy to STANDARD (i.e. EMVCo rule where update conditions are not checked) |
adbResetDataBase | | Reserved to Agnos core engine. Reset database structure |
adbSetStrategy | | Reserved to Agnos core engine and contactless card processing. By default, Agnos databse uses EMVco tags storage strategy where no check is performed on tags' update conditions. If a storage strategy is defined (by a contactless card processing) then: If an AddTag_Contacltess callback is defined (by a contactless card processing), Agnos database calls the callback to check wheter a tag can be added Else, Agnos database uses its default contactless storage strategy
|
adbAddTag | | Reserved to Agnos core engine. Check whether a tag may be added into EMV tags database. In order to store EMV tags directly into Agnos database, use agnSetAgnosDataBase primitive instead |
adbAddUnknownTag | | Add any tags into EMV tags database in “UnknowTag” bucket |
adbGetUnknowTags | | Get all tags stored into unknown tags bucket |
adbGetUnknownTagsLength | | Get the bucket’s length |
adbGetUnknownTagsCount | | Get tags count from the bucket |
adbGetAllTLV | | Get all TLV stored in AgnosDB. Code Block |
---|
tTagDataBase db;
unsigned char buffer[100]="";
unsigned short maxLength=100, actualLength=0;
aceOut(adbGetVersionNumber());
adbResetDataBase(&db);
adbGetAllTLV(&db,buffer,maxLength,&actualLength);
aceSendRawDD(buffer,actualLength);
adbAddUnknownTag(&db,(const unsigned char*)"\x9F\x02\x06\x99\x99\x99\x99\x99\x99",0x09);
adbGetAllTLV(&db,buffer,maxLength,&actualLength);
aceSendRawDD(buffer,actualLength); |
|
Code Example |
---|
See emvco.c. and selectionlogic.h. They provide good examples on agnos.h and selection.h integration in the scope of contact card processing. |