Desarrollo con SAP Commerce Cloud developing-with-sap-commerce-cloud
El marco de integración incluye una capa de integración con una API. Esto le permite:
-
conectar un sistema de comercio electrónico y extraer datos de productos en Adobe Experience Manager AEM ()
-
AEM crear componentes de para las capacidades de comercio independientemente del motor específico de comercio electrónico
AEM Se proporcionan varios componentes listos para usar para usar de la capa de integración de. Actualmente son:
- un componente de visualización del producto
- un carro de compras
- check-out
AEM Para la búsqueda, se proporciona un gancho de integración que le permite utilizar la búsqueda de la, la búsqueda del sistema de comercio electrónico, una búsqueda de terceros o una combinación de estos.
Selección de motor de comercio electrónico ecommerce-engine-selection
AEM El marco de comercio electrónico se puede utilizar con cualquier solución de comercio electrónico, el motor que se utilice debe ser identificable por los siguientes puntos:
-
Los motores de comercio electrónico son servicios OSGi que admiten la interfaz
CommerceService
- Los motores se pueden distinguir mediante una propiedad de servicio
commerceProvider
- Los motores se pueden distinguir mediante una propiedad de servicio
-
AEM Compatibilidad con
Resource.adaptTo()
paraCommerceService
yProduct
-
La implementación
adaptTo
busca una propiedadcq:commerceProvider
en la jerarquía del recurso:-
Si se encuentra, el valor se utiliza para filtrar la búsqueda del servicio de comercio.
-
Si no se encuentra, se utiliza el servicio de comercio de mayor clasificación.
-
-
Se usa un mixin
cq:Commerce
para quecq:commerceProvider
se pueda agregar a recursos con establecimiento inflexible de tipos.
-
-
La propiedad
cq:commerceProvider
también se usa para hacer referencia a la definición de fábrica de comercio adecuada.-
Por ejemplo, una propiedad
cq:commerceProvider
con el valorhybris
se correlaciona con la configuración OSGi para Day CQ Commerce Factory for Hybris (com.adobe.cq.commerce.hybris.impl.HybrisServiceFactory), donde el parámetrocommerceProvider
también tiene el valorhybris
. -
Aquí se pueden configurar más propiedades, como Catalog version (cuando corresponde y está disponible).
-
Consulte los siguientes ejemplos:
cq:commerceProvider = geometrixx
cq:commerceProvider = hybris
Ejemplos example
/content/store
+ cq:commerceProvider = hybris
+ mens
+ polo-shirt-1
+ polo-shirt-2
+ employee
+ cq:commerceProvider = jcr
+ adobe-logo-shirt
+ cq:commerceType = product
+ price = 12.50
+ adobe-logo-shirt_S
+ cq:commerceType = variant
+ size = S
+ adobe-logo-shirt_XL
+ cq:commerceType = variant
+ size = XL
+ price = 14.50
/apps/geometrixx-outdoors/components/hybris/product/product.jsp
Desarrollo para hybris 4 developing-for-hybris
La extensión hybris del marco de integración de comercio electrónico se ha actualizado para admitir Hybris 5, manteniendo al mismo tiempo la compatibilidad con versiones anteriores con Hybris 4.
La configuración predeterminada del código está ajustada para Hybris 5.
Para desarrollar Hybris 4, se requiere lo siguiente:
-
Al invocar Maven, agregue el siguiente argumento de la línea de comandos al comando
-P hybris4
Descarga la distribución preconfigurada de Hybris 4 y la incrusta en el paquete
cq-commerce-hybris-server
. -
En el administrador de configuración de OSGi:
-
Deshabilite la compatibilidad con Hybris 5 para el servicio Analizador de respuestas predeterminado.
-
Asegúrese de que el servicio Controlador de autenticación básica de Hybris tenga una clasificación de servicio inferior a la del servicio Controlador de autenticación de Hybris.
-
Gestión de sesión session-handling
hybris utiliza una sesión de usuario para almacenar información como el carro de compras del cliente. El identificador de sesión se devuelve de hybris en una cookie JSESSIONID
que debe enviarse en solicitudes posteriores a hybris. Para evitar almacenar el ID de sesión en el repositorio, se codifica en otra cookie que se almacena en el explorador del comprador. Se realizan los siguientes pasos:
-
En la primera solicitud, no se establece ninguna cookie en la solicitud del comprador; por lo que se envía una solicitud a la instancia de hybris para crear una sesión.
-
Las cookies de sesión se extraen de la respuesta, se codifican en una nueva cookie (por ejemplo,
hybris-session-rest
) y se establecen en la respuesta del comprador. La codificación de una nueva cookie es obligatoria, ya que la cookie original solo es válida para una ruta determinada y, de lo contrario, no se devolverá desde el explorador en solicitudes posteriores. La información de la ruta debe añadirse al valor de la cookie. -
En solicitudes posteriores, las cookies se descodifican de las cookies
hybris-session-<*xxx*>
y se establecen en el cliente HTTP que se utiliza para solicitar datos de hybris.
CommerceSession commercesession
-
Esta sesión "posee" el carro de compras
-
realiza operaciones add/remove/etc.
-
realiza los distintos cálculos en el carro de compras;
commerceSession.getProductPrice(Product product)
-
-
Es propietario de la ubicación de almacenamiento para los datos de order
CommerceSession.getUserContext()
-
Es propietario de la conexión de procesamiento payment
-
Es propietario de la conexión fulfillment
Sincronización y publicación de productos product-synchronization-and-publishing
AEM Los datos del producto que se mantienen en hybris deben estar disponibles en la práctica de la. Se ha implementado el siguiente mecanismo:
- hybris proporciona una carga inicial de ID como fuente. Puede haber actualizaciones en esta fuente.
- AEM hybris proporciona información actualizada a través de una fuente (que se utiliza para sondear las encuestas de la que se dispone en el caso de los).
- AEM Cuando está utilizando datos de productos de, envía solicitudes de vuelta a hybris para los datos actuales (solicitud de obtención condicional con fecha de última modificación).
- En Hybris, es posible especificar el contenido de las fuentes de forma declarativa.
- AEM AEM La asignación de la estructura de fuente al modelo de contenido de la se produce en el adaptador de fuente del lado del.
-
AEM El importador (b) se utiliza para la configuración inicial de la estructura del árbol de páginas en los catálogos de la página de la página de la página de la página de la página de la página de la página de la página de la página de la página de la página de la página de la página de destino de los catálogos.
-
AEM AEM Los cambios de catálogo en los híbridos se indican para que se puedan aplicar a través de una fuente, que luego se propagan a la (b).
-
Producto añadido/eliminado/modificado con respecto a la versión del catálogo.
-
Producto aprobado.
-
-
AEM La extensión hybris proporciona un importador de encuestas ("esquema hybris"), que se puede configurar para importar cambios en un intervalo especificado (por ejemplo, cada 24 horas en las que el intervalo se especifica en segundos):
code language-javascript http://localhost:4502/content/geometrixx-outdoors/en_US/jcr:content.json { * "jcr:mixinTypes": ["cq:PollConfig"], * "enabled": true, * "source": "hybris:outdoors", * "jcr:primaryType": "cq:PageContent", * "interval": 86400 }
-
AEM La configuración del catálogo en reconoce las versiones de catálogo En prueba y En línea en el catálogo.
-
AEM La sincronización de productos entre versiones de catálogo requiere la activación o desactivación de la página de la página de la versión correspondiente (a, c).
-
Para agregar un producto a una versión de catálogo Online es necesario activar la página del producto.
-
La eliminación de un producto requiere la desactivación.
-
-
AEM La activación de una página en el apartado © requiere una comprobación (b) y solo es posible si
-
El producto está en una versión de catálogo En línea para páginas de productos.
-
Los productos a los que se hace referencia están disponibles en una versión del catálogo En línea para otras páginas (por ejemplo, páginas de campañas).
-
-
Las páginas de productos activadas deben tener acceso a la versión en línea (d) de los datos del producto.
-
AEM La instancia de Publish requiere acceso a hybris para la recuperación de datos personalizados y del producto (d).
Arquitectura architecture
Arquitectura de producto y variantes architecture-of-product-and-variants
Un solo producto puede tener varias variaciones; por ejemplo, puede variar según el color y/o el tamaño. Un producto debe definir qué propiedades provocan la variación; términos de Adobe para estos ejes de variante.
Sin embargo, no todas las propiedades son ejes de variante. Las variaciones también pueden afectar a otras propiedades; por ejemplo, el precio puede depender del tamaño. Estas propiedades no pueden ser seleccionadas por el comprador y, por lo tanto, no se consideran ejes de variante.
Cada producto o variante está representado por un recurso y, por lo tanto, se asigna 1:1 a un nodo de repositorio. Es un corolario que un producto específico o una variante se puedan identificar de forma exclusiva por su ruta.
El recurso de producto/variante no siempre contiene los datos de producto reales. Podría ser una representación de datos almacenados en otro sistema (como hybris). AEM Por ejemplo, las descripciones de los productos y los precios no se almacenan en el sistema de comercio electrónico, sino que se recuperan en tiempo real del motor de comercio electrónico.
Cualquier recurso de producto se puede representar mediante un Product API
. La mayoría de las llamadas de la API de producto son específicas de las variaciones (aunque las variaciones pueden heredar valores compartidos de un antecesor), pero también hay llamadas que enumeran el conjunto de variaciones ( getVariantAxes()
, getVariants()
, etc.).
Product.getVariantAxes()
:- hybris lo define para la implementación de hybris
-
size
-
más uno más
variationAxis
de la referencia del producto (normalmente color
para Geometrixx Outdoors).Referencias y datos del producto product-references-and-product-data
En general, los datos del producto se encuentran en /etc
y las referencias del producto en /content
.
Debe haber una asignación individual entre las variaciones de productos y los nodos de datos de productos.
Las referencias de producto también deben tener un nodo para cada variación presentada, pero no es necesario presentar todas las variaciones. Por ejemplo, si un producto tiene variaciones de S, M y L, los datos del producto podrían ser:
etc
|──commerce
| |──products
| |──shirt
| |──shirt-s
| |──shirt-m
| |──shirt-l
Mientras que un catálogo "Grande y Alto" podría tener solo:
content
|──big-and-tall
| |──shirt
| |──shirt-l
Por último, no es necesario utilizar datos de productos. Puede colocar todos los datos del producto debajo de las referencias en el catálogo; pero, en realidad, no puede tener varios catálogos sin duplicar todos los datos del producto.
API
Interfaz de com.adobe.cq.commerce.api.Product com-adobe-cq-commerce-api-product-interface
public 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;
}
com.adobe.cq.commerce.api.VariantFilter com-adobe-cq-commerce-api-variantfilter
/**
* Interface for filtering variants and AxisFilter provided as common implementation
*
* The <code>VariantFilter</code> is used to filter variants,
* for example, when using {@link Product#getVariants(VariantFilter filter)}.
*/
public interface VariantFilter {
public boolean includes(Product product);
}
/**
* A {@link VariantFilter} for filtering variants by the given
* axis and value. The following example returns a list of
* variant products that have a value of <i>blue</i> on the
* <i>color</i> axis.
*
* <p>
* <code>product.getVariants(new AxisFilter("color", "blue"));</code>
*/
public class AxisFilter implements VariantFilter {
private String axis;
private String value;
public AxisFilter(String axis, String value) {
this.axis = axis;
this.value = value;
}
/**
* {@inheritDoc}
*/
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;
}
}
-
Mecanismo de almacenamiento general
-
Los nodos de producto son
nt:unstructured
. -
Un nodo de producto puede ser:
-
Una referencia, con los datos del producto almacenados en otra parte:
-
Las referencias de productos contienen una propiedad
productData
, que apunta a los datos del producto (normalmente bajo/etc/commerce/products
). -
Los datos del producto son jerárquicos; los atributos del producto se heredan de los antecesores de un nodo de datos del producto.
-
Las referencias de producto también pueden contener propiedades locales, que anulan las especificadas en sus datos de producto.
-
-
Un producto en sí:
-
Sin una propiedad
productData
. -
Un nodo de producto que contiene todas las propiedades localmente (y no contiene una propiedad productData) hereda directamente los atributos de producto de sus propios antecesores.
-
-
-
-
AEM Estructura de producto no genérica de
-
Cada variante debe tener su propio nodo de hoja.
-
La interfaz de producto representa productos y variantes, pero el nodo de repositorio relacionado es específico sobre cuál es.
-
El nodo de producto describe los atributos de producto y los ejes de variante.
-
Ejemplos example-1
+ banyan_shirt
- cq:commerceType = product
- cq:productAttributes = [jcr:title, jcr:description, size, price, color]
- cq:productVariantAxes = [color, size]
- jcr:title = Banyan Shirt
- jcr:description = Flowery, all-cotton shirt.
- price = 14.00
+ banyan_shirt_s
- cq:commerceType = variant
- size = S
+ banyan_shirt_s_red
- cq:commerceType = variant
- color = red
+ banyan_shirt_s_blue
- cq:commerceType = variant
- color = blue
+ banyan_shirt_m
- cq:commerceType = variant
- size = M
+ banyan_shirt_m_red
- cq:commerceType = variant
- color = red
+ banyan_shirt_m_blue
- cq:commerceType = variant
- color = blue
+ banyan_shirt_l
- cq:commerceType = variant
- size = L
+ banyan_shirt_l_red
- cq:commerceType = variant
- color = red
+ banyan_shirt_l_blue
- cq:commerceType = variant
- color = blue
+ banyan_shirt_xl
- cq:commerceType = variant
- size = XL
- price = 18.00
Arquitectura del carro de compras architecture-of-the-shopping-cart
Componentes
-
El carro de compras es propiedad de
CommerceSession:
CommerceSession
realiza las operaciones de agregar o quitar, etc.CommerceSession
también realiza los distintos cálculos en el carro de compras. "
-
Aunque no está directamente relacionado con el carro de compras,
CommerceSession
también debe proporcionar información sobre los precios del catálogo (ya que posee precios)-
Los precios pueden tener varios modificadores:
- Descuentos por cantidad.
- Diferentes monedas.
- Deudor de IVA y exento de IVA.
-
Los modificadores están abiertos con la siguiente interfaz:
int CommerceSession.getQuantityBreakpoints(Product product)
String CommerceSession.getProductPrice(Product product)
-
Almacenamiento
-
Almacenamiento
- En el caso de hybris, el servidor de hybris es propietario del carro de compras.
- AEM En el caso genérico de la, los carros de compras de se almacenan en el ClientContext.
Personalización
-
Siempre dirija la personalización a través del ClientContext.
-
Se crea un ClientContext
/version/
del carro de compras en todos los casos:- Los productos deben agregarse usando el método
CommerceSession.addCartEntry()
.
- Los productos deben agregarse usando el método
-
A continuación se muestra un ejemplo de información del carro de compras en el carro de ClientContexts:
Arquitectura del cierre de compra architecture-of-checkout
Datos de pedido y carro de compras
CommerceSession
es propietario de los tres elementos:
-
Contenido del carro
-
Precio
-
Los detalles del pedido
-
Contenido del carro
La API corrige el esquema de contenido del carro de compras:
code language-java public void addCartEntry(Product product, int quantity); public void modifyCartEntry(int entryNumber, int quantity); public void deleteCartEntry(int entryNumber);
-
Precio
La API también fija el esquema de precios:
code language-java public String getCartPreTaxPrice(); public String getCartTax(); public String getCartTotalPrice(); public String getOrderShipping(); public String getOrderTotalTax(); public String getOrderTotalPrice();
-
Detalles del pedido
Sin embargo, la API no corrigió los detalles del pedido:
code language-java public void updateOrderDetails(Map<String, String> orderDetails); public Map<String, String> getOrderDetails(); public void submitOrder();
Cálculos de envío
-
Los formularios de pedido suelen presentar varias opciones de envío (y precios).
-
Los precios pueden estar basados en artículos y detalles del pedido, como el peso y/o la dirección de entrega.
-
CommerceSession
tiene acceso a todas las dependencias, por lo que se puede tratar de manera similar a como se trata a los precios de los productos:CommerceSession
posee precios de envío.- Puede recuperar o actualizar los detalles de envío usando
updateOrder(Map<String, Object> delta)
yourProject/commerce/components/shippingpicker
:-
Básicamente podría ser una copia de
foundation/components/form/radio
, pero con devoluciones de llamadas aCommerceSession
para: -
Comprobación de si el método está disponible
-
Adición de información de precios
-
AEM Para permitir que los compradores actualicen la página de pedidos en el (incluido el superconjunto de métodos de envío y el texto que los describe), sin dejar de tener el control para exponer la información relevante de
CommerceSession
.
Procesamiento de pagos
-
CommerceSession
también posee la conexión de procesamiento de pago. -
Los implementadores deben agregar llamadas específicas (al servicio de procesamiento de pagos que hayan elegido) a la implementación de
CommerceSession
.
Satisfacción de pedidos
CommerceSession
también posee la conexión de cumplimiento.- Los implementadores deben agregar llamadas específicas (al servicio de procesamiento de pagos que hayan elegido) a la implementación de
CommerceSession
.
Definición de búsqueda search-definition
Siguiendo el modelo de API de servicio estándar, el proyecto de comercio electrónico proporciona un conjunto de API relacionadas con la búsqueda que pueden implementar los motores de comercio individuales.
El proyecto de comercio electrónico contiene un componente de búsqueda predeterminado en:
/libs/commerce/components/search
Utiliza la API de búsqueda para consultar el motor de comercio seleccionado (consulte Selección del motor de comercio electrónico):
API de búsqueda search-api
El proyecto principal proporciona varias clases genéricas/de ayuda:
-
CommerceQuery
Describe una consulta de búsqueda (contiene información sobre el texto de la consulta, la página actual, el tamaño de página, el orden y las facetas seleccionadas). Todos los servicios de comercio electrónico que implementan la API de búsqueda reciben instancias de esta clase para realizar su búsqueda. Se puede crear una instancia de
CommerceQuery
a partir de un objeto de solicitud (HttpServletRequest
). -
FacetParamHelper
Es una clase de utilidad que proporciona un método estático -
toParams
- que se utiliza para generarGET
cadenas de parámetros a partir de una lista de facetas y un valor alternado. Esto resulta útil en la interfaz de usuario, donde debe mostrar un hipervínculo para cada valor de cada faceta, de modo que cuando el usuario haga clic en el hipervínculo, se alterne el valor respectivo. Es decir, si se seleccionó, se elimina de la consulta; de lo contrario, se agrega. Esto se encarga de toda la lógica de administrar facetas múltiples o de un solo valor, anular valores, etc.
El punto de entrada para la API de búsqueda es el método CommerceService#search
que devuelve un objeto CommerceResult
. Consulte la Documentación de la API para obtener más información sobre este tema.
Integración de usuarios user-integration
AEM La integración se proporciona entre los sistemas de comercio electrónico de los distintos sistemas de comercio electrónico y de los que se puede acceder. AEM AEM Esto requiere una estrategia para sincronizar a los compradores entre los distintos sistemas, de modo que el código específico de los clientes solo tenga que saber sobre los puntos de venta y, a la inversa, solo tenga que saber sobre los puntos de venta:
-
Autenticación
AEM Se presume que el front-end web only es el de la página web y, por lo tanto, realiza la autenticación all.
-
Cuentas en Hybris
AEM crea una cuenta correspondiente (subordinada) en hybris para cada comprador. AEM El nombre de usuario de esta cuenta es el mismo que el nombre de usuario de la. AEM Una contraseña criptográficamente aleatoria se genera automáticamente y se almacena (codifica) en el código de acceso de los usuarios de la red de servicios de Internet ().
Usuarios preexistentes pre-existing-users
AEM Un front-end se puede colocar delante de una implementación de hybris existente. AEM Además, se puede añadir un motor hybris a una instalación existente de la. Para ello, los sistemas deben poder gestionar correctamente los usuarios existentes en cualquiera de ellos:
-
AEM > hybris
-
AEM Al iniciar sesión en hybris, si no existe el usuario de la:
- crear un usuario de hybris con una contraseña criptográficamente aleatoria
- AEM almacene el nombre de usuario de hybris en el directorio de usuario del usuario de la
-
Ver:
com.adobe.cq.commerce.hybris.impl.HybrisSessionImpl#login()
-
-
AEM hybris >
-
AEM Al iniciar sesión en, si el sistema reconoce al usuario, haga lo siguiente:
- intente iniciar sesión en hybris con el nombre de usuario/pwd proporcionado
- AEM AEM AEM si se ejecuta correctamente, cree el usuario en la cuenta de usuario con la misma contraseña (los resultados de sal específicos de la en el hash específico de la cuenta de usuario).
-
El algoritmo anterior se implementó en un Sling
AuthenticationInfoPostProcessor
- Ver:
com.adobe.cq.commerce.hybris.impl.user.LazyUserImporter.java
- Ver:
-
Personalización del proceso de importación customizing-the-import-process
Para crear a partir de la funcionalidad existente su controlador de importación personalizado:
-
tiene que implementar la interfaz
ImportHandler
-
puede ampliar
DefaultImportHandler
.
/**
* Services implementing the <code>ImportHandler</code> interface are
* called by the {@link HybrisImporter} to create actual commerce entities
* such as products.
*/
public interface ImportHandler {
/**
* Not used.
*/
public void createTaxonomie(ImporterContext ctx);
/**
* Creates a catalog with the given name.
* @param ctx The importer context
* @param name The catalog's name
* @return Path of created catalog
*/
public String createCatalog(ImporterContext ctx, String name) throws Exception;
/**
* Creates a product from the given values.
* @param ctx The importer context
* @param values The product's properties
* @param parentCategoryPath The containing category's path
* @return Path of created product
*/
public String createProduct(ImporterContext ctx, ValueMap values, String parentCategoryPath) throws Exception;
/**
* Creates a variant product from the given values.
* @param ctx The importer context
* @param values The product's properties
* @param baseProductPath The base product's path
* @return Path of created product
*/
public String createVariantProduct(ImporterContext ctx, ValueMap values, String baseProductPath) throws Exception;
/**
* Creates an asset for a product. This is usually a product
* image.
* @param ctx The importer context
* @param values The product's properties
* @param baseProductPath The product's path
* @return Path of created asset
*/
public String createAsset(ImporterContext ctx, ValueMap values, String productPath) throws Exception;
/**
* Creates a category from the given values.
* @param ctx The importer context
* @param values The category's properties
* @param parentPath Path of parent category or base path of import if there is a root category
* @return Path of created category
*/
public String createCategory(ImporterContext ctx, ValueMap values, String parentCategoryPath) throws Exception;
}
Para que el importador reconozca el controlador personalizado, debe especificar la propiedad service.ranking
con un valor superior a 0, por ejemplo.
@Component
@Service
@Property(name = "service.ranking", value = 100)
public class MyImportHandler extends DefaultImportHandler
{
...
}