Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 71 additions & 2 deletions 15/umbraco-commerce/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

* [Umbraco Commerce Documentation](README.md)
* [Release Notes](release-notes/README.md)
* [v14.0.0](release-notes/v14.0.0.md)
* [v14.0.0-Alpha](release-notes/v14.0.0-alpha.md)
* [v15.0.0-Rc](release-notes/v15.0.0-rc.md)

## Commerce Products

Expand All @@ -15,23 +14,93 @@

* [Requirements](getting-started/requirements.md)
* [Installation](getting-started/install.md)
* [Licensing](getting-started/the-licensing-model.md)
* [Configuration](getting-started/umbraco-configuration.md)
* [User Interface](getting-started/user-interface.md)

## Upgrading

* [Upgrading Umbraco Commerce](upgrading/upgrade.md)
* [Version Specific Upgrade Notes](upgrading/version-specific-upgrades.md)
* [Migrate from Vendr to Umbraco Commerce](upgrading/migrate-from-vendr-to-umbraco-commerce/README.md)
* [Migrate Umbraco Commerce Checkout](upgrading/migrate-from-vendr-to-umbraco-commerce/migrate-umbraco-commerce-checkout.md)
* [Migrate custom Payment Providers](upgrading/migrate-from-vendr-to-umbraco-commerce/migrate-custom-payment-providers.md)

## How-To Guides

* [Overview](how-to-guides/overview.md)
* [Configure SQLite support](how-to-guides/configure-sqlite-support.md)
* [Limit Order Line Quantity](how-to-guides/limit-orderline-quantity.md)
* [Use an Alternative Database for Umbraco Commerce Tables](how-to-guides/use-an-alternative-database-for-umbraco-commerce-tables.md)

## Key Concepts

* [Get to know the main features](key-concepts/overview.md)
* [Base Currency](key-concepts/base-currency.md)
* [Calculators](key-concepts/calculators.md)
* [Currency Exchange Rate Service Provider](key-concepts/currency-exchange-rate-service-providers.md)
* [Dependency Injection](key-concepts/dependency-injection.md)
* [Discount Rules / Rewards](key-concepts/discount-rules-and-rewards.md)
* [Events](key-concepts/events/README.md)
* [List of validation events](key-concepts/events/list-of-validation-events.md)
* [List of notification events](key-concepts/events/list-of-notification-events.md)
* [Fluent API](key-concepts/fluent-api.md)
* [Order Calculation State](key-concepts/order-calculation-state.md)
* [Payment Forms](key-concepts/payment-forms.md)
* [Payment Providers](key-concepts/payment-providers.md)
* [Pipelines](key-concepts/pipelines.md)
* [Price/Amount Adjustments](key-concepts/price-amount-adjustments.md)
* [Price Freezing](key-concepts/price-freezing.md)
* [Product Adapters](key-concepts/product-adapters.md)
* [Product Bundles](key-concepts/product-bundles.md)
* [Product Variants](key-concepts/product-variants/README.md)
* [Complex Variants](key-concepts/product-variants/complex-variants.md)
* [Properties](key-concepts/properties.md)
* [ReadOnly and Writable Entities](key-concepts/readonly-and-writable-entities.md)
* [Sales Tax Providers](key-concepts/sales-tax-providers.md)
* [Search Specifications](key-concepts/search-specifications.md)
* [Settings Objects](key-concepts/settings-objects.md)
* [Shipping Package Factories](key-concepts/shipping-package-factories.md)
* [Shipping Providers](key-concepts/shipping-providers.md)
* [Shipping Range/Rate Providers](key-concepts/shipping-range-and-rate-providers.md)
* [Tax Sources](key-concepts/tax-sources.md)
* [UI Extensions](key-concepts/ui-extensions/README.md)
* [Analytics Widgets](key-concepts/ui-extensions/analytics-widgets.md)
* [Entity Quick Actions](key-concepts/ui-extensions/entity-quick-actions.md)
* [Order Properties](key-concepts/ui-extensions/order-properties.md)
* [Order Collection Properties](key-concepts/ui-extensions/order-collection-properties.md)
* [Order Line Properties](key-concepts/ui-extensions/order-line-properties.md)
* [Store Menu Items](key-concepts/ui-extensions/store-menu-items.md)
* [Umbraco Properties](key-concepts/umbraco-properties.md)
* [Unit of Work](key-concepts/unit-of-work.md)
* [Umbraco Commerce Builder](key-concepts/umbraco-commerce-builder.md)
* [Webhooks](key-concepts/webhooks.md)

## Reference

* [Stores](reference/stores/README.md)
* [Shipping](reference/shipping/README.md)
* [Fixed Rate Shipping](reference/shipping/fixed-rate-shipping.md)
* [Dynamic Rate Shipping](reference/shipping/dynamic-rate-shipping.md)
* [Realtime Rate Shipping](reference/shipping/realtime-rate-shipping.md)
* [Taxes](reference/taxes/README.md)
* [Fixed Tax Rates](reference/taxes/fixed-tax-rates.md)
* [Calculated Tax Rates](reference/taxes/calculated-tax-rates.md)
* [Storefront API](reference/storefront-api/README.md)
* [Endpoints](reference/storefront-api/endpoints/README.md)
* [Order](reference/storefront-api/endpoints/order.md)
* [Checkout](reference/storefront-api/endpoints/checkout.md)
* [Product](reference/storefront-api/endpoints/product.md)
* [Customer](reference/storefront-api/endpoints/customer.md)
* [Store](reference/storefront-api/endpoints/store.md)
* [Currency](reference/storefront-api/endpoints/currency.md)
* [Country](reference/storefront-api/endpoints/country.md)
* [Payment method](reference/storefront-api/endpoints/payment-method.md)
* [Shipping method](reference/storefront-api/endpoints/shipping-method.md)
* [Content](reference/storefront-api/endpoints/content.md)
* [Management API](reference/management-api/README.md)
* [Go behind the scenes](reference/go-behind-the-scenes.md)
* [Telemetry](reference/telemetry/README.md)

## Tutorials

Expand Down
4 changes: 2 additions & 2 deletions 15/umbraco-commerce/getting-started/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Getting Started with Umbraco Commerce.

In this article, you will find the key steps needed to get started with Umbraco Commerce.

It is assumed that you have an Umbraco 14+ website configured and ready for the Umbraco Commerce installation.
It is assumed that you have an Umbraco 15+ website configured and ready for the Umbraco Commerce installation.

{% hint style="info" %}
For detailed instructions on installing the latest version of Umbraco, refer to the [Umbraco CMS documentation](https://docs.umbraco.com/umbraco-cms/fundamentals/setup/install).
Expand All @@ -16,7 +16,7 @@ For detailed instructions on installing the latest version of Umbraco, refer to

The minimum requirements for using Umbraco Commerce are:

* Umbraco CMS version 14+
* Umbraco CMS version 15+
* SQL Server 2015+ Database
* **SQLite** is acceptable for testing but not recommended for live deployments. For more details, see the [Configuring SQLite support](../how-to-guides/configure-sqlite-support.md) article.

Expand Down
6 changes: 5 additions & 1 deletion 15/umbraco-commerce/getting-started/the-licensing-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ Once you have received your license code it needs to be installed on your site.
```json
"Umbraco": {
"Licenses": {
"Umbraco.Commerce": "YOUR_LICENSE_KEY"
"Products": {
"Umbraco.Commerce": "YOUR_LICENSE_KEY"
}
}
}
```



### Verify the license installation

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 license dashboard which should display the status of your license.
Expand Down
8 changes: 4 additions & 4 deletions 15/umbraco-commerce/how-to-guides/limit-orderline-quantity.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ public class ProductAddValidationHandler : ValidationEventHandlerBase<ValidateOr
_productService = productService;
}

public override void Validate(ValidateOrderProductAdd evt)
public override async Task ValidateAsync(ValidateOrderProductAdd evt)
{
var order = evt.Order;
var productReference = evt.ProductReference;

var stock = _productService.GetProductStock(productReference);
var stock = await _productService.GetProductStockAsync(productReference);

var totalQuantities = order?.OrderLines.Where(x => x.ProductReference == productReference).Sum(x => x.Quantity) ?? 0;

Expand All @@ -53,12 +53,12 @@ public class OrderLineQuantityValidationHandler : ValidationEventHandlerBase<Val
_productService = productService;
}

public override void Validate(ValidateOrderLineQuantityChange evt)
public override async Task ValidateAsync(ValidateOrderLineQuantityChange evt)
{
var orderLine = evt.OrderLine;
var productReference = orderLine.ProductReference;

var stock = _productService.GetProductStock(productReference);
var stock = await _productService.GetProductStockAsync(productReference);

if (stock.HasValue && evt.Quantity.To > stock.Value)
evt.Fail($"Only {stock} quantities can be purchased for {productReference}.");
Expand Down
4 changes: 2 additions & 2 deletions 15/umbraco-commerce/key-concepts/calculators.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ public class MyProductCalculator : ProductCalculator
: base(taxService, storeService)
{ }

public override TaxRate CalculateProductTaxRate(IProductSnapshot productSnapshot, TaxSource taxSource, TaxRate fallbackTaxRate)
public override async Task<TaxRate> CalculateProductTaxRateAsync(IProductSnapshot productSnapshot, TaxSource taxSource, TaxRate fallbackTaxRate)
{
// Do custom tax rate calculation here
}

public override Price CalculateProductPrice(IProductSnapshot productSnapshot, Guid currencyId, TaxRate taxRate)
public override async Task<Price> CalculateProductPriceAsync(IProductSnapshot productSnapshot, Guid currencyId, TaxRate taxRate)
{
// Do custom price calculation here
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ An example of an Order Discount Rule Provider would look something like this:
[DiscountRuleProvider("myCustomOrderRule")]
public class MyCustomOrderRuleProvider : OrderDiscountRuleProviderBase<MyCustomOrderRuleProviderSettings>
{
public override DiscountRuleResult ValidateRule(DiscountRuleContext ctx, MyCustomOrderRuleProviderSettings settings)
public override async Task<DiscountRuleResult> ValidateRuleAsync(DiscountRuleContext ctx, MyCustomOrderRuleProviderSettings settings)
{
if (/* Some custom logic */)
return Fulfilled();
Expand Down Expand Up @@ -69,7 +69,7 @@ An example of an Order Line Discount Rule Provider would look something like thi
[DiscountRuleProvider("myCustomOrderLineRule")]
public class MyCustomOrderLineRuleProvider : OrderLineDiscountRuleProviderBase<MyCustomOrderLineRuleProviderSettings>
{
public override DiscountRuleResult ValidateRule(DiscountRuleContext ctx, MyCustomOrderLineRuleProviderSettings settings)
public override async Task<DiscountRuleResult> ValidateRuleAsync(DiscountRuleContext ctx, MyCustomOrderLineRuleProviderSettings settings)
{
if (/* Some custom logic */)
return Fulfilled(fulfilledOrderLines);
Expand Down Expand Up @@ -100,7 +100,7 @@ An example of a Discount Reward Provider would look something like this:
[DiscountRewardProvider("myDiscountReward")]
public class MyDiscountRewardProvider : DiscountRewardProviderBase<MyDiscountRewardProviderSettings>
{
public override DiscountRewardCalculation CalculateReward(DiscountRewardContext ctx, MyDiscountRewardProviderSettings settings)
public override async Task<DiscountRewardCalculation> CalculateRewardAsync(DiscountRewardContext ctx, MyDiscountRewardProviderSettings settings)
{
var result = new DiscountRewardCalculation();

Expand Down
20 changes: 10 additions & 10 deletions 15/umbraco-commerce/key-concepts/fluent-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ An added side effect of having [ReadOnly and Writable entities](readonly-and-wri
You could perform a write operation as follows:

```csharp
_uowProvider.Execute(uow =>
await _uowProvider.ExecuteAsync(async (uow) =>
{
// Fetch the currency
var currency = _currencyService.GetCurrency(currencyId);
var currency = await _currencyService.GetCurrencyAsync(currencyId);

// Convert the currency into it's Writable form
var writableCurrency = currency.AsWritable(uow);
var writableCurrency = await currency.AsWritableAsync(uow);

// Perform the write operation
writableCurrency.SetName("New Name");
await writableCurrency.SetNameAsync("New Name");

// Persist the changes to the database
_currencyService.SaveCurrency(currency);
await _currencyService.SaveCurrencyAsync(currency);

// Close the transaction
uow.Complete();
Expand All @@ -34,13 +34,13 @@ _uowProvider.Execute(uow =>
This could be simplified further by defining these actions fluently, chaining all of the entity methods into a succinct command sequence as follows:

```csharp
_uowProvider.Execute(uow =>
await _uowProvider.ExecuteAsync(async (uow) =>
{
var currency = _currencyService.GetCurrency(currencyId)
.AsWritable(uow)
.SetName("New Name");
var currency = await _currencyService.GetCurrencyAsync(currencyId)
.AsWritableAsync(uow)
.SetNameAsync("New Name");

_currencyService.SaveCurrency(currency);
await _currencyService.SaveCurrencyAsync(currency);

uow.Complete();
});
Expand Down
14 changes: 7 additions & 7 deletions 15/umbraco-commerce/key-concepts/payment-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ The Payment Capture workflow can be the hardest part of a Payment Provider. This

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.
* **GenerateFormAsync** - The `GenerateFormAsync` method generates 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 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 form appears on a checkout **Review** page before payment, featuring a **Continue to Payment** button to submit the form and redirect to the gateway.
* **ProcessCallbackAsync** - The `ProcessCallbackAsync` method handles the response coming back from the payment gateway and processing whether the payment was successful or not. This can occur _synchronously_, if the payment gateway sends information back during the confirmation page redirect. It can also occur _asynchronously_ if the payment gateway sends the information back via an out-of-band webhook request.
* **GetOrderReferenceAsync** - The `GetOrderReferenceAsync` method extracts an order reference number from a request when a payment gateway uses an asynchronous webhook to finalize an order. This method is specifically used where the payment gateway 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 a unique callback URL that identifies the order reference as part of the URL parameters. When using the per transaction URL provided, implementing this method becomes unnecessary.

_\* denotes a required method implementation_.

Expand All @@ -70,10 +70,10 @@ These features are optional and not required for Payment Provider developers to

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.
* **FetchPaymentStatusAsync** - The `FetchPaymentStatusAsync` method communicates with the 3rd party payment gateway in order to fetch the current status of the given transaction.
* **CapturePaymentAsync** - The `CapturePaymentAsync` method communicates with the 3rd party payment gateway to capture a previously authorized payment associated with the given transaction.
* **CancelPaymentAsync** - The `CancelPaymentAsync` method communicates with the 3rd party payment gateway to cancel a previously authorized payment associated with the given transaction.
* **RefundPaymentAsync** - The `RefundPaymentAsync` 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.

Expand Down
4 changes: 2 additions & 2 deletions 15/umbraco-commerce/key-concepts/pipelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ An example of a Pipeline task would look something like this:
```csharp
public class AddCustomAttachmentTask : PipelineTaskWithTypedArgsBase<EmailSendPipelineArgs, EmailContext>
{
public override PipelineResult<EmailContext> Execute(EmailSendPipelineArgs args)
public override Task<PipelineResult<EmailContext>> ExecuteAsync(EmailSendPipelineArgs args)
{
var attachment = new Attachment(File.OpenRead("path\to\license.lic"), "license.lic");

Expand All @@ -33,7 +33,7 @@ public class AddCustomAttachmentTask : PipelineTaskWithTypedArgsBase<EmailSendPi
}
```

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.
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 `ExecuteAsync` method that accepts an instance of the argument's type as input and expects a `Task<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.

All pipelines occur within a [Unit of Work](unit-of-work.md). In case a Pipeline task fails, the whole pipeline will fail and no changes will persist.

Expand Down
Loading
Loading