Drupal Commerce 2
A comprehensive overview for Drupal developers and technical managers
Drupal Commerce 2 is the latest version of the popular open source ecommerce platform for Drupal.
Redesigned from the ground up with the experiences from more than 60,000 sites using the Drupal 7 version, Drupal Commerce 2 leverages the new architecture of Drupal 8 to provide robust core APIs, more features out of the box, and a vastly improved developer experience.
Built with customer experience as a first priority, Commerce 2 provides the core features most e-commerce sites need with minimal requirements on contributed modules or custom code and the foundation for developing flexible omnichannel sales platforms, custom user experiences, and seamless third-party integrations.
This article will learn about the central systems and design patterns in Drupal Commerce 2, meet each of the core modules, and explore the online business opportunities made available by Drupal Commerce.
Special thanks to Steve Oliver for providing this technical overview.
Based on the free and open source content management framework Drupal, Drupal Commerce 2 is distributed under the GNU General Public License (GPL), which guarantees end users the freedom to run, study, share and modify the software. Companies implementing Drupal Commerce 2 are not bound to any service provider and retain complete control over their e-commerce codebase, free to innovate. At the same time, they follow the collective progress of the project.
Developer experience and support
Drupal Commerce 2 has been developed from the start with a priority on helping other developers and agencies learn, use, and contribute to the project. Every day, nearly every hour, there are code pull requests posted and reviewed on Github; discussion, support and planning on drupal.org; and ongoing threads of development and support topics on Slack.
Semantic versioning and dependency management
Like Drupal Core, Drupal Commerce follows semantic versioning and a fixed release schedule. Drupal Commerce 2.0 was released on September 20, 2017, and 2.1 on November 3. Releases will be on the first Wednesday of each month. Like most well-managed PHP projects, dependencies are managed with Composer.
From the project page:
Whereas eCommerce solutions are often developed with an application mindset, highlighting what you can do with it out of the box, Drupal Commerce was developed with a framework mindset, focusing on what you can build with it. The core Commerce systems make no hard-coded assumptions about your business model, privileging developers and site builders at the core level to build custom eCommerce solutions to suit.
Many of the primary objects in Drupal Commerce 2 are either configuration or content entities, which means they can be altered, swapped, and extended as needed. Entities regularly pass through the various system via events, while event subscribers from enabled modules manipulate the state of the entity and/or dispatch other events; Below is a complete list of all core entity types (as of Commerce 2.1):
Entity forms and displays
There are a few things regarding entity forms and displays:
- Drupal display and form modes are used to configure the appearance and behavior of products and variations in add to cart forms and order item displays.
- Many plugins provide or modify forms, e.g the checkout pane plugins provide child structures to the completed checkout form.
- Entity form classes are defined in PHP annotations and YAML services files and can be overridden in module alter hooks. (For example: the Cart module, if enabled, adds an ‘Add to cart’ form mode and sets the default form class for commerce order items.)
Several common plugins are YAML-type plugins — things like log categories and templates and checkout and order workflows. This simple text format makes it easy to implement custom customer experience and sales optimizations with a simple change to one file in your site’s configuration.
For things like checkout flows which have a custom presentation and business logic with dependencies on other services, annotated PHP class plugins are used.
To implement your own functionality you can use, extend or replace these types of core plugins:
- Adjustment type (YAML — see commerce_order.commerce_adjustment_types.yml)
- Log category (YAML — see commerce_log.log_categories.yml)
- Log template (YAML — see commerce_log.log_templates.yml)
- Checkout flow (PHP — see CheckoutFlowInterface.php)
- Checkout pane (PHP — see CheckoutPaneInterface.php)
- Condition (PHP — see CommerceCondition.php, CommerceConditionManager.php)
- Promotion offer (PHP — see PromotionOfferInterface.php)
- Payment gateway (PHP — see PaymentGatewayInterface.php)
Drupal 8 uses a dependency injection (DI) container to discover, access, and replace useful objects and dependencies. In Commerce 2, some of the primary entry points and core helpers for most functionality are service collectors, event subscribers, order processors, resolvers, providers, managers, and cache context services. Work with these core services or use them as a reference when implementing custom functionality in Drupal Commerce:
Managers collect and instantiate different types of plugins, and services like the Cart manager and the Availability manager provide points of contact for custom and contributed code outside Drupal Commerce.
Order Refresh is a service that refreshes draft orders (such as carts) when they are saved and/or loaded. The Order entity’s storage handler calls the service’s ::refresh() method which runs all registered order processors (see Services above). The order refresh mode and frequency are configurable per Order type.
Workflows, states and transitions
Workflows are YAML-based plugins that declare the available states and transitions for things like orders and payments. Workflows can be changed at run-time based on custom business rules, and states and state transitions can be evaluated and manipulated, e.g. to skip a step in a checkout flow or take action after transition events.
Events in Drupal 8 (largely replacing the hooks that existed in Drupal 7) are objects that are dispatched with a specific name at various times during the page and entity lifecycles, allowing other parts of the system opportunity to take actions or make changes to the object(s), decoupled from the code that dispatched the event.
Modules implement event subscriber services that listen for these named events and modify the passed objects or return specific responses to the dispatcher as needed. The event-dispatching code then considers the response(s) and/or modified event object.
Simple PHP classes that contain specific structured values for use throughout the system:
Commerce modules are designed to be very loosely coupled, with few dependencies between core modules and dependable ways of responding to events and providing and altering plugins between modules. These 10 core modules provide the base functionality and example implementations for major e-commerce features and are all designed to be easily replaced and extended by contributed and custom modules.
The Cart module extends the order module by adding a ‘cart’ field to Order entities that allows orders to be considered “carts” and provides services for managing carts and cart items for users. It defines an Add to cart form display and sets the default plugin for Order item entities.
Dependencies: Order, Price, Product
Dependent modules: Checkout
- Extends Order content entity with a ‘cart’ field
- Handles carts for anonymous and user sessions
- Defines an ‘Add to cart’ form display for Order items
- Sets the default ‘Add to cart’ form class for order items
- Provides a Cart block
The Checkout module provides a default checkout implementation for orders, with a default checkout flow plugin that allows checkout panes to be grouped and ordered in sequential steps of a multi-step form. Modules provide custom functionality by defining checkout flows for each order type and providing custom checkout panes, form building plugins that attach their functionality to their configured position in the current checkout form.
Dependencies: Order, Cart
Dependent modules: (None)
- Extends Order type config entity with a checkout flow
- Extends Order content entity with a checkout step
- Checkout flows define steps with their labels and visibility in a checkout flow
- Checkout panes are configurable forms embedded into the checkout flow form
- Adds a ‘Checkout’ link to Cart views
- Provides a Checkout progress block
The Log module provides activity logs for Commerce entities, implemented entirely in Twig and YAML. Modules can implement their own log categories and templates and generate log entries by passing the required context (variables) to any log template.
Dependent modules: (None)
- Log templates are Twig templates defined in YAML
- Log entries are created from the ‘commerce_log’ entity storage handler’s ::generate()
- See the Log module generate log entries for order workflow transitions and events
- See the Log module generate log entries when items are added and removed from carts
The Order module defines the Order entity and associated features. Orders require order items, and order items require purchased entities. By default (in Commerce core) the only purchasable entity is the product variation. The order item type defines the order type and purchasable entity type it will support, and defines the configuration of the purchasable entity’s Add to cart form.
Dependencies: Price, Store
Dependent modules: Cart, Checkout, Payment, Promotion
- Order item type = Purchasable entity type + Order type
- Order item type defines purchasable entity’s Add to cart form display
- Order item represents Purchased entity @ Unit price x Quantity
- Order entities require Order item entities
The Payment module provides payment functionality to orders, with interfaces for specifying which features a payment gateway supports (e.g. authorizations, stored payment methods, refunds, etc.), and base classes for developing onsite and offsite payment gateway plugins.
Dependent modules: (None)
- Payment gateways are PHP plugins that supports onsite and offsite payment operations
- Payment gateways are configured, with conditions (e.g store)
- Payment methods (e.g. credit cards) can be stored locally/tokenized
- Payments have fields for state/remote state, gateway and mode, amount/refunded amount and currency, and authorization and capture times.
The Price module defines the Currency entity, a Price field, and associated features used in other Commerce modules. Currency entities are used by Stores to define which currencies they support, and Price fields are use for the base price of product variations and the unit price of Order items.
Dependent modules: Cart, Order, Product, Store
The Product module defines the product entities and associated features. Product entities represent one or more product variation entities in one or more stores. The Product module’s product variation entity is the default purchasable entity, and contains a SKU and price, plus any other fields configured for each product variation type. The product variation type defines the order item type that will represent the product variation in an order and the attributes that are available for those types of variations.
Dependencies: Price, Store
Dependent modules: Cart
- Product variation type = Order item type + attributes
- Product variation entities are the default purchasable entity
- Product variations contain SKU, Price, and other configurable fields per variation type
- Product entities require product variation entities
The Promotion module provides a UI for managing promotions. It runs a Promotion order processor that evaluates active promotion entities and any configured conditions, and applies fixed amount or percentage discounts to orders and order items during the Order refresh process. Promotions apply to stores and order types, and have an offer, start and end dates, usage limits, conditions, and compatibility settings with other promotions. Coupons can be used to limit access to promotions, and can be enabled/disabled and made available for a limited number of uses per coupon.
Dependent modules: (None)
- Promotion = Offer for Order type(s) at Store(s) with Condition(s) + Coupons
- Promotions are [re-]applied during Order Refresh
- Coupons can limit access to promotions
The Store module defines the Store entity and associated features. Stores can be used to represent different sales locations and/or different sellers in an online marketplace. Store content entities define the name, address, email, default currency, and supported billing countries for the store. Store type configuration entities define custom fields and entity modes for different types of stores. Order entities require exactly one store reference and product entities require one or more store references.
Dependent modules: Order, Product
- Stores represent different sales locations and/or sellers
- Stores define the default currency to use
- Stores define the supported billing countries
- Orders and products require store(s)
The tax module provides tax functionality to orders. It interacts with the order module by implementing an order processor that runs each order through applicable instances of configured Tax type plugins that apply tax type adjustments to the order or order items.
The core tax plugins work well for simple tax situations, but for situations requiring complex tax calculation and accounting, such as in the US, third party services such as Commerce Avatax now have modules for Drupal Commerce 2.
Dependent modules: (None)
While Commerce 2 provides most of the base functionality for e-commerce, and several of the contributed modules needed in Drupal 7/Commerce 1 are no longer required, contributed modules still provide advanced functionality on top of core Commerce modules for several different use cases.
There are several payment gateways available for Drupal Commerce 2. Here is a list of gateways with stable releases:
The Commerce Shipping module has been developed as a contrib project for now. At some point it may be part of Commerce core, but for now, it is a stable module with a few popular shipping provider modules already released or being actively developed:
The Commerce Recurring module is being actively developed and nearly has a stable release.
- Configurable billing intervals (charge every N days/weeks/months/years)
- Fixed and rolling interval types (charge on the 1st of the month VS 1 month from the subscription date)
- Prepaid and postpaid billing types (charge at the beginning or at the end of the billing period).
- Prorating (adjusting the charged price based on the duration of its usage)
- Configurable retries (for payment soft/hard declines)
Planned: Usage tracking, free trials.
- Commerce Product Bundle - works for static bundles, needs work for dynamic
- Commerce Stock - works, but API is not yet stable
- Commerce Order Number - works, but a custom order number resolver service may work just as well, and simpler for some situations.
- There are other modules, but there is no current comprehensive list. Ask in #commerce on drupal.slack.com for recommendations on specific solutions.
With this introduction to the fundamental concepts, main components, and core modules of Drupal Commerce 2, the reader should understand how entities, types, plugins, events and services provide the foundation for configuring, altering, and developing powerful custom ecommerce experiences.
Future articles will elaborate on individual features of Drupal Commerce and the contributed modules being developed for Commerce.
The main Commerce 2 events and services are listed here for convenience.
These are all the events passed at various times throughout the system.
These are all the different types of services within the core Commerce modules.
- Adjustment type manager (plugin.manager.commerce_adjustment_type)
Manages adjustment type plugins.
- Availability manager (commerce.availability_manager)
Returns an availability response from all registered availability checkers.
- Cart manager (commerce_cart.cart_manager)
Creates, adds, updates, and removes order items, empties carts, and resets checkout.
- Checkout order manager (commerce_checkout.checkout_order_manager)
Manages checkout flows for orders.
- Condition manager (plugin.manager.commerce_condition)
Manages discovery and instantiation of condition plugins.
- Checkout flow manager (plugin.manager.commerce_checkout_flow)
Manages checkout flow plugins.
- Checkout pane manager (plugin.manager.commerce_checkout_pane)
Manages checkout pane plugins.
- Log template manager (plugin.manager.commerce_log_template)
Manages log template plugins.
- Log category manager (plugin.manager.commerce_log_category)
Manages log category plugins.
- Payment gateway manager (plugin.manager.commerce_payment_gateway)
Manages discovery and instantiation of payment gateway plugins.
- Payment method type manager (plugin.manager.commerce_payment_method_type)
Manages discovery and instantiation of payment method type plugins.
- Payment type manager (plugin.manager.commerce_payment_type)
Manages discovery and instantiation of payment type plugins.
- Product attribute field manager (commerce_product.attribute_field_manager)
Manages attribute fields.
- Promotion offer manager (plugin.manager.commerce_promotion_offer)
Manages discovery and instantiation of promotion offer plugins.
- Tax type manager (plugin.manager.commerce_tax_type)
Manages tax type plugins.