1. Documentation
  2. AppFlow
  3. Introduction
  4. Guides

Guides


Flow types

AEVI defined flows

This page contains a list of AEVI defined flow types.

Acquirers and/or flow services may support additional types to these. Please see Bespoke Data for information about this.

Please note that the flow types that are available in any given acquirer environment / device are down to the flow configurations. The flows can be queried for programmatically - see Querying for Information for more information. Do not take for granted that all types are always available on all devices using AppFlow.

There are two different models and initiation methods for payments vs generic requests. The summary table defines what request class each type is.

If you can't find a flow type you are after, or require additional data to be part of a particular scenario. please contact AEVI to discuss. The following is not an exhaustive list, rather it is what has been defined by AEVI so far.

Click the links in the sidebar for detailed information on how to initiate that particular type of request.

For information on reference data, values and formats to go with these requests, see Reference Values

Summary of all defined types

Flow type Request class Description Relevant stages
sale Payment Sale/purchase/payment - charge the customer All payment stages
refund Payment Refund the customer PRE_FLOW, TRANSACTION_PROCESSING, POST_FLOW
preAuthorisation Payment Pre-authorise some amount All payment stages
preAuthCompletion Payment Complete a previous pre-authorisation All payment stages
motoSale Payment MOTO (customer not present) sale flow All payment stages
motoRefund Payment MOTO (customer not present) refund flow PRE_FLOW, TRANSACTION_PROCESSING, POST_FLOW
deposit Payment Customer deposit PRE_FLOW, TRANSACTION_PROCESSING, POST_FLOW
tokenisation Request Retrieve a token to identify the customer (typically from card) GENERIC, POST_GENERIC
reversal Request Reversal / Void of previous transaction GENERIC, POST_GENERIC
batchClosure Request Close a batch GENERIC, POST_GENERIC
receiptDelivery Request Deliver a receipt for cash/cheque/etc payment to customer or re-deliver a receipt obtained from a previous transaction GENERIC, POST_GENERIC
basketStatusUpdate Request Notify apps of changes to basket STATUS_UPDATE
customerStatusUpdate Request Notify apps of changes to customer data STATUS_UPDATE

Sale

A sale is commonly also referred to as payment or purchase. It involves charging a customer for services or goods. As this is a payment flow type, it can go through a number of stages and be augmented by a number of flow services. That process is not detailed here, but rather how to initiate a sale with relevant parameters.

For general information about initiating payments please see Flow Initiation. For information about how to handle responses (regardless of type), see Handling Responses.

Create sale request

String flowName = getSaleFlow(); // Optional, if the flow name is known and required
Amounts amounts = new Amounts(1000, "USD"); // $10.00
PaymentBuilder paymentBuilder = new PaymentBuilder()
        .withPaymentFlow("sale", flowName)
        .withAmounts(amounts);

// If there is a basket
paymentBuilder.withBasket(basket);

// If splitting the bill
paymentBuilder.withSplitEnabled(true);

// If you have a card token stored that should be used
paymentBuilder.withCardToken(token);

// If you have customer details
paymentBuilder.withCustomer(customer);

// If you want to add some bespoke data (values can be of any type)
paymentBuilder.addAdditionalData("myDataKey", "myDataValue");

// When done, build the payment
Payment payment = paymentBuilder.build();

Payment requests are built via the PaymentBuilder. Below are the relevant parameters for a sale.

Refund

A refund involves transferring back all or a portion of money that was previously charged to a customer, typically via a sale flow.

For general information about initiating payments please see Flow Initiation. For information about how to handle responses (regardless of type), see Handling Responses.

Create refund request

String flowName = getRefundFlow(); // Optional, if the flow name is known and required
Amounts amounts = new Amounts(1000, "USD"); // $10.00
PaymentBuilder paymentBuilder = new PaymentBuilder()
        .withPaymentFlow("refund", flowName)
        .withAmounts(amounts);

// If there is a basket detailing what items are being refunded
paymentBuilder.withBasket(basket);

// If you have a card token stored that should be used
paymentBuilder.withCardToken(token);

// If you have customer details
paymentBuilder.withCustomer(customer);

// If you want to add some bespoke data (values can be of any type)
paymentBuilder.addAdditionalData("myDataKey", "myDataValue");

// When done, build the payment
Payment payment = paymentBuilder.build();

Payment requests are built via the PaymentBuilder. Below are the relevant parameters for a refund.

Preauthorisation and completion

Pre-authorisation is the process of holding or reserving a particular amount of money without actually charging it, and completion is the finalisation of a pre-authorisation where the customer is charged some actual amount. This process is commonly used for reservations such as hotels or cars and for starting a tab in a bar, etc.

For general information about initiating payments please see Flow Initiation. For information about how to handle responses (regardless of type), see Handling Responses.

Create pre-authorisation request

String flowName = getPreAuthFlow(); // Optional, if the flow name is known and required
Amounts amounts = new Amounts(1000, "USD"); // $10.00
PaymentBuilder paymentBuilder = new PaymentBuilder()
        .withPaymentFlow("preAuthorisation", flowName)
        .withAmounts(amounts);

// If there is a basket
paymentBuilder.withBasket(basket);

// If you have a card token stored that should be used
paymentBuilder.withCardToken(token);

// If you have customer details
paymentBuilder.withCustomer(customer);

// If you want to add some bespoke data (values can be of any type)
paymentBuilder.addAdditionalData("myDataKey", "myDataValue");

// When done, build the payment
Payment payment = paymentBuilder.build();

Payment requests are built via the PaymentBuilder. Below are the relevant parameters for a pre-authorisation.

Create completion request

public AdditionalData getPreAuthReferences() {
    TransactionResponse preAuthToComplete =             paymentResponse.getTransactions().get(desiredTxnIndex).getPaymentAppResponse();
    if (preAuthToComplete != null) {
        return preAuthToComplete.getReferences();
    }
    return null;
}

First, you need to look up the TransactionResponse generated by the payment app for for the initial pre-auth flow.

Note the getPaymentAppResponse() call, which will always return a response from the payment application, if one was generated. A payment application is almost guaranteed to be called for a pre-authorisation request, but your code should check that one is available to be sure.

AdditionalData preAuthReferences = getPreAuthReferences(); // As per above

String flowName = getPreAuthCompletionFlow(); // Optional, if the flow name is known and required
Amounts amounts = new Amounts(1000, "USD"); // $10.00
PaymentBuilder paymentBuilder = new PaymentBuilder()
        .withPaymentFlow("preAuthCompletion", flowName)
        .withAmounts(amounts)
        .addAdditionalData(preAuthReferences); // So that the payment app can link this back to the previous pre-auth transaction

// If there is a basket
paymentBuilder.withBasket(basket);

// If you have a card token stored that should be used
paymentBuilder.withCardToken(token);

// If you have customer details
paymentBuilder.withCustomer(customer);

// If you want to add some bespoke data (values can be of any type)
paymentBuilder.addAdditionalData("myDataKey", "myDataValue");

// When done, build the payment
Payment payment = paymentBuilder.build();

Now, we can build the completion request.

Tokenisation

Request that a token is generated. The source of the token and method used to generate it is typically application specific. For the most case the source of the token is a payment card.

If you require additional data for your use case / scenario, please contact AEVI to discuss.

See Handling Card Tokens for general information about tokens.

Create Request

Request tokenisationRequest = new Request("tokenisation");

// If the request has an amount associated with it
tokenisationRequest.addAdditionalData("amount", new Amount(amountValue, currency));

Create Response

// If your app requires an amount to process the request,
Amount tokenisationAmount = tokenisationRequest.getRequestData().getValue("amount", Amount.class)
...
Response tokenisationResponse = new Response(tokenisationRequest, <outcome>, "Outcome message");
// If a token was successfully generated
Token token = new Token(tokenValue, tokenSource);
tokenisationResponse.addAdditionalData("token", token);

Parse Response

if (tokenisationResponse.wasSuccessful()) {
    Token token = tokenisationResponse.getResponseData().getValue("token", Token.class);
    String tokenValue = token.getValue();
}

Reversal/Void

Request that a previously initiated transaction is reversed. Commonly referred to as reversal or void.

public AdditionalData getTransactionReferences() {
    TransactionResponse responseToReverse = paymentResponse.getTransactions().get(desiredTxnIndex).getPaymentAppResponse();
    if (responseToReverse != null) {
        return responseToReverse.getReferences();
    }
    return null;
}

A transaction is reversed by providing the previous references of a transaction, which assumes you have access to the TransactionResponse for that transaction from the PaymentResponse for the previously initiated flow. If split transactions are not relevant, the desiredTxnIndex can be hardcoded to 0.

Note the getPaymentAppResponse() call, which will always return a response from the payment application, if one was generated. A payment application is not necessarily called for a transaction. There may be responses that would have come from value added flow services paying off a portion (or all) of the amounts, such as loyalty points / rewards. If getPaymentResponse() returns null, there is nothing that can be reversed.

If you require additional data for your use case / scenario, please contact AEVI to discuss.

Create Request

// References retrieved as per above section
Request request = new Request("reversal", getTransactionReferences); // ensure you send ALL references so the PA can match up to the correct transaction

Create Response

AdditionalData references = ...; // create new references for reversal transaction
...
// Add payment app specific transaction reference data  here
Response reversalResponse = new Response(reversalRequest, <outcome>, "Outcome message", references);

Parse Response

String reversedSuccessfully = reversalResponse.wasSuccessful();

Batch close

Request that the current batch is closed / settled.

If you require additional data for your use case / scenario, please contact AEVI to discuss.

Create Request

Request batchCloseRequest = new Request("batchClosure");

Create Response

Response batchCloseResponse = new Response(batchCloseRequest, <outcome>, "Outcome message");

Parse Response

String closedSuccessfully = batchCloseResponse.wasSuccessful();

Receipts

Receipts are typically generated for any payment flow, but there are scenarios where client applications may want to initiate specific receipt requests.

Receipt redelivery

If the merchant and/or customer needs a receipt to get redelivered (via whatever delivery mechanism the receipt app on that device uses, such as printing), the client application can initiate a receiptDelivery request. For this type of request. The request will contain information from the previous transaction which will be sent along with the request as additional data.

Create Request from a Previous Transaction

// First, retrieve the previous transaction to use for the request
Transaction transaction = paymentResponse.getTransactions().get(desiredTxnIndex);

Request request = new Request("receiptDelivery");
request.addAdditionalData("transaction", transaction);

// If the receipt handling application supports more than one delivery mechanism
request.addAdditionalData("deliveryMechanism", "printing");

Receipt generation

If the merchant and/or customer needs a receipt for a non-card based payment e.g. cash. Then a request can be made with different additional data that can fulfil this type of request.

Create Request for a Generic Receipt

Request request = new Request("receiptDelivery");
request.addAdditionalData("receiptAmounts", new Amounts(15000, "EUR"));
request.addAdditionalData("receiptPaymentMethod", "cash");
request.addAdditionalData("receiptOutcome", "APPROVED");
Basket basket = new Basket();

// populate basket
request.addAdditionalData("receiptBasket", basket);

Optionally a basket can also be added to the request using the key "receiptBasket" e.g.

Create Response

AdditionalData requestData = genericStageModel.getRequest().getRequestData();
if (requestData.hasData("transaction")) {
    Transaction transaction = requestData.getValue("transaction", Transaction.class);

    // If you want to re-use functionality in your application from printing payment transactions.
    // You may want to create your own `TransactionSummary` object at this point from the `Transaction` e.g.
    TransactionSummary transactionSummary = new TransactionSummary(transaction,
    "receiptDelivery", DeviceAudience.CUSTOMER, transaction.getLastResponse().getCard()))

    // handle printing of transactionSummary here

else if (requestData.hasData("receiptPaymentMethod")) {
    Amounts amounts = requestData.getValue("receiptAmounts", Amounts.class);
    String paymentMethod = requestData.getStringValue("receiptPaymentMethod");
    String outcome = requestData.getStringValue("receiptOutcome");

    // handle printing from the above fields here

}

// If the receipt was successfully delivered, outcome should be `true`, and `false` otherwise.
Response response = new Response(request, <outcome>, <outcome message>);
// Setting the delivery mechanism is optional but may be useful for the client application
response.addAdditionalData("deliveryMechanism", "printing");

Receipt delivery flow services should ensure that they handle both types of request described above for re-delivery of a receipt as well as receipts for non-card based payments.

Parse Response

if (response.wasSuccessful()) {
    // Handle success
} else {
    // Handle failure
}

Basket Status Update

Most POS applications deal with a basket to represent the goods or services for a customer. Usually a basket is passed to a payment flow where flow services can read and augment it. There are also scenarios where applications need to react to basket updates in real time e.g. before the payment flow is initiated.

To support this scenario, a basketStatusUpdate flow can be used.

Data keys

See StatusUpdateKeys for defined constants.

Data key Value Description
"basketUpdated" Basket Send the entire basket in the update
"basketItemsAdded" BasketItem[] Send newly added basket items
"basketItemsRemoved" BasketItem[] Send newly removed basket items
"basketItemUpdated" BasketItem Send a single updated basket item

Initialise request

Request basketUpdateRequest = new Request("basketStatusUpdate");

// Example of a single data key - see more examples in data keys section
basketUpdateRequest.addAdditionalData("basketUpdated", myBasket);

Create and parse response

It is optional for applications to pass back any data from a status request, and any data that may be passed back will be down to specific requirements for the environment the apps are built for.

Customer Status Update

Flow initiation applications may support identifying customers and keep associated customer details, such as name, tokens, etc. For these purposes, AppFlow has the Customer model. If a customer has been identified and/or updated, the initiation application can notify interested parties of this via the use of a customerStatusUpdate flow.

Data keys

See StatusUpdateKeys for defined constants.

Data key Value Description
"customerUpdate" Customer Send customer details

Initialise request

Request customerUpdateRequest = new Request("customerStatusUpdate");
customerUpdateRequest.addAdditionalData("customerUpdate", myCustomer);

Create and parse response

It is optional for applications to pass back any data from a status request, and any data that may be passed back will be down to specific requirements for the environment the apps are built for.