Broadleaf Microservices

Payment Components

Overview

Payment management and operations are invoked during checkout. The following components are the ones primarily responsible for managing payments for a cart. These are invoked through interactions with the CartOperationService and CheckoutWorkflow components.

CartOperationServices

Overview

CartOperationServices handles adding, updating, and removing payment methods to the cart prior to initiating the CheckoutWorkflow. At least one active payment must be added to the cart before entering the checkout workflow, and the sum of payments must equal the cart’s total.

REST API Access

CartOperationEndpoint provides REST API access to managing payments. See Cart Pricing OpenAPI documentation.

Configuration

CartOperationServices uses following configuration properties:

  • broadleaf.cartoperation.service.priceInvalidation.addPaymentMethod: Whether to consider pricing invalid if a payment is added to the cart, that is, whether the cart should be repriced in that case.

    • Payment might matter in the case of offers and promotions that target specific payment types.

    • Default is false.

  • broadleaf.cartoperation.service.priceInvalidation.updatePaymentMethod: Whether to consider pricing invalid if a payment is updated, that is, whether the cart should be repriced in that case.

    • Default is false.

  • broadleaf.cartoperation.service.priceInvalidation.removePaymentMethod: Whether to consider pricing invalid if a payment is removed, that is, whether the cart should be repriced in that case.

    • Default is false.

CartPaymentStatusService

Overview

This service provides a mechanism to determine and set a payment’s status based on the state of its transactions. This service is usually invoked by the CartPaymentMethodValidationActivity and PaymentConfirmationActivity during the CheckoutWorkflow. The default statuses for payments are:

  • UNCONFIRMED: This represents the state where the customer has not yet authorized the completion of the payment

  • PENDING: This represents the state where payment data has been gathered, but a payment gateway transaction is intentionally being delayed for a later time.

  • AUTHORIZED: This is equivalent to having a successful authorized transaction on the payment, but there are no transactions indicating that payment has been captured, i.e., funds have not been transferred.

  • AUTHORIZED_REVERSED: This is equivalent to having a successful authorized transaction on the payment, but a second transaction was executed to reverse the authorization, meaning that it needs to be authorized again before capturing.

  • CAPTURED: This is equivalent to having a successfully captured transaction on the payment, i.e., transferred the funds, and there are no transactions indicating that payment has had any reversals issued against it.

  • CAPTURED_REVERSED: This is equivalent to having a successfully captured transaction on the payment, but the transaction has been reversed via a void, refund, or other type of reversal.

Default Implementation Details

These statuses are mapped from DefaultTransactionTypes in DefaultCartPaymentStatusService#determinePaymentStatus. The following details how the transactions types map to payment statuses:

  1. If a payment has a VOID, REFUND, or DETACHED_CREDIT transaction, then its status is CAPTURED_REVERSED

  2. If a payment has a CAPTURE or AUTHORIZE_AND_CAPTURE transaction, then its status is CAPTURED

  3. If a payment has an AUTHORIZE transaction, then its status is AUTHORIZED

  4. If a payment has a REVERSE_AUTH transaction, then its status is AUTHORIZED_REVERSED

  5. If a payment has no transactions, then its status is UNCONFIRMED

Note
PENDING is not used by default.

PaymentConfirmationService

Overview

This service is meant to coordinate the confirmation (and possible rollback) of a cart’s payments in the context of the CheckoutWorkflow.

Tip
See the PaymentConfirmationActivity for usage.

Default Implementation Details

During the PaymentConfirmationActivity, DefaultPaymentConfirmationService will first work through all of the active payments on the cart and determine their statuses. Then, it will authorize all of the unconfirmed payments using the PaymentGatewayTransactionServiceProvider to determine the configured PaymentGatewayTransactionService that actual interacts with the payment gateway for the authorization.

The service also determines which payments are valid for rollbacks in the case of checkout failure and uses the configured PaymentGatewayTransactionService to do the rollback, that is, reverse the authorization. Typically, this won’t happen since the PaymentConfirmationActivity should be the last activity in the workflow. Instead, reverse authorizations will be triggered by the OMS after the submitted cart is converted into an order.

PaymentRequestService

This service is used by the PaymentConfirmationService to create a PaymentRequest to send to the configured payment gateway via the PaymentGatewayTransactionService. PaymentRequests represent all of the information that is needed by a payment gateway to complete a transaction including the breakdown of the transaction total, customer info, shipping, and billing addresses.

The PaymentRequest uses a builder pattern to provide a convenient way for its construction.

Example 1. Example of using the payment request builder
PaymentRequest paymentRequest = new PaymentRequest()
      .orderId(referenceNumber)
      .customer()
          .customerId("1")
          .done()
      .shipTo()
          .firstName("Bill")
          .lastName("Broadleaf")
          .addressLine1("123 Test Dr.")
          .city("Austin")
          .stateRegion("TX")
          .postalCode("78759")
          .done()
      .billTo()
          .firstName("Bill")
          .lastName("Broadleaf")
          .addressLine1("123 Test Dr.")
          .city("Austin")
          .stateRegion("TX")
          .postalCode("78759")
          .done()
      .shippingTotal(0)
      .taxTotal(0)
      .orderDescription("My Order Description")
      .orderSubtotal(10.00)
      .transactionTotal(10.00)
      .lineItem()
          .name("My Product")
          .description("My Product Description")
          .shortDescription("My Product Short Description")
          .systemId("1")
          .amount(10.00)
          .quantity(1)
          .itemTotal(10.00)
          .tax(0)
          .total(10.00)
          .done();

PaymentTransactionService

This service is used by the PaymentConfirmationService to create a PaymentTransaction to send to the configured payment gateway via the PaymentGatewayTransactionService as well as record the response of the authorization on the transaction. PaymentTransactions store individual transactions for Payments, that is, the operations the payment has undergone through a payment gateway. Thus, in a typical Broadleaf flow, there would be an "authorize" transaction created during checkout indicating the payment method is valid and authorized by the payer for use; then, at the time of fulfillment, a "capture" transaction would be added to the payment indicating the funds have been transferred. PaymentTransactions also contain some audit data.

DefaultTransactionTypes defines the default types of transactions:

  • AUTHORIZE: Funds have been authorized for capture. This might appear as a 'pending' transaction on a customer’s credit card statement.

  • REVERSE_AUTH: The reverse of an AUTHORIZE transaction. This can only occur after funds have been authorized, and before they have been captured.

  • CAPTURE: Funds have been charged/submitted/debited from the customer and payment is complete. Can only occur after an amount has been authorized.

  • AUTHORIZE_AND_CAPTURE: Funds have been captured/authorized all at once. While this might be the simplest to implement from an order management perspective, the recommended approach is to AUTHORIZE during checkout, and then CAPTURE at the time of fulfillment.

    • Many gateways like to refer to this as also a SALE transaction.

  • SETTLED: This represents a payment that has been balanced by the payment provider. Can only occur after a payment has been captured.

    • This represents more finality than a CAPTURE.

    • Some payment providers might not explicitly expose the details of settled transactions which are usually done in batches at the end of the day.

  • REFUND: Funds have been refunded/credited. This can only occur after funds have been captured or settled.

    • This should only be used when money goes back to a customer.

    • This can also be referred to as a "follow-on credit"

  • DETACHED_CREDIT: Some payment processors allow you to issue credit to a customer that is not tied to an initial AUTHORIZE or AUTHORIZE_AND_CAPTURE transaction.

    • Most payment gateways disable this feature by default because it is against card association (e.g. Visa, MasterCard) rules.

    • However, there may be legitimate instances where you had a sale transaction but are not able to issue a refund (e.g. closed account of original payment, etc…​)

    • This can also be referred to as a "blind credit" or "stand-alone credit"

  • VOID: Void can happen after a CAPTURE, but before it has been SETTLED. Payment transactions are usually settled in batches at the end of the day.

PassthroughTransactionService

Out-of-the-box, Broadleaf provides an implementation of the PaymentTransactionService for development-only purposes that doesn’t actual integrate with any payment gateway provider (e.g., PayPal or Stripe) called PassthroughPaymentTransactionService. This will allow developers to work on the checkout process without having to immediately handle integrating a payment gateway. It will handle requests to authorize, capture, auth-and-capture, refund, and void with dummy responses that can be used seamlessly in the checkout flow just by enabling it with the property, broadleaf.payment.gateway.passthrough-transactions.active=true. If also using the starter commerce app, set REACT_APP_PAYMENT_GATEWAY_TYPE=PASSTHROUGH; otherwise, make sure to include the gateway type of PASSTHROUGH in the payment’s gateway properties during checkout: paymentGatewayProperties['gatewayType'] = PASSTHROUGH.