Broadleaf Microservices
  • v1.0.0-latest-prod

Transaction Reversals for Checkout Interactions (since 1.0.2)

In some checkout scenarios, you can be left with a successful payment transaction and an overall failed checkout. For example, if you have 2 payments, the first payment’s transaction is successful, and the second payment’s transaction fails. In this case, the successful transaction should eventually be reversed, if it’s not used for a subsequent successful checkout.

To support this behavior, we use the CheckoutRollbackEventListener to mark the successful transactions as reversal candidates (i.e. managementState = "REVERSAL_CANDIDATE"). These transactions are identified by the payment’s related cart id & the checkout attempt’s requestId.

From there, the PaymentTransactionReversalJobListener is responsible for identifying reversal candidate transactions and executing reversal transactions. By default, this scheduled job is configured to execute every 5 minutes, and uses a 15 minutes buffer for identifying transactions. Therefore, reversal candidate transactions have a 15-minute window where they can still contribute to a successful checkout attempt.

Note
  • The frequency of the scheduled job’s execution can be configured via the paymentTransactionReversal 's cron expression.

  • The 15-minutes window can be adjusted using the property broadleaf.paymenttransaction.reversal-reversal-candidate-ttl.

To avoid a race condition where the CheckoutRollbackEventListener and the customer’s second checkout attempt don’t negatively effect each other, we take the following steps:

  1. Lock the payment when taking action against its transaction(s)

  2. When reusing a successful transaction for the second checkout attempt, we update the transaction’s requestId and clear its managementState (previously blank or "REVERSAL_CANDIDATE"). Therefore, if the CheckoutRollbackEvent is processed after this checkout attempt, then it won’t find the successful transaction to mark it as a reversal candidate. NOTE: This is done via PaymentTransactionExecutionActivity (CartOperationServices) calling PaymentTransactionManagementEndpoint#claimTransactionsForRequest(…​) (PaymentTransactionServices).

Note
When a checkout successfully completed, the cart’s payment transactions have their managementState set to "AUTOMATIC_REVERSAL_NOT_ALLOWED" to block the reversal of the transactions.