AEM (CQ) eCommerce Framework

18,187 views

Published on

As part of Adobe Experience Manager, CQ 5.6 provides a new Commerce Framework to build Experience Driven Commerce websites on top of a 3rd party Commerce Platform. This session provides an overview of the framework from an architectural perspective and presents some details of the reference implementation, based on the JCR repository.

Published in: Technology

AEM (CQ) eCommerce Framework

  1. 1. Paolo MottadelliAdobe Technical Marketing eCommerce Integration FrameworkCQ Gems Adobe® Experience Manager Adobe® Marketing Cloud
  2. 2. Commerce Integrated Platform dynamic PIM surfer 1 4 2 Experience Manager PIM/ecommerce JCR repo 3 product DB content editor PIM editor PIM synch
  3. 3. Commerce Integrated Platform surfer 1. Product display component 1. Product information integrity 2. Shopping cart 2. Pricing 3. Promotions and vouchers 3. Stock-keeping inventory 4. Catalog blueprints 4. Variations on shopping cart 5. Check-out 6. Search content editor PIM editor
  4. 4. AEM eCommerce Integration Modules1. The integration framework (API used for eCommerce implementations)2. AEM native (JCR) implementation3. hybris implementation4. A number of out-of-the-box AEM components5. Search (AEM, eCommerce, 3rd party)6. Catalog management7. Promotions management Experience Manager PIM/ecommerce8. Client context cart store JCR repo product DB
  5. 5. Architecture of the Commerce Framework AEM Commerce Components AEM Commerce API Implementation AEM native impl hybris impl other impl JCR Repository hybris DB other
  6. 6. eCommerce Engine Selection Site Component CommerceService commerceService = 2 resource.adaptTo(CommerceService.class); CommerceSession session = commerceService.login(slingRequest, slingResponse); Product baseProduct = resource.adaptTo(Product.class); 3 OSGi container bundle bundle 1 GeoImpl bundle otherImpl cq:commerceProvider = geometrixx (geometrixx) hybrisImpl (xyz) (hybris)
  7. 7. CommerceSession • addCartEntry(Product product, int quantity); • modifyCartEntry(int entryNumber, int quantity); cart content • deleteCartEntry(int entryNumber); •updateOrderDetails(Map<String, String> orderDetails); •getOrderDetails(); pricing •submitOrder(); •updateOrderDetails(Map<String, String> orderDetails); •getOrderDetails(); order details •submitOrder();
  8. 8. CommerceSession is RESTful style (1)
  9. 9. CommerceSession is RESTful style (2) Name: CommercePersistence, Host: geometrixx.com, Path: / ORDER%3a%3dorderId%253d9c1346bf-3813-4205-80ec-2fdfd1644143%7cCART%3a %3dquantity3%253d1%252cquantity0%253d1%252cquantity1%253d1%252cpromotionCoun t%253d2%252cquantity2%253d1%252cvoucherCount%253d0%252cpromotion1%253d %252fcontent%252fcampaigns%252fgeometrixx-outdoors%252fcosy-up-to-winter %252fwinter-female%252fcosy-companions%252cpromotion0%253d%252fcontent %252fcampaigns%252fgeometrixx-outdoors%252fbig-spender %252fordervalueover100%252ffree-shipping%252cproduct3%253d%252fcontent %252fgeometrixx-outdoors%252fen%252fequipment%252fskiing%252fhalifax-winter %252fjcr%253acontent%252fpar%252fproduct%252cproduct0%253d%252fcontent %252fgeometrixx-outdoors%252fen%252fwomen%252fcoats%252fcalgary-winter%252fjcr %253acontent%252fpar%252fproduct%252f397122-s%252cproduct2%253d%252fcontent %252fgeometrixx-outdoors%252fen%252fseasonal%252fwinter%252fequipment %252fkamloops-snow%252fjcr%253acontent%252fpar%252fproduct %252f37924450-7%252centryCount%253d4%252cproduct1%253d%252fcontent %252fgeometrixx-outdoors%252fen%252fequipment%252fskiing%252fkelowna-snow %252fjcr%253acontent%252fpar%252fproduct%7c
  10. 10. CommerceSession is RESTful style (3)public class AbstractJcrCommerceSession implements CommerceSession { ... cartStore = ContextSessionPersistence.getStore(request, "CART", CommerceConstants.COMMERCE_COOKIE_NAME); ...}
  11. 11. Products and Variants architecture: 1 1 1 1 - type: product - variant - variant - variant - axes: color, size - color: purple - size: S - size: M - id: 397122 - id: 397122.1 - title: Saskatoon 1 1 - price: 299 - variant - variant - size: L - size: XL 1 1 1 - variant - variant - variant - color: purple - size: S - size: M -id: 397122.2 1 1 - price: 199 - variant - variant - size: L - size: XL
  12. 12. PIM Data & Product References 1 /etc/commerce/products 2 /content 1 1 1 1 1 1 1 1 1 1 1
  13. 13. Product interfacepublic interface Product extends Adaptable { public String getPath(); // path to specific variation public String getPagePath(); // path to presentation page for all variations public String getSKU(); // unique ID of specific variation public String getTitle(); // shortcut to getProperty(TITLE) public String getDescription(); // shortcut to getProperty(DESCRIPTION) public String getImageUrl(); // shortcut to getProperty(IMAGE_URL) public String getThumbnailUrl(); // shortcut to getProperty(THUMBNAIL_URL) public <T> T getProperty(String name, Class<T> type); public Iterator<String> getVariantAxes(); public boolean axisIsVariant(String axis); public Iterator<Product> getVariants(VariantFilter filter) throws CommerceException;}
  14. 14. AxisFilter implements VariantFilterpublic class AxisFilter implements VariantFilter { ... public boolean includes(Product product) { ValueMap values = product.adaptTo(ValueMap.class); if(values != null) { String v = values.get(axis, String.class); return v != null && v == value; } return false; }}
  15. 15. Shopping Cart architecture (CommerceSession)The CommerceSession performs add, remove, etc.The CommerceSession also performs the various calculations on the cart.The CommerceSession also applies vouchers and promotions that have fired to the cart.Pricing modifiers:- Quantity discounts.- Different currencies.- VAT-liable and VAT-free.
  16. 16. session.calcCart() protected void calcCart() { ... for (int i = 0; i < cart.size(); i++) { ... for (Promotion p : promotions) { try { PromotionHandler ph = p.adaptTo(PromotionHandler.class); PriceInfo discount = ph.applyCartEntryPromotion(this, p, entry); if (discount != null && discount.getAmount().compareTo(BigDecimal.ZERO) > 0) { ... entry.calcPrices(); ... } ... cartTotalPrice = cartTotalPrice.add(entry.getPriceInfo(new PriceFilter("POST_TAX", currencyCode)).get(0).getAmount()); } setPrice(new PriceInfo(cartPreTaxPrice, currency), "CART", "PRE_TAX"); setPrice(new PriceInfo(cartTax, currency), "CART", "TAX"); setPrice(new PriceInfo(cartTotalPrice, currency), "CART", "POST_TAX"); ... }
  17. 17. Shopping Cart architecture (Storage)In AEM-native carts are stored in theClientContextPersonalization should always be driventhrough the ClientContext.CommerceSession.addCartEntry()
  18. 18. Checkout architectureCart and Order DataThe CommerceSession owns the three elements: Cart contents Pricing The order details Cart contents The cart contents schema is fixed by the API: public void addCartEntry(Product product, int quantity); public void modifyCartEntry(int entryNumber, int quantity); public void deleteCartEntry(int entryNumber); Pricing The pricing schema is also fixed by the API: public String getCartPreTaxPrice(); public String getCartTax(); public String getCartTotalPrice(); public String getOrderShipping(); public String getOrderTotalTax(); public String getOrderTotalPrice();
  19. 19. Checkout architecture (order details)Order details are not fixed by the API:updateOrderDetails(Map<String, String> orderDetails);Shipping options (and prices) depend on weight, delivery address, etc...The CommerceSession owns shipping pricing; to retrieve and update delivery details:updateOrder(Map<String, Object> delta)
  20. 20. Hands on
  21. 21. Defining the scope1. Build a new Commerce Implementation: “training”2. Apply the new implementation to Geometrixx Outdoors3. Store the cart data in the repository (/home/users/a/admin/commerce/cart)
  22. 22. adobe.com/go/gems @CQDev

×