Jcard Internals PDF
Jcard Internals PDF
Jcard Internals PDF
Table of Contents
Copyright notice ......................................................................................................................... v
1. jCard Server ........................................................................................................................... 1
1.1. jCard Server Lifecycle ............................................................................................... 1
1.2. jPOS CMF Server ...................................................................................................... 1
1.3. jPOS XML Server ...................................................................................................... 2
1.4. jCard Request Dispatcher ........................................................................................... 2
1.5. Incoming Handlers ..................................................................................................... 3
2. jCard Transaction Manager ................................................................................................... 5
3. jCard Transaction Manager Participants ............................................................................... 8
3.1. PrepareContext ............................................................................................................ 8
3.2. Open ............................................................................................................................ 9
3.3. Switch ....................................................................................................................... 10
3.4. Balance Inquiry Group ............................................................................................. 12
3.4.1. CheckFields participant ................................................................................. 13
3.4.2. CreateTranLog participant ............................................................................. 16
3.4.3. CheckCard participant ................................................................................... 18
3.4.4. CheckTerminal participant ............................................................................ 19
3.4.5. CheckAcquirer participant ............................................................................. 20
3.4.6. SelectAccount participant .............................................................................. 20
3.4.7. ComputeBalances participant ........................................................................ 21
ii
List of Figures
2.1. Transaction Manager .......................................................................................................... 5
2.2. Transaction Participants ..................................................................................................... 6
3.1. Card / CardHolder / Account Relatioship ........................................................................ 18
3.2. Terminal / Merchant related relationships ........................................................................ 19
3.3. Card / CardHolder / Account Relatioship ........................................................................ 21
iii
List of Tables
3.1. jCard supported transactions ............................................................................................ 11
3.2. CheckFields special constant names ................................................................................ 13
iv
Copyright notice
Copyright © 1998-2015 by Alejandro Revilla d/b/a jPOS Consulting, Company# 212 752 380 016 - Uruguay. All rights
reserved. No part of this book may be reproduced in any form or by any electronic or mechanical means, including
information storage and retrieval systems, without permission in writing from Alejandro Revilla, except by a reviewer who
may quote brief passages in a review.
v
Chapter 1. jCard Server
1.1. jCard Server Lifecycle
The lifecycle of a transaction managed by jCard starts at a server.
jCard can have multiple servers that in turn can operate using different ISO-8583 version/
variants.
• jCard Native servers that operate using the jPOS CMF [http://jpos.org/doc/jPOS-CMF.pdf]
• Customer specific servers that use other ISO-8583 versions/variants, or even non ISO-8583
based protocols and convert all incoming and outgoing messages to and from the jPOS
CMF
The non jCard servers can operate on the same JVM as jCard (if deployed on the same deploy
directory), or they can run at external JVMs or even external systems and in turn connect to a
native jCard server after the conversion to and from jPOS CMF took place.
We call those customer specific servers (either running on the same JVM or on external JVMs)
Source Stations.
The previous configuration instantiates a standard jPOS ISOServer that listens on a port
defined in the target file (i.e. devel.properties)
The jPOS-EE build process uses Jakarta Ant’s filters to preprocess properties
defined in the build files (i.e. build.xml, build.properties, devel.properties)
providing property expansion. In the default jCard configuration, the property
iso2003_server_port is defined in devel.properties with a value of 8001.
1
jCard Server
The server uses the jPOS CSChannel and GenericPackager configured for ISO-8583
v2003. It uses a 5 minutes timeout (300000ms) and defines a request listener
org.jpos.jcard.Dispatcher and passes some configuration parameters to it, such as a space,
a transaction manager queue (JCARD.TXN) and a class prefix (org.jpos.jcard.Incoming_).
The Dispatcher completes the class name using the incoming message’s MTI and forwards the
transaction to the appropriate class, i.e:
• Incoming_100
• Incoming_200
• Incoming_220
• …
• …
The previous configuration instantiates a standard jPOS ISOServer that listens on a port
defined in the target file (i.e. devel.properties).
See jPOS CMF Server for an explanation of how filters work as well as how the
request listener is configured.
This XML server uses jPOS XML representation of ISO-8583 messages (same as shown in the
jPOS logs).
2
jCard Server
This is a very simple handler that would just echo back a 810 response.
On the other hand, other messages, such as 100, 200, 220, 304 and 420s are more complex
and handled by the Transaction Manager. The implementation classes inherit from
IncomingSupport and are implemented like this:
3
jCard Server
This basically:
In adition to the queue name, we define a timeout (in millis). The Context is placed in the
Space for a given time; ideally, it should be picked immediately by the TransactionManager.
If the timeout expires, the entry will be lost. Interesting enough, due to the way the
ISO-8583 operates, this is a good thing. If for some reason a transaction doesn’t reach the
TransactionManager in a reasonable short period of time, it would indicate that the system is
experiencing problems (such as a database being down, extremely high load, network issue,
etc.). The best thing is to ignore the aging transactions so that the system recovers faster when
the situation gets resolved. The remote endpoint will retry the transactions and the system will
be back up and running faster than if we try to process transactions that wouldn’t reach the
remote endpoint anyway, because they have been timed out already.
4
Chapter 2. jCard Transaction Manager
jCard uses the jPOS TransactionManager [http://jpos.org/doc/javadoc/org/jpos/
transaction/TransactionManager.html] 1 to implement its business logic using
reusable TransactionParticipant’s [http://jpos.org/doc/javadoc/org/jpos/transaction/
TransactionParticipant.html].
jCard splits the business logic implementation into small little reusable chunks that we call
participants. A typical transaction would:
5
jCard Transaction Manager
This creates a TransactionManager named txnmgr (it doesn’t explicitly define a name
attribute, so the element name is used as the service name) and define the following properties:
6
jCard Transaction Manager
As we said above, if the TransactionManager definition has its debug property enabled, it
will produce log ticket. Here is a sample of what they look like:
T 2010.589" lifespan="56ms">
<debug>
txnmgr-0:151
prepare: org.jpos.jcard.PrepareContext NO_JOIN
prepare: org.jpos.transaction.Open READONLY NO_JOIN
prepare: org.jpos.jcard.Switch READONLY NO_JOIN
groupSelector: reversal prepareresponse logit close sendresponse
prepare: org.jpos.jcard.CheckFields NO_JOIN
prepare: org.jpos.jcard.CreateTranLog NO_JOIN
prepare: org.jpos.jcard.CheckCard NO_JOIN
prepare: org.jpos.jcard.CheckTerminal NO_JOIN
prepare: org.jpos.jcard.CheckAcquirer NO_JOIN
prepare: org.jpos.jcard.FindOriginal READONLY NO_JOIN
prepare: org.jpos.jcard.Reverse READONLY NO_JOIN
prepare: org.jpos.jcard.PrepareResponse NO_JOIN
prepare: org.jpos.jcard.LogIt READONLY NO_JOIN
prepare: org.jpos.transaction.Close READONLY
prepare: org.jpos.jcard.SendResponse READONLY
prepare: org.jpos.jcard.ProtectDebugInfo READONLY
prepare: org.jpos.transaction.Debug READONLY
commit: org.jpos.transaction.Close
commit: org.jpos.jcard.SendResponse
commit: org.jpos.jcard.ProtectDebugInfo
commit: org.jpos.transaction.Debug
head=152, tail=152, outstanding=0, tps=12, peak=13, avg=9.38, elapsed=56ms
<profiler>
prepare: org.jpos.jcard.PrepareContext [0.0/0.0]
prepare: org.jpos.transaction.Open [0.6/0.6]
prepare: org.jpos.jcard.Switch [0.0/0.6]
prepare: org.jpos.jcard.CheckFields [0.2/0.9]
prepare: org.jpos.jcard.CreateTranLog [1.2/2.1]
prepare: org.jpos.jcard.CheckCard [4.2/6.4]
prepare: org.jpos.jcard.CheckTerminal [0.8/7.2]
prepare: org.jpos.jcard.CheckAcquirer [0.6/7.9]
prepare: org.jpos.jcard.FindOriginal [2.3/10.2]
prepare: org.jpos.jcard.Reverse [29.5/39.7]
prepare: org.jpos.jcard.PrepareResponse [1.7/41.5]
prepare: org.jpos.jcard.LogIt [0.1/41.7]
prepare: org.jpos.transaction.Close [0.0/41.7]
prepare: org.jpos.jcard.SendResponse [0.0/41.7]
prepare: org.jpos.jcard.ProtectDebugInfo [0.0/41.7]
prepare: org.jpos.transaction.Debug [0.0/41.7]
commit: org.jpos.transaction.Close [4.5/46.3]
commit: org.jpos.jcard.SendResponse [0.8/47.1]
commit: org.jpos.jcard.ProtectDebugInfo [0.1/47.3]
commit: org.jpos.transaction.Debug [9.0/56.3]
end [56.9/56.9]
</profiler>
</debug>
</log>
7
Chapter 3. jCard Transaction Manager
Participants
Once the transaction reaches the top of the Transaction Manager’s queue, it gets processed by
the participants defined in the file modules/jcard/src/dist/deploy/10_txnmgr.xml.
In this chapter we’ll take a look at some of the most significant ones, to have an idea of what
they do and how they work together to accomplish a full transaction. :numbered:
3.1. PrepareContext
The PrepareContext participant is the very first participant in the execution chain. It is
configured in ../deploy/10_txnmgr.xml like this:
<txnmgr ...>
...
<participant class="org.jpos.jcard.PrepareContext" logger="Q2" realm="PrepareContext" />
...
</txnmgr>
• TIMESTAMP:It is desirable that all participants in a given transaction use exactly the same
timestamp, in order to avoid edge conditions where a transaction starts at a given date (i.e.
23:59:59.99) and finish the next day (i.e.: at 00:00:00.00). These conditions not only happen
at day boundary, they could happen at cutover times, etc.
• TXNMGR: In situations where a transaction is forwarded from one transaction manager
to another one (using the Forward participant), this context variable keeps a list of the
transaction managers involved in a given transaction.
8
jCard Transaction
Manager Participants
The code is straight forward, but it deserves a few comments and clarifications:
3.2. Open
The Open participant creates a new org.jpos.ee.DB object, which in turns holds a live
Hibernate and JDBC session. It stores a reference to the DB object in the context, under the
name DB (defined in the org.jpos.ee.Constants interface). In addition, it begins a Hibernate/
JDBC transaction, and stores it under the name TX.
• checkpoint: This participant uses the general purpose jPOS Profiler [http://jpos.org/doc/
javadoc/org/jpos/util/Profiler.html] in order to have realtime, fine grained, information
about the system’s performance. We store a checkpoint called open that will appear at the
end of every transaction (courtesy of the participant Debug that dumps the Context variables
to the jPOS log).
• timeout: This is a timeout passed to Hibernate, which in turn passes it to the underlying
JDBC session. It is expressed in tenths of a second (in this case, 30.0 seconds).
1
Duck typing
9
jCard Transaction
Manager Participants
3.3. Switch
Once the Context is prepared, and a Hibernate/JDBC session has been opened, we are
ready to analize the transaction and decide how to route it, using a TransactionManager's
GroupSelector [http://jpos.org/doc/javadoc/org/jpos/transaction/GroupSelector.html].
Switch extends TxnSupport just to enjoy a couple of helper methods, such as the fact that
it already implements org.jpos.util.Configurable. It does nothing at prepare time, and
returns a PREPARE | READONLY | NO_JOIN value that tells the TransactionManager that:
Then the select method uses the TXNNAME provided by the incoming handlers in order to
figure out which set of groups are going to process this transaction. It keys off the TXNNAME
using configuration properties provided in the transaction manager configuration file
(.../deploy/10_txnmgr.xml) that looks like this:
...
<participant class="org.jpos.jcard.Switch" logger="Q2" realm="Switch">
<property name="100.30"
value="balanceinquiry prepareresponse logit close sendresponse" />
<property name="100.00"
value="authorization prepareresponse logit close sendresponse" />
<property name="100.02"
value="auth-void prepareresponse logit close sendresponse" />
<property name="100.20"
value="refund prepareresponse logit close sendresponse" />
<property name="100.22"
value="refund-void prepareresponse logit close sendresponse" />
...
...
</participant>
...
10
jCard Transaction
Manager Participants
The identifiers that appear in the value attributes of each property are the names
of groups defined in the transaction manager configuration file. For a deeper
explanation, please refer to the previous chapter, and to the Programmer’s Guides
given on that chapter’s footnote.
The interesting point about jPOS TransactionManager in general, and jCard’s use
of it in particular, is the fact that the system reuses most of the transaction participant
implementations, and even the groups of participants placed together under a given name (i.e.:
logit, or sendresponse, etc.).
11
jCard Transaction
Manager Participants
ITC Name Description
200.40 Account transfer Used to transfer funds from different accounts of the same cardholder
(i.e.: checking to savings)
220.00.0000 Purchase advice.
A previously
authorized
transaction
(pending layer)
gets confirmed
by a purchase
advice.
220.20.0000 Refund advice Same for refunds
220.00.1000 Force post Records a refund that was not previously authorized by the system.
The value 1000 here represents: "Stand-In processing at the card
issuer’s option".
See jPOS-CMF document, Appendix D, Reason Codes.
220.00.2000 Force post Representment
220.20.1000 Refund/Return
force post
220.20.4500 Chargeback
notification
420.00.0000 Purchase/
Authorization
reversal
420.01.0000 Cash withdrawal
reversal
420.02.0000 Void reversal
420.20.0000 Refund reversal
420.21.0000 Deposit reversal
420.40.0000 Transfer reversal
304.301.CUSTOMER File update Adds a new customer
304.301.MERCHANT File update Adds a new merchant
For a complete list of Message Type Indicators and Processing Codes, refer to the
jPOS-CMF [http://jpos.org/doc/jPOS-CMF.pdf] document.
• balanceinquiry
• prepareresponse
• logit
• close
• sendresponse
and then continues to the participants ProtectDebugInfo and Debug defined after the main
Switch.
12
jCard Transaction
Manager Participants
This section describes the participants used by the balanceinquiry group.
The class org.jpos.jcard.CheckFields, located in the jcard module, checks for mandatory
and optional fields in the incoming message (available in the Context under the constant name
REQUEST.
In addition to checking field presence by their field number, CheckFields understands several
special names that, when found, are then placed in the Context for the benefit of the following
participants.
13
jCard Transaction
Manager Participants
Constant Name Description
Field 7 If Field 7 (transmission date) is present in the list of mandatory or optional
fields, a TRANSMISSION_TIMESTAMP Date object is placed in the Context.
Field 12 If Field 12 (local transaction date) is present in the list of mandatory or optional
fields, a LOCAL_TRANSACTION_TIMESTAMP Date object is placed in the Context.
Field 41 If field 41 (Terminal ID) is present in the list of mandatory or optional fields,
its string representation gets placed in the Context under the name TID.
Field 42 If field 42 (Merchant ID) is present in the list of mandatory or optional fields,
its string representation gets placed in the Context under the name MID.
Sample transaction
The Debug participant dumps the context after the transaction has been processed. A typical
Context would look like this:
<log realm="debug" at="Fri Oct 15 18:22:54 UYST 2010.351">
<commit>
<id>148</id>
<context>
<entry key='REQUEST'>
<isomsg direction="incoming">
<!-- org.jpos.iso.packager.GenericPackager[cfg/iso2003binary.xml] -->
<field id="0" value="2100"/>
<field id="2" value="0000000001"/>
<field id="3" value="000000"/>
<field id="4" currency="840" type="amount" value="6.00"/>
<field id="7" value="1015182254"/>
<field id="11" value="000000000144"/>
<field id="12" value="20101015182254"/>
<field id="13" value="001015"/>
<field id="14" value="4912"/>
<field id="17" value="1015"/>
<field id="32" value="000001"/>
<field id="37" value="150622174247"/>
<field id="41" value="29110001 "/>
<field id="42" value="001001"/>
<isomsg id="43">
<!-- org.jpos.iso.packager.GenericSubFieldPackager -->
<field id="2" value="jCard Selftest system"/>
<field id="4" value="Lagos"/>
<field id="5" value="LG "/>
<field id="7" value="NG "/>
</isomsg>
</isomsg>
</entry>
<entry key='TXNNAME'>100.00</entry>
<entry key='SOURCE'>org.jpos.iso.channel.CSChannel@59d6e3d2</entry>
<entry key='PROFILER'>
<profiler>
open [0.7/0.7]
create-tranlog [1.5/2.3]
check-card [5.0/7.3]
check-terminal [0.8/8.1]
check-acquirer [0.7/8.8]
select-account [0.0/8.9]
check-previous-reverse [3.7/12.6]
check-velocity [9.9/22.5]
authorization-start [0.0/22.6]
authorization-pre-lock-journal [1.9/24.5]
authorization-post-lock-journal [2.6/27.1]
authorization-compute-balance [3.6/30.8]
authorization-post-transaction [16.2/47.1]
authorization [0.0/47.1]
create-cache-ledger [26.1/73.2]
create-cache-pending-and-credit [6.8/80.0]
create-cache-pending [7.8/87.9]
14
jCard Transaction
Manager Participants
compute-balances [0.0/87.9]
prepare-response [2.8/90.7]
log-response [0.2/91.0]
close [4.7/95.7]
end [98.1/98.1]
</profiler>
</entry>
<entry key='TIMESTAMP'>Fri Oct 15 18:22:54 UYST 2010</entry>
<entry key='TXNMGR'>txnmgr</entry>
<entry key='DB'>org.jpos.ee.DB@7f4f84d5</entry>
<entry key='SWITCH'>100.00 (authorization prepareresponse logit close sendresponse)</entry>
<entry key='PCODE'>000000</entry>
<entry key='PCODE_TXN_TYPE'>00</entry>
<entry key='PCODE_ACCOUNT_TYPE'>00</entry>
<entry key='PCODE_ACCOUNT2_TYPE'>00</entry>
<entry key='TRANSMISSION_TIMESTAMP'>Fri Oct 15 18:22:54 UYST 2010</entry>
<entry key='LOCAL_TRANSACTION_TIMESTAMP'>Fri Oct 15 18:22:54 UYST 2010</entry>
<entry key='AMOUNT'>6.00</entry>
<entry key='CURRENCY'>840</entry>
<entry key='TID'>29110001 </entry>
<entry key='NETWORK_CAPTURE_DATE'>Fri Oct 15 12:00:00 UYST 2010</entry>
<entry key='MID'>001001</entry>
<entry key='TRANLOG'>org.jpos.ee.TranLog@635e6e9f[id=147]</entry>
<entry key='CAPTURE_DATE'>Fri Oct 15 00:00:00 UYST 2010</entry>
<entry key='CARD'>org.jpos.ee.Card@67360e7[id=4,pan=000000...0001]</entry>
<entry key='CARDHOLDER'>org.jpos.ee.CardHolder@3fea9527[id=2]</entry>
<entry key='ISSUER'>org.jpos.ee.Issuer@64fa32bb[id=1,name=1]</entry>
<entry key='ACQUIRER'>org.jpos.ee.Acquirer@6f3fd5c[id=1,name=1]</entry>
<entry key='ACCOUNT'>org.jpos.gl.FinalAccount@1cb4ccc5[id=1042,code=21.0000000001.00]</entry>
<entry key='LOGEVT'><log realm="" at="Fri Oct 15 18:22:54 UYST 2010.352" lifespan="90ms">
<log>
---- reverse check ----
CriteriaImpl(org.jpos.ee.TranLog:this[][date>=Fri Oct 15 17:22:54 UYST 2010, irc=1816, stan=000000
</log>
</log>
</entry>
<entry key='GLSESSION'>org.jpos.gl.GLSession@3d99fd3f</entry>
<entry key='RC'>0000</entry>
<entry key='APPROVAL_NUMBER'>464166</entry>
<entry key='LEDGER_BALANCE'>8.05</entry>
<entry key='AVAILABLE_BALANCE'>4.00</entry>
<entry key='IRC'>0</entry>
<entry key='RESPONSE'>
<isomsg direction="outgoing">
<!-- org.jpos.iso.packager.GenericPackager[cfg/iso2003binary.xml] -->
<field id="0" value="2110"/>
<field id="2" value="0000000001"/>
<field id="3" value="000000"/>
<field id="4" currency="840" type="amount" value="6.00"/>
<field id="7" value="1015182254"/>
<field id="11" value="000000000144"/>
<field id="12" value="20101015182254"/>
<field id="13" value="001015"/>
<field id="14" value="4912"/>
<field id="17" value="1015"/>
<field id="32" value="000001"/>
<field id="37" value="150622174247"/>
<field id="38" value="464166"/>
<field id="39" value="0000"/>
<field id="41" value="29110001 "/>
<field id="42" value="001001"/>
<isomsg id="43">
<!-- org.jpos.iso.packager.GenericSubFieldPackager -->
<field id="2" value="jCard Selftest system"/>
<field id="4" value="Lagos"/>
<field id="5" value="LG "/>
<field id="7" value="NG "/>
</isomsg>
<field id="54" value="00028402C00000000040000018402C000000000805"/>
<field id="63" value="APROBADO"/>
</isomsg>
</entry>
</context>
</commit>
</log>
15
jCard Transaction
Manager Participants
Some of the variables there, such as MID,
TID, NETWORK_CAPTURE_DATE, PCODE,
PCODE_TXN_TYPE, PCODE_ACCOUNT_TYPE, PCODE_ACCOUNT2_TYPE, etc. are placed by this
CheckFields participant.
Once the CheckFields participant has performed reasonable sanity checks against the
incoming message, we are ready to create a TranLog record.
The time is expressed in millis, in this case, the open participant took half a millisecond, and
the create-tranlog participant 3.7ms. The second figure is the running total (in this case, 3.7ms
+0.5ms=4.3ms).
16
jCard Transaction
Manager Participants
CreateTranLog creates a TranLog record in the database, and populates a set of initial fields
that include:
• Date: it uses the TIMESTAMP Date object available in the Context, courtesy of the
PrepareContext participant.
• LocalTransactionDate: LOCAL_TRANSACTION_TIMESTAMP taken by CheckFields from fields
12 and 13 when available.
• TransmissionDate: TRANSMISSION_TIMESTAMP taken by CheckFields from field 7, usually
available.
• Node: this is the Node name taken from the participant’s configuration property node.
• Itc: the Internal Transaction Code, this is the TXNNAME context variable, placed by the
request listener (IncomingSupport).
• originalItc: On reversals and voids, CheckFields takes the original data elements off the
composite field 56. In particular, originalItc is taken off ORIGINAL_MTI.
• localId: This is the per-instance TransactionManager's id for this transaction. Can be used
to track the transaction in the jPOS logs for debugging purposes.
• Outstanding: This is the number of pending Contexts available in the
TransactionManager's input queue. Usually provides an estimate of the system load. This
value should be really low, ideally 0, at all times.
A higher value here means the system is under heavy load or experiencing a problem and
requires further review.
• Acquirer: taken directly from field 32, if present, otherwise defaults to 000000.
• Mid: Merchant ID, taken directly from field 42, if present.
• Tid: Terminal ID, taken directly from field 41 (usually present).
• Stan: Serial Transaction Audit Number, taken directly from field 11 (usually present).
• ApprovalNumber: taken from field 38, if available.
• ResponseCode: on force-post transactions, field 39 (response code) may be present.
• Currency: The CURRENCY object optionally placed in the Context by CheckFields, taken
from the composite amount field 4.
• Amount: Transaction amount, placed in the Context by CheckFields under the name
AMOUNT.
• AdditionalAmount: If available, placed in the Context by CheckFields under the name
ADDITIONAL_AMOUNT.
• CaptureDate: The system’s capture date, taken from the CaptureDate service.
• FunctionCode: Taken directly from field 24, if present.
• ReasonCode: Taken directly from field 25, if present.
• FileName: on File Update transactions (MTI=304), taken from field 101 (file name), if
present.
After populating the TranLog object with the aforementioned fields, and saving it to the
underlying Hibernate/JDBC session (created by the Open participant), CreateTranLog sets the
following objects in the Context:
17
jCard Transaction
Manager Participants
CheckCard locates the Card from the card table, but there’s a caveat: the Primary Account
Number (PAN) available in the Context (placed by the CheckFields participant) can’t be used
to find the card in the table because, due to PCI compliance, cards are encrypted.
In addition, the encryption scheme we use (DUKPT 3 can not be used either, because the same
card encrypted two different times will create two different cryptograms. So jCard uses a hash
(hash column in the card table).
CheckCard then picks the PAN off the Context, computes its hash, and searches using that
hash in the Card database. Once found, a live reference to the org.jpos.ee.Card entity is
placed in the Context under the name CARD.
Once we have the Card reference in memory, we can pull the CardHolder using the
card.getCardHolder() method. CheckCard verifies that we have a valid and active
cardholder (its active property has to be true). It also performs some verifications and sanity
checks on the card (it must be active, not suspended/stolen/lost and its start and end dates are
within operational range).
CheckCard can raise some exceptions that would, in turn, abort the transaction, raising errors
such as:
• CARD_NOT_ACTIVE
• CARD_SUSPENDED
• CARD_STOLEN
• CARD_LOST
• CARD_NOT_CONFIGURED, if the card is not associated with a CardProduct entity.
• CARD_EXPIRED
• CARD_SUSPICIOUS, if the received expiration date doesn’t match our records.
2
The classes in the org.jpos.gl package are part of jPOS-EE’s miniGL [https://github.com/jpos/jPOS-EE/tree/master/modules/
minigl/src] module
3
Derived Unique Key Per Transaction
18
jCard Transaction
Manager Participants
• CARDHOLDER_NOT_CONFIGURED
• CARDHOLDER_NOT_ACTIVE
• CARDHOLDER_EXPIRED
• CARD
• CARDHOLDER, pulled off the Card using card.getCardHolder()
• ISSUER, taken from the CardProduct associated with this Card
(card.getCardProduct().getIssuer())
CheckTerminal reads a configuration property called force-check and decides if the terminal
and merchant has to be actually validated as the jCard system can be installed in situations
where the terminals and merchants are handled by the acquirer and are provided just as general
purpose information.
If check is required (force-check is true), the system validates that the Terminal exists and is
active, and that belongs to a Merchant that also exists and is active.
19
jCard Transaction
Manager Participants
There’s another optional flag, lock-terminal that can be used to lock the terminal, so that
transactions performed from a single terminal are serialized.
CheckTerminal can raise some exceptions that would in turn abort the transaction, raising
errors such as:
• INVALID_TERMINAL
• INVALID_MERCHANT
• INACTIVE_TERMINAL
• INACTIVE_MERCHANT
• ACQUIRER_MISMATCH
• TERMINAL
• MERCHANT pulled off the Card using card.getCardHolder()
The Card, located by the previous CheckCard participant is associated with a CardProduct,
which in turn belongs to an Issuer, which is placed in the context (courtesy of CheckCard).
The current code will just pick the first active acquirer and place it in the Context.
• ACQUIRER
20
jCard Transaction
Manager Participants
Figure 3.3. Card / CardHolder / Account Relatioship
This participant uses the CardHolder reference provided by the CheckCard participant, and
the PCODE_ACCOUNT_TYPE and CURRENCY information provided by the CheckFields participant
in order to locate a cardholder’s account suitable for this account type (i.e. checking/savings/
credit/prepaid, etc.) and currency combination.
Once located, it places in the Context a reference to the FinalAccount object using the name
ACCOUNT.
If the transaction type (PCODE_TXN_TYPE) equals "40" (a transfer transaction according to jPOS
CMF), SelectAccount uses the destination account type (last two digits of field 3, stored in
PCODE_ACCOUNT2_TYPE) and currency to select the destination account, which is placed in the
context as ACCOUNT2.
• ACCOUNT_NOT_FOUND
• ACCOUNT
• ACCOUNT2 (on transfer transactions)
In addition to setting variables in the Context, SelectAccount takes the opportunity to pick
the TranLog object created by the CreateTranLog participant from the Context (it’s stored
under the name TRANLOG) and populates the account and optionally account2 properties.
ComputeBalances creates a miniGL session and picks the ACCOUNT subject to this balance
calculation from the Context. It uses the ISSUER in order to locate the miniGL Journal used
by this issuer (a Journal is the accounting book where all transactions specific to this issuer
get recorded), as well as the current TIMESTAMP provided by the PrepareContext participant.
21
jCard Transaction
Manager Participants
jCard uses miniGL' multi-layer feature to store its transactions. Its layer plan involves using
the href="http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html[ISO-4217
currency code] as the accounting layer (confirmed transactions that impacts the accounting
balance), and specific offset numbers for pending (unconfirmed authorizations that affect
the available balance but don’t touch the accounting balance) as well as credit overdraft
transactions.
This participant is used in the balance inquiry transaction, but also on other
transactions that have financial impact, such as POS purchases and ATM
withdrawals, and still return a balance (usually printed on receipts). For credit
transactions (account type equals 30), the accounting balance field returns the credit
allowance, in this case, taken from layer 2840.
• LEDGER_BALANCE
• AVAILABLE_BALANCE
22