Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Order and payment processing breaking changes

Breaking changes to the order system, workflow engine, discount infrastructure, and payment processing APIs in Commerce Connect 15.

This article covers breaking changes to the order system, payment processing pipeline, workflow engine, and discount infrastructure in Commerce Connect 15.

Workflow engine removal

The entire legacy workflow engine has been removed from Commerce 15. This is one of the largest breaking changes in this release. The following components are affected:

Mediachase.Commerce.Workflow project (removed)

The Mediachase.Commerce.Workflow project and assembly have been completely removed. This project contained all legacy workflow activity implementations:

  • All ActivityFlow implementations (CartCheckoutActivityFlow, CartPrepareActivityFlow, CartValidateActivityFlow, etc.)
  • All Activity implementations (ProcessPaymentActivity, CalculateTotalsActivity, AdjustInventoryActivity, etc.)
  • The assembly Mediachase.Commerce.Workflow.dll is no longer produced or distributed.

Any code that references this assembly will fail to compile. Remove all references and using statements for Mediachase.Commerce.Workflow namespaces.

ActivityFlow engine infrastructure (removed)

The following types in Mediachase.Commerce.Engine have been removed:

  • ActivityFlow (abstract base class)
  • ActivityFlowRunner
  • ActivityFlowContext
  • ActivityFlowContextPropertyAttribute
  • ActivityFlowConfigurationAttribute
  • ActivityFlowEventArgs
  • ExecutionManager
  • WorkflowResults
  • WorkflowStatus enum
  • DuplicatedPropertyException
  • Internal.ActivityFlowModel
  • Mediachase.Commerce.Extensions.ActivityFlowExtensions

WorkflowCompatibility namespace (removed)

The entire Mediachase.Commerce.WorkflowCompatibility namespace has been removed:

  • Activity (abstract base class)
  • ActivityExecutionContext
  • ActivityExecutionStatus enum
  • ConditionalEventArgs
  • ValidationError
  • ValidationErrorCollection
  • WorkflowValidationFailedException

OrderGroupWorkflowManager (removed)

Mediachase.Commerce.Orders.Managers.OrderGroupWorkflowManager has been entirely removed.

Workflow-dependent methods (removed)

The following methods that depend on the workflow infrastructure have been removed:

OrderStatusManager (all obsolete methods):

  • RecalculatePurchaseOrder(PurchaseOrder) (all overloads)
  • CancelOrder(PurchaseOrder) and CancelOrder(PaymentPlan)
  • HoldOrder(PurchaseOrder) and HoldOrder(PaymentPlan)
  • ReleaseHoldOnOrder(PurchaseOrder) and ReleaseHoldOnOrder(PaymentPlan)
  • ReleaseOrderShipment(Shipment)
  • CancelOrderShipment(Shipment)
  • CompleteOrderShipment(Shipment)
  • PickForPackingOrderShipment(Shipment)
  • ReturnFromPackingOrderShipment(Shipment)
  • ProcessOrder(PurchaseOrder)

ReturnExchangeManager:

  • RecalculateReturnOrderForm(OrderForm)
  • ExecuteReturnFormWorkflow(string, OrderForm)

ReturnFormStatusManager:

  • CompleteReturn(OrderForm) (all overloads)
  • CancelReturn(OrderForm) (all overloads)
  • AcknowledgeReceiptItems(OrderForm) (all overloads)

OrderGroup:

  • RunWorkflow(string) (all 3 overloads)

OrderContext:

  • ExecutionManager property

Migration path

Migrate all workflow-based order processing to the modern processor-based APIs:

For order calculations:

  • Use IOrderGroupCalculator for order totals calculation.
  • Use ITaxCalculator for tax calculations.
  • Use IShippingCalculator for shipping cost calculations.

For promotions:

  • Use IPromotionEngine for applying promotions and discounts.

For order processing:

  • Use IPurchaseOrderProcessor for purchase order operations (cancel, hold, release, process).
  • Use IPaymentPlanProcessor for payment plan operations.
  • Use IShipmentProcessor for shipment operations (release, cancel, complete, pick for packing).

For cart operations:

  • Use ICartService for cart management.
  • Use IOrderRepository for saving and loading orders.
  • Use IOrderGroupExtensions.ValidateOrder() for cart validation.
  • Use OrderGroupExtensions.CalculateTotals() for cart/order total calculations.

For inventory:

  • Use IInventoryProcessor for inventory adjustments.

For payment processing:

  • Use IPaymentProcessor for payment authorization and capture.
  • Implement custom payment gateways using IPaymentPlugin interface.

For status management, use the non-obsolete methods in OrderStatusManager:

  • IsOrderCancellable(PurchaseOrder/PaymentPlan)
  • IsOrderHoldable(PurchaseOrder/PaymentPlan)
  • IsShipmentReleasable(Shipment)
  • IsShipmentCancellable(Shipment)
  • IsShipmentCompletable(Shipment)
  • IsShipmentPackable(Shipment)
  • GetPurchaseOrderStatus(PurchaseOrder/PaymentPlan)
  • GetOrderShipmentStatus(Shipment)

For return form processing:

  • Use IReturnOrderService.CompleteReturn for completing returns.
  • Use IReturnOrderService.CancelReturn for canceling returns.

Example migration:

// Before (Commerce 14) - Workflow-based
cart.RunWorkflow(OrderGroupWorkflowManager.CartCheckOutWorkflowName);

// After (Commerce 15) - Processor-based
var validationIssues = cart.ValidateOrder();
if (!validationIssues.Any())
{
    var orderReference = _orderRepository.SaveAsPurchaseOrder(cart);
    var purchaseOrder = _orderRepository.Load<IPurchaseOrder>(orderReference.OrderGroupId);

    // Process payment
    var processedPayments = purchaseOrder.GetFirstForm().Payments
        .Where(p => _paymentProcessor.ProcessPayment(purchaseOrder, p, shipment));

    // Calculate totals
    var totals = _orderGroupCalculator.GetOrderGroupTotals(purchaseOrder);

    // Adjust inventory
    _inventoryProcessor.AdjustInventoryOrRemoveLineItem(
        shipment, OrderStatus.InProgress, (item, issue) => { });

    _orderRepository.Save(purchaseOrder);
}

Discount infrastructure removal

The obsolete discount infrastructure has been removed. These classes were marked obsolete since August 2018 with guidance to use the promotion system in EPiServer.Commerce.Marketing instead.

Removed types

  • Mediachase.Commerce.Orders.Discount (abstract base class)
  • Mediachase.Commerce.Orders.LineItemDiscount
  • Mediachase.Commerce.Orders.OrderFormDiscount
  • Mediachase.Commerce.Orders.ShipmentDiscount
  • Mediachase.Commerce.Orders.LineItemDiscountCollection
  • Mediachase.Commerce.Orders.OrderFormDiscountCollection
  • Mediachase.Commerce.Orders.ShipmentDiscountCollection

Removed discount collection properties

LineItem.Discounts, OrderForm.Discounts, and Shipment.Discounts collections have been removed, including all serialization support for these discount collections.

Migration path

Use the modern promotion engine:

  • Use EPiServer.Commerce.Marketing.IPromotionEngine for applying promotions and discounts.
  • Create promotions using the built-in promotion types in EPiServer.Business.Commerce.Marketing.Promotions.
  • Implement custom promotions by inheriting from PromotionData and creating custom promotion processors.
  • Use IOrderGroup extension methods for retrieving applied discount information:
    • GetDiscountTotal() – Get total discount amount on order/form/line item.
    • GetShipmentDiscountPrice() – Get discount applied to shipment.
  • Access discount details through IOrderForm.Promotions and ILineItem extension methods.

IOrderGroup.Market property removal

The IOrderGroup.Market property has been removed. This property was marked obsolete since May 2019. It has been removed from:

  • EPiServer.Commerce.Order.IOrderGroup interface
  • Mediachase.Commerce.Orders.OrderGroup class
  • EPiServer.Commerce.Order.Internal.InMemoryOrderGroup class
  • EPiServer.Commerce.Order.Internal.InMemoryPurchaseOrder class
  • EPiServer.Business.Commerce.Order.Internal.SerializableCart class

Use IMarketService to get the market from the order's MarketId:

// Before (Commerce 14)
var market = orderGroup.Market;

// After (Commerce 15)
var market = _marketService.GetMarket(orderGroup.MarketId);

ILineItemInventory removal

The ILineItemInventory interface in Mediachase.Commerce.Orders has been removed. This interface was obsoleted in 2018 with guidance to use IInventoryService instead. The interface implementation has been removed from LineItem and SerializableLineItem classes.

The properties that were part of ILineItemInventory (Code, AllowBackordersAndPreorders, InStockQuantity, BackorderQuantity, PreorderQuantity, InventoryStatus, MaxQuantity, MinQuantity) remain available directly on the LineItem class for backward compatibility, though inventory operations should use IInventoryService.

LineItem obsolete properties removal

The following obsolete properties have been removed from Mediachase.Commerce.Orders.LineItem:

Removed PropertyReplacement
MinQuantityUse content API to get minimum order quantity from entry content
MaxQuantityUse content API to get maximum order quantity from entry content
ListPriceUse IPriceService to get list prices
ShippingAddressIdNot used
ShippingMethodNameUse IShipment.ShippingMethodId to get shipping method information
ShippingMethodIdUse IShipment.ShippingMethodId instead
InStockQuantityUse IInventoryService.Get() to get inventory information
PreorderQuantityUse IInventoryService.Get() to get preorder quantity from InventoryRecord
BackorderQuantityUse IInventoryService.Get() to get backorder quantity from InventoryRecord

OrderSearchFilter.MarketId removal

The OrderSearchFilter.MarketId property has been removed. Use MarketIds (plural) instead for filtering by multiple markets. The MarketIds property accepts an IEnumerable<string> for specifying one or more market IDs:

// Before (Commerce 14)
var filter = new OrderSearchFilter { MarketId = "US" };

// After (Commerce 15)
var filter = new OrderSearchFilter { MarketIds = new[] { "US" } };

OrderStatusManager.IsOrderPaid removal

OrderStatusManager.IsOrderPaid(PurchaseOrder) has been removed. Use the IPurchaseOrder.IsPaid() extension method from the EPiServer.Commerce.Order namespace instead.

OrderGroup.PopulateCollection removal

The OrderGroup.PopulateCollection<T> internal protected method has been removed. The Cart class now uses its own PopulateCartCollection method for loading cart collections from the database.

PurchaseOrderManager methods removal

All three overloads of PurchaseOrderManager.AddLineItemToShipmentDetectedByLineItemShipmentInfo have been removed. This functionality is no longer supported. Use the standard shipment and line item APIs to manage order shipments.

OrderCache.CreateCacheKey overload removal

The OrderCache.CreateCacheKey(CultureInfo, params string[]) overload has been removed. Use CreateCacheKey(params string[] keys) instead (without CultureInfo).

Tax API changes

  • TaxManager.GetTaxes(Guid siteId, ...) – The overload with siteId parameter has been removed. Site functionality is no longer supported. Use the GetTaxes overload without the siteId parameter.
  • TaxDto.TaxValueRow.SiteId property and related members (IsSiteIdNull(), SetSiteIdNull()) have been removed. Tax values are now application-wide and not site-specific.
  • The TaxValueDataTable.AddTaxValueRow method no longer accepts a SiteId parameter.

OrderValidationService constructor change

The EPiServer.Business.Commerce.Order.OrderValidationService constructor without OrderOptions parameter has been removed. Use the constructor that includes the OrderOptions parameter.

Async order repository APIs

Commerce 15 introduces async versions of all IOrderRepository methods. While the synchronous methods remain available for backward compatibility, new implementations should use the async versions:

  • CreateAsync<TOrderGroup>(Guid customerId, string name, CancellationToken cancellationToken)
  • LoadAsync(OrderReference orderLink, CancellationToken cancellationToken)
  • LoadAsync<TOrderGroup>(int orderGroupId, CancellationToken cancellationToken)
  • LoadAsync<TOrderGroup>(Guid customerId, string name, CancellationToken cancellationToken)
  • SaveAsync(IOrderGroup order, CancellationToken cancellationToken)
  • SaveAsPaymentPlanAsync(IOrderGroup cart, CancellationToken cancellationToken)
  • SaveAsPurchaseOrderAsync(IOrderGroup cart, CancellationToken cancellationToken)
  • DeleteAsync(OrderReference orderLink, CancellationToken cancellationToken)

The IPurchaseOrderRepository also adds:

  • LoadAsync(string trackingNumber, CancellationToken cancellationToken)

ReportingOrderEventListener behavior change

ReportingOrderEventListener now executes listeners synchronously and not in a background thread. This is a behavior change that may affect performance characteristics of order save operations in implementations that rely on asynchronous event processing.