Split Considerations - AEVI-AppFlow/pos-android-sdk GitHub Wiki

  • IN PROGRESS *

Split applications are arguably the most complex of all the flow services. For this reason, we have this dedicated page to assist in making sure you get it right.

The role of a split application is to allow a payment to be broken up into multiple transactions. There are two ways in which this could be done;

  • A split app sets up all the transactions with amounts / basket details in advance and FPS takes it from there
  • A split app creates new transactions "on demand" as FPS calls it for each round

The first case may seem appealing as a solution, but it falls short when you start looking at details like partially fulfilled transactions, declined transactions, errors etc. AppFlow is quite a dynamic solution in that it reacts to the events that occur in the flow and the same is true for split applications.

The way FPS works is by having a "flow loop", as is illustrated in this diagram default sale flow

At the end of a transaction (after POST_TRANSACTION), FPS will check if the processed amounts across all transactions is equal or greater than the requested amount in the payment. If it is, then the flow is done and it will move to finalise it. If not, it will go back to the SPLIT stage and call the split app again. This process is repeated until the check above is true.

Here is an example split flow based on amount splitting,

  1. A POS app initiates a payment with £10.00 and split enabled
  2. FPS will call the split app in the SPLIT stage
  3. The split app sets the request amounts for the first transaction to be £4.00
  4. FPS will run through the "inner flow" (PRE-TRANSACTION to POST_TRANSACTION)
  5. FPS checks if the processed amounts is equal or greater than the requested amounts, which it is not at this stage
  6. FPS will call the split app again, which can now see the previous transaction outcome
  7. The split app sets the request amounts to be the remaining £6.00
  8. FPS will run through the "inner flow" (PRE-TRANSACTION to POST_TRANSACTION)
  9. FPS checks the processed amounts which is now equal to requested
  10. The flow is completed

Before we look at edge cases, let's review what the options are for splitting.

Splitting by amounts

Splitting by amounts is the easiest option programmatically, as it simply involves letting a customer specify how much they want to pay. This leaves complexities such as sharing items like a bottle of wine, etc to the customers themselves.

Once the application has received the desired amount and performed validation on that input, it can call SplitModel.setBaseAmountForNextTransaction(amount) to set the amount to process for the next transaction.

Splitting by basket items

Allowing customers to split by basket items (if available) is generally a much better customer experience, as they don't have to try to calculate how much each person owes etc. It is also fairly trivial to implement a user interface to allow this selection of basket items. However, there are complexities such as:

  • Customers wanting to split a single item, like a bottle of wine - when splitting by basket items it is very difficult to track the splitting a single item within the basket. Careful management of the basket items would have to be used to track partial payment for items and customised baskets would have to be used in order to pass sensible information to any receipt printing app.
  • Partially fulfilled transactions - some payment applications allow the concept of a partial authorisation. This means only some of the total amount is paid during a single transaction. If splitting by basket items this could leave an amount unpaid. Therefore, for this reason, it is NOT recommended to split by items for flows containing a payment application that will allow partial auth/payment.

In order to assist with splitting by basket, the API samples contains a SplitBasketHelper class that helps by tracking what items have been paid for, what is remaining and what is being added for the next transaction. This class can be copied into your application and adapted to suit your needs. The reason it is not part of the API itself is that there is a wide range of split scenarios from simple to very complex and we can not cater for all of these in a sensible way.

Edge cases

  • additional amounts
  • flow services adding basket / additional amounts, meaning the requested amounts increase ....

Handling different outcomes

Technically it is possible, but extremely unlikely, that a payment app would process more than requested. There are however other scenarios that are likely to happen:

  • A transaction is declined
  • A transaction is partially fulfilled
  • The payment is cancelled
  • An error occurs

A split application needs to be able to deal with all these outcomes, which is what makes it the implementation of one very complex.

Handling declined transactions

Split apps must display information for the previous split transaction (if any) outcome including any decline reason. This is to help merchants identify what happened to the last transaction, which is particularly important for declined transactions.

Any additional amounts added by flow services as part of a declined transaction are contained and will not be added to the total requested amounts. Hence, if a follow-up transaction is made for the same customer, the additional amounts will need to be added again.

Handling partially fulfilled transactions

A partially fulfilled transaction is the result of two possible scenarios;

  • The payment app host/gateway performed a partial auth, only authorising a portion of the requested amounts
  • A value added flow service (such as loyalty) paid off a portion of the amounts and the host then declined during transaction processing

In these circumstances, a split flow can not be allowed to continue until the customer has paid his share in full, either via a new flow or via a payment method offered via the split app (such as paying in cash).

Providing merchant controls

Split apps must allow the merchant to cancel the transaction via its UI. This is done via calling SplitModel.setCancelTransaction(true). Split apps are the only apps allowed to do this.

There are two important requirements that all split apps have to fulfil to be accepted;

  1. TODO

Split apps have a much longer timeout than other flow apps to allow for split selection/configuration, etc.