Broadleaf Microservices

Key Concepts

Payment Summary

The PaymentSummary was introduced to provide enough information for external services/systems to make decisions and execute transactions, while avoiding exposing sensitive Payment and PaymentTransaction data to those services/systems. In short, you can think of the PaymentSummary as a safe summary of the Payment and its PaymentTransactions.

Notable PaymentSummary Properties:

  • amountAuthorized - The total authorized amount

    • This value is calculated as "total authorized - total reverse-authorized"

  • amountCaptured - The total captured amount

    • This value is calculated as "total captured - total refunded"

  • amountRefunded - The total refunded amount

  • amountCredited - The total detached credit amount

  • amountAvailableForAuthorize - The amount that can be authorized

  • amountAvailableForCapture - The amount that can be captured

  • amountAvailableForAuthorizeAndCapture - The amount that can be authorized and captured

  • amountAvailableForReverseAuthorization - The amount that can be reverse-authorized

  • amountAvailableForRefund - The amount that can be refunded

  • fullyAuthorized - If the payment summary is fully authorized (i.e. amountAuthorized equals Payment#amount)

  • fullyCaptured - If the payment summary is fully captured (i.e. amountCaptured equals Payment#amount)

  • partiallyCaptured - If the payment summary is partially captured (i.e. amountCaptured is greater than 0, but less than Payment#amount)

The amounts calculated in the PaymentSummary do not include the amounts from unsuccessful transactions, or transactions that are to be reversed (i.e. in one of the following management states: REQUIRES_REVERSAL, REVERSAL_IN_PROGRESS, REVERSED, FAILED_REVERSAL, REVERSAL_TRANSACTION).

Payment Locking

A payment locking mechanism was introduced to avoid scenarios where simultaneous actions could be working against the same Payment. For example, a payment could be updated by one request while another request is executing a transaction against that payment.

Each Payment-modifying action is surrounded by PaymentLockService#doWithLock(…​). For example, see DefaultPaymentManagementService#updatePayment(…​) or DefaultTransactionExecutionService#authorize(…​). If a lock cannot be established (likely because the payment is already locked), then a ResourceLockException is thrown and the Payment-modifying action is not executed.

Within PaymentTransactionServices, you may notice that some actions encounter several PaymentLockService#doWithLock(…​) boundaries. For example, DefaultPaymentManagementService#updatePayment(…​) calls DefaultPaymentService#update(…​), both of which attempt to establish a lock on the Payment. By passing the lockToken gathered in DefaultPaymentManagementService#updatePayment(…​) into DefaultPaymentService#update(…​), we’re allowing the DefaultPaymentService to make use of the same lock.

Payment locks can also be used by external processes via the payment lock endpoints. For example, during a checkout, CartOperationServices establishes locks for each the cart’s payments, so that it can execute validation & transactions, without the payments being modified by another process.

By default, each payment lock is established with a TTL of 10 seconds. Once the 10 seconds have passed, the lock is automatically removed & other requests can take action against the payment. All actions that establish a lock on a payment must complete their work within this timeframe. If the timeframe is too tight, then it should be expanded by modifying the broadleaf.paymenttransaction.service.payment-lock-ttl property.