Receipt Considerations - AEVI-AppFlow/pos-android-sdk GitHub Wiki
Receipts should usually be printed by a flow service application that is executed in the POST_TRANSACTION or POST_GENERIC stage. Therefore, a receipt printing application implement a service extending BasePaymentFlowService
and override the two methods onPostTransaction
and onGeneric
. Within onPostTransaction
the service will retrieve the TransactionSummary
and use this to construct a receipt. Within the onGeneric
method the receipt app must obtain the correct data from the request data and use the information to print the receipt. See receipts for more details on the type of data you can expect.
Receipts for payments
The TransactionSummary
object contains information about who the receipt is for and details of the Transaction
that has just occurred in the previous stages. The Transaction
object can contain lots of data that may or may not need to be printed on the receipt which has been added by any number of flow apps in the flow so far. It is likely that as well as the different data acquirers will have there own requirements as to what needs to be printed on the receipt.
However, there are certain data structures that will always be present which are described below.
Baskets
Both POS applications and flow services can add baskets to the transaction. It is most likely that these all simply need to be printed onto the receipt. This can be done by simply finding all the baskets in the TransactionSummary
and adding to the receipt e.g.
String currency = transactionSummary.getRequestedAmounts().getCurrency();
for (Basket basket : transactionSummary.getBaskets()) {
addBasketDetails(printPayload, basket, currency);
}
Where the addBasketDetails
method above does the work of adding all the basket lines items to the receipt.
Basket objects can themselves contain other additional data items that may require specific handling in certain use cases.
Different amounts
The TransactionSummary
object also contains all TransactionResponses
that may have occurred during a flow. Each TransactionResponse
contains information about an amount that has been paid. The TransactionResponse
contains at least a amount processed, which should always be added to the receipt, and can optionally include any number of additional amounts. Usually these amounts indicate sub totals such as tax, cashback, tip etc. These additional amounts can simply be iterated and added to the receipt.
for (TransactionResponse transactionResponse : transactions) {
Amounts amounts = transactionResponse.getAmountsProcessed();
String paymentMethod = transactionResponse.getPaymentMethod();
Map<String, Long> addAmounts = amounts.getAdditionalAmounts();
for (String type : new TreeSet<>(addAmounts.keySet())) {
append(printPayload, type.toUpperCase(), formatAmount(new Amount(addAmounts.get(type), amounts.getCurrency())));
}
append(printPayload, getPaidByMessage(paymentMethod), formatAmount(amounts.getTotalAmount()));
}
Note that of course amounts in the API are always longs and should be converted sensibly to the correct currency and unit display, shown above as formatAmount
method. Care should be taken to ensure the units are displayed correctly.
The getPaidByMessage
method referenced above will convert the payment method string supplied into a user friendly string to display on the receipt. Usually this would indicate how the payment was fulfilled e.g. by card, cash or loyalty points etc.
Customer details
Depending on the use-case it may be a requirement to display customer data on a receipt. For Payment
requests a specific Customer
object is made available if it has been added during the flow. The Customer
object contains some basic standard fields as well as a number of additional data fields described here. Customer information can be added before the Payment
is initiated or at any time in the flow by a flow service that is able to identify the customer in some way e.g. card token.
Ads/promotions
It is possible that an advertising flow service might add data to augment a flow. This may need to be displayed on the receipt. This could include adding images and/or a QR code that can be scanned by a customer to access further content from the advert. See here for more details of the kind of data an advert service may add to the transaction
Card details
If a response was paid for by card then the TransactionResponse
object will contain a Card
object containing the details. This can be extracted and added to a receipt like so.
Card card = transactionResponse.getCard();
if (card != null) {
if (card.getCardholderName() != null) {
appendToReceipt(card.getCardholderName());
}
if (card.getMaskedPan() != null) {
appendToReceipt(card.getMaskedPan());
}
if (card.getExpiryDate() != null) {
appendToReceipt(card.getExpiryDate());
}
AdditionalData cardData = card.getAdditionalData();
appendIfPresent(cardData, "network");
appendIfPresent(cardData, "entryMethod");
}
As well as the standard card fields other data may also be available in the additionalData stored with the Card
. As above you can see the code is extracting the "network" and "entryMethod". The complete list of additional data for card can be found here
Transaction references
Each TransactionResponse
can also contain any number of bespoke references these can be found in the AdditionalData
returned from the getReferences()
method. These references are usually added by a payment flow service and acquirers may mandate that certain ones are shown on the receipt. e.g. transaction ID and certain EMV values.
The references may also contain other bespoke data that does not fit into any of the objects above e.g loyalty data. This may also need to be printed on the receipt. For example these references may contain loyalty data which can be extracted as below.
AdditionalData references = transactionResponse.getReferences();
appendIfPresent(references, "earnPoints");
appendIfPresent(references, "redeemPoints");
appendIfPresent(references, "totalPoints");