General description
TPM is handling most of the user-triggered transactions of various different types (transfer, top-up, cash-out, etc.). It’s main purpose is to:
Initialise transaction
Create transaction information in core banking system
Send transaction to 3rd party services (via payment gateway)
Listen to callbacks from core banking / payment gateway
Send information about transaction as an event to Kafka (THM)
Send asynchronous updates to frontend
Context
TPM mostly listens to transaction initialisation requests from frontend, that are handled via REST API calls. The REST endpoints are exposed also via Swagger. Initialisation requests are synchronous and depending on the type of transaction they can perform the whole flow to successful transaction execution (for instance the interbank transaction flow) or they can return partial outcome of transaction (for instance interbank transaction) within the response to the REST call.
Initialisation requests are idempotent, which was implemented according to approach defined in Idempotency .
Within the processing flow, there are several actions repeated for most of the transactions:
Fetch transaction related information from internal services via REST (customer, account, merchant information)
Calculate fees for customer and vendor. These are REST calls to internal services. Customer fee is using
subscription-operation-usage
endpoints in product manager, which is handling also consumation of free transaction within customer’s subscription plan.Check for fraudulent transactions. These are calls to Slacker REST API and based on the outcome the transaction can be continued, suspended or rejected.
Store transaction to internal TPM database and send information about transaction event to Kafka. TPM uses internal PostgreSQL for tracking ongoing transactions, but it also sends events to Kafka for e.g. history recording (Transaction History Manager). Currently, TPM sends only one type of Kafka event which is fire-and-forget event that transaction “occurred”.
The most important part, however, is communication with core banking and external payment systems:
Every transaction is recorded in core banking system - Though Machine. Depending on transaction type there are different types of Postings sent (authorization, settlement,…). We send postings via Kafka and receive updates from TM via Kafka as well. All requests sent to TM are asynchronous and idempotent (handled in TM side).
We are using Payment Gateways to communicate with 3rd part payment systems (e.g. Paynamics). Initialisation of transaction in payment gateway is done via synchronous REST call (currently it is not idempotent, see: SM-7445 - [BE] Idempotency for paynamics-gateway Blocked Task ) and the callbacks are received via Kafka. Messages received from Kafka are handled in an idempotent manner.
Transaction processing
The usual process is:
Initialise transaction in
Controller
Map the request DTO into internal model via
Mapper
Start transaction flow in
Service
Send information to Thought machine via
PostingService
and receive response viaPostingListener
Save information about transactions via
Repository
layerCreate transactions via 3rd party vendors in
PaynamicsGateway
(or any*Gateway
) and listen for updates inPaynamicsGatewayUpdatesListener
Scalability
TPM should be able to run in multiple instances, as long as the database is the same for each instance.
Approach to security
We are relying on authorization library used throughout all SaFi back-end services and also Kafka ACL (managed outside TPM scope).
Domain model
Request/Response model (example for InterBank transaction)
Internal domain model (example for InterBank transaction)
Entity model (example for InterBank transaction)
Current technical debt
fully asynchronous transaction processing: SM-2055 - Transaction initiation should be asynchronous in Transaction Processor Manager To Do , see also technical analysis: Asynchronous transaction processing
generic processing of transactions, decrease duplication of code
improve logging and error handling of edge cases
Attachments:
image-20221130-071444.png (image/png)
image-20221130-072208.png (image/png)
image-20221130-072454.png (image/png)