Online documentation (Javadoc)
The online API documentation can be found at the following address: https://fbe-host.ca/agnos/agnos-2.0.0-javadoc/index.html .
Sample code
The code snippets below are just an example of how things can be done, absolutely not the only way to go!
Basic transaction
A basic OLA transaction includes the following steps:
OLA classes
...
instantiation (once at startup)
Code Block |
---|
private final Ola ola; private final OlaEmv emv; private final OlaContactless contactless; private final Dev dev; this.ola = Ola.AccessLowLevelgetInstance(); this.emvcontactless = OlaEmvOlaContactless.AccessLowLevelgetInstance(); this.contactlessemv = OlaContactlessOlaEmv.AccessLowLevelgetInstance(); this.dev = new Dev(this, this, this, false, |
OLA component initialisation (once at startup)
Code Block |
---|
/** * Configures OLA layer (key files paths, trace, etc...) */ private void olaConfig() { final byte[] path = {(byte)0xdf, 0x01, 28}; final String pathValue = "/data/data/<application_name>ca.amadis.tester/"); /* internal storage pathfinal example */ |
OLA component initialization (Ola.ola_initialize)
Code Block |
---|
private void txnInit() {byte[] cakeys = {(byte)0xdf, 0x02, 34}; final String pathcakeysValue = "/data/data/comca.amadis.agnos_tester/CAKeys"; final Stringbyte[] CAKeyscrl = path + "CAKeys"{(byte)0xdf, 0x03, 31}; final String CRLcrlValue = path + ""/data/data/ca.amadis.tester/CRL"; final Stringbyte[] EFLefl = path + "EFL"{(byte)0xdf, 0x04, 31}; final String langInieflValue = path + "lang.ini"/data/data/ca.amadis.tester/EFL"; final byte[] paramspcsc = {0x00(byte)0xdf, 0x000x05, 0x00, 0x10, 0x05}; // pcsc not used final byte[] lang = {(byte)0xdf, 0x06, 0x00}; // lang not used final byte[] paramsLenruntimeParams = {(byte)params.length0xdf, 0x07, 0x07, 0x00, 0x0F, 0x04, 0x0F, 0x0A, 0x00, 0x01}; final byte[] traceLevel = {(byte)50xdf, 0x08, 0x01, 0x05}; final byte[] ola.ola_initialize(new OlaInit(path, CAKeys, CRL, EFL, langIni, params, paramsLen, traceLevel)); } |
...
pollingTechno = {(byte)0xdf, 0x10, 0x01, 0x04}; // Contactless only
final byte[] sredMode = {(byte)0xdf, 0x17, 0x01, 0x01}; // SRED mode active
try
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(path);
out.write(pathValue.getBytes());
out.write(cakeys);
out.write(cakeysValue.getBytes());
out.write(crl);
out.write(crlValue.getBytes());
out.write(efl);
out.write(eflValue.getBytes());
out.write(pcsc);
out.write(lang);
out.write(runtimeParams);
out.write(traceLevel);
out.write(pollingTechno);
out.write(sredMode);
byte[] tlv = out.toByteArray();
ola.initializeAtStartUp(tlv);
}
catch (IOException e)
{
}
} |
AID configuration (once at startup)
Code Block |
---|
private OlaContactlessResultvoid txnPreProcessterminalContactlessConfig() { contactless.flushAIDSupported(); for (OLAConfig.ContactlessCfg config : OLAConfig.contactlessCfg) OlaContactlessResult ret = contactless.ola_contactless_preprocess( { contactless.addAIDSupported( config.aid, config.partial, (byte)config.kernelId, config.additionalData ); } contactless.commitSupportedAIDs(); } |
Keys configuration (once at startup)
Code Block |
---|
private void terminalPublicKeyConfig() { publicKey.flush(); new byte rid[] = {(byte)0xA0, 0x00, 0x00, 0x00, 0x0A}, , 0x03}; byte idx = (byte)0x92; byte modulus[] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; byte exponentValue[] = {0x03}; byte expirDate[] = {0x22, 0x12, 0x31}; Holders.SingleObjectHolder<Boolean> wasMaxReached_holder = new Holders.SingleObjectHolder<Boolean>(false); new BCD.BCD_YYMMDD(20, 12, 31)OlaPublicKey.PublicKeyData key = publicKey.new PublicKeyData(rid, idx, modulus, exponentValue, expirDate); publicKey.add(key, null, wasMaxReached_holder); publicKey.commit(); } |
Transaction related data (before each transaction)
Code Block |
---|
private void txnSetTransactionRelatedData() { emv.setTag(OlaTag.TRANSACTION_DATE, new byte[]{0x20, 0x10, 0x28}); // 9A emv.setTag(OlaTag.TRANSACTION_TIME, new BCD.BCD_YYMMDD(12, 59, 59), byte[]{0x12, 0x00, 0x00}); // 9F21 emv.setTag(OlaTag.AMOUNT_AUTHORISED, new byte[]{0x00, 0x00, 0x00, 0x00, 0x01, 0x50}); // 9F02 emv.setTag(OlaTag.AMOUNT_OTHER_NUM, new BCD(0, 0, 0, 1) byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x50}); // 9F03 emv.setTag(OlaTag.TRANSACTION_CURRENCY_CODE, new byte[]{0x08, 0x40}); // 5F2A emv.setTag(OlaTag.TRANSACTION_CURRENCY_EXPONENT, new byte[]{0x02}); // 5F36 emv.setTag(OlaTag.TRANSACTION_TYPE, new BCD(0) ); byte[]{0x00}); // 9C /* * Other possible tags to set here: * Account Type (5F57) * Transaction Category Code (9F53) * * All other tags must be set through the combinations! */ } |
Preprocessing
Code Block |
---|
private OlaError txnPreProcess() { OlaError ret = contactless.preprocess(); if (ret != OlaContactlessResultOlaError.OLA_OK) { Log.e("OLA-TESTER", "contactless pre-process failed"); } return ret; } |
Card detection
Code Block |
---|
private short txnGetCard() { Log.d("OLA-TESTER", "PRESENT CARD"); int foundTechnos = dev.technoPolling(60000); l("Result of foundTechnos: "+ foundTechnos); if (foundTechnos==4) { return clcEMV_CARD; //TODO remove hard-coding } else { return 0; } } |
...
Do transaction
Code Block |
---|
private OlaContactlessResultOlaError txnBuildCandidateListdoTransaction() { SingleObjectHolder<Integer> nbCandidatesHolder = new SingleObjectHolder<Integer>(); OlaContactlessResultOlaError ret = contactless.ola_contactless_build_candidate_listbuildCandidateList(nbCandidatesHolder); if (ret != OlaContactlessResultOlaError.OLA_OK) { showOutcome(ret); } /* * For now, finalSelectCandidate is useless. Everything from preprocessing to card * processing is return ret; } |
Select application (OlaContactless.ola_contactless_final_select_candidate)
Code Block |
---|
private OlaContactlessResult txnFinalSelectCandidate() { done in "buildCandidateList". This will change as soon as exit conditions * are availble in OLA 2.x, hence we keep all the function calls here */ SingleObjectHolder<Byte> kernel_id_holder = new SingleObjectHolder<Byte>(); OlaContactlessResult ret = contactless.ola_contactless_final_select_candidatefinalSelectCandidate(1, kernel_id_holder); if (ret != OlaContactlessResultOlaError.OLA_OK) { showOutcome(ret); } return ret; } |
Start transaction (OlaContactless.ola_contactless_do_transaction)
Code Block |
---|
private void txnDoTransaction() { SingleObjectHolder<OlaEntryMode> entryMode_holder = new SingleObjectHolder<OlaEntryMode>(); OlaContactlessResult ret = contactless.ola_contactless_do_transaction(entryMode_holder); showOutcome(ret)ret = contactless.doTransaction(); showOutcome(ret); if (ret == OlaError.OLA_OK) { SingleObjectHolder<byte[]> bytesHolder = new SingleObjectHolder<byte[]>(); for (int olaTag : batch) { OlaError result = emv.getTag(olaTag, bytesHolder); if (result == OlaError.OLA_OK) l("Result for ola_contactless_get_tag(): "+result+" => "+ Arrays.toString(bytesHolder.get())); else l("Result for ola_contactless_get_tag(): "+result+" => tag missing"); } } Log.d("OLA-TESTER", "**** REMOVE CARD **** "); return ret; } |