Transaction flow
Basic flow
flowchart TD
A@{shape: circle, label: 'Start'}
A --> B@{shape: cyl, label: 'Generate purchase id and store in database'}
B --> C@{shape: rect, label: 'POST /transaction/purchase'}
C --> D@{shape: diamond, label: 'Wait for response state'}
D -->|PROCESSING| C
D -->|network error| C
D -->|AWAITING_CONFIRM| E@{shape: cyl, label: 'Store transaction result in database'}
D -->|abort| E
E --> F@{shape: rect, label: 'POST /transaction/confirm'}
subgraph Background processing
F --> G@{shape: diamond, label: 'Wait for response state'}
G -->|network error| F
G -->|CONFIRMED| H@{shape: cyl, label: 'Mark transaction as completed in database'}
H --> I@{shape: dbl-circ, label: 'Done'}
end
Performing a purchase starts by allocating a unique id, external_id
, for the purchase transaction and storing it in stable storage, such as a database. Care should be taken that the id is stored durably before sending the first purchase command, as explained in “transactional reliability”.
The client then sends a POST
request to the /transaction/purchase
endpoint with the required fields for purchase which includes external_id
. The server will wait for a maximum of options.wait_timeout
seconds for the transaction to be processed. It will then always respond with the current state of the transaction. If the transaction is still PROCESSING
or if there was network error, the POST
request should be repeated until the transaction is in AWAITING_CONFIRM
state.
At this point, the result_code
in the transaction will either be SUCCESS
if the transaction has so far been successful, or will contain an error code, such as INSUFFICIENT_FUNDS
that means the transaction can no longer be successful. The client should record this transaction result in the database as the final status of the purchase, and print a success or error receipt for the customer.
At any point in the transaction flow so far, the client can abort the transaction by simply storing an error for the transaction in the database, and closing any pending requests towards the server.
After the final result of the transaction is stored in the database, the client must confirm every transaction also to the server as a background process. A POST
request to the /transaction/confirm
endpoint should be sent with the external_id
of the transaction, containing the final result of the transaction (whether it was successful or not). The server will then respond with the final state of the transaction. At this point the transaction is confirmed and no further actions are required.
The background sending of the confirm messages must be repeated indefinitely for every transaction until a successful confirm response is returned. This is crucial to maintain transactional reliability, as explained in Transactional reliability. The server will also reject new transactions if there are too many unconfirmed transactions for a terminal. A reasonable delay or back-off should be used between attempts to confirm a transaction to not overload the network.
Aborting or cancelling via confirming as failed
The client can abort a transaction at any point in the flow by sending a POST
to /transaction/confirm
endpoint with the external_id
of the transaction and a result_code
of something other than SUCCESS
. This will immediately mark the transaction as CONFIRMED
and failed, and the server will run any necessary cleanup for the transaction in the background.
After a transaction has been confirmed to success, it can still be confirmed as failed during a grace period of 1 hour. During this time, if it is found that the transaction was done in error, such as a typing mistake on the ECR, marking the transaction as failed will ensure that any held funds will be returned to the customer immediately. After the grace period is over, the transaction will be marked as COMMITTED
and cannot be changed anymore.
Pausing a transaction
Pausing is not yet supported in the preview version of the API.
The client can request the server to pause the transaction processing at a certain point by sending pause
for some on_*
action inside options
in the purchase request. This means that the
transaction will go into AWAITING_CONTINUE
state when it reaches that point, such as after the customer has been identified by their payment instrument. The transaction will then stay in this state and all the available transaction fields can be inspected.
The client can then send a POST
request to the /transaction/continue
endpoint to continue the transaction. This request can also contain an updated amount for the transaction, if for example the client wants to change the amount of the transaction based on the customer identification. The transaction will then go back into PROCESSING
state and the server will continue processing the transaction. The return value from the continue request is the same as the one from the original purchase request.
In case the client does not send the continue request within a certain time limit, the server will automatically abort the transaction and the transaction state will be AWAITING_CONFIRM
with a result code of ABORTED
.