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.