Technical Articles
How to enable QR code in SAP Commerce for an Omni-Channel experience?
In this blog I would like to showcase how I created capability to generate a Barcode of QR code type and how you can use similar steps to enable and generate QR codes in SAP commerce.
Barcodes are used to convey information visually. We’ll most likely provide an appropriate barcode image in a web page, email, or a printable document.
QR(Quick Response) Codes are becoming the most widely recognised 2D barcodes worldwide.
The big benefit of the QR code is that we can store large amounts of data in a limited space.
Business Use Case : Creating an Omni-Channel Experience where we can scan QR code and navigate to PDP page on mobile devices.
This can be extended to attach QR code with In-store products and navigate directly to online store creating a seamless experience.
Technical Use Case : Generate a QR code on Product details page(PDP) which can be scanned using a Barcode/QR code scanner on mobile device in order to navigate PDP from your website/In-store product to mobile device, creating an omni-channel experience.
Note : For simplicity purpose I have used link of PDP inside a QR code although you can have any type of link like a Wishlist or paragraph information as well concealed in it.
Technical Details:
Pre-requisite/Setup:
I have created myprojectstorefront using modulegen and enabled Electronics storefront in my local system for demo.
In case you want to understand how modulegen is used to generate electronics storefront please check this SAP Help page: Customizing the B2C Accelerator to Have B2B and B2C Storefronts
Barcode Library Used
I have used the following Open Source Java Barcode Libraries can be used to generate barcodes in custom extension in SAP commerce:
- Barcode4j : It offers 2D barcode formats – like QR code , DataMatrix and PDF417 – and more output formats.
Note: There are other open source libraries such as ZXing also available at your disposal to accomplish similar task, but for out article we are going forward with Barcode4j.
Solution:
- Add Barcode4j library to external-dependencies.xml of myprojectfacades
as shown below code snippet:<dependency> <groupId>net.sf.barcode4j</groupId> <artifactId>barcode4j</artifactId> <version>2.1</version> </dependency>
Important : To generate barcode4j.2.1.jar on ant build you need to make sure that usemaven=“true” in /myprojectfacades/extensioninfo.xml.
Result : Run ant clean all and you should be able to see barcode4j.2.1.jar in lib folder in lib folder.
- Generate QR code On Load of Product data
Generate QR code in myprojectFacades extension by creating Custom Facade and extending DefaultProductFacade<ProductModel> and over-ridding getProductForCodeAndOptions function. - Create a BarcodeMediaModel ( which is an Out-of-Box(OOB) Model provided in SAP Commerce ) on load of each product and add link of product as data of QR code to be scanned.
- Assign that BarcodeMediaModel to ProductModel
I have added new attribute to store barcode media model in myprojectcore-items.xml for product model.
Below is code snippet for the same:<attribute autocreate="true" qualifier="productQRCode" type="BarcodeMedia"> <modifiers read="true" write="true" search="false" optional="true" /> <persistence type="property" /> </attribute>
IMPORTANT: Please run System update after this change.
- Populate and Show BarcodeMediaModel to Frontend PDP page by adding it to ProductData by converting BarcodeMediaModel to MediaData using OOB mediaModelConverter
as shown below. - Custom Java Code Snippet:
public class CustomProductFacade extends DefaultProductFacade<ProductModel>
{
private static final Logger LOG = Logger.getLogger(CustomProductFacade.class);
@Resource(name = "mediaService")
MediaService mediaService;
@Resource(name = "mediaModelConverter")
Converter<MediaModel, MediaData> mediaModelConverter;
@Override
public ProductData getProductForCodeAndOptions(final String code, final Collection<ProductOption> options)
{
final ProductModel productModel = getProductService().getProductForCode(code);
try
{
if (null == productModel.getProductQRCode())
{
final BufferedImage QRImage = this.generateQRCodeImage("https://localhost:9002/myprojectstorefront/en/USD/p/" + code);
LOG.info("finished generateQRCodeImage ");
final String filePath = "productQRCode.png";
final int size = 125;
final File qrFile = new File(filePath);
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(QRImage, "png", outputStream); // Passing: (RenderedImage im, String formatName, OutputStream output)
final InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
LOG.info("Created Input stream ");
final BarcodeMediaModel barcodeMediaModel = getModelService().create(BarcodeMediaModel.class);
barcodeMediaModel.setCatalogVersion(productModel.getCatalogVersion());
barcodeMediaModel.setCode("productQRCode" + productModel.getCode());
barcodeMediaModel.setRealFileName("productQRCode" + productModel.getCode() + ".png");
barcodeMediaModel.setBarcodeText("https://localhost:9002/myprojectstorefront/en/USD/p/" + code);
barcodeMediaModel.setBarcodeType(BarcodeType.QR);
getModelService().save(barcodeMediaModel);
getModelService().refresh(barcodeMediaModel);
mediaService.setStreamForMedia(barcodeMediaModel, inputStream);
final Collection<BarcodeMediaModel> barcodeMediaList = new ArrayList<>();
barcodeMediaList.add(barcodeMediaModel);
productModel.setProductQRCode(barcodeMediaModel);
getModelService().saveAll(barcodeMediaModel, productModel);
LOG.info("Created Barcode media model in product ");
}
}
catch (final Exception e)
{
e.printStackTrace();
}
final ProductData productData = getProductConverter().convert(productModel);
final MediaData mediaData = mediaModelConverter.convert(productModel.getProductQRCode());
productData.setProductQRCodeMedia(mediaData);
if (options != null)
{
getProductConfiguredPopulator().populate(productModel, productData, options);
}
return productData;
}
public static BufferedImage generateQRCodeImage(final String barcodeText) throws Exception
{
LOG.info("Inside generateQRCodeImage ");
final QRCodeWriter barcodeWriter = new QRCodeWriter();
final BitMatrix bitMatrix = barcodeWriter.encode(barcodeText, BarcodeFormat.QR_CODE, 200, 200);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
- Spring Entries in /resources/myprojectfacades-spring.xml
<alias name="customProductFacade" alias="productFacade"/> <bean id="customProductFacade" class="com.hybris.myproject.facades.impl.CustomProductFacade" parent="defaultProductFacade" />
- Bean entry and Product Data code in /resources/myprojectfacades-beans.xml updated for frontend rendering:
<bean class="de.hybris.platform.commercefacades.product.data.ProductData"> <property name="genders" type="java.util.List<com.hybris.myproject.facades.product.data.GenderData>"/> <property name="productQRCodeMedia" type="de.hybris.platform.cmsfacades.data.MediaData" /> </bean>
- Add following code in /myprojectstorefront/web/webroot/WEB-INF/tags/responsive/product/productDetailsPanel.tag
<img src="${fn:escapeXml(product.productQRCodeMedia.url)}" />
PDP page view:
Figure 1: PDP page view showing QR code generated in Frontend. * Click to enlarge
Backoffice View for Product having Barcodes:
Figure 2 : Product model linked to Barcode* Click to enlarge
Figure 3 : Barcode Media In Backoffice* Click to enlarge
Scan QR codes using a barcode scanner in your mobile device:
You will be able to see encoded link which you have provided in JAVA code above as below:
https://localhost:9002/myprojectstorefront/en/USD/p/553637
Using above approach you can enable and generate different type of barcodes depending on your requirements.
Thanks for reading.
You should now be able to enable QR code in SAP Commerce cloud code and show it on your accelerator storefront.
Please feel free to share feedback and your thoughts on this topic.
Related Links:
- SAP Commerce Cloud
- Ask questions about SAP Commerce Cloud here
Nice post Rahul
Very helpful!
Informative. Thanks for sharing.