The integration framework includes an integration layer with an API. This allows you to build AEM components for eCommerce capabilities (independent of your specific eCommerce engine). It also allows you to use the internal CRX database or to plug in an eCommerce system and pull product data into AEM.

A number of out-of-the-box AEM components are provided to use the integration layer. Currently these are:

A product display component

A shopping cart

Promotions and vouchers

Catalog and section blueprints

Check-out

Search

For search an integration hook is provided that allows you to use the AEM search, a third party search (like Search&Promote) or a combination thereof.

eCommerce Engine Selection

The eCommerce framework can be used with any eCommerce solution, the engine being used needs to be identified by AEM - even when using the AEM generic engine:

The adaptTo implementation looks for a cq:commerceProvider property in the resource's hierarchy:

If found, the value is used to filter the commerce service lookup.

If not found, the highest-ranked commerce service is used.

A cq:Commerce mixin is used so the cq:commerceProvider can be added to strongly-typed resources.

The cq:commerceProvider property is also used to reference the appropriate commerce factory definition.

For example, a cq:commerceProvider property with the value geometrixx will correlate to the OSGi configuration for Day CQ Commerce Factory for Geometrixx-Outdoors (com.adobe.cq.commerce.hybris.impl.GeoCommerceServiceFactory) - where the parameter commerceProvider also has the value geometrixx.

Here further properties can be configured (when appropriate and available).

In a standard AEM installation a specific implementation is required, for example:

cq:commerceProvider = geometrixx

geometrixx example; this includes minimal extensions to the generic API

Using CRXDE Lite you can see how this is handled in the product component for the AEM generic implementation:

/apps/geometrixx-outdoors/components/product

Session Handling

A session to store information related to the customer's shopping cart.

The CommerceSession:

Owns the shopping cart

performs add/remove/etc

performs the various calculations on the cart;commerceSession.getProductPriceInfo(Product product, Predicate filter)

Owns persistance of the order data: CommerceSession.getUserContext()

Can retrieve/update delivery details by using updateOrder(Map<String, Object> delta)

Also owns the payment processing connection

Also owns the fulfillment connection

Architecture

Architecture of Product and Variants

A single product can have multiple variations; for instance, it might vary by color and/or size. A product must define which properties drive variation; we term these variant axes.

However, not all properties are variant axes. Variations can also affect other properties; for example, the price might be dependant on size. These properties cannot be selected by the shopper and therefore are not considered variant axes.

Each product and/or variant is represented by a resource, and therefore maps 1:1 to a repository node. It is a corollary that a specific product and/or variant can be uniquely identified by its path.

Any product resource can be represented by a Product API. Most calls in the product API are variation specific (although variations might inherit shared values from an ancestor), but there are also calls which list the set of variations (getVariantAxes(), getVariants(), etc.).

Remarque :

In effect a variant axes is determined by whatever Product.getVariantAxes() returns:

for the generic implementation AEM reads it from a property in the product data (cq:productVariantAxes)

While products (in general) can have many variant axes, the out-of-the-box product component only handles two:

size

plus one more
This additional variant is selected via the variationAxis property of the product reference (usually color for Geometrixx Outdoors).

Product References and PIM Data

In general:

PIM data is located under /etc

Product references under /content.

There must be a 1:1 map between product variations and product data nodes.

Product references must also have a node for each variation presented - but there is no requirement to present all variations. For instance, if a product has S, M, L variations, the product data might be:

etc
commerce
products
shirt
shirt-s
shirt-m
shirt-l

While a "Big and Tall" catalog might have only:

content
big-and-tall
shirt
shirt-l

Finally, there is no requirement to use product data. You can place all product data under the references in the catalog; but then you cannot really have multiple catalogs without duplicating all the product data.

public String getCartPreTaxPrice();
public String getCartTax();
public String getCartTotalPrice();
public String getOrderShipping();
public String getOrderTotalTax();
public String getOrderTotalPrice();

Search API

There are several generic / helper classes provided by the core project:

CommerceQuery
Is used to describe a search query (contains information about the query text, current page, page size, sort and selected facets). All eCommerce services that implement the search API will receive instances of this class in order to perform their search. A CommerceQuery can be instantiated from a request object (HttpServletRequest).

FacetParamHelper
Is a utility class that provides one static method - toParams - that is used for generating GET parameter strings from a list of facets and one toggled value. This is useful on the UI side, where you need to display a hyperlink for each value of each facet, such that when the user clicks on the hyperlink the respective value is toggled (i.e. if it was selected it is removed from the query, otherwise added). This takes care of all the logic of handling multiple/single-valued facets, overriding values, etc.

The entry point for the search API is the CommerceService#search method which returns a CommerceResult object. See the API Documentation for more information on this topic.

Developing Promotions and Vouchers

Vouchers:

A Voucher is a page-based component that is created / edited with the Websites console and stored under:/content/campaigns

Vouchers supply:

A voucher code (to be typed into the cart by the shopper).

A voucher label (to be displayed after the shopper has entered it into the cart).

A promotion path (which defines the action the voucher applies).

Vouchers do not have their own on and off date/times, but use those of their parent campaigns.

External commerce engines can also supply vouchers; these require a minimum of:

A voucher code

An isValid() method

The Voucher component (/libs/commerce/components/voucher) provides:

A renderer for voucher administration; this shows any vouchers currently in the cart.

The edit dialogs (form) for administrating (adding/removing) the vouchers.

The actions required for adding/removing vouchers to/from the cart.

Promotions:

A Promotion is a page-based component that is created / edited with the Websites console and stored under:/content/campaigns

Promotions supply:

A priority

A promotion handler path

You can connect promotions to a campaign to define their on/off date/times.

You can connect promotions to an experience to define their segments.

Promotions not connected to an experience will not fire on its own, but can still be fired by a Voucher.

This way, the CommerceSession is responsible for checking whether a voucher exists and if it can be applied or not. This might be for vouchers that can only be applied if a certain condition is met; for example, when the total cart price is greater than $100). If a voucher cannot be applied for any reason, the addVoucher method will throw an exception. Also, the CommerceSession is responsible for updating the cart's price(s) after a voucher is added / removed.

The Voucher is a bean-like class that contains fields for:

Voucher code

A short description

Referencing the related promotion that indicates the discount type and value

The AbstractJcrCommerceSession provided can apply vouchers. The vouchers returned by the class getVouchers() are instances of cq:Page containing a jcr:content node with the following properties (amongst others):

sling:resourceType (String) - this needs to be commerce/components/voucher

jcr:title (String) - for the voucher's description

code (String) - the code the user has to enter to apply this voucher

promotion (String) - the promotion to be applied; e.g. /content/campaigns/geometrixx-outdoors/article/10-bucks-off

Promotion handlers are OSGi services which modify the shopping cart. The cart will support several hooks that will be defined in the PromotionHandler interface.