Broadleaf Microservices
  • v1.0.0-latest-prod

OMS Payment Interactions

The Order Operation Service can execute several types of transactions against payments on an Order via an external payment transaction execution service. By default, this would be our out-of-box Payment Transaction Services:

  • Capture

  • Reverse Authorize

  • Refund

Important Guidelines

There are several important guidelines that are followed whenever executing these transactions:

  1. Whenever executing transactions against payments for an Order, a lock should always be obtained to ensure no other conflicting operations occur simultaneously

    1. This lock should be obtained at the very start of any operation involving payments for the Order

    2. After the lock is obtained, the PaymentSummaries should be re-read from the PaymentTransactionServices to ensure no payments are out of date

    3. ResourceLockProvider provides this ability to create a lock on the Order, stored in the OrderService

  2. By default, Broadleaf only supports performing transactions that encompass one Order Fulfillment at once, not the whole Order

    1. For example, it’s only possible to capture one Order Fulfillment at once

      1. In a partial capture scenario, the Order Fulfillment is split prior the capture, then the capture is performed on the split fulfillment. See Fulfillment Splitting Docs for more details

    2. When Return Confirmations result in refunds, one refund is issued per relevant Return Confirmation

  3. Transaction’s Source Entity Type and Id should always be set in tandem with a new transaction execution

    1. These properties associate a transaction with the entity that triggered it

      1. When a Fulfillment is captured, it connects the capture transaction to that Fulfillment

      2. When a Fulfillment is cancelled, it connects the reverse-authorize or refund transactions to that Fulfillment

      3. When a Return is confirmed, it connects the refund transaction to the Return Confirmation that triggered it

Configurations

All the payment interactions within the OMS are executed through the Payment Transaction Services via the Payment Provider. For payment-related configurations, please refer to:

Payment Interactions

For all the payment transaction executions within the OMS, regardless of the transaction type, are executed with the following flow:

Note
For more details on payment locking concepts, please refer to the Payment Locking Docs

Identifying Payments

When identifying the payments for an Order, its payments are gathered by owner type and id, which are BLC_CART and the cart id stored on the Order by default.

Sorting Payments

Once the payments are gathered, they are then sorted based on configured payment priority based on payment gateway type.

The out-of-box configuration for OMS supports multiple payments for a single Order. In some cases, the sorting order of these payments may matter, such as when you’re capturing or refunding payments (i.e. you may have a preference on which gateway should be used to execute transactions first).

To allow customizations of the payment sorting order, a hook point has been added for the transaction execution in OrderOperationServices:

  1. Capture

    1. DefaultPaymentCaptureService#sortPaymentsByPriority

  2. Reverse Authorize

    1. DefaultPaymentAuthReversalService#sortPaymentsByPriority

  3. Refund

    1. DefaultPaymentRefundService#sortPaymentsByPriority

By default, each of those hook points (except for reverse authorize) delegates to PaymentPriorityStrategy to sort the payments based on the payment gateway type, which can be configured in the Configuration section.

By default, payments are not for reverse authorize transactions, because these transactions are executed against an entire order to reverse all of the remaining authorized amounts for all the order’s payments. Therefore the ordering for reverse authorize transactions doesn’t make much impact.

Configuration

Each configuration property controls the payment priorities for different transaction types.

Important
It is crucial to understand that the list of payment gateways for each property is ordered. Payment gateway that is placed at the first of the list will be the highest priority.
Capture Priorities

Controls the priorities of payments when performing a CAPTURE transaction.

  • Property: broadleaf.orderoperation.service.payment.capture-payment-gateway-priorities

  • Contains the ordered list of payment gateways

Example
broadleaf:
  orderoperation:
    service:
      payment:
        capture-payment-gateway-priorities:
          - PAYPAL
          - CYBERSOURCE
          - AMAZON_PAYMENT_SERVICES
          - STRIPE

With this configuration, capture transactions for PayPal payments will be executed first, then CyberSource, so on and so forth.

Refund Priorities

Controls the priorities of payments when performing a REFUND transaction.

  • Property: broadleaf.orderoperation.service.payment.refund-payment-gateway-priorities

  • Contains the ordered list of payment gateways

Example
broadleaf:
  orderoperation:
    service:
      payment:
        refund-payment-gateway-priorities:
          - STRIPE
          - PAYPAL
          - AMAZON_PAYMENT_SERVICES

In this example, refund transactions for Stripe payments will be executed first, then PayPal, so on and so forth.

Capture

Performing a payment capture via the OMS is usually done to a single Order Fulfillment which can represent an entire Order or a partial Order. To signify that the Order Fulfillment is being captured, its status is updated to CAPTURING_PAYMENT.

Note
The fulfillment status can be changed to CAPTURE_AWAITING_RESULT if payment transaction results will be provided asynchronously. See Asynchronous Payment Transaction Support.

Therefore, when performing a partial capture on an Order Fulfillment, it is first split into two Order Fulfillments, then the capture transaction is executed against the newly split Order Fulfillment.

For more details on the fulfillment status change and splitting, please refer to Changing Status Docs and Fulfillment Splitting Docs.

Reverse Authorize

Reverse authorize transactions are typically performed for cancelled Order Fulfillments and are triggered by an Order Fulfillment status change.

A fulfillmentCancelled message is sent when an Order Fulfillment is cancelled, and it will be picked up by the PaymentReversalFulfillmentCancelledListener for processing. The listener executes reverse authorize transaction against any authorized amount on the order, and issues a refund for any captured amount for the fulfillment (more details in the Refund From Cancelled Fulfillment Section).

Important
It is crucial to understand that the reverse authorize transactions will not be executed until the entire order has been fully captured and/or cancelled

Refund

Out of the box, refunds can be triggered from two scenarios, cancelled fulfillment and confirmed returns.

Refund From Cancelled Fulfillment

Similar to Reverse Authorize Transaction, refunds can be issued when the Order Fulfillment is cancelled as well.

The refunds can potentially be issued by the same listener, PaymentReversalFulfillmentCancelledListener. However, refunds will only be issued if the Order Fulfillment has been fully captured. If there’s any amount that is able to be captured, no refunds will be issued. Otherwise, an refund will be issued for the entire fulfillment total.

For refund-related configurations, please refer to Auto Reverse or Refund For Cancelled Fulfillment Property.

Refund From Confirmed Returns

The other scenario of how a refund can be issued is from confirmed returns. Once a return is confirmed, a refund is issued with the calculated refund amount.

For more details on the return flow and refunding, please refer to the Return Flow Docs.

For details on the merchandise total to refund calculation, please refer to the Merchandise Refund Calculation Docs.

Important
It is crucial to understand that the refund transactions will not be executed until all the returns have been confirmed within the same Return Authorization

For return confirmation-related refund configurations, please refer to Auto Refund After Confirmed Return Property.

Asynchronous Payment Transaction Support

Many payment gateways leverage webhooks to asynchronously communicate transaction results. In most cases, they are used as a secondary means of communicating results. On the other hand, some gateways use webhooks as the primary means of communicating transaction results for Capture, Refund, & ReverseAuthorize (Void) transactions. In these cases, the Capture, Refund, & ReverseAuthorize transaction response will simply inform you that the request is received/queued, instead of providing transaction results. Once the transaction has been executed, the transaction result is communicated via webhooks.

To support the gathering of async results for capture & refund transactions in the context of fulfilling or returning items, we introduced the FulfillmentCaptureWebhookListener and ReturnConfirmationRefundWebhookListener. These listeners are used to advance the fulfillment & return confirmation processes, once transaction results are received.

Since most projects likely won’t require these components, they’re disabled by default. With that being said, they can be enabled via the broadleaf.orderoperation.async-payment-transaction-support.enabled property.