Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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;
}