Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Get an overview of the things changed and fixed in each version of Umbraco Commerce.
In this section, we have summarized the changes to Umbraco Commerce released in each version. Each version is presented with a link to the Commerce issue tracker showing a list of issues resolved in the release. We also link to the individual issues themselves from the detail.
If there are any breaking changes or other issues to be aware of when upgrading they are also noted here.
If you are upgrading to a new major version, check the breaking changes in the Version Specific Upgrade Notes article.
This section contains the release notes for Umbraco Commerce 10 including all changes for this version.
Fixed issue with stock synchronizer prematurely looking up a store #536.
Added pessimistic locking to the payment provider callback endpoint to prevent concurrency issues if the endpoint is called too many times at once #533.
Fixed percentage discounts not taking the stores rounding method into account during calculation #506.
Fixed issue where order lines with a zero value would cause a concurrency exception due to the fact their prices aren't frozen but the order recalculation process was attempting to refreeze them.
Updated Order properties to trim whitespace around values to prevent unexpected behavior #528.
Fixed error in SearchOrder
when searching with date ranges #496.
Fixed properties set in the background from an entity action lost when resaving the entity from the UI after the action (wasn't fully fixed in 10.0.9) #472.
Added support for localhost sub domains in dev license #493.
Added a WithUmbracoBuilder
extension for IUmbracoCommerceBuilder
to allow access to the Umbraco configuration within an Umbraco Commerce registration.
Fixed properties set in the background from an entity action lost when resaving the entity from the UI after the action #472.
Fixed unable to override cart editor view like you can the order editor view #474.
Fixed issue with date range order searches not working correctly #468.
Fixed error in SafeLazy not taking null into account and so causing errors when an entity cache entry is evicted #466.
Incremented Newtonsoft.Json
version dependency to 13.0.1 as 13.0.0 doesn't exist on NuGet anymore #451.
Added licensing fallback to use any previously validated license within the last 7 days
Updated Umbraco.Licenses
version dependency to the latest
Made WithUmbracoCommerceBuilder
extension public to allow accessing the IUmbracoCommerceBuilder
instance outside of the AddUmbracoCommerce
call
Fixed Cross-site scripting (XSS) issue in email/print templates.
Use Microsoft.Data.SqlClient for migrations to support Azure connection strings #443.
Move system config files to system.{}.config.json
to allow overriding as per the docs #448.
Updated order/cart editor config to allow template
option for custom property rendering #446.
Fixed UI spelling mistakes as documented in issue #427.
Fixed issue where adding a product with a uniqueness property, and then adding the same product without a uniqueness property would replace the initial orderline, rather than adding a new one #438
Fixed localization issue where -1
in querystrings would get incorrectly formatted. Root ids are now formatted with an invarient culture.
Allow overriding of SameSite
/Path
for Umbraco Commerce cookies.
Updated productSource
resolution to check for both IPublishedContent
and IEnumerable<IPublishedContent>
as it depends on the picker used and what its return type is.
Updated default order number template from CART-{0}
to ORDER-{0}
.
Updated product adapter to resolve product details correctly from child node variants.
You can find the release notes for Vendr in the Change log file on GitHub.
Version specific documentation for upgrading to new major versions of Umbraco Commerce.
This page covers specific upgrade documentation for when migrating to major 10 of Umbraco Commerce.
If you are upgrading to a new minor or patch version, you can find information about the breaking changes in the Release Notes article.
Version 10 is the initial Long-term support (LTS) release of the Umbraco Commerce product. It contains a number of breaking changes from the previous, Vendr product.
See the Migrate from Vendr to Umbraco Commerce guide for full details.
You can find the version specific upgrade notes for versions out of support in the Legacy documentation on GitHub.
Detailed steps on how to migrate the Checkout package from Vendr to Umbraco Commerce.
Throughout the following steps, we will migrate the Checkout package from Vendr to Umbraco Commerce.
Make a backup of any custom templates and Vendr UI configuration files.
Make a note of all configuration values on the Vendr.Checkout Checkout node.
Delete Vendr.Checkout generated checkout nodes.
Checkout
Customer Information
Shipping Method
Payment Method
Review Order
Process Payment
Order Confirmation
Delete all Vendr.Checkout generated Document Types.
[Vendr Checkout] Page
[Vendr Checkout] Checkout Page
[Vendr Checkout] Checkout Step Page
Delete all Vendr.Checkout generated Data Types.
[Vendr Checkout] Step Picker
[Vendr Checkout] Theme Color Picker
Uninstall the Vendr.Checkout Nuget package:
Delete any remaining files and folders in the ~/App_Plugins/VendrCheckout
directory.
Install the Umbraco.Commerce.Checkout package:
Locate the Umbraco Commerce Checkout dashboard in the Settings section
Click the "Install" button to reinstall the Checkout components in the previous location.
Copy any custom configuration files back into the solution.
Copy any custom Views into the ~/Views/UmbracoCommerceCheckout/
folder.
Getting Started with Umbraco Commerce.
In this section, you will find information about the key steps necessary to get you started with Umbraco Commerce.
It is assumed that you have an Umbraco 10+ website configured, and ready to install Umbraco Commerce.
Find detailed instructions on how to install the latest version of Umbraco in the Umbraco CMS documentation.
The minimum requirements for using Umbraco Commerce are as follows:
Umbraco CMS version 10+
SQL Server 2015+ Database
SQLite is fine for testing, but not recommended for live deployments. See Configuring SQLite support for more details.
This is an add-on product to Umbraco CMS. Umbraco Commerce follows the versioning strategy laid out for Umbraco CMS.
Follow the steps outlined below to migrate your custom payment providers to Umbraco Commerce.
Throughout the following steps, we will migrate custom payment providers used for Umbraco Commerce into Umbraco Commerce.
Remove any installed Umbraco Commerce packages
Install the Umbraco.Commerce
packages for the payment providers.
Update any namespace references.
Update project framework to net7.0
.
The final step in the migration is to update all abstract async methods exposed by the base class. It needs to be updated to accept an additional CancellationToken cancellationToken = default
parameter as the final method argument. Your Integrated Development Environment (IDE) should provide feedback on all the methods that have been updated.
Umbraco Commerce is a commercial product. You can run an Umbraco Commerce unrestricted locally without the need a license. Running Umbraco Commerce on a public domain will display a warning banner in the backoffice and will limit the maximum number of orders (20). To remove these restrictions, you'll need to have a valid license.
Licenses are sold per backoffice domain and will also work on all subdomains. If you have alternative staging/qa environment domains, additional domains can be added to the license on request.
The licenses are not bound to a specific product version. They will work for all versions of the related product.
Let's say that you have a license configured for your domain, mysite.com
, and you've requested two development domains, devdomain.com
and devdomain2.com
.
The license will cover the following domains:
localhost
*.local
*.mysite.com
www.mysite.com
devdomain.com
www.devdomain.com
devdomain2.com
www.devdomain2.com
You can have only 1 license per Umbraco installation.
There are a few differences as to what the licenses cover:
A single license covers the installation of Umbraco Commerce in 1 production backoffice domain, as well as in any requested development domains.
The production domain includes all subdomains (e.g. *.mysite.com
).
The development domains work with or without the www
subdomain.
The license allows for an unlimited number of orders.
The license also includes localhost
and *.local
as a valid domain.
If you have multiple backoffice domains pointing at the same installation, you have the option to purchase and add additional domains to your license.
This is an add-on domain for existing licenses. Refunds will not be given for this product.
You can look at the pricing, features, and purchase a license on the Umbraco Commerce page. A member of the sales team will manage this process. You will need to provide all domains you wish to have covered by the license such as primary and development/staging/QA domains. You should then receive a license code to be installed in your solution.
If you require to add addition domains to the license, reach out the sales team with your request and they will manage this process.
Once you have received your license code it needs to be installed on your site.
Open the root directory for your project files.
Locate and open the appSettings.json
file.
Add your Umbraco Commerce license key to Umbraco:Licenses:Umbraco.Commerce
:
You might run into issues when using a period in the product name when using environment variables. Use an underscore in the product name instead, to avoid problems.
You can verify that your license is successfully installed by logging into your project's backoffice and navigating to the settings section. Here you will see a licenses dashboard which should display the status of your license.
UmbracoApplicationUrl
If you are running on a single domain for both your frontend and backend environments, it's not necessary to configure a UmbracoApplicationUrl
.
If you have different domains for your frontend and backend, then it's advised that you configure an UmbracoApplicationUrl
set to your backoffice URL. This helps the licensing engine know which URL should be used for validation checks. Without this configuration setting, the licensing engine will try and work out the domain to validate from the HTTP request object. This can lead to errors when switching between domains.
An UmbracoApplicationUrl
can be configured in your appSettings.json
file like so:
See the Fixed Application URL documentation for more details about this setting.
UmbracoApplicationUrl
on Umbraco CloudIf you are hosting on Umbraco Cloud you will find the configuration described above won't be reflected in your environment. The reason for this is that Umbraco Cloud sets this value as an environment variable set to the Cloud project domain (<your project>.umbraco.io
). This overrides what is set via the appSettings.json
file.
There are two options in this case:
Either the domains for each of your Cloud environments can be added to your license.
Or, for more control and to ensure this value is set correctly for other reasons, you can apply the configuration via code.
For example, in your Startup.cs
file, you can add the following to the ConfigureServices
method:
In practice, you will probably want to make this a bit more sophisticated. You can read the value from another configuration key, removing the need to hard-code it and have it set as appropriate in different environments. You can also move this code into a composer or an extension method if you prefer not to clutter up the Startup.ConfigureServices
method.
Some Umbraco installations will have a highly locked down production environment, with firewall rules that prevent outgoing HTTP requests. This will interfere with the normal process of license validation.
On start-up, and periodically whilst Umbraco is running, the license component used by Umbraco Commerce will make an HTTP POST request to https://license-validation.umbraco.com/api/ValidateLicense
.
If it's possible to do so, the firewall rules should be adjusted to allow this request.
If such a change is not feasible, there is another approach you can use.
You will need to have a server, or serverless function, that is running and can make a request to the online license validation service. That needs to run on a daily schedule, making a request and relaying it onto the restricted Umbraco environment.
To set this up, firstly ensure you have a reference to Umbraco.Licenses
version 10.1 or higher. If the version of Commerce you are using depends on an earlier version, you can add a direct package reference for Umbraco.Licenses
.
Then configure a random string as an authorization key in configuration. This is used as protection to ensure only valid requests are handled. You can also disable the normal regular license checks - as there is no point in these running if they will be blocked:
Your Internet enabled server should make a request of the following form to the online license validation service:
The response should be relayed exactly via an HTTP request to your restricted Umbraco environment:
A header with a key of X-AUTH-KEY
and value of the authorization key you have configured should be provided.
This will trigger the same processes that occur when the normal scheduled validation completes ensuring your product is considered licensed.
Learn how to migrate a Vendr solution to Umbraco Commerce.
This guide provides a step-by-step approach to migrating a default Vendr solution to Umbraco Commerce.
Upgrade to the latest version of Vendr before continuing with the migration.
You can upgrade your installation by installation the latest version on top of the existing one.
You can find details on migrating the Checkout package as well as custom Payment Providers in the Further Migrations section of this article.
Before outlining the exact steps, there are a few key changes to be aware of.
These changes will dictate the steps to take in the process of migrating to Umbraco Commerce.
Vendr.Common
Umbraco.Commerce.Common
Vendr.Core
Umbraco.Commerce.Core
Vendr.Infrastructure
Umbraco.Commerce.Infrastructure
Vendr.Persistence
Umbraco.Commerce.Persistence
Vendr.Persistence.Sqlite
Umbraco.Commerce.Persistence.Sqlite
Vendr.Persistence.SqlServer
Umbraco.Commerce.Persistence.SqlServer
Vendr.Umbraco
Umbraco.Commerce.Cms
Vendr.Umbraco.Web
Umbraco.Commerce.Cms.Web
Vendr.Web
Umbraco.Commerce.Web
Vendr.Web.UI
Umbraco.Commerce.Web.StaticAssets
Vendr.Umbraco.Startup
Umbraco.Commerce.Cms.Startup
Vendr
Umbraco.Commerce
In this first step, we will be replacing all existing Vendr dependencies with Umbraco Commerce dependencies.
Remove any installed Vendr packages (including Payment Providers):
Take a backup of any Vendr-specific templates and config files you will want to reuse:
Delete the Vendr App_Plugins
folder:
Install Umbraco.Commerce
:
Install Umbraco Commerce packages including any payment providers previously removed.
Reapply any backed-up config files in their new App_Plugins
location.
Move any backed-up templates into the ~/Views/UmbracoCommerce/Templates/
folder.
Rename any config files with a .json
file extension rather than .
Compile your project against .NET 7.0.
Based on the Key Changes outlined above update all Vendr references to the new Umbraco Commerce alternatives. Ensure you update any Views/Partials that also reference these.
In this step, we will cover updating the database for Umbraco Commerce.
Backup your database
Rename database tables using the following query:
Swap Vendr property editors for Umbraco Commerce property editors:
Swap the Vendr variants editor for the Umbraco Commerce variants editor in the block list data entry:
Swap Vendr price/amount adjustments to Umbraco Commerce price/amount adjustments:
Update template paths:
Update the migrations log:
Update the activity logs:
Delete any obj/bin folders in your projects to ensure a clean build.
Recompile all projects and ensure all dependencies are restored correctly
Delete the existing Vendr license files in the umbraco\Licenses
folder.
Add your new Umbraco.Commerce license key to the appSettings.json
file:
Update any payment gateways that use a global webhook:
Run the project.
It is highly recommended to ensure everything works as expected, before moving on to migrating packages and custom payment providers.
If you have been using the Vendr Checkout package, you will need to follow some additional steps to migrate this package to Umbraco Commerce. Follow the link below for a complete guide:
Any custom payment providers used with Vendr also need to be migrated to Umbraco Commerce. Follow the link below to find detailed steps on how to perform this migration:
The User Interface for Umbraco Commerce.
The Umbraco Commerce UI consists of a number of key areas, split over three sections within the Umbraco backoffice:
Settings for managing the different store settings.
Commerce for managing store-related content (orders, discounts, etc).
Content for managing the Umbraco Commerce products.
The Settings section is where the configuration of all Store settings is managed. From here you can manage how the Store works as well as what options will be available within the Store.
The UI for the Settings section consists of a Tree which lists all available Stores and their key areas available for configuration. It also contains a right-hand editor panel. This can either act as an editor interface or as a list view interface for listing items within that given configuration area.
Each Store has 8 key areas of configuration accessible within the Settings section:
Store: Each Store node contain Store level configuration settings.
Order Statuses contain the configuration of the different Statuses an order can be in. Think of these as an organizational structure for your Orders.
Shipping Methods contains the list of Shipping Methods available to a Store.
Payment Methods contains the list of Payment Methods available to a Store.
Countries contain the list of Countries the Store is able to trade with.
Currencies contain the list of accepted Currencies for the Store.
Taxes contains the list of Tax Classes and their Tax Rates for the Store.
Email Templates contains the list of Email Templates supported by the Store.
The Commerce section contains a Tree to access the Stores and their different features, as well as a right-hand panel for managing the items.
The Content section is where the Umbraco Commerce product nodes are managed. Managing products with Umbraco Commerce is similar to working with regular content nodes.
This article shows how to manually upgrade Umbraco Commerce to run the latest version. When upgrading Umbraco Commerce, be sure to also consult the notes to learn about potential breaking changes and common pitfalls.
Before upgrading, it is always advisable to take a complete backup of your site and database.
To upgrade to the latest version of Umbraco Commerce you can use:
NuGet
Visual Studio
NuGet installs the latest version of the package when you use the dotnet add package Umbraco.Commerce
command unless you specify a package version: dotnet add package Umbraco.Commerce --version <VERSION>
After you have added a package reference to your project by executing the dotnet add package Umbraco.Commerce
command in the directory that contains your project file, run dotnet restore
to install the package.
Go to Tools
-> NuGet Package Manager
-> Manage NuGet Packages for Solution...
in Visual Studio, to upgrade Umbraco Commerce:
Select Umbraco.Commerce.
Select the latest version from the Version drop-down and click Install.
When the command completes, open the .csproj file to make sure the package reference is updated:
If you are using one or more of the below sub-packages, they also need to be upgraded as well:
How-To Guide to configure SQLite support for Umbraco Commerce.
Out of the box, Umbraco Commerce only supports SQL Server-based databases as this is the recommended database platform for live environments. To aid testing and rapid prototyping, however, Umbraco Commerce can be configured to use an SQLite database.
Whilst Umbraco Commerce does support SQLite for testing, we do not recommend using it in a live environment. Due to the high levels of active connections required to manage concurrent shopping carts, this is not something SQLite handles well at all.
To add SQLite support, you will need to install the SQLite persistence layer NuGet package for Umbraco Commerce.
Once the NuGet package is installed, you need to register SQLite support with Umbraco Commerce via the interface.
Add .AddUmbracoCommerce()
below .AddWebsite()
in the Program.cs
file.
After configuring Umbraco CMS with SQLite, Umbraco Commerce will automatically utilize the same database configuration. If you wish to install Umbraco Commerce into its own SQLite database you can configure its connection string in the appSettings.json
like so:
Learn the steps needed in order to install Umbraco Commerce into your Umbraco CMS website.
Learn how to install Umbraco Commerce into your Umbraco CMS implementation.
You can also find information about how to upgrade and how to install and activate your Umbraco Commerce license.
Umbraco Commerce is available via .
To install Umbraco Commerce via NuGet you can run the following command directly in the NuGet Manager Console window:
Alternatively, you can also find and install the NuGet package via the NuGet Package Manager in Visual Studio. You will see a number of packages available, however, you will want to install the main Umbraco Commerce package.
For most sites using a single solution, the above will be all you need to install Umbraco Commerce into your project. When you have a more complex solution structure consisting of multiple projects, Umbraco Commerce is available in multiple sub-packages with varying dependencies.
Browse the Umbraco Commerce documentation to learn more about the addon and how to use it.
Umbraco Commerce is the official Umbraco e-commerce addon for your Umbraco CMS website. It can be used to set up small webshops, while it can also be implemented for big-scale e-commerce solutions spanning multiple countries.
Are you looking for Vendr documentation?
The articles and topics covered on this documentation site are for Umbraco Commerce.
Documentation for Vendr is located on the .
These docs are aimed at developers who have at least a basic understanding of , as well as C# and MVC principals.
If you require assistance you can use our support channels to seek assistance.
Configuring Umbraco for Umbraco Commerce.
Before you can start to use Umbraco Commerce, you need to configure Umbraco to allow access to the relevant sections. The Umbraco Commerce UI is split over three sections within the Umbraco backoffice:
Settings for managing the different store settings.
Commerce for managing store-related content (orders, discounts, etc).
Content for managing the Umbraco Commerce products.
In order to access these sections, you will need to ensure a User account with the relevant permissions to do so. When logged in as Administrator, access to the Settings and Content sections is already granted.
To gain access to the Commerce section additional configuration is needed.
To gain access to the Commerce section, it is advised to create a new User Group called Commerce.
Navigate to the User section of the Umbraco backoffice.
Open the User Groups page.
Create a new User Group called Commerce.
Assign the relevant User accounts to that User Group.
Allow that User Group access to the Commerce section as a whole.
Creating a custom User Group provides a way of managing Users who have access to the Commerce section, rather than allowing individual Users access.
Learn more about .
Once created and assigned, you should be able to refresh the backoffice and see that we now have access to the new Commerce section.
See the for details on how to install a license.
Umbraco.Commerce.Common
A shared project of common, non-Commerce-specific patterns and helpers.
Umbraco.Commerce.Core
Core Commerce functionality that doesn't require any infrastructure-specific dependencies.
Umbraco.Commerce.Infrastructure
Infrastructure-specific project containing implementations of core Commerce functionality.
Umbraco.Commerce.Persistence.SqlServer
Persistence-specific project containing implementations of core Commerce persistence functionality for SQL Server.
Umbraco.Commerce.Persistence.Sqllite
Persistence-specific project containing implementations of core Commerce persistence functionality for SQLite.
Umbraco.Commerce.Web
Core Commerce functionality that requires a web context.
Umbraco.Commerce.Cms
Core Commerce functionality that requires an Umbraco dependency.
Umbraco.Commerce.Cms.Web
The Commerce functionality for the Umbraco presentation layer.
Umbraco.Commerce.Cms.Web.UI
The static Commerce assets for the Umbraco presentation layer.
Umbraco.Commerce.Cms.Startup
The Commerce functionality for registering Commerce with Umbraco.
Umbraco.Commerce
The main Commerce package entry point package.
Umbraco.Commerce.Common
A shared project of common, non-Commerce-specific patterns and helpers.
Umbraco.Commerce.Core
Core Commerce functionality that doesn't require any infrastructure-specific dependencies.
Umbraco.Commerce.Infrastructure
Infrastructure-specific project containing implementations of core Commerce functionality.
Umbraco.Commerce.Persistence.SqlServer
Persistence-specific project containing implementations of core Commerce persistence functionality for SQL Server.
Umbraco.Commerce.Persistence.Sqllite
Persistence-specific project containing implementations of core Commerce persistence functionality for SQLite.
Umbraco.Commerce.Web
Core Commerce functionality that requires a web context.
Umbraco.Commerce.Cms
Core Commerce functionality that requires an Umbraco dependency.
Umbraco.Commerce.Cms.Web
The Commerce functionality for the Umbraco presentation layer.
Umbraco.Commerce.Cms.Web.UI
The static Commerce assets for the Umbraco presentation layer.
Umbraco.Commerce.Cms.Startup
The Commerce functionality for registering Commerce with Umbraco.
Umbraco.Commerce
The main Commerce package entry point package.
How-To Guide to limit order line quantity in Umbraco Commerce.
In this guide, we will be looking at Validation events in Umbraco Commerce. These enabled you to limit order line quantity based on:
The existing stock value of the product, and
The existing quantity of the product in the cart.
When adding a product to the cart we need to verify that the product is in stock. We also need to verify that the customer does not already have the remaining quantities in the cart.
When changing the order line quantity on the cart page, we need to ensure that the quantities being changed are in stock.
Finally, we need to register the Umbraco Commerce event handlers via an IUmbracoCommerceBuilder
extension.
How-To Guide to configure using an alternative database for the tables of Umbraco Commerce.
By default, Umbraco Commerce will use the same database as Umbraco to store its data. As e-commerce and content management have different database needs, it may be beneficial to house the Umbraco Commerce database tables in an alternative database.
To do this, you can configure a Umbraco Commerce-specific connection string in your app settings ConnectionStrings
section using the umbracoCommerceDbDSN
prefix.
When Umbraco Commerce runs, it will perform all of its migrations and operations against this database instead of the default Umbraco database.
Base Currency for standardized reporting in Umbraco Commerce.
Within Umbraco Commerce we have support for showing analytics reports, including summaries of sales figures. At the same time, Umbraco Commerce also supports orders being placed in multiple currencies. These pose a problem of how to display a succinct sales figure when the orders are placed in multiple currencies. The answer to this is the store's Base Currency.
When you configure a store you need to assign a base currency to it. This currency is there to identify which currency the store should use as its basis for reports and sales figures. This will be used regardless of whatever currency the order was placed in.
When a store has a base currency configured, any order placed will track the price of the order in the customer's chosen currency. It will also track the current exchange rate between that currency and the store's base currency. Whenever a report is run the order total prices will be converted using this exchange rate. This means that they can all be automatically presented in the single base currency of the store.
Umbraco Commerce uses an ICurrencyExchangeRateService
to retrieve the most up-to-date rate to be able to track the current exchange rate. This is done for each individual order.
Out of the box, Umbraco Commerce comes with a number of available services you can choose to use. Some are free services, whilst others require a paid subscription.
ExchangeRatesApiCurrencyExchangeRateService uses the free exchangeratesapi.io API and is the default option.
FixerCurrencyExchangeRateService uses the fixer.io API which is a reliable paid option (with a reasonable free plan).
CurrencyLayerCurrencyExchangeRateService uses the currencylayer.com API which is another reliable paid option (with a reasonable free plan).
If you wish to change the currency exchange rate service used, you can do so via the dependency injection approach. This is used to override the default service configuration. For services that require configuration to be passed in, such as service API keys, you'll need to use the factory-based override as follows:
Umbraco Commerce has a background service that will attempt to ensure that all historic orders without an exchange rate defined get updated. This is done in case the third-party APIs fail and we need a method of cleaning data. It is also done in case the store base currency is ever changed. In this case, we need to re-process all orders again with the newly selected base currency.
The currency exchange rate background task will run once every 24 hours or after 20 seconds after an app pool recycle.
Perform bulk operations on entities in Umbraco Commerce.
You might need to execute a custom action for each entity in a selection while extending Umbraco Commerce. For example, being able to trigger label printing for a series of orders, or printing physical gift cards for specific gift card entities.
Umbraco Commerce allows extending the different table views, adding in Bulk Actions to the bulk action bar that appears when you select multiple items. Out of the box all list views contain at minimum a Delete bulk action.
Bulk actions are client-side concepts and so additional bulk actions are injected with JavaScript in an AngularJS configuration module.
To create a configuration module you can create a custom folder in the App_Plugins
directory and create a JavaScript file to hold your configuration in.
Create a custom folder in the App_Plugins
directory.
Create a JavaScript file with this new folder.
Register the file in a package.manifest
file within the same folder.
Add the following JSON to the package.manifest
file:
Inject a bulk action inside the umbraco-commerce-bulk-actions-config.js
by adding the following:
Once created, the bulk action will be displayed in the bulk actions bar for the configured entities.
name
Name of your bulk action that will be displayed in the bulk action button.
icon
Icon for your bulk action that will be displayed in the bulk action button next to the name.
sortOrder
The order in which to display this action in the bulk actions bar. System bulk actions sort orders are in multiples of 100
in order to allow the positioning of items between system bulk actions.
configure(items)
A function to run before the bulk operation in order to provide configuration for the bulk action. Returns a Promise that returns an object which is then passed to the item/bulk action methods.
itemAction(item, config)
Individual action to perform per selected item. A status will be displayed after each processed item shows progress. Returns a Promise.
bulkAction(items, config)
Single action to be performed for all selected items in one go. Returns a Promise.
getConfirmMessage(total)
A function that can provide a message to display before a bulk action is triggered should confirmation be required for the action to run. Returns a Promise that returns a string.
getStatusMessage(count, total)
Function used to provide a status message after each item has been processed. Displayed in the bulk actions bar after each itemAction
has been called. Returns a Promise that returns a string.
getSuccessMessage(total)
A function to return a success message after all bulk actions have been performed. Returns a Promise that returns a string.
condition(context)
As all bulk actions are registered globally for all entity types, the condition
function can be used to filter when, and for which entities a bulk action will display.
Only an itemAction
or a bulkAction
method can be defined for a bulk action configuration. If both are present, the bulkAction
will be used and the itemAction
will be ignored. If processing of items can be done individually, it is better to use the itemAction
in order to provide user feedback. The bulkAction
can only be used where items need to be processed in a single action.
Most methods apart from itemAction
or bulkAction
are optional. If methods aren't present, a default implementation will be used. Where the methods trigger, specific functionality such as the configure
or getConfirmMessage
methods will become disabled.
The array-based syntax for registering is a bulk action with angular dependencies. Each bulk action is registered as an array, where all dependencies are defined first and then a factory function is defined last which returns the actual bulk action definition.
Whilst these docs outline how to define a bulk action, you will likely need to register further resources or services that can perform the given bulk operation and include these as a dependency for your action.
The following section display an example of a bulk action with dialog configuration step:
You can integrate your Umbraco Commerce implementation with a series of different payment providers.
Learn everything you need to know about the main features and concepts of Umbraco Commerce.
Calculation context in Umbraco Commerce.
When extending the calculation process of Umbraco Commerce, either by custom or custom it is important to be aware of the OrderCalculation
object.
When an order asks to be re-calculated, this triggers a calculation pipeline which in turn runs a series of calculation tasks. It then calls a number of extendable calculators in order to work out the orders' different prices. Throughout this process, Umbraco Commerce needs to keep track of all these prices as they change. At the same time, it also needs to ensure that the calculation is transactional in case something goes wrong. To accomplish both of these requirements we use a temporary state object called OrderCalculation
to store all the information. Only at the end of the calculation, if everything was successful, we can copy those calculated prices back to the order.
In the different calculation extension points, Umbraco Commerce will often pass you both an Order
object and the OrderCalculation
object. We pass the order to get you access to any information held on it that you may need for calculations, such as custom properties. This shouldn't be used for accessing any price-related values of the order.
As mentioned above, in order to maintain data integrity during the calculation process, the order itself is not updated until the end. This means that any calculations based on the order entities' price values would be based on the orders' previously calculated price values.
In order to base your calculation on the current calculated price values you should instead access the OrderCalculation
object.
From the OrderCalculation
object you can access the different order prices, including order line calculations. The order line calculations are stored in a dictionary. In this dictionary, the key is the order line's ID, and the value is an OrderLineCalculation
object holding the calculated prices.
By using the prices from the OrderCalculation
object you can ensure that your calculation is based on the most up-to-date values for the order.
You should always base your price on the OrderCalculation
object's price values when the following applies:
Your values are based on another price held on an order
You have access to an OrderCalculation
an object that isn't null
.
It should also only fall back to the order entity if there is no OrderCalculation
available.
Minimizing dependencies via dependency injection with Umbraco Commerce.
Dependency Injection (DI) can be an intimidating subject. DI reduces the number of hard-coded dependencies within a codebase by providing a means to define dependencies independently and have them "injected" dynamically. These dependencies are often exposed as interfaces, rather than concrete types. This enables them to be swapped out or replaced with minimal effort.
The ability to "swap out" dependencies is used in Umbraco Commerce in a number of places to allow developers to provide alternative implementations of specific features. This could be the ability to:
Swap out the default Product Calculator to change how product prices are calculated.
Swap out the default Order Number Generator should you wish to provide an alternative order numbering strategy.
Umbraco Commerce makes heavy use of the dependency injection mechanism in Umbraco to manage many of the features. It is important to understand how to work with the registration process.
What follows are examples of common tasks you'll need to be able to perform via the DI container in order to work effectively with Umbraco Commerce. For more detailed documentation, it is highly recommended that you read the .
Registering dependencies is an important ability to understand as this is used to register Umbraco Commerce event handlers and to extend system pipelines.
To register a dependency you need to do so via the IUmbracoBuilder
interface. This is exposed within the main Startup
class, inside the ConfigureServices
method between the AddComposers()
method call and the Build()
method call.
You can also add your registration logic inside an IUmbracoBuilder
extension method and then call that within the ConfigureServices
method. This is the recommended approach.
Registering a dependency is achieved by working with the IUmbracoBuilder
API:
Like it is possible to add new dependencies it is also possible to replace existing dependencies. This could be dependencies such as the different Calculators available in Umbraco Commerce.
Where a feature is replaceable, replacing that dependency is also achieved via the IUmbracoBuilder
API:
As well as registering dependencies, you will also need to know how to access Umbraco Commerce dependencies from within your Controllers. To do this, we add parameters to our Controllers constructor for the dependencies we require. Then, the IoC container will inject them automatically for us.
Performing calculations with Calculators in Umbraco Commerce.
Calculators are small service implementations with the sole responsibility of calculating prices for a given aspect of an Order. There are five main Calculator service interfaces in Umbraco Commerce:
IShippingCalculator - Responsible for calculating the Shipping Method price/tax rate of a given Shipping Method.
IPaymentCalculator - Responsible for calculating the Payment Method price/tax rate of a given Payment Method.
IProductCalculator - Responsible for calculating the Product unit price/tax rate of a given Product.
IOrderLineCalculator - Responsible for calculating the price/tax rate of a given OrderLine.
IOrderCalculator - Responsible for calculating the entire Order.
All Calculator services can be replaced with alternative implementations should you wish to change how Umbraco Commerce performs its calculations.
The individual Calculator interfaces may differ but the process for defining a custom Calculator implementation is the same for all of them. It is possible to create a new class that implements the default system Calculator that you wish to replace. You can then override the relevant calculation methods.
Listening for changes within Umbraco Commerce.
Much like the standard events in .NET, Umbraco Commerce has an events system to notify you when certain things happen within the application. However, Umbraco Commerce differs slightly in the types of events that are fired and how you register your event handlers.
Events in Umbraco Commerce are registered via the interface, rather than via static event delegates. This has a number of advantages, such as being able to control the order of when event handlers are fired. It also allows us to inject dependencies into the event handlers making it a much more decoupled approach to eventing.
In Umbraco Commerce, there are two main types of events you can create handlers for. Both are explained in detail below.
Validation events are events that fire immediately before a change is about to be made to an entity. These events allow you to inject your own logic to decide whether an action should be possible or not. We already have a number of validation handlers built in to maintain the consistency of your data. Validation events allow you to extend this behavior with your own rules.
An example of a Validation event handler would look something like this:
All Validation event handlers inherit from a base class ValidationEventHandlerBase<TEvent>
where TEvent
is the Type of the event the handler is for. They then have a Validate
method that accepts an instance of the event type, and inside which you can perform your custom logic. If the event fails the validation logic, you can call evt.Fail("Your message here")
to block the related action from happening and have a ValidationException
be thrown. This can then be captured in the front end to display a friendly error message.
You can control the order of when Validation event handlers run, before or after another Validation event handler. This is done by registering them via the RegisterHandlerBefore<THandler>()
or RegisterHandlerAfter<THandler>()
methods respectively.
Notification events are events that fire, often immediately before or after an action is executed. It provides you the ability to run custom logic to react to that action occurring. This is useful for scenarios such as sending emails when an Order is finalized or allowing you to synchronize stock updates with an external system.
Notification events won't allow you to change the behavior of how Umbraco Commerce runs. They provide you with an effective means of reacting when changes occur.
An example of a Notification event handler would look something like this:
All Notification event handlers inherit from a base class NotificationEventHandlerBase<TEvent>
where TEvent
is the Type of the event the handler is for. They then have a Handle
method that accepts an instance of the event type, and inside which you can perform your custom logic.
You can also control the order of when Notification event handlers run by registering them via the RegisterHandlerBefore<THandler>()
or RegisterHandlerAfter<THandler>()
methods respectively.
Define when a Discount should apply and what should be the Reward in Umbraco Commerce.
Discounts in Umbraco Commerce are defined using a series of rules and reward builders that let you configure the following:
When a Discount should apply.
What the Reward should be for that Discount.
These builders come with a handful of the most common Rules and Rewards that should suit the majority of web stores' needs. When need to create your own Rules or Rewards then these are extendable via a Provider model allowing you to incorporate your own custom logic.
There are two types of Discount Rules in Umbraco Commerce:
Order Discount Rules: Determine whether a discount should apply to an Order. Returns a Fulfilled/Unfulfilled status depending on whether the Rule logic has been met.
Order Line Discount Rules: Determine whether a discount should apply to an Order Line within an Order. Returns a Fulfilled/Unfulfilled status depending on whether the Rule logic has been met. Where the status is Fulfilled, a list of all Order Lines that are fulfilled by this Rule is also returned.
An example of an Order Discount Rule Provider would look something like this:
All Order Discount Rule Providers inherit from a base class OrderDiscountRuleProviderBase<TSettings>
. TSettings
is the type of a Plain Old Class Object (POCO) model class representing the Discount Rule Providers settings.
The class must be decorated with DiscountRuleProviderAttribute
which defines the Discount Rule Providers alias
and name
, and can also specify a description
or icon
to be displayed in the backoffice. The DiscountRuleProviderAttribute
is also responsible for defining a labelView
for the Provider.
Rule Providers have a ValidateRule
method that accepts a DiscountRuleContext
as well as an instance of the Providers TSettings
settings model. Inside this you can perform your custom logic, returning a DiscountRuleResult
to notify Umbraco Commerce of the Rule outcome.
If the passed-in context (which contains a reference to the Order) meets the Rule's criteria, then a fulfilled DiscountRuleResult
can be returned by calling return Fulfilled();
. Alternatively, if the Order didn't meet the Rules criteria an unfulfilled DiscountRuleResult
can be returned by calling return Unfulfilled();
.
An example of an Order Line Discount Rule Provider would look something like this:
All Order Line Discount Rule Providers inherit from a base class OrderLineDiscountRuleProviderBase<TSettings>
and follows much the same requirements as the Order Discount Rule Provider defined above. Where they differ is in the ValidateRule
method implementation and when a fulfilled DiscountRuleResult
is returned. In this case, an Order Line Discount Rule returns a collection of Order Lines processed by the Rule that have met the rules criteria. Whether the rules are met, is checked by calling return Fulfilled(fulfilledOrderLines);
.
An example of a Discount Reward Provider would look something like this:
All Discount Reward Providers inherit from a base class DiscountRewardProviderBase<TSettings>
. TSettings
is the Type of a POCO model class representing the Discount Reward Providers settings.
The class must be decorated with DiscountRewardProviderAttribute
which defines the Discount Reward Providers alias
and name
. It can also specify a description
or icon
to be displayed in the Umbraco Commerce backoffice. The DiscountRewardProviderAttribute
is responsible for defining a labelView
for the Provider.
Reward Providers have a CalculateReward
method that accepts a DiscountRewardContext
as well as an instance of the Providers TSettings
settings model. Inside this, you can perform your custom calculation logic, returning a DiscountRewardCalculation
instance that defines any Reward values to apply to the Order.
Both the DiscountRuleProviderAttribute
and the DiscountRewardProviderAttribute
allow you to define a labelView
for the Provider. It should be the path to an Angular JS view file that will be used to render a label in the Rule/Reward Builder UI. Where no labelView
is supplied, one will be looked for by convention at the following location:
~/app_plugins/umbracocommerce/views/discount/{Type}/labelViews/{ProviderAlias}.html
Type
is either rules
or rewards
, depending on the Type of Provider it refers to. ProviderAlias
is the alias of the Provider.
The Rule/Reward Label View should provide a user-friendly summary of its settings to display in the relevant Builder UI.
The Label View file will be passed a model
property which will be a JavaScript representation of the given Providers settings object.
Preparing to enter a Payment Providers payment gateway in Umbraco Commerce.
In Umbraco Commerce, a Payment Form is a form that is displayed immediately prior to redirecting to the Payment Gateway for payment processing. This is usually displayed on some kind of review page, allowing a final review of the Order before commencing payment.
The role of the Payment Form is to perform two tasks:
Prepare the Order for the Payment Gateway - This includes initializing the Orders transaction info and assigning the Order with an Order Number. It's also at this time that the Order is assigned to a Member if there is currently a logged-in session. This task may also involve passing information to the Payment Gateway to create a session, which the customer will complete in the next step. This is dependent on the Payment Provider implementation.
Redirect to the Payment Gateway - The configured Payment Provider will return a Form that contains all the relevant information the Payment Gateway needs. This includes the Forms action
attribute is set to post to a page on the Payment Gateways server, starting the payment capture process.
An Order's Order Number is assigned at the point of the Payment Form being rendered. This is to ensure that an Order has an Order Number prior to redirecting to the Payment Gateway. When the customer is redirected to the Confirmation page, there is always an Order Number to display
The reason this is necessary is that many Payment Gateways finalize Orders asynchronously via webhooks. This means that it is possible that the customer will be redirected to the Confirmation page prior to actual finalization. This is why we set it early to ensure it is always available.
It can happen that a customer cancels a payment mid-way through the capture process and returns to the Order to make modifications. In these cases, a new Order Number will be assigned at the point of re-displaying the Payment Form.
An example of displaying a Payment Form would look something like this:
The Payment Form is rendered using a using
statement to wrap any additional form elements you wish to add, such as a submit button.
It's important to know that the Payment Form by default doesn't contain any button inputs to submit the Form. These must be supplied by the implementer. This is to ensure that the form will work with the design of the Site in question, giving developers more freedom.
Learn about adjusting prices in Umbraco Commerce.
In some cases, you may want to tweak the figures of an order. It could be reducing the price of a product if a customer purchases a given amount of a product. To handle this, Umbraco Commerce has the concept of Price/Amount Adjustments. What adjustments allow you to do is create a record/log of any changes that occur to a price/amount throughout the calculation process. Umbraco Commerce uses the adjustments in the calculation process to work out its final pricing and provides this list of the adjustments on the order. This makes it clear exactly how the price was calculated.
Umbraco Commerce has two types of adjustments:
Price Adjustment - Adjusts one of the orders' price properties (discounts, fees).
Amount Adjustment - Adjusts the final transaction amount of the order (gift cards, loyalty points).
Adjustments are applied using a IPriceAdjuster
or IAmountAdjuster
with developers able to create their own adjusters to apply custom adjustments.
Adjusters apply adjustments to the given price they wish to affect. Adjustments are strongly typed and each adjuster should define their own adjustment type, providing properties to collect any relevant information for the adjustment. This "metadata" gets serialized with the adjustment as is constantly available when accessing the given adjustment.
Adjustments inherit from either PriceAdjustment<TSelf>
or AmountAdjustment<TSelf>
depending on the type of adjustment being applied. Both base classes follow a similar structure, the difference being whether the adjustment value is a Price
or Amount
.
Once defined, the adjuster should be registered with the DI container to enable Umbraco Commerce to be aware of it and include it in the calculation process.
Performing sequential tasks with Pipelines in Umbraco Commerce.
Pipelines allow a series of tasks to be performed in a set sequence. This is done with the input of a given task being the output of the preceding task. It allows a result to be built up as an input is passed through these individual tasks, instead of being calculated in one go.
The Pipelines feature provides an approach to insert additional steps into the process as pipeline tasks can be added or removed from the pipeline sequence.
Where Pipelines is used, it allows an additional point at which developers can interject some custom logic, tweaking how Umbraco Commerce works.
Consider these use-case examples:
An additional task could be injected into the CalculateOrderPipeline
to alter how an Order is calculated.
A task could be injected into the EmailSendPipeline
to add a dynamic attachment to an email.
An example of a Pipeline task would look something like this:
All Pipeline tasks inherit from a base class PipelineTaskWithTypedArgsBase<TPipelineArgs, TModel>
. TPipelineArgs
is the type of arguments supported by the pipeline and TModel
is the pipeline's return model Type. You then need to implement an Execute
method that accepts an instance of the argument's type as input and expects a PipelineResult<TModel>
as its output. Inside this method, you can perform your custom logic as required. To complete the pipeline task, you can call Ok(TModel)
if the task was successful. This will pass in the updated TModel
instance to returnæ. Otherwise, you can call Fail()
to fail the whole pipeline.
You can also control the order of when Pipeline tasks run, before or after another task, by appending them via the InsertBefore<TTask>()
or InsertAfter<TTask>()
methods respectively.
Freezing prices for shopping carts in Umbraco Commerce.
Price Freezing in Umbraco Commerce is the ability to freeze prices for products that are added to the shopping cart. Umbraco Commerce takes a snapshot of a product's price once it's added to the shopping card. This is done in order to ensure the price is honored for the life of the shopping cart. This process prevents a customer's shopping cart from suddenly changing in value should a price change occur whilst their cart session is in progress.
A product's price is frozen from the point it is added to the current Order, and only for the current Currency of the Order. Should the Customer change the Currency of their Order, then a new snapshot of the product price will be taken for that Currency.
There are times when you may wish to control when a frozen price should expire. This could be if a product was incorrectly priced, or if you have rules on how long an Order-session is allowed to maintain price.
On these occasions, you can force frozen prices to expire by using the IPriceFreezerService
and its ThawPrices
method.
All frozen prices have an OrderId
property and a Key
that uniquely identifies them. For product prices, this key consists of a generated token of the following format {StoreId}_{OrderId}_{ProductReference}
. In addition, the product prices Currency, and date of the freeze are also tracked. It is important to know these details as we can use all of these attributes to target which prices we wish to thaw.
For example, to thaw all prices for a product with the reference c0296b75-1764-4f62-b59c-7005c2348fdd
we could call:
Or to thaw all prices for a given Currency that are greater than 30 days old we could call:
Creating bundles of products with Umbraco Commerce.
Occasionally you may need to create a product with multiple sub-products. A good example of this is when buying a computer where you may pick the computer as the main product. You can then choose the different components to make up the computer, such as the hard disk options. The final order line then becomes the composite order line of the selected primary product and all its sub-product options. To achieve this kind of configurable product in Umbraco Commerce, we can use a feature called product bundling.
To create a bundle, we first add the primary product to an order as we normally would. In addition to the product/quantity information, we also provide a unique bundleId
to identify that adding this product should create a bundle order line.
With the primary product added as a bundle, we can then add sub-products to that bundle by calling one of the AddProductToBundle
order methods.
By adding sub-products to a bundle, Umbraco Commerce knows to automatically sum up all the sub-product prices together. It will then add them to the unit price of the primary order line for you. This means that there is nothing extra you need to do in the calculation process.
As you can imagine, product bundles could get rather large making it a little difficult to display them in the backoffice. Umbraco Commerce bundles order lines together in a collapsible user interface. This gives you a clear view of your orders whilst still being able to drill into the detail of the items purchased.
Calculators are interface using the AddUnique<TServiceInterface, TReplacementService>()
method on the Services
property. The TServiceInterface
parameter in this case is the Calculator interface Type you wish to replace and TReplacementService
is the Type of your custom Calculator implementation.
Validation event handlers are interface using the WithValidationEvent<TEvent>()
builder extension method. This is done to identify the event you want to handle and then call the RegisterHandler<THandler>()
method to register your handler(s) for that event.
Notification event handlers are interface using the WithNotificationEvent<TEvent>()
builder extension method. This is used to identify the event you want to handle and then call the RegisterHandler<THandler>()
method to register your handler(s) for that event.
See the section below for more information on Settings objects.
See the section below for more information on Label Views.
See the documentation for more information on Settings objects.
See the section below for more information on Label Views.
See the documentation for more information on Settings objects.
All pipelines occur within a . In case a Pipeline task fails, the whole pipeline will fail and no changes will persist.
Pipeline tasks are interface using the appropriate With{PipelineName}Pipeline()
builder extension method. This is done to identify the pipeline you want to extend. You can then call the Add<TTask>()
method to add your task to the end of that pipeline.
Umbraco Properties
Umbraco Commerce is based on Umbraco CMS, which means that some of the things you'll be working with are native to the core product.
Calculators
Learn more about the different calculators that Umbraco Commerce ships with and how you can customize and extend them.
Product Variants
With Umbraco Commerce you can create a large array of different product variants. Learn more about how this all works.
Great performance and simplified change tracking using ReadOnly and Writable entities in Umbraco Commerce.
When working with the Umbraco Commerce entities, it's important to know that all entities come in two states, ReadOnly and Writable. By default, all Umbraco Commerce API methods will return entities in their ReadOnly state. This means that when you are accessing Umbraco Commerce entities directly from an API endpoint you are able to read and iterate over its properties. You won't, however, be able to make changes to that entity without first converting it into its Writable state.
The reason why we have split entities in this way for a number of reasons, however, the two primary factors are:
Making APIs fast by default - By returning ReadOnly entities by default we can ensure all API methods are as fast as possible by feeding values directly out of our caching layer. Because the entities can't change it means we don't have to laden the entities with extra change tracking logic, we can feed out the cached values directly and only worry about that logic when the entities become Writable.
Simplified change tracking - When we convert a ReadOnly entity to its writable state, internally we take a deep clone of that state so that changes can occur within a scoped "sandbox". At the same time, we retain a copy of the original state meaning when it comes time to persist those changes we have two copies of the state we can perform a comparison on, simplifying the whole change tracking process.
To convert a ReadOnly entity into its Writable form, we achieve this by calling the entities AsWritable(uow)
method, passing in a valid Unit of Work instance to perform the write operations on. Once we have a Writable entity, we can then perform the write operations we desire and persist those changes back to the database.
All write operations must occur within a Unit of Work so by passing in a Unit of Work instance into the entities AsWritable
method, we are ensuring that you are in fact within an active Unit of Work.
Converting product sources into understandable products for Umbraco Commerce.
The role of a Product Adapter in Umbraco Commerce is to provide an interface between a product information source and convert it into a standardized format. This is done to prevent the need for Umbraco Commerce to be tied to that source.
What this means for developers is that Product Adapters allow you to hook in alternative product information sources that may not be Umbraco node based. You may hold your product information in a third-party database table. A custom Product Adapter would then allow Umbraco Commerce to interface with that custom data in the same way it would the default Umbraco node data.
An example of a Product Adapter would look something like this:
All Product Adapters implement the IProductAdapter
interface which requires three method implementations:
Two GetProductSnapshot
methods that retrieve a Product Snapshot for either a product or product variant by reference parameters.
A TryGetProductReference
method which retrieves a product/variant reference for a product that belongs to a given storeId
and has the given sku
.
A Product Snapshot consists of the following properties in order to present a Product to Umbraco Commerce in a standard way.
To allow Umbraco Commerce to search for products/variants to add to a cart via the backoffice, Product Adapters can implement 3 additional methods. This can also be done to support editable carts.
The IProductSummary
, Attribute
and IProductVariantSummary
consists of the following properties in order to present a Product to Umbraco Commerce in a standard way.
typeProduct Adapters are registered via the IUmbracoCommerceBuilder interface using the AddUnique<IProductAdapter, TReplacementAdapter>()
method on the Services
property. The TReplacementAdapter
parameter is the type of our custom Product Adapter implementation.
Creating product variants with Umbraco Commerce.
Product variants are the ability to define variants of a given product. If a product was available in multiple color options, you would create a primary product with product variants for each of the color options.
Out of the box, Umbraco Commerce supports two types of product variant setups.
Child variants are where the product variants are set up as child nodes below the primary product. Generally speaking, this setup is only sustainable for single variant options, where there is only one differing option between the variants.
By using child variants the only thing you need to create is your own variant nodes as you already do in Umbraco.
When a child variant is added Umbraco Commerce checks the primary product node for any properties that can't be found on the variant child node.
This approach is how most of the official Demo store is set up.
Complex variants are where products vary by multiple possible options, such as by size, color, and fit. Complex variants tend to create a lot of variant products which makes the child variants approach impractical.
For complex variants, Umbraco Commerce comes with a variants property editor which will handle a lot of this complexity for you. You can set up a variant element type to use as your data blueprint for your variant products. This can then be linked to the property editor. The variants property editor will use this as the data structure for your variants. You will be presented with the relevant UI to input the product details.
For more information on how you can setup Complex Variants, head to the Complex Variants article.
To aid with the setup of the complex variants, Umbraco Commerce has the Product Attributes concept which defines the individual options that make up your product variants. This could be colors, sizes, and fits. Each product attribute is made up of a label and as many values as needed.
Product attributes are used by the complex variants property editor allowing you to select the combinations of product variants you wish to create. It will automatically generate the product variant entries for you, ready for product information updating.
For more information on how you can setup Product attributes, head to the Complex Variants article.
Learn more about the flexible search functionaities in Umbraco Commerce.
Providing a search API for developers to be able to search for entities that match given criteria is a bit of a balancing act. You want to provide a flexible API to allow for meaningful results to be returned but at the same time, you don't want to allow every possible search combination as this can lead to performance problems.
The way we have addressed this is by using the Specification pattern.
Specifications are a programming design pattern that allows you to encapsulate business rules in blocks that can be chained together to define boolean logic.
What this means is that we can provide a series of specifications for the types of queries we are able to support in a performant way and allow developers to chain these together in whatever combination they require in order to create dynamic filters for entity searches.
To perform a search using specifications you'll need to use one of the search methods on the given entity service that accepts a Func<IEntityQuerySpecificationFactory, IQuerySpecification<Entity>>
parameter. This parameter type might look complex, but its use should be pretty straightforward thanks to the use of delegates.
To use one of the search methods, the implementation will look something like the following:
The above is an example, but it demonstrates the use of a delegate method that then uses a fluent specifications API to build up a query filter. The query filter itself can be made up of many different individual queries which themselves can be grouped using AND
and OR
query logic.
Because the API is fluent it is also self-documenting, with Visual Studio intellisense able to guide developers through all the available specifications.
Alongside the query specifications documented above, we also have to sort specifications that allow a similar fluent API for defining the order in which results are returned. These are passed in a similar way to the search methods as demonstrated below.
Key Umbraco node properties used by Umbraco Commerce.
Umbraco Commerce uses Umbraco nodes as its source of information. In order for Umbraco Commerce to gather the information it needs, it requires that a number of properties are defined at different locations. These properties must have specific property aliases.
store
Umbraco.Commerce.StorePicker
Often placed on the site root node, but can be placed on any node higher than the product nodes themselves, this property links the website to a specific Umbraco Commerce store configuration.
productName
Textstring
Optional product node property that allows you to define an explicit product name other than the product nodes .Name
property, which will be used as fallback.
sku
Textstring
Product node property defining the unique SKU
of the product.
price
Umbraco.Commerce.Price
Product node property defining the prices for the product.
stock
Umbraco.Commerce.Stock
Product node property defining the stock level of the product.
taxClass
Umbraco.Commerce.StoreEntityPicker
Optional product node property that allows you to define an explicit Tax Class
for the product, should it differ from the stores default.
isGiftCard
True/False
Optional product node property that defined whether the product node should be considered a Gift Card product, in which case it triggers the automatic generation of a Gift Card in the backoffice and emails it directly to the customer on checkout.
productSource
ContentPicker
Optional product node property allowing you to link a product to another product outside of it's hierarchy to be used as it's source of product information.
Transactional updates using the Unit of Work pattern in Umbraco Commerce.
When working with Umbraco Commerce's API it is important that data integrity is maintained should any errors occur. In order to achieve this Umbraco Commerce uses the Unit of Work pattern to effectively create a transaction that wraps around sections of your code ensuring that all Umbraco Commerce write operations that occur within that code block must succeed and be persisted in their entirety, otherwise, none of them should, and the database should rollback to its state prior to when those changes were made.
Creating a unit of work will require access to Umbraco Commerce's IUnitOfWorkProvider
which can be injected into your Controller directly, or can also be accessed via the UoW
property on the IUmbraco CommerceApi
helper.
Once you have access to either of these entry points, you can define a Unit of Work as follows
The anatomy of a Unit of Work is an Execute
method call on the IUnitOfWorkProvider
instance which accepts a delegate function with a uow
argument. Inside the delegate, we perform our tasks and confirm the Unit of Work as complete by calling uow.Complete()
. If we fail to call uow.Complete()
either due to forgetting to add the uow.Complete()
call or due to an exception in our code, then any write operations that occur within that code block will not be persisted in the database.
When using a Unit of Work it is best practice that you should perform all write operations inside a single Unit of Work and not create individual Units of Work per write operation.
Perform all write operations in a single Unit of Work
It is not recommended to create a Unit of Work per write operation.
Identifying the source of taxation of an Order within Umbraco Commerce.
A Tax Source identifies which geographic location an Order should use in order to calculate its tax liability. Depending on the country that the web store is operating in and the country, an order is being purchased from/shipping to, this can dictate how your taxes should be calculated.
To aid with this Umbraco Commerce allows the Tax Source of a Store to be configured via the implementation of a Tax Source Factory. The Tax Source Factory is responsible for determining the source of Tax given the billing and shipping country of an Order.
Out of the box, Umbraco Commerce comes with two Tax Source Factory implementations:
DestinationTaxSourceFactory - (Default) Sets the Tax Source as being the destination country where an Order will be shipped to.
OriginTaxSourceFactory - Sets the Tax Source as being the origin country where an Order was billed to.
Tax Source Factories are registered via the IUmbracoCommerceBuilder interface using the AddUnique<ITaxSourceFactory, TReplacementTaxSourceFactory>()
method on the Services
property where the TReplacementTaxSourceFactory
parameter is the type of your replacement Tax Source Factory implementation.
Step-by-Step Tutorials on getting started with Umbraco Commerce.
In this section, we will provide a series of follow-along tutorials on how to implement Umbraco Commerce. These will be aimed at getting you set up and running without going into heavy theoretical details. Once you are familiar with working with Umbraco Commerce, you can use the other sections of the documentation to gain a more in-depth knowledge of the different things you'll have implemented.
Order and Order Line metadata in Umbraco Commerce.
There is little information that Umbraco Commerce needs to know about a product in order for it to do its job. There are, however, times when developers require the ability to store additional information against an Order or Order Line. This could be the billing/shipping address of an Order, or any specific configuration details of a given Product on an Order Line.
To help facilitate this Umbraco Commerce has the concept of a Properties collection on both the Order entity and the Order Line entity respectively. The Properties collection of these entities can be thought of as a general store for additional information required by an implementation, but not strictly required by Umbraco Commerce itself.
Anything you need to remember about an Order / Order Line can be stored in its Properties collection.
To set a Property on an Order or Order Line, it needs to be in its Writable state. Then it's a case of calling one of the related property setting methods:
Property values can either be a string
, or a Umbraco Commerce PropertyValue
which allows you to define a value as being Server Side Only. This means that it won't be returned via non-server APIs or Read Only meaning it can't be updated once set.
On occasions where Umbraco Commerce needs to capture some information about an Order or Order Line, it uses the Properties collection to store this information. It's useful to know what these properties are as you should avoid using these system-related property keys.
email
The email address of the person placing the order. Is where order.CustomerInfo.Email
reads it's value from.
firstName
The first name of the person placing the order. Is where order.CustomerInfo.FirstName
reads it's value from.
lastName
The last name of the person placing the order. Is where order.CustomerInfo.LastName
reads it's value from.
sku
Umbraco Commerce has a built-in mechanism that can be configured to automatically copy properties from a Product information source to the Order Line automatically. This is done by using the Product Property Aliases field on the Store settings screen.
When a Product is added to the Order containing a comma-separated list of property aliases, the property values are automatically copied to the Order Lines Properties collection.
This is useful for occasions such as rendering out the Order Lines on a Cart page and you have Product information you want to display. By copying it to the Order Lines Properties collection, you have instant access to those properties without the need to re-fetch the original Product entity.
Another use of the Properties collection for an Order Line is that of identifying product "Uniqueness".
Umbraco Commerce uses Product Uniqueness to identify either of the two:
Whether a Product is added to a Cart should be considered as a Quantity increase on an existing Order Line
Whether it should be considered as a unique product combination and so should be given an Order Line of its own.
A good example of this is when you have configurable products, such as customizable T-Shirt designs. In this case, each unique configuration should be considered as its own Order Line so that you can manage the specific configurations.
Product uniqueness is configured via the Product Uniqueness Property Aliases field on the Store setting screen.
When set to a comma-separated list of property aliases and a Product is added to an Order, the properties are compared against all pre-existing Order Lines for that Product. Should their values be different, then a unique Order Line will be created for that Product.
Strongly typed Settings objects in Umbraco Commerce.
There are places in Umbraco Commerce where you can use Settings Objects to pass configuration to a Provider, such as Discount Rule Providers, Reward Providers, and Payment Providers.
The settings objects have a number of responsibilities.
Typed Settings Model - The type represents a strongly typed settings model the given Provider accepts. Any stored settings in the database will be deserialized to this type before being passed to the Provider for processing. This provides strongly typed access to the relevant configuration settings.
UI Scaffold - The settings object defines metadata on its properties via an Attribute implementing UmbracoCommerceSettingAttribute
, each Provider type has its own attribute type in case they require additional config, for example DiscountRewardProviderSettingAttribute
, DiscountRuleProviderSettingAttribute
or PaymentProviderSettingAttribute
. The attributes are used to dynamically build the AngularJS-based UI for the given Provider configuration. See the UI Scaffolding section below for more information on UI Scaffolding.
JavaScript Settings Model - The settings object also defines the JavaScript settings model passed to the Provider editor UI, using either the settings Property name as the object property key, or using the key
property of the Setting Attribute declared on the given Property.
An important element of the Settings object is UI Scaffolding. UI Scaffolding is where Umbraco Commerce reads a series of Settings Attributes defined on your Settings object properties in order to dynamically build a User Interface for that Providers settings.
An example of a Discount Reward Settings Object might look something like this:
Attributes define a property key
, name
, description
to display in the UI as well as an optional view
and config
option to define the Umbraco property editor to use to edit the given property. If no view is defined, one will attempt to automatically be chosen based on the properties value type.
An example of a generated UI built from these properties would look something like this:
To define default values for a settings object, you can assign a value to a property in your model and Umbraco Commerce will automatically fall back to that value if no explicit value is defined.
Customizing the UI in Umbraco Commerce.
With Umbraco Commerce, there are minimal rules about what information you are required to record about an Order, however, this does pose a problem for how we provide a User Interface for managing carts and orders when we don't know exactly what properties you are going to be recording.
In order to allow this flexibility whilst still providing the ability to view and manage carts and orders in the backoffice, Umbraco Commerce supports a number of UI config files to map Order/Order Line Properties to its UI elements.
The configuration files supported by Umbraco Commerce are.
cart.list.config.json - Cart list view configuration.
cart.editor.config.json - Cart editor view configuration.
order.list.config.json - Order list view configuration.
order.editor.config.json - Order editor view configuration.
If there are no cart config files defined, then Umbraco Commerce will fall back to the order config files.
To assign a UI config file to a Store, this is done by file name convention. This is where configs are looked for in App_Plugins/UmbracoCommerce/config
with the following file name format {storeAlias}.{entityType}.{viewType}.config.json
. If no store-specific file is found, it will fallback into the default {entityType}.{viewType}.config.json
.
With these configuration files, you can customize the columns displayed in the Cart/Order list view.
The following properties are supported:
alias
The alias of the Order property to use
label
A label to display as the table column header
align
Sets the alignment of the column. Can be left
(default), center
or right
placeholder
The placeholder value to display if there is now Order property value
template
An angular template to use for rendering the property value. Defaults to {{ properties['alias'].value }}
Properties configured to display in the list view will appear in order, after the cart name column.
With these configuration files, you can customize the Cart/Order Editor interface to suit your particular needs.
An example of an Order Editor config file would look something like this:
The Cart/Order Editor config file is broken up into a series of sections, each of which relates to a particular section of the Cart/Order Editor User Interface.
The Order Line config block configures which Order Line properties should be viewable and/or manageable within the Cart/Order Editor UI. For each Order Line Property, you can provide the following options:
alias
The alias of the Order Line property
label
A friendly label to display for this property in the editor interface
description
A friendly description to display for this property in the editor interface
template
An angular template to use for rendering the property value. Defaults to {{ properties['alias'].value }}
isReadOnly
Sets the property as read only and so doesn't provide a means of editing the value in the editor interface (Default: false
)
showInOrderLineSummary
Sets whether to display this property in the Order Lines summary next to the SKU
in the Order editor interface (Default: true
)
view
Sets the name or path of a Property Editor to use when editing this property
config
Defines a JSON config for the Property Editor if required
Properties configured to display in the Order Line Summary will be displayed inline next to the "Order Lines SKU
" as follows:
Where there are editable Order Line Properties for an Order Line, a pencil icon is displayed next to the Order Lines Product name which when clicked will open out the Order Line Property editor interface for that Order Line.
The Customer config block configures which Cart/Order properties relate to a Cart/Orders customer information. The following properties are supported.
firstName
The customers first name. Uses the order.CustomerInfo.FirstName
system property
lastName
The customers last name. Uses the order.CustomerInfo.LastName
system property
email
The customers email address. Uses the order.CustomerInfo.Email
system property
company
The company the customer works for
taxCode
The tax code of the company the customer works for
telephone
The contact telephone number of the customer
Any missing property definition in this config block will disable that property from displaying/being editable.
For each property, the following config options are available:
alias
The alias of the Order property to use
label
A friendly label to display for this property in the editor interface
description
A friendly description to display for this property in the editor interface
view
Sets the name or path of a Property Editor to use when editing this property
config
Defines a JSON config for the Property Editor if required
A fully configured Customer config block will produce a Customer summary like so:
Clicking the Customer Details Edit
button will display an editing interface like so:
The Billing config block configures which Cart/Order properties relate to a Cart/Orders billing information. The following properties are supported.
addressLine1
Line 1 of the billing address
addressLine2
Line 2 of the billing address
city
The City of the billing address
zipCode
The Zip/Postal Code of the billing address
telephone
The telephone number of the billing address
In addition to these properties, the order.PaymentInfo
Country/Region will be associated with the billing address.
Any missing property definition in this config block will disable that property from displaying/being editable.
For each property, the following config options are available:
alias
The alias of the Order property to use
label
A friendly label to display for this property in the editor interface
description
A friendly description to display for this property in the editor interface
view
Sets the name or path of a Property Editor to use when editing this property
config
Defines a JSON config for the Property Editor if required
A fully configured Billing config block will produce a Billing Address summary like so:
Clicking the Customer Details Edit
button will display an editing interface like so:
The Shipping config block configures which Cart/Order properties relate to a Cart/Orders shipping information. The following properties are supported.
enabled
Sets whether the collection of shipping information is enabled or not. If set to false
not shipping info will be displayed (Default: true
)
sameAsBilling
Determines the Order property to use as a flag to indicate the shipping address is the same as the billing address
firstName
The first name of the shipping contact
lastName
The last name of the shipping contact
addressLine1
Line 1 of the shipping address
addressLine2
Line 2 of the shipping address
city
The City of the shipping address
zipCode
The Zip/Postal Code of the shipping address
telephone
The telephone number of the shipping address
In addition to these properties, the order.ShippingInfo
Country/Region will be associated with the shipping address.
Any missing property definition in this config block will disable that property from displaying/being editable.
For each property, except enabled
or sameAsBilling
, the following config options are available:
alias
The alias of the Order property to use
label
A friendly label to display for this property in the editor interface
description
A friendly description to display for this property in the editor interface
view
Sets the name or path of a Property Editor to use when editing this property
config
Defines a JSON config for the Property Editor if required
For the sameAsBilling
property, the following config options are available:
alias
The alias of the Order property to use
label
A friendly label to display next to a toggle switch for this property in the editor interface
trueValue
The value to expect for a true
value
falseValue
The value to expect for a false
value
A fully configured Shipping config block, where the sameAsBilling
property is false
, will produce a Shipping Address summary like so:
Where as, a fully configured Shipping config block, where the sameAsBilling
property is true
, will produce a Shipping Address summary like so:
Clicking the Customer Details Edit
button will display an editing interface like so:
If the sameAsBilling
toggle switch is toggled, the appropriate Cart/Order property will be toggled between the configured Properties true/false values, and the editor interface will be collapsed like so:
The Notes config block configures which Cart/Order properties relate to a Cart/Orders note information. The following properties are supported.
customerNotes
The property to use for customer provided notes
internalNotes
The property to use to store internal notes that shouldn't be sent to the customer
Any missing property definition in this config block will disable that property from displaying/being editable.
For each property the following config options are available:
alias
The alias of the Order property to use
label
A friendly label to display for this property in the editor interface
description
A friendly description to display for this property in the editor interface
A fully configured Notes config block will produce an editor interface like so:
The Additional Info config block configures any other Cart/Order properties you wish to display in the Cart/Order editor interface in the Additional Info section. For each Order Property to display you can provide the following options:
alias
The alias of the Order property
label
A friendly label to display for this property in the editor interface
description
A friendly description to display for this property in the editor interface
template
An angular template to use for rendering the property value. Defaults to {{ properties['alias'].value }}
isReadOnly
Sets the property as read only and so doesn't provide a means of editing the value in the editor interface (Default: false
)
view
Sets the name or path of a Property Editor to use when editing this property
config
Defines a JSON config for the Property Editor if required
A fully configured Additional Info config block will produce an Additional Info summary interface like so:
Clicking the Additional Info Edit
button will display an editing interface like so:
If you wish to entirely replace the Cart/Order Editor view with a custom implementation you can create a Cart/Order Editor Config file with a single view
config option which points to the path of an alternative AngularJS view file to use for editing the Order.
Creating complex variants with Umbraco Commerce.
The Commerce Complex Variants feature is powered by a new Variants Editor property editor that you can attach to your product content nodes. The editor itself is based on the Umbraco Block List editor format so under the hood we make use of the new data structure.
We also make use of Umbraco’s block editor APIs. You can add supporting data needed to record against your variants simply by defining a document type and linking it with the editor. By basing the editor on the block editor data structure, we can take advantage of improvements made in Umbraco Commerce. An example is optimized persistence/searching.
The Variants Editor isn’t just a regular property editor. Managing variant data is a complex task and having variants mingled in with the product content fields would be distracting. So a bit of Umbraco magic is used to allow the editor to render itself as a content app. By doing this it gives a focused tab on which to manage complex-variants and allows to create a much richer content management experience.
All you have to do is add the variants editor as a property on your product Document Type and Umbraco Commerce hooks up the rest.
Before you can go creating variants, there is another concept that you need to understand and that is product attributes.
Product attributes are essentially lists of options that can be used to create your variant combinations. For example, things like color, size, or fit if you were selling clothing.
Each product attribute consists of a name and a series of attribute values for the given options. So for example, color attribute might have a series of values like red, and blue, and size might have values of large, medium, and small.
In order to manage these product attributes, we’ve created a new Options node inside the Commerce section, beneath each store. From this section, you can define as many product attributes + values as you need. If you're working with a multi-lingual setup, you can provide label translations.
Linked with product attributes, there is also the concept of product attribute presets.
What product attribute presets do is allow to define groups of product attributes/values based on a specific theme. Then they are displayed at the point of product variant creation. This is where you can choose from a smaller, focused list of product attributes than if you were just presented with every possible option.
With the product attributes defined (and optional product attribute presets), and the variants editor defined (on product Document Type), you can start creating product variants.
With the product node open, you’ll now see the new Variants content app in the top right corner. From there you can click the Create Product Variants button to launch the create dialog.
From the create dialog, you’ll be presented with a list of product attributes so that you can select all the combinations you want to create variants. If you have setup any product attribute presets, these will be presented first.
Selecting a preset will show a smaller list of product attributes/values to choose from. To create the variants, check the checkbox against the attribute values and click Select. Then rows will be automatically created in the variants table for every combination of the selected attributes.
With variants defined in the variants table, you can manage the content for each variant by clicking the SKU of the row. Then it will launch the content editor for that variant. From here you’ll be presented with all the fields defined on your variants Document Type and can add and save the information required.
In the variants table view, we've also added filtering features so you can filter by attribute values. You can also search for specific variant SKUs to easily locate items. Additionally, the table also supports sorting on the table columns, so you can also order the results as you need.
You can change a variant attribute combination at any time by clicking the cog icon on the row. Then you can select a new combination. Lastly, you can remove a variant by clicking the trash can icon against the row.
Whilst you are free to add any fields you like to your variant, there are a few fields that you might want/need to add.
The only required field is an SKU field with the alias sku
. All the following fields are optional, with Umbraco Commerce falling back to the parent node if one isn’t found.
Price [price]
- The fixed price of the product variant. Should use a Commerce Price input field.
Price Adjustment [priceAdjustment]
- Used instead of a price field to create a dynamic price by adding the adjustment amount to the parent product price. Should use a Commerce Price input field and can contain negative values.
Stock [stock]
- Allows for individual variant stock management.
Once the variants are defined, you’ll then want to be able to access that data on the frontend. To do this the variants editor comes with a built-in value converter. This allows you to access a strongly typed collection of all the defined variants from the parent product node.
The property value will be of type ProductVariantCollection
that contains a series of ProductVariantItem
entities. Each of these entities has a Config property which contains details of the product attribute combination for the variant. It also contains a content property of type IPublishedElement from which you can access the variant's data. The Content property can also be cast to a models builder model type for strongly typed access to the variant content too.
Umbraco Commerce also ships with a helper extension method on the ProductVariantCollection
class, GetInUseProductAttributes(storeId).
This provides a convenient way to get a list of all attributes + values used by the variants collection. It comes in handy when rendering out the list of options on the front end, ensuring only attributes in use are displayed.
The last piece of the complex variants puzzle is a few updates to Umbraco Commerce's API.
This is largely around the AddProduct
methods on the Order entity which now have additional signatures. These signatures take both a productReference and a productVariantReference which must both be supplied when adding a variant item to an order.
Order lines have also been updated to expose a new Attribute property. This provides a collection of attribute combinations for the order lines product so that these can be rendered on carts and checkouts. The "uniqueness" logic for an order line has also been updated to take these attributes into account.
With both of these changes, updates have also been made to the IProductAdapter/IProductSnapshot
interfaces and built-in implementations. This is in order to support product variants and attributes, as it has the product and price freezer services.
The built-in stock property editor has also had a slight overhaul in order to support both regular products and product variants. If anyone needs to provide an alternative implementation, a new IStockService
interface has been created as well.
Explore the core services and methods in Umbraco Commerce, used for extending the product.
You can find all the reference documentation for Umbraco Commerce on GitHub. We might eventually move this to this or another site.
Learn more about the different options for configured Umbraco Commerce.
When it comes to configuring and extending Umbraco Commerce, such as by registering your own event handlers, we achieve this with the IUmbracoCommerceBuilder
interface that can be accessed via a delegate function passed into the AddUmbracoCommerce()
extension method called on the IUmbracoBuilder
interface when explicitly registering Umbraco Commerce.
The SKU
of the product, extracted from the product node via the .
The IUmbracoCommerceBuilder
interface gives you access to the current IServiceCollection
and IConfiguration
to allow you to register dependencies like you would with the but its primary use case would be to access Umbraco Commerce's own collection builders, such as for registering validation or notification events, and any other Umbraco Commerce-specific configuration APIs.
As per the , whilst you can register your dependencies directly within this configuration delegate, you may prefer to group your dependencies registration code into an extension method.
Faster development thanks to the Fluent API of Umbraco Commerce.
An added side effect of having ReadOnly and Writable entities is that all of an entity's write operations are now performed via methods. This is instead of property setters, enabling to us convert Umbraco Commerce's write API in a fluent API.
You could perform a write operation as follows:
This could be simplified further by defining these actions fluently, chaining all of the entity methods into a succinct command sequence as follows:
We know not everyone likes to write their code fluently and so the Umbraco Commerce Fluent API is an optional feature. Both code examples above are valid coding styles that will both work as well as each other. The Fluent API is an opt-in layer of syntax sugar that developers can use depending on their preferred style of coding.
Accepting payments via Payment Providers in Umbraco Commerce.
Payment Providers are how Umbraco Commerce is able to accept multiple different methods of payment on a Site. Their job is to provide a standard interface between third-party payment gateways and Umbraco Commerce itself. This is done in order to allow the passing of information between the two platforms.
How the integrations work is often different for each payment gateway. The Umbraco Commerce Payment Providers add a flexible interface that should be able to work with most payment gateways.
An example of a bare-bones Payment Provider would look something like this:
All Payment Providers inherit from a base class AsyncPaymentProviderBase<TSettings>
. TSettings
is the type of a Plan Old Class Object (POCO) model class representing the Payment Providers settings. The class must be decorated with PaymentProviderAttribute
which defines the Payment Providers alias
, name
and description
, and can also specify an icon
to be displayed in the Umbraco Commerce backoffice.
The settings class consists of a series of properties, each decorated with a PaymentProviderSettingAttribute
defining a name, description, and possible angular editor view file. These will all be used to dynamically build an editor interface for the given settings in the backoffice.
There are two main responsibilities of a Payment Provider, and those are:
Payment Capture - Capturing the initial Order payment and finalizing the Order.
Payment Management - Managing a payment post Order finalization, such as being able to Capture authorized payments or Refunding captured payments.
The Payment Capture workflow can be the hardest part of a Payment Provider. This is due to the fact that no two payment gateways are alike. Therefore it can be difficult to figure out how best to implement the gateway into the provider format.
Generally, there are three methods within a Payment Provider that you may need to implement, and each one has a specific responsibility.
GenerateForm - The GenerateForm
method is responsible for generating an HTML form that will redirect the customer to the given payment gateway payment form. In this method you may need to communicate with the payment gateway in order to initialize a payment, letting the payment gateway know how much to capture. This often results in some kind of code or redirect URL being returned which will need to be embedded into the generated form. The generated form is then usually displayed on a checkout Review page, the last page before payment is captured and will have an implementer-defined Continue to Payment button to submit the form and redirect the customer to the gateway.
ProcessCallback - The ProcessCallback
method is responsible for handling the response coming back from the payment gateway and processing whether the payment was successful or not. This can sometimes occur synchronously, if the payment gateway sends information back as part of the confirmation page redirect, or can occur asynchronously if the payment gateway sends the information back via an out-of-band webhook request.
GetOrderReference - The GetOrderReference
method is responsible for extracting an order reference number from a request when the payment gateway uses an asynchronous webhook to finalize an Order and it uses a global webhook URL strategy for all notifications rather than a notification URL per transaction. Where a webhook URL can be passed per transaction, then Umbraco Commerce provides you with a unique callback URL you can register with the gateway that already identifies the order reference as part of the URL parameters, making implementing this method unnecessary.
* denotes a required method implementation.
What follows is a generalized diagram in order to help in visualizing when each of these methods is called within a regular checkout flow.
In addition to the initial payment capture flow, Payment Providers can also be set up to manage the payment post-checkout. This could be Capturing Authorized transactions or Refunding Captured transactions.
These features are optional and not required for Payment Provider developers to implement. They allow store owners to manage payments directly in the backoffice rather than through the payment gateway's portal when performing these types of actions.
The implementable management methods are:
FetchPaymentStatus - The FetchPaymentStatus
method communicates with the 3rd party payment gateway in order to fetch the current status of the given transaction.
CapturePayment - The CapturePayment
method communicates with the 3rd party payment gateway to capture a previously authorized payment associated with the given transaction.
CancelPayment - The CancelPayment
method communicates with the 3rd party payment gateway to cancel a previously authorized payment associated with the given transaction.
RefundPayment - The RefundPayment
method communicates with the 3rd party payment gateway to refund a previously captured payment associated with the given transaction.
For each implemented method above, developers should also implement a corresponding boolean property returning a true
value. This is to let Umbraco Commerce know that the given feature is supported by the Payment Provider.
CanFetchPaymentStatus
CanCapturePayments
CanCancelPayments
CanRefundPayments
For all implemented methods of a Payment Provider, all method return types support the returning of additional Meta Data. This is to allow Payment Providers to capture and store relevant information. This information will aid the provider in doing its job, or for storing useful reference information to display for the retailer.
Any returned Meta Data from a Payment Provider method will be stored against the Order in its Properties collection. Should you need to retrieve these values from other areas of the Payment Provider, you can use the passed-in Orders Properties collection.
Meta Data is stored in Orders Properties collections. Prefix your Meta Data keys with the Payment Providers alias to prevent possible conflicts.
The Meta Data that is returned from the Payment Provider is useful for the retailer. The Payment Provider can also be used to display Meta Data descriptions and information in the backoffice. This is done by exposing a TransactionMetaDataDefinitions
property consisting of a list of TransactionMetaDataDefinition
values. Each of the values defines the alias
, name
and optional description
of a Meta Data entry.