# Wednesday, 13 October 2010

The uCommerce Catalog Foundation holds all the catalog information in your installation and as such serves as the most important foundation in uCommerce. This post will give you an idea of one of the most basic building blocks of the Catalog Foundation: Product Definitions… but first some basics.

Products, Product Families, and Variants. Oh My!

Before we get into the nitty gritty of things we need to get the terminology right so we agree on what’s what.

Products are pretty straight forward they represent a single product in the system with no variants associated.

Product Families are pretty much the same as a product but differ in that they’ve got variants associated with them, hence the product family.

Variants represents a single product much like a stand alone product, but they cannot stand by themselves. Variants are always associated with a product family.

uCommerce supports both products and product families and the good news is you don’t have to go with one over the other. You simply decide on a per product basis whether or not to support variants. So you might have some products be stand alone products and others be product families. Whatever works for your scenario.

Product Definitions

Product Definitions 2Before you can start using catalogs you need to perform some setup to determine the data you’ll be working with, i.e. the taxonomy of your site, the various types of products you’ll support in the site, and finally your pricing scheme.

Product definitions are the most fundamental building blocks of the uCommerce Catalog Foundation. If you’re familiar with Umbraco think of them as Document Types for products. Basically a product definition determines what data you’re working with in uCommerce, both via the UIs and the APIs.

Each product definition in uCommerce represents a different type of product available through your store. Say you’re selling Software and Shirts as in the screenshot below. Software requires a completely different set of data to sell from a Shirt. Notice that Software has different properties from the Shirt.

With product definitions you can tailor uCommerce to your client’s needs.

Adding a New Product Definition

uCommerce supports as many product definitions as you need. Simply right click the Product Definitions node and click create to add a new definition. Each of the product definitions must be named uniquely so you can find it later on.

Adding New Properties to Product Definitions

You can add new properties by right clicking the product definition and clicking Create. Just as you would do when creating a new content node in Umbraco. As you can see the product definition needs a name which will be your key for reference the product definition from code as well the identifier for the product type.

The product family check box indicates whether the product definition allows variants or not. A product family is basically a product with a bunch variants associated with it while a non-product family (product) represent just a single product.

uCommerce Product Definition Create New Property

Once created you’ll have the opportunity to change the meta data of the property to suit your needs.

uCommerce Product Definitions Property Details 

Multilingual Properties

If you need to maintain the data of the property in multiple languages you can tick off the multilingual check box. This will give you a field per language configured in Umbraco.

uCommerce Multilingual Property Definition

If you specify a property to be multilingual the property will show up under the multilingual tabs when you go and edit products.

uCommerce Product Editor Multilingual Properties

Display on Website

A true/false value which is set on the property when accessed via the API.

uCommerce Display on Site Property Definition

Variant Properties

Determines whether the property should be a variant property that you maintain under a product family. If one or more exist the product will turn into a product family automatically and enable you to create multiple variants associated with the product family.

uCommerce Variant Property Definition

Setting the property as a variant property will add the Variants tabs to the editor to any product based on the product definition and will enable you to create variations of a product as part of a product family.

uCommerce Variant Editor

Render in Editor

Sometimes you need data that you don’t want the user to edit. Ticking this check box will tell uCommerce not to render this property as part of the editor UI essentially giving you meta data that you can use and maintain from the API without having to worry about the user tampering with it.

uCommerce Render in Editor Property Definition

Data Types

Each of the properties created in the previous paragraphs are based on data types, which you select when you create new ones. uCommerce comes with a number of built-in data types such as ShortText, LongText, Number, Boolean, Enum, and Image.

uCommerce DataType Property Definition 

Data types include string, number, bool, and enum which is a special type which enables you to predefine a list of values allowed for the user to select, e.g. colors, sizes, basically data with a finite number of options to choose from.

uCommerce Data Type Editor

Validation Expressions

Data types can have validation expressions associated with them to validate user input when editing in the product editor. A validation expression is a standard regular expression evaluated whenever a user clicks the save button.

uCommerce Data Type Validation Expression

In Conclusion

The Product Definition is the secret sauce which makes the uCommerce Catalog Foundation extremely powerful enabling you to model the reality you face be it as a developer creating an e-commerce solution for a client or for yourself.

An important aspect about a product definition is that you can change your mind whenever you please. If you start out without variants nothing is holding you back from moving your properties around even after you start creating products based on that product definition. uCommerce will simply reflect the changes you need without you having to create you products from scratch.

posted on Wednesday, 13 October 2010 21:17:46 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Thursday, 02 September 2010

When working in the uCommerce Admin tool it can be useful to be able to add your own custom nodes some in the trees, e.g. a new node under Product Catalog, Orders, Analytics, or Settings. This post describes how to achieve this.

The uCommerce tree handlers are using the standard Umbraco extension point for creating new trees. You can learn more about that in the excellent Umbraco.tv episode Adding a Custom tree.

uCommerce-UI-extension-1-New-Node

Finding the Extension Point

uCommerce comes with a bunch of tree handlers for managing all aspects of the uCommerce Foundations. Each tree handler deals with a separate root node in the uCommerce tree so depending on which tree you want to insert your custom node in you’ll need a different tree handler.

The tree handlers are called Load<whatever> where the whatever is the actual tree that it’s dealing with. All handlers are found in the assembly called UCommerce.Umbraco.dll which contains the integration pieces for Umbraco.

Handlers include:

Product Catalog tree – UCommerce.Umbraco.Menu.LoadCatalog
Orders tree– UCommerce.Umbraco.Menu.LoadOrders
Analytics tree– UCommerce.Umbraco.Menu.LoadAnalytics
Settingstree – UCommerce.Umbraco.Menu.LoadSettings

 

uCommerce-UI-extension-2-Tree-Handlers

Overriding the Default uCommerce Tree Handler

When you’ve found the handler you want to extend you need to  derive from the uCommerce class. In my case I’m extending the Product Catalog handler so I will derive from the LoadCatalog class.

To add your own node your need to override the method called Render(XmlTree tree) on the tree handler. This method is responsible for actually rendering the tree and will be triggered by Umbraco once configured to do so later on.

Please note that Umbraco isn’t exactly forthcoming with error messages which crop up during development of a tree handler so you’ll have to whip out the Sherlock Holmes thinking cap to find some of the issues which crop up. Especially Javascript for your Action will cause you grief.

public class MyCustomTreeHandler : LoadCatalog
{
    // Constructor is required by base type
    public MyCustomTreeHandler(string application) : base(application)
    {   
    }
 
    public override void Render(ref umbraco.cms.presentation.Trees.XmlTree tree)
    {
        base.Render(ref tree);
 
        XmlTreeNode node = XmlTreeNode.Create(this);
 
        string nodeId = "MyCustomNode";
        // Unique id of the node, can be used to store information about a data object being displayed on a particular node
        node.NodeID = nodeId;
 
        // Text to display on the node itself
        node.Text = "My Custom Node";
 
        // Action trigged by mouse click
        node.Action = string.Format("javascript:{0}", "parent.right.document.location.href = '~/MyPage.htm';"); 
 
        node.Icon = "folder.png";
        node.OpenIcon = "folder.png";
 
        // The node type refers to a config file with Umbraco
        // which specifies additional config for a particular node
        // like dialogs and available right click actions
        // ~/umbraco/config/create/UI.xml
        node.NodeType = "my_custom_node_type";
 
        // Available right click actions as per UI.xml
        node.Menu = new List<IAction>(new IAction[] { ActionNew.Instance, ContextMenuSeperator.Instance, ActionDelete.Instance, ContextMenuSeperator.Instance, ActionRefresh.Instance });
 
        // Indicates whether the nodes is expandable
        node.HasChildren = false;
 
        // Source is used to perform async calls
        // uCommerce provides an abstraction which works for both Umbraco 4 and 4.5
        // Notice that the nodeId is reused for this call
        node.Source = GetVersionSafeTreeServiceUrl(nodeId);
 
        tree.Add(node);
    }
}

With the following code the node shows up in the tree. Interestingly the custom node turns up as a subnode to every single node in the catalog system, which isn’t what we’re after. We’d like to be able to insert a node anywhere in the tree, but just that one time.

Read on to find out what’s going in.

Determining Where You are in the uCommerce Tree

uCommerce trees are different from Umbraco trees in the sense that a single tree works with many different types of nodes. For example a catalog consists of product catalog groups (the store level), catalogs, and categories. To help you figure out where you are there are two properties you can ask: CurrentId and CatalogNodeType.

When uCommerce builds its tree ids are consistently built up in the format catalogNodeTypeName_ObjectId. This helps uCommerce determine which internal type we’re working with, e.g. a catalog group, a catalog, or a category, and which data object is currently in play.

To insert our node in a specific location we can ask CatalogNodeType what the type of the node currently being rendered is thus enabling us to only insert the custom node in a specific location in the tree.

For my example I’m inserting the node on the same level as the product catalog groups by inserting the following piece of code in the Render method of the tree handler:

public override void Render(ref umbraco.cms.presentation.Trees.XmlTree tree)
{
    base.Render(ref tree);
    
    if (CurrentNodeType != CatalogNodeType.Root) return;
    
    ...
}

Enabling Child Nodes for a Custom Node

Should you need child nodes for your new node that’s absolutely possible as well. Some additional plumbing is needed to determine which nodes to load for a particular super node.

This is where the Node.Source property comes into play. You’ll have seen it configured on our custom node already like so node.Source = GetVersionSafeTreeServiceUrl(nodeId);.

Basically Umbraco loads child nodes on the fly by requesting a back end URL which is called TreeDataService.ashx. Among the parameters passed to this handler is the nodeKey which tells you the sub tree being requested.

uCommerce-UI-extension-5-Tree-Data-Service

To make sure that we only generate child nodes for our MyCustomNode a check to determine which node is being requested is required as a single handler does all the work for the entire tree. For that to work we have to refactor our code a bit to support the sub nodes.

The Render method is still our main entry point from Umbraco so it has to act as an check point which will determine what needs to be rendered.

public override void Render(ref umbraco.cms.presentation.Trees.XmlTree tree)
{
    // Make sure to only render the default nodes at the root
    // and not under our custom node
    if (NodeKey != "MyCustomNode")
        base.Render(ref tree);
 
    XmlTreeNode node = null;
 
    // If the NodeKey passed by Umbraco is our custom id
    // we know that we need to render subnodes for our
    // custom node
    if (NodeKey == "MyCustomNode")
    {
        node = XmlTreeNode.Create(this);
        node.NodeID = "MyCustomSubnode";
        node.Text = "My Custom Subnode";
        node.Action = string.Format("javascript:{0}", "parent.right.document.location.href = '~/MySubPage.htm';");
        node.Icon = "folder.png";
        node.OpenIcon = "folder.png";
        node.NodeType = "my_custom_node_type";
        node.HasChildren = false;
    }
    // If we're at the root of the catalog
    // we render the custom node
    else if (CurrentNodeType == CatalogNodeType.Root)
    {
        node = RenderMyCustomNode();
    }
    else return;
 
    // Add the rendered content to the tree
    tree.Add(node);
}

Final Code

Final code with support for a custom node under Product Catalog and child nodes for that looks like this:

using System;
using System.Collections.Generic;
using UCommerce.Umbraco.Menu;
using umbraco.cms.presentation.Trees;
using umbraco.interfaces;
using umbraco.BusinessLogic.Actions;
 
namespace MyUCommerceApp.Umbraco
{
    public class MyCustomTreeHandler : LoadCatalog
    {
        // Constructor is required by base type
        public MyCustomTreeHandler(string application)
            : base(application)
        {
        }
 
        public override void Render(ref umbraco.cms.presentation.Trees.XmlTree tree)
        {
            // Make sure to only render the default nodes at the root
            // and not under our custom node
            if (NodeKey != "MyCustomNode")
                base.Render(ref tree);
 
            XmlTreeNode node = null;
 
            // If the NodeKey passed by Umbraco is our custom id
            // we know that we need to render subnodes for our
            // custom node
            if (NodeKey == "MyCustomNode")
            {
                node = XmlTreeNode.Create(this);
                node.NodeID = "MyCustomSubnode";
                node.Text = "My Custom Subnode";
                node.Action = string.Format("javascript:{0}", "parent.right.document.location.href = '~/MySubPage.htm';");
                node.Icon = "folder.png";
                node.OpenIcon = "folder.png";
                node.NodeType = "my_custom_node_type";
                node.HasChildren = false;
            }
            // If we're at the root of the catalog
            // we render the custom node
            else if (CurrentNodeType == CatalogNodeType.Root)
            {
                node = RenderMyCustomNode();
            }
 
            else return;
 
            tree.Add(node);
        }
 
        public XmlTreeNode RenderMyCustomNode()
        {
            XmlTreeNode node = XmlTreeNode.Create(this);
 
            string nodeId = "MyCustomNode";
 
            // Unique id of the node, can be used to store information about a data object being displayed on a particular node
            node.NodeID = nodeId;
 
            // Text to display on the node itself
            node.Text = "My Custom Node";
 
            // Action trigged by mouse click
            node.Action = string.Format("javascript:{0}", "parent.right.document.location.href = '~/MyPage.htm';");
 
            // Images are picked up from ~/umbraco/images/umbraco
            node.Icon = "folder.png";
            node.OpenIcon = "folder.png";
 
            // The node type refers to a config file with Umbraco
            // which specifies additional config for a particular node
            // like dialogs and available right click actions
            // ~/umbraco/config/create/UI.xml
            node.NodeType = "my_custom_node_type";
 
            // Available right click actions as per UI.xml
            node.Menu = new List<IAction>(new IAction[] { ActionNew.Instance, ContextMenuSeperator.Instance, ActionDelete.Instance, ContextMenuSeperator.Instance, ActionRefresh.Instance });
 
            // Indicates whether the nodes is expandable
            node.HasChildren = true;
 
            // Source is used to perform async calls to load children of the node
            // uCommerce provides an abstraction which works for both Umbraco 4 and 4.5
            // Notice that the nodeId is reused for this call
            node.Source = GetVersionSafeTreeServiceUrl(nodeId);
            return node;
        }
    }
}

Configuring Your Custom Tree Handler with Umbraco

To replace the uCommerce tree handler with your own you need to open up the Umbraco database and look for the table called umbracoAppTree.

This table specifies the piece of code which builds a given tree and which app it’s associated with. The default uCommerce config will some like this:

uCommerce-UI-extension-3-Configure-Tree-Handler-with-Umbraco

The fields in question are called treeHandlerAssembly and treeHandlerType, which contains the name of the DLL which contains your new class and the name of the class which will handle the tree.

With the custom tree handler in place the configuration will now look like this:

uCommerce-UI-extension-4-Configure-Tree-Handler-with-Umbraco

In Summary

You can hook into almost any aspect of the uCommerce Admin to replace or extended the existing UIs thanks to the flexibility of Umbraco and the custom extensions built on top.

Working with the uCommerce trees is much the same process as the default Umbraco approach although you will have to deal with different types of nodes in a single tree.

With this extension in place you’re free to load your own webform and do whatever you want with it.

posted on Thursday, 02 September 2010 12:29:45 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Friday, 27 August 2010

uCommerce holds rich information about each product in the system with the ability to customize the product schema to customer needs. This flexibility comes at a cost though as the database schema to hold both the product information and the meta information can be quite difficult to grok.

This posts highlights the tables used for both the products and variants themselves.

Product schema

Product table
Product and the variants for a given product. Variants are associated with the product family by using the ParentProductId found in the table. Products (without variants) and product families (with variants) will have a null values in the ParentProductId column, which can be useful for querying the system.

ProductProperty table
Invariant product properties are stored in this table meaning any property not configured as Multi lingual in the uCommerce backend.

Invariant product properties

 

ProductDescription and ProductDescriptionProperty tables

Whenever multi lingual properties come into play this table stores the header for each language. Say you configure Umbraco to support English and German two rows will be inserted per product to store display name, short- and long description, but more importantly this table acts as the main hub for additional multilingual properties on a product.

Each multilingual property value stored for a product is stored in the ProductDescriptionProperty table as such is very similar to the ProductProperty table described above.

Multilingual product properties


PriceGroupPrice table

Each product in uCommerce may hold multiple prices which are stored in PriceGroupPrice. The convoluted name is an indication of the link to a price group. Prices are stored the same way regardless of product and variants due to the fact that essentially a product and variant is the same thing, ParentProductId notwithstanding.

PriceGroup table

Usually you’ll configure the price groups you need in uCommerce Admin, but you still have to link up new prices with a price group to be able to add a new price for a product, either via .NET or SQL.

uCommerce price groups UI

In conclusion the uCommerce product schema holds all your custom data and can be populated from external sources either via .NET code or SQL directly to the tables. Regardless of the approach you select the schema is important to know even from a .NET perspective because the uCommerce entities reflect the data schema closely to make the disconnect between the data models as tiny as possible.

posted on Friday, 27 August 2010 07:44:13 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Friday, 28 May 2010

One of the questions I’ve come across a couple of times with uCommerce is using the LINQ API to query products by custom properties added to a product definition.

Here’s how:

var q = from product in Product.All()
  where product.ProductProperties.Where(property => 
    (property.ProductDefinitionField.Name == "MyProperty" && property.Value == "MyPropertyValue") 
    || (property.ProductDefinitionField.Name == "MyOtherProperty" && property.Value == "MyotherPropertyValue")).Count() == 2
    && product.ParentProductId == null
  select product;
posted on Friday, 28 May 2010 15:07:28 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Tuesday, 25 May 2010

One thing you might want to do before putting a new uCommerce solution into a production environment is remove any test baskets and orders you might have placed during development. The schema gets a little complicated with the rich functionality found in the uCommerce Transaction Foundation requiring the objects to be removed in a certain order.

image

Here’s how you go about deleting them.

*** WARNING! HERE BE DRAGONS! ***

Please be aware that running the following script will remove any baskets and orders found in the system with no way to get them back unless you have a database backup handy.

--DELETE PURCHASEORDERS AND ASSOCIATED DATA
BEGIN TRAN
 
-- Delete reviews
DELETE FROM uCommerce_ProductReviewComment
DELETE FROM uCommerce_ProductReview
 
-- Delete discounts
DELETE FROM uCommerce_OrderLineDiscountRelation
DELETE FROM uCommerce_Discount
 
-- Remove shipment <-> order line link
UPDATE uCommerce_OrderLine SET ShipmentId = NULL
 
UPDATE uCommerce_PurchaseOrder SET BillingAddressId = NULL
DELETE FROM uCommerce_Shipment
DELETE FROM uCommerce_OrderAddress
DELETE FROM uCommerce_OrderProperty
DELETE FROM uCommerce_OrderLine
DELETE FROM uCommerce_PaymentProperty
DELETE FROM uCommerce_Payment
DELETE FROM uCommerce_OrderStatusAudit
DELETE FROM uCommerce_PurchaseOrder
DELETE FROM uCommerce_Address
DELETE FROM uCommerce_Customer
--COMMIT

As an added precaution I uncommented the commit statement in case you were wondering why the data isn’t being deleted :)

This post was written for uCommerce 2.0.0.0 (schema version 50).

posted on Tuesday, 25 May 2010 22:55:00 (Romance Daylight Time, UTC+02:00)  #    Comments [2] Trackback
# Wednesday, 19 May 2010

You will learn how to create a Payment Method Service, which integrates uCommerce with an online payment processer such as Sage, DIBS, PayPal, Cyber Source, or another processor used during checkout. This information is based onuCommerce 1.0.3.x and 1.0.3.2.

Create Visual Studio Project

Create a new Visual Studio solution and choose Class Library for your project type.

 Project structure - File Explorer

 

Add References to Your Project

uCommerce.dll

uCommerce.Infrastructure.dll

Subsonic.Core.dll

VS add reference select UC assemblies

Import Namespaces

Import the UCommerce.Transactions.Payment and UCommerce.Entities namespaces in you class file

Import namespaces

Implement interface IPaymentMethodService on your class

The IPaymentMethodService interface gives you full control over the behavior of the service. Alternatively you can inherit from AbstractPaymentService, which gives a default implementation for ProcessPaymentRequest, which will give you a properly initialized Payment.

Implement interface 

Implement interface 2

Implement Name property

The name property is used to uniquely identify your Payment Method Service. It is read from configuration and set on your service at runtime.

public class MyPaymentService : IPaymentMethodService
{
    public string Name { get; set; }    
}

Implement RequestPayment(PaymentRequest)

RequestPayment can be used in one of two ways: 1) Either to redirect the customer to the remote server handling payment information there, e.g. credit card information, or 2) to simply send payment information received on your server directly to the provider.

1)

public Payment RequestPayment(PaymentRequest request) 
{ 
    // Package up information for the backend service, 
    // in the form of a http request 
    // Redirect customer to backend service with 
    // the needed information 
    // Payment would be set pending authorization status (the status will have to be added to the uCommerce_PaymentStatus table) 
}

2)

public Payment RequestPayment(PaymentRequest request)
{
    // Processing is happening synchronously so we just
    // call the backend service with ProcessPaymentRequest
    return ProcessPaymentRequest(request);
}

Implement ProcessPaymentRequest(PaymentRequest)

ProcessPaymentRequest is used to handle any processing before or callbacks from the remote server in the case of a payment processing being handled exclusively by a remote party.

1) In the case of a callback scenario you use ProcessPaymentRequest to handle the callback and do any needed processing like updating order status. To receive the callback an endpoint needs to be exposed to the remote party such an http handler or a module. The handler or module will call ProcessPaymentRequest to complete the payment.

public Payment ProcessPaymentRequest(PaymentRequest request)
{
// Update payment according to received status from remote 
// party, e.g. Accepted, Declined
 
// Grab any transaction ids and put them on the payment before 
// returning the Payment
}

2) For a synchronous scenario ProcessPaymentRequest would be used to perform the query to the backing system and create a new Payment according to the result received.

public Payment RequestPayment(PaymentRequest request) 
{ 
    // Package up information for the backend service, 
    // in the form of a http request 
    // Redirect customer to backend service with 
    // the needed information 
    // Payment would be set pending authorization status 
}

Implement AcquirePayment(Payment)

For legal reason you sually can’t withdraw money from the customer until you actually ship their order. AcquirePayment is ment for this very scenario where you first authorize the payment and later withdraw from their account.

AcquirePayment(Payment) is used for capturing the payment from the customer.

public Payment ProcessPaymentRequest(PaymentRequest request)
{
    // Send request to remote party
 
    // Update payment according to received status from remote 
    // party, e.g. Accepted, Declined
 
    // Grab any transaction ids and put them on the payment before 
    // returning the Payment
}

Implement CancelPayment(Payment)

If you wish to cancel af payment with your payment method service you need to implement CancelPayment, and have it reach out the remote payment processor. Typical scenarios for cancelling a payment includes a customer return, cancelled order and typically requires you to handle two scenarios: Payment authorized but not capture and payment authorized and captured.

public Payment CancelPayment(Payment payment)
{
    // Update payment according to received status from remote 
    // party, e.g. Cancelled
 
    // Grab any transaction ids and put them on the payment before 
    // returning the Payment
}

Implement CalculatePaymentFee(PaymentRequest)

If applicable, used for calculating the fee associated with the payment method.

public virtual Money CalculatePaymentFee(PaymentRequest request)
{
    var order = request.PurchaseOrder;
    var paymentMethod = request.PaymentMethod;
 
    var fee = paymentMethod.GetFeeForCurrency(order.BillingCurrency);
 
    if (!order.SubTotal.HasValue)
        return new Money(0, 
new CultureInfo(Globalization.CultureCode), order.BillingCurrency);
 
    return new Money(order.SubTotal.Value 
        * (paymentMethod.FeePercent / 100) 
        + fee.Fee, 
new CultureInfo(Globalization.CultureCode), order.BillingCurrency);
}

Optionally Implement IPaymentFactory Interface on Your Provider

With uCommerce 1.0.3.2 the option for deferred payment requests was introduced meaning that you can create a payment placeholder for the choices made by a user and then later perform the actual payment request to the backend service.

If you need this functionality your PaymentMethodService should implement the interface IPaymentFactory (new for version 1.0.3.2), which will be used for creating the new Payment.

/// <summary>
/// Creates a new payment fully initialized
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public Payment CreatePayment(PaymentRequest request)
{
    PurchaseOrder order = request.PurchaseOrder;
 
    var payment = new Payment
    {
        TransactionId = Guid.NewGuid().ToString(),
        OrderId = order.OrderId,
        PaymentMethodName = GetPaymentName(request.PaymentMethod),
        Created = DateTime.Now,
        PaymentMethodId = request.PaymentMethod.PaymentMethodId,
        Fee = CalculatePaymentFee(request).Value,
        FeePercentage = request.PaymentMethod.FeePercent,
        PaymentStatusId = 1, // Status new
        Amount = request.Amount.Value
    };
 
    return payment;
}

Copy Your Assembly to Your Umbraco Site

Copy MyUCommerceApp.Library.dll to the /bin folder of your Umbraco site.

Add Your Payment Method Service to web.config

Configure your new Payment Method Service in web.config of your Umbraco site. In the <paymentMethodServices> element of you web.config add the following xml:

<add name="MyPaymentMethodService" type="MyUCommerceApp.Library.MyPaymentMethodService, MyUCommerceApp.Library" />

image 

Configure Payment Method to Use Your Service

Configure Payment Method to use your new service in uCommerce Backoffice.

Configure Payment Method to use PaymentMethodService - 2 

Execute Your Payment Method Service from Commerce XSLT Library

You have two options when you need to carry out your payment request: Either create and request a payment in one go by or do a two step request whereby you create a payment, but defer the actual request of the payment to backend service to a later time.

Please note that the two-step request is only available with uCommerce 1.0.3.2 or newer.

Typically the two step approach is used when you’re dealing with a redirect scenario in which part of the payment authorization happens on a remote server.

For a single step request, you'll use this XSLT extension:

<xsl:variable name="result" select="CommerceLibrary:CreatePayment($paymentMethodId, -1, true(), true())"></xsl:variable>

or the version with no amount argument, which will default to the SubTotal of the PurchaseOrder, i.e. use this if you only accept one payment per purchase order.

If you need the two step version you’ll use a couple of extensions. First the one which creates a payment for you and second an extension, which performs the request. Please note that your PaymentMethodService must implemention IPaymentFactory for this to work.

// -1 is a convenience which will tell uCommerce to grab the total of the order for the payment
// The first bool parameter indicates whether to perform the payment request
// The second bool parameter will overwrite existing payments if set to true (a way to avoid duplicates)
<xsl:variable name="result" select="CommerceLibrary:CreatePayment($paymentMethodId, -1, false(), true())"/>

The uCommerce Store executes CreatePayment in the macro called UpdatePayment[XSLT].

To perform the payment request you’ll execute:

// Perform request payment for all payments associated with the basket
<xsl:variable name="paymentResult" select="CommerceLibrary:RequestPayments()"/>
 
- or -
 
// Perform request payment for a single payment
<xsl:variable name="paymentResult" select="CommerceLibrary:RequestPayment(paymentId)"/>

Execute Your Payment Method Service from .NET

To execute your Payment Service directly from .NET code you use the following snippet:

public void ExecutePaymentMethodService(PaymentMethod paymentMethod, 
    PurchaseOrder purchaseOrder, decimal amount)
{
 
    var cultureInfo = new CultureInfo(Globalization.CultureCode);
 
    // Create a new payment request to 
    var paymentRequest = new PaymentRequest(
                purchaseOrder,
                paymentMethod,
                new Money(
                    amount,
                    cultureInfo,
                    purchaseOrder.BillingCurrency)
                             );
 
    Payment payment = paymentMethod
                    .GetPaymentMethodService()
                    .RequestPayment(paymentRequest);
}
posted on Wednesday, 19 May 2010 12:52:18 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Wednesday, 03 June 2009

Microsoft-Commerce-Server-LogoBack in 2007 I was faced with designing a multi-currency catalog solution for Commerce Server. I knew from previous experience that we would need a general purpose solution, which we could employ for many clients.

Back then Commerce Server 2007 was new thus performance characteristics were new territory as well. I ended up designing a solution based solely on virtual catalogs. Basically one catalog for each price group/currency. You can read the details on multi-currency/price groups, which we’ve employed successfully numerous times since then.

Since 2007 we’ve gotten a new version of Commerce Server though no significant new features were added in the catalog system, and we’ve gained valuable new knowledge on both the pricing scenarios and limitation of the Commerce Server catalog system. With that information in hand I’m going to try my hand at redesigning the original multi-currency catalog structure from 2007 to both address performance issues and increased flexibility.

Virtual Catalogs are Slow

Virtual catalogs are slow and so they make a poor choice to expressing essentially a single piece of data. You might say that virtual catalogs perform perfectly well if you materialize them and you would be right. You gain in the order of 10x performance by materializing a virtual catalog but lose the ability to make any changes in them in the process.

Basing my original multi-currency solution on virtual catalogs seemed to make perfect sense, but with the added requirement of changing the category hierarchy two levels of modifiable virtual catalogs were needed, thus the ability to materialize was lost.

To make matters worse we rarely deal with clients who are inclined to go with an Enterprise license for their Commerce Server solution, so we don’t see very many full fledged staged solutions, which would take care of the challenge handily.

Virtual Catalogs Two Levels Deep

Virtual catalogs are by nature limited to two levels, i.e. you can have a total of three levels of catalogs, one with base catalogs and two with virtual catalogs. Are we to use one of these levels of virtual catalogs for pricing we lose it for other purposes, and gain very little other than the ability to store another price group per catalog.

Pricing is a Separate Issue

What I’ve come to realize over the years is that product pricing is a completely separate issue from the product itself. While the two might seem like one and the same; in reality they aren’t. Sure the customer needs to be told a certain price, but more often than not the price is determined by context surrounding the product, rather than the product itself.

An example would be a seasonal business, which is highly dependant on calendar time, the product would probably sell for a higher rate at specific times of the year and lower rates the rest of the year, e.g. ChristmasTreesOnline.com. The context in this particular instance is time.

Now for business to business scenarios the context might be especially convoluted as you might go for pricing granularity, which allow organizations, groups within the organization, even individual people in the organization to have specific prices, e.g. memberships to the gym provided by your company or framework agreements made between supplier and customer. The context deciding the price is who you are in this case, not the product itself.

Pricing is a Service

To handle the separate issue of pricing we need something akin to a service in domain driven design parlance. The service is responsible for looking up the right price based on whichever context is present for a given customer request.

Of course we need some sort of structure to maintain the pricing for individual price groups, and catalogs come in handy to solve this as I’ll show you next.

The Product Catalog

Our product catalog would in the new scheme continue to exist as we know and love it with one minor exception. The list price of the product is either to be ignored or used only to get an idea of what the pricing is like. The list price will not be picked up from the product catalog, which contains the marketing data for a product. Please note that I define marketing data in this instance as data used to display to potential customers, but other than that serve no purpose to the system.

The Pricing Catalog

In Commerce Server we have the notion of different types of catalogs, i.e. the product catalog and the inventory catalog. I’m going to introduce a third kind called the Pricing Catalog. As you might imagine a pricing catalog concerns itself only with price and as such contains only the bare minimum of data to identify a product.

The pricing catalog will have metadata to indicate that it is in fact a pricing catalog. Each pricing catalog reflects a single price group such as “Internet Users”, “Gold Customers”, whatever makes sense for the particular scenario.

Having pricing split out like this means that we can price products based on the calendar time context as a standard Commerce Server catalog has dates associated with it to allow us to display it within only a given period of time.

For a pricing catalog these fields are used to determine whether a price is valid or not, so you could have the seasonal pricing expressed as two different pricing catalogs for our ChristmasTreesOnline.com, one for holiday pricing and one for the rest of the year. The pricing service would then grab the pricing from the proper Pricing Catalog and display it to the customer.

Pricing Definitions

Finally I propose a new kind of definition called the Pricing Definition. What this is is a specialized Product Definition used for creating Pricing in the Pricing Catalogs for advanced scenarios, e.g. complex pricing matrices defined in external systems such as an ERP.

Products, i.e. Prices, created based on a Pricing Definition would contain at least the SKU, name, description, and of course the list price. These specialized products go into a Pricing Catalog as we discussed in the previous paragraph.

Tying it All Together

Another context we discussed in a previous section is the organizational context, which might also influence product pricing. Fortunately Commerce Server comes with CatalogSets as a neat way of bundling catalog together. CatalogSets leveraged with our Product Catalogs and Pricing Catalogs would allow us to do multi-currency and, incidentally, a bunch of even more interesting scenarios.

Imagine if you will a scenario where our online retail outlet would like to give Internet customers access to only currencies, which make sense for their particular region, e.g. here in Denmark Euro and our national currency Kroner would make sense, while UK customers should be enabled to shop in either Pounds or Euro.

Simple! Create two catalog sets one called Denmark and one called UK. For the Denmark catalog set select our one product catalog containing all products or the one which reflects the range available in Denmark and select the two Pricing Catalogs Kroner and Euro. For the UK catalog set select Euro and Pounds Pricing Catalogs.

By way of the metadata on the catalogs we’re now able to display the same range for both UK and Danish customers, but in three different currencies with Pound being available to the British and Kroner available only to the Danish customers.

posted on Wednesday, 03 June 2009 14:21:57 (Romance Daylight Time, UTC+02:00)  #    Comments [2] Trackback
# Monday, 30 March 2009

So I've been migrating my life over to the Mac that I bought late last year and briefly mentioned in my summary post of 2008. Mostly I'm there but one aspect keeps tripping me up: Which blogging tool to use for posting to the couple of blogs I maintain?

On Windows I'm very happy with Windows Live Writer and I figured that with all the creative writing people of the Mac it wouldn't be an issue at all to find a nice comparable tool on the other side.

Boy was I ever wrong in assuming that. For some reason there isn't really a very good tool which has feature parity with Live Writer on the Mac. The most prevalent tool out there is MarsEdit, which to me doesn't fit the bill. It does everything right in the technical department but lacks in one key area: The editor.

Over the years I've grown accustomed to having a couple of features which really help out in the process of writing a new post:

  • The tool must be desktop based. Web interfaces are handy but too cumbersome to work with
  • WYSIWYG editor
  • Auto creation of image thumbnails with links to the original
  • Image formatting tools like alignment and custom margins
  • Support for BlogEngine.NET and DasBlog (categories, upload images via MetaWeblog API)
  • Ideally rich image formatting features like drop shadow

MarsEdit 2
I don't know about you but I expect to be able to edit my posts in the WYSIWYG interface, which might occasionally require me to drop into HTML view to do some of the more tricky stuff (read: I've done this maybe four time in the five years I've kept a blog). MarsEdit, however, is built on the notion that the writer should have complete control of the HTML and thus provides nothing but raw HTML editing, even billing it as a feature, not a bug. I'm sorry but in 2009 I expect so much more from a tool like that. A tool which even requires me to spend $29,95.

I read a review which describes MarsEdit as being very windowy. I think you'll agree when you take a look at the screenshot below. Basically you've got a window for displaying previous posts, a windows for the raw HTML editor, and a preview window to display what your HTML looks like. Nastylicous!

Qumana
Qumana was my second attempt at reaching a blogging solution on par with what I have on Windows. It was even free so I was off to a great start. Qumana looks like Live Writer enough that I thought I was home free and stopped looking any further. Qumana is a pretty good tool which gets the job done. However, it lacks polish which turned me away from it in the end. No support for picture thumbnails was a huge point for me.

As far as windoyness it's far better than MarsEdit and it does provide a WYSIWYG editor, which was sorely lacking from MarsEdit 2. To sum up Qumana comes close but lacks thumbnail support.

Blogo
Now Blogo is a relatively new tool on the Mac as I understand it. I came across Blogo while listening to Leo Laporte's excellent Macbreak Weekly podcast in which he's got a segment where the panel picks their favorite tool. Blogo was in there and I decided to check it out.

My first encounter with Blogo was a nice one to a certain point when it failed one of my requirements miserably. Read on to find out how.

Hopes were not exactly high when I started using the tool the first time around but that quickly changed as I set out to create my first blog post. Sure image preview was sort of a strange feature in the sense that you get a little standard placeholder which shows you that an image is there. As for actual image preview you're out of luck.

Unfortunately Blogo doesn't support BlogEngine.NET 1.4.5 fully. It seems like it's almost there but posting doesn't happen when categories are in the mix. Editing a post after it's posted to BlogEngine.NET also presents some problems. Blogo "sees" the post but when it's pulled down no content is present inside it. Too bad it's really the only piece of puzzle missing for me to start using Blogo on the Mac instead of Live Writer inside my Fusion virtualized Windows 7 install.

A particularly nice feature of Blogo is its fullscreen editing, which basically allows Blogo to take over the entire screen to focus your attention on the blog post and nothing else. Love it!

All in all I'm not quite there yet. I'm hoping for support for BlogEngine.NET in a future release of Blogo, although I'm not holding my breath in that one. I already contacted the good folks at Drink Brain Juice (yeah I know :)) but nothing has happened as of yet. Crossing fingers and toes as it would see and end to that particular dilemma of my migration.


posted on Monday, 30 March 2009 12:37:30 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback