---
title: Order and payment processing breaking changes
slug: commerce-connect-15/docs/order-and-payment-processing-breaking-changes
docTags: 
createdAt: 2026-07-30T20:34:42.000Z
---

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:**

```csharp
// 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`:

```csharp
// 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 Property     | Replacement                                                                    |
| -------------------- | ------------------------------------------------------------------------------ |
| `MinQuantity`        | Use content API to get minimum order quantity from entry content               |
| `MaxQuantity`        | Use content API to get maximum order quantity from entry content               |
| `ListPrice`          | Use `IPriceService` to get list prices                                         |
| `ShippingAddressId`  | Not used                                                                       |
| `ShippingMethodName` | Use `IShipment.ShippingMethodId` to get shipping method information            |
| `ShippingMethodId`   | Use `IShipment.ShippingMethodId` instead                                       |
| `InStockQuantity`    | Use `IInventoryService.Get()` to get inventory information                     |
| `PreorderQuantity`   | Use `IInventoryService.Get()` to get preorder quantity from `InventoryRecord`  |
| `BackorderQuantity`  | Use `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:

```csharp
// 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.
