Introduction
Introduction
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 needed by most e-commerce sites 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.
In this article we will learn about the main systems and design patterns in 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.
Last updated on February, 2018
View the module's project page or the official documentation for further information.
Basics
Basics
Open source
Open source
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 that implement Drupal Commerce are not bound to any service provider, and retain complete control over their e-commerce codebase, free to innovate while they follow the collective progress of the project.
Developer experience and support
Developer experience and support
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 of the day, 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
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 the first Wednesday of each month. Like most well-managed php projects, dependencies are managed with Composer.
Core concepts
Core concepts
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.
Entities
Entities
Many of the primary objects in Commerce 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):
Content entities
Purchasable entities
Any entity that implements the PurchasableEntityInterface can be used by Commerce to represent a purchased entity in an order item. Commerce ships with one purchasable entity: the product variation. Other examples of purchasable entities are product bundles.
Entity forms and displays
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.)
Plugins
Plugins
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 custom presentation and business logic with dependencies on other services, annotated PHP class plugins are used.
Plugin types
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)
Core plugins
Drupal Commerce 2 ships with default plugins that provide some of the most common functionality required for modern sales and e-commerce platforms:
- Checkout flows:
- Checkout: Multistep - Default (see commerce_checkout_flow.default.yml)
- Checkout panes:
- Checkout: Billing information
- Checkout: Completion message
- Checkout: Contact information
- Checkout: Login
- Checkout: Order summary
- Checkout: Review
- Payment: Payment information
- Payment: Payment process
- Conditions:
- Order: Order billing address
- Order: Order currency
- Order: Order customer role
- Order: Order email
- Order: Order store
- Order: Order total price
- Order: Order type
- Product: Order item product
- Product: Order item product type
- Product: Order item variation type
- Promotion offers:
- Promotion: Fixed amount off order item
- Promotion: Fixed amount off order
- Promotion: Percentage off order item
- Promotion: Percentage off order
- Payment gateways:
- Payment example: Offsite redirect
- Payment example: Onsite
Custom plugins
Custom plugins can extend one of the base plugins to add promotion conditions or offers, for example, change the behavior of the add to cart form, provide custom panes in a checkout flow, or define a new order workflow.
Here are a few example contributed module plugins for Drupal Commerce 2:
Services
Services
Drupal 8 uses a dependency injection (DI) container to discover, access, and replace useful objects and their dependencies. In Commerce 2, some of the primary entry-points and core helpers for most of the functionality is provided by 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
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.
Resolvers / service collectors
Resolvers are services ordered to form a chain of responsibility where modules can respond to situations they care about (or return nothing and pass the option along for a response from other modules). Drupal Commerce, usually via managers, determines things like unit price, tax rate, store, order type, and checkout flow using resolvers.
Custom or contributed code can implement resolvers to provide custom pricing, for example, or use a custom checkout flow for certain types of users.
Event dispatchers
Event dispatchers are not a type of service, but these services are listed here to point out that they, in addition to other code, dispatch events. For example, the Cart manager creates, adds, updates, and removes order items, empties carts, and resets checkouts by dispatching events; the Order assignment service dispatches an event to assign anonymous orders to user accounts; the Order item matcher dispatches an event that finds matching order items and combines order items in the add to cart process.
There are several events that can be dispatched, and new events allow your code to trigger changes elsewhere in the system without needing to be concerned with the implementations of the event subscribers.
Event subscribers
Event subscribers are PHP classes registered in services.yml files and ordered via a priority tag, that listen for different events broadcast from the system and take actions when appropriate. For example, the default Cart event subscriber displays a message when an entity is added to the cart, the Order number subscriber generates an order number when an order is placed, and the Order receipt subscriber sends an order receipt email when an order is placed.
Utilities
Various utility services exist to provide helpers and additional points of contact with Commerce. For example, the Cart provider creates, gets, and finalizes carts for an account; the Current store service holds a reference to the current store, resolved on demand; and the Promotion usage service tracks promotion usage.
Order processors
Order processors are services that make changes based on availability, promotions, or tax rules, for example, and are run during Order Refresh—the process used to modify an order periodically. The Availability order processor removes entities that are no longer available; The Promotion order processor applies promotions to orders; and the Tax order processor applies taxes to orders during the order refresh process.
Cache contexts
When creating renderables dependent upon commerce entities, cache contexts are available for country, cart, and store.
Order refresh
Order refresh
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, 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.
See commerce_order.workflows.yml, commerce_payment.workflows.yml
Events
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.
Value objects
Value objects
Simple PHP classes that contain specific structured values for use throughout the system:
- Adjustment - holds type, label, amount and other values to represent adjustments.
- Context - holds customer, store and time values for “context” in various events.
Core modules
Core modules
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.
Cart module
Cart module
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
Checkout module
Checkout module
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
Log module
Log module
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.
Dependencies: (None)
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
Order module
Order module
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
See Reference > Events > Order event objects
See Docs > User guide > Orders
See Docs > Developer guide > Orders
Payment module
Payment module
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.
Dependencies: Order
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.
See Reference > Events > Payment event objects
See Docs > User guide > Payments
See Docs > Developer guide > Payments > Available payment gateways
Price module
Price module
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.
Dependencies: (None)
Dependent modules: Cart, Order, Product, Store
See Reference > Events > Price event objects
See Docs > Developer guide > Core components > Currencies
Product module
Product module
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
See Reference > Events > Product event objects
See Docs > User guide > Products
See Docs > Developer guide > Products
Promotion module
Promotion module
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.
Dependencies: Order
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
See Reference > Events > Promotion event objects
See Docs > User guide > Promotions
Store module
Store module
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.
Dependencies: Price
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)
See Reference > Events > Store event objects
See Docs > User guide > Setting up your store
See Docs > Developer guide > Stores
Tax module
Tax module
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.
Dependencies: Order
Dependent modules: (None)
Contributed modules
Contributed modules
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.
Payments
Payments
There are several payment gateways available for Drupal Commerce 2. Here is a list of gateways with stable releases:
See Docs > Developer guide > Payments > Available payment gateways
Shipping
Shipping
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:
Recurring
Recurring
The Commerce Recurring module is being actively developed and nearly has a stable release.
Features:
- 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.
Others
Others
- 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.
Summary
Summary
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.
Reference
Reference
The main Commerce 2 events and services are listed here for convenience.
Events
Events
These are all the events passed at various times throughout the system.
Core event objects
Passed during events named in CommerceEvents:
- Filter conditions event - when filtering available conditions.
- Referenceable plugin types event - when altering the referenceable plugin types.
Cart event objects
Passed during events named in CartEvents:
- Cart empty event - after emptying the cart order.
- Cart entity add event - after adding a purchasable entity to the cart.
- Cart order item remove event - after removing an order item from the cart.
- Cart order item update event - after updating a cart's order item.
- Order item comparison fields event - when altering the list of comparison fields.
Order event objects
Passed during events named in OrderEvents:
- Order assign event - after assigning an anonymous order to a user.
- Order event - when creating, loading, updating or deleting an order.
- Order item event - when creating, loading, updating or deleting an order item.
Payment event objects
Passed during events named in PaymentEvents:
- Filter payment gateways event - when filtering the available payment gateways.
Price event objects
Passed during events named in PriceEvents:
- Number format event - when loading a number format.
Product event objects
Passed during events named in ProductEvents:
- Filter variations event - when filtering variations.
- Product attribute value event - when creating, loading, updating or deleting an attribute value.
- Product event - when creating, loading, updating or deleting a product.
- Product variation ajax change event - after changing the product variation via ajax.
- Product variation event - when creating, loading, updating or deleting a variation.
Promotion event objects
Passed during events named in PromotionEvents:
- Coupon event - when creating, loading, updating or deleting a coupon.
- Promotion event - when creating, loading, updating or deleting a promotion.
Store event objects
Passed during events named in StoreEvents:
- Store event - when creating, loading, updating or deleting a store.
Tax event objects
Passed during events named in TaxEvents:
- Customer profile event - when determining the customer's profile.
Services
Services
These are all the different types of services within the core Commerce modules.
Managers
- 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.
Resolvers
- Order refresh (commerce_order.order_refresh)
Runs order refresh on draft orders, processing all services tagged ‘commerce_order.order_processor’ - Chain checkout flow resolver (commerce_checkout.chain_checkout_flow_resolver)
Returns the checkout flow first returned from any registered checkout flow resolver. - Default checkout flow resolver (commerce_checkout.default_checkout_flow_resolver)
Returns the order type's default checkout flow. - Chain price resolver (commerce_price.chain_price_resolver)
Returns the unit price first returned from any registered price resolver. - Default price resolver (commerce_price.default_price_resolver)
Returns the price from the ‘price’ field of the purchased entity. - Chain order type resolver (commerce_order.chain_order_type_resolver)
Return the order type first returned from any registered order type resolver. - Default order type resolver (commerce_order.default_order_type_resolver)
Returns the order type, based on order item type configuration. - Order store resolver (commerce_order.order_store_resolver)
Returns the order's store, when an order is present in the URL. - Chain store resolver (commerce_store.chain_store_resolver)
Runs the added resolvers one by one until one of them returns the store. - Default store resolver (commerce_store.default_store_resolver)
Returns the default store, if known. - Store country resolver (commerce_store.store_country_resolver)
Returns the store's billing country. - Chain tax rate resolver (commerce_tax.chain_tax_rate_resolver)
Runs the added resolvers one by one until one of them returns the tax rate. - Default tax rate resolver (commerce_tax.default_tax_rate_resolver)
Returns the tax zone's default tax rate.
Event dispatchers
- Cart manager (commerce_cart.cart_manager)
Creates, adds, updates, and removes order items, empties carts, and resets checkout. - Order assignment (commerce_order.order_assignment)
Handles assigning anonymous orders to user accounts. - Order item matcher (commerce_cart.order_item_matcher)
Finds matching order items; Used for combining order items in the add to cart process.
Event subscribers
- Cart event subscriber (commerce_cart.cart_subscriber)
Displays a message when an entity is added to the cart. - Order event subscriber (commerce_cart.order_subscriber)
Finalizes the cart as an order is placed. - Order number subscriber (commerce_order.order_number_subscriber)
Generates an order number when an order is placed. - Order receipt subscriber (commerce_order.order_receipt_subscriber)
Sends an order receipt email when an order is placed. - Profile label subscriber (commerce_order.profile_label_subscriber)
Sets the customer profile label to the first address line. - Timestamp event subscriber (commerce_order.timestamp_event_subscriber)
Sets the order's placed timestamp. - Promotion conditions subscriber (commerce_promotion.filter_conditions_subscriber)
Removes unneeded conditions (those that are not for promotions) when needed. - Promotion order event subscriber (commerce_promotion.order_subscriber)
Registers promotion usage when the order is placed.
Utilities
- Cart provider (commerce_cart.cart_provider)
Creates, gets, and finalizes carts for an account. - Cart session (commerce_cart.cart_session)
Stores active and completed cart ids in the anonymous user's session. - Current store (commerce_store.current_store)
Holds a reference to the current store, resolved on demand. - Order assignment (commerce_order.order_assignment)
Handles assigning anonymous orders to user accounts. - Order total summary (commerce_order.order_total_summary)
Builds the totals for the given order. - Price rounder (commerce_price.rounder)
Rounds the given price to its currency precision. - Product lazy builders (commerce_product.lazy_builders)
Provides #lazy_builder callbacks, e.g. for building the add to cart form. - Product variation field renderer (commerce_product.variation_field_renderer)
Renders variation fields. - Promotion usage (commerce_promotion.usage)
Tracks promotion usage.
Order processors
- Availability order processor (commerce_order.availability_order_processor)
Provides an order processor that removes entities that are no longer available. - Promotion order processor (commerce_promotion.promotion_order_processor)
Applies promotions to orders during the order refresh process. - Tax order processor (commerce_tax.tax_order_processor)
Applies taxes to orders during the order refresh process.
Cache contexts
- Country cache context (cache_context.country)
Defines the ‘country’ context, for "per country" caching. - Cart cache context (cache_context.cart)
Defines the ‘cart’ context, for "per cart" caching. - Store cache context (cache_context.store)
Defines the ‘store’ context, for "per store" caching.
Download and install Drupal Commerce 2
Download and install Drupal Commerce 2
Drupal Developer? Test drive the code using our install tool
Commerce Kickstart is the quickest way to get up and running with Drupal Commerce 2 and Drupal 8.