Transaction handling
Participants of cashless system:
Customer: The end user who loads money to his account (top-up) and makes purchases at the festival.
Merchant: The entity that sells products and services to the customer.
Festival: The organizer of the event, collects money from the customer and pays the merchant
Money is booked in the system on accounts like a double entry bookkeeping system: Each transaction has a debit and credit side, where the debit side is the account that receives money and the credit side is the account that pays money.
Type of transactions:
Top-up: Customer adds money to his account, the money is handled by the festival. Entry from open loop side.
Purchase: Customer buys a product or service from a merchant.
Chargeback: Customer returns a product or service to a merchant and gets money back.
Refund: Festival returns leftover money to the customer. Return to open loop side.
Type of accounts:
Customer Account: The account of the customer, where the closed loop balance is stored.
Merchant Account: The account of the merchant, where the sales is booked.
Top-up Account: The account of the festival, where the money arriving from the open loop side is stored.
Fee Account: The account of the festival, where the fees collected by the festival is booked.
Transaction types
Top-up transaction
Transaction item | debit account | credit account |
|---|---|---|
topup | customer | top-up |
topup fee | fee | customer |
Toup 100 CHF with a topup fee of 5 CHF:
Purchase (closed loop) transaction
Transaction item | debit account | credit account |
|---|---|---|
purchase | merchant | customer |
Purchase 55 CHF:
Purchase (open loop) transaction
This transaction is used if the customer has not enough money on his closed loop account to pay for the purchase. In this case, the customer can pay directly with a credit card at the time of purchase.
This will be handled by creating two transactions, one top-up and one purchase transaction.
Transaction handling
Transactions can be created:
in the backend system: (admin site, background jos) like online top-up, auto top-up, chargeback, admin topup, refund to payment gateway, manual refund.
in the terminal: like cash or card top-up, purchase, cash refund.
Identification of transactions:
Each transaction has a unique integer ID generated in the backend database once it reaches the backend.
Transactions created in the terminal will be identified by assignment id and terminal transaction number ( generated in the terminal as an increasing number), assignment id and terminal transaction number must be unique for each event edition. In this case and RFID tag is also present when the transaction is created. The tag will also create and increasing transaction number tag transaction number, which is supposed to be unique together with the UID for each event edition. However, in case the tag data is corrupt the tag transaction number can be restarted and duplicates might occur, for this uniqueness should not be enforced by backend (we will monitor duplicates to spot issues with on tag data handling).
assignment id is a unique ID per event edition, it is generated at the time of assignment of the terminal to an event edition, right after this assignment the terminal database is created and transaction number is set to start at 1.
Terminal data model
This ER diagram describes the tables used to store transactions on the terminal before they are synced to the backend.
Terminal transaction handling
Purchase and refund transaction lowering customer account balance with reserve step:
Transaction states (terminal)
State | Description | can be replicated |
|---|---|---|
Open | The transaction has been created | no |
TerminalConfirmStarted | Checkout started | no |
TerminalConfirmUnknown | Indeterminate state (crash) | yes |
Committed | Transaction complete | yes |
Aborted | yes |
We have to implement a cleanup procedure to handle transactions that are in the TerminalConfirmStarted state but not yet confirmed or aborted. This can happen if the terminal crashes. Normally the transaction will be either committed or aborted. The cleanup procedure should be run at startup of the terminal, before each purchase before exit of the terminal.
Transaction states (backend)
State | Description | balance |
|---|---|---|
Open | The transaction has been created | |
TerminalConfirmUnknown | The terminal has started second tap but no result is available | |
ReservePending | Reserved at terminal checkout, can be aborted or released after timeout | Reserve from customer |
Reserve | Reserved based on uploaded tag data, can not be aborted, no timeout | Reserve from customer |
ReserveExpired | ReservePending has not been confirmed with a full transaction | |
ExternalPending | The open loop payment in top-up is in an indeterminate state, checking for update | |
ExternalUnknown | The open loop payment in top-up is in an indeterminate state, no more checking | |
Commited | The transaction is fully booked | Booked |
Aborted | Failed or not finished transaction |
Online and auto top-up:
Purchase at terminal:
Transaction replication
The terminal will replicate transactions to the backend in the background, this can happen after the transaction is committed or aborted. The backend receiving replicated transaction should check the above logic and only accept the transaction based on the above transitions. Invalid state transitions should be stored to a log table. and an error