oo

Product API - Creating a Product with Multiple SKUs

You can create products with multiple active SKUs using the product API or from the Products application. To create such a product, you must first have an option template created using the Option API or through the Options application, and have values present for the option. You can add values from the Options application or use the Option Value API.

note

You can also create an option template from the Options tab on a product. The values added here, however, are specific to the product and doesn’t get added to the option template found under Global Menu (Applications Menu icon) → Commerce → Options.

Adding a Product with Multiple SKUs

Start a new Liferay DXP instance by running

docker run -it -m 8g -p 8080:8080 liferay/dxp:2024.q1.1

Sign in to Liferay at http://localhost:8080 using the email address test@liferay.com and the password test. When prompted, change the password to learn.

Then follow these steps:

  1. Download and unzip Product API - Adding a Product with Multiple SKUs.

    curl https://resources.learn.liferay.com/commerce/latest/en/product-management/developer-guide/liferay-q8t5.zip -O
    
    unzip liferay-q8t5.zip
    
  2. A product is scoped to a catalog, and the catalog ID is one of the required parameters. To have multiple active SKUs, the product must also have options. You can create an option template to reuse it with multiple products. To link an option template to a product, the option ID is required.

    To get the catalog ID, open the Global Menu (Applications Menu icon), and go to CommerceCatalogs. Select the catalog where you’ll add products and note the ID that’s next to its name.

    To get the option ID, open the Global Menu (Applications Menu icon), and go to CommerceOptions. Select the option you want to link to the product and note the ID that’s next to its name.

    important

    This example assumes you have an option template created with the name Able containing two values, Baker and Charlie.

  3. Use the cURL script to add a new product with multiple SKUs to the catalog. On the command line, navigate to the curl folder. Execute the Product_POST_ToCatalog.sh script with your catalog ID and option ID as parameters.

    ./Product_POST_ToCatalog.sh 1234 5678
    

    The JSON response shows a new product with multiple SKUs has been added:

    {
       "actions" : {
          "get" : {
             "method" : "GET",
             "href" : "http://localhost:8080/o/headless-commerce-admin-catalog/v1.0/products/46860"
          },
          "update" : {
             "method" : "PATCH",
             "href" : "http://localhost:8080/o/headless-commerce-admin-catalog/v1.0/products/46860"
          },
          "delete" : {
             "method" : "DELETE",
             "href" : "http://localhost:8080/o/headless-commerce-admin-catalog/v1.0/products/46860"
          }
       },
       "active" : true,
       "catalogId" : 1234,
       "categories" : [ ],
       "createDate" : "2023-06-09T11:32:27Z",
       "customFields" : [ ],
       "description" : {
          "en_US" : ""
       },
       "displayDate" : "2023-06-09T11:32:00Z",
       "expando" : { },
       "externalReferenceCode" : "82462cc8-1af3-0d14-30f2-d47b38946cf2",
       "id" : 46860,
       "metaDescription" : {
          "en_US" : ""
       },
       "metaKeyword" : {
          "en_US" : ""
       },
       "metaTitle" : {
          "en_US" : ""
       },
       "modifiedDate" : "2023-06-09T11:32:27Z",
       "name" : {
          "en_US" : "Foo"
       },
       "productAccountGroupFilter" : false,
       "productChannelFilter" : false,
       "productId" : 46861,
       "productStatus" : 0,
       "productType" : "simple",
       "productTypeI18n" : "Simple",
       "shortDescription" : {
          "en_US" : ""
       },
       "skuFormatted" : "(Multiple SKUs)",
       "tags" : [ ],
       "thumbnail" : "/o/commerce-media/default/?groupId=43744",
       "urls" : {
          "en_US" : "foo"
       },
       "version" : 1,
       "workflowStatusInfo" : {
          "code" : 0,
          "label" : "approved",
          "label_i18n" : "Approved"
       }
    }
    

    Note the skuFormatted field shows (Multiple SKUs) confirming the creation of more than one SKU.

  4. Verify this by opening the Global Menu (Applications Menu icon), and navigating to CommerceProducts. Click the Options tab to see the linked product option. Click the SKUs tab to see two new SKUs with the Approved status.

    See that a new product with multiple SKUs has been added.

  5. You can also call the REST service using the Java client. Navigate out of the curl folder and into the java folder. Compile the source files:

    javac -classpath .:* *.java
    
  6. Run the Product_POST_ToCatalog class. Replace the catalogId and optionId with the appropriate values.

    java -classpath .:* -DcatalogId=1234 -DoptionId=5678 Product_POST_ToCatalog
    

Examine the cURL Command

The Product_POST_ToCatalog.sh script calls the REST service with a cURL command.

curl \
	"http://localhost:8080/o/headless-commerce-admin-catalog/v1.0/products" \
	--data-raw '
		{
			"active": true,
			"catalogId": "'"${1}"'",
			"name": {
				"en_US": "Foo"
			},
			"productOptions": [
				{
					"fieldType": "select",
					"key": "able",
					"name": {
						"en_US": "Able"
					},
					"optionId": "'"${2}"'",
					"required": true,
					"skuContributor": true
				}
			],
			"productType": "simple",
			"skus": [
				{
					"published": true,
					"purchasable": true,
					"sku": "SKU-01",
					"skuOptions": [
						{
							"key": "able",
							"value": "Baker"
						}
					]
				},
				{
					"published": true,
					"purchasable": true,
					"sku": "SKU-02",
					"skuOptions": [
						{
							"key": "able",
							"value": "Charlie"
						}
					]
				}
			]
		}' \
	--header "Content-Type: application/json" \
	--request "POST" \
	--user "test@liferay.com:learn"

Here are the command’s arguments:

Arguments Description
-H "Content-Type: application/json" Indicates that the request body format is JSON.
-X POST The HTTP method to invoke at the specified endpoint
"http://localhost:8080/o/headless-commerce-admin-catalog/v1.0/products" The REST service endpoint
-d "{\"active\": true, \"catalogId\": \"${1}\", \"name\": {\"en_US\": \"Foo\"}, \"productOptions\": [{\"fieldType\": \"select\", \"key\": \"able\", \"name\": {\"en_US\": \"Able\"}, \"optionId\": \"${2}\", \"required\": true, \"skuContributor\": true}], \"productType\": \"simple\", \"skus\": [{\"published\": true, \"purchasable\": true, \"sku\": \"SKU-01\", \"skuOptions\": [{\"key\": \"able\", \"value\": \"Baker\"}]}, {\"published\": true, \"purchasable\": true, \"sku\": \"SKU-02\", \"skuOptions\": [{\"key\": \"able\", \"value\": \"Charlie\"}]}]}" The data to post
-u "test@liferay.com:learn" Basic authentication credentials
note

Basic authentication is used here for demonstration purposes. For production, you should authorize users via OAuth2. See Using OAuth2 to Authorize Users for a sample React application that utilizes OAuth2.

Examine the Java Class

The Product_POST_ToCatalog.java class adds a product with multiple SKUs by calling the product-related service.

public static void main(String[] args) throws Exception {
	ProductResource.Builder builder = ProductResource.builder();

	ProductResource productResource = builder.authentication(
		"test@liferay.com", "learn"
	).build();

	System.out.println(
		productResource.postProduct(
			new Product() {
				{
					active = true;
					catalogId = Long.valueOf(
						System.getProperty("catalogId"));
					name = new HashMap<String, String>() {
						{
							put("en_US", "Foo");
						}
					};
					productOptions = new ProductOption[] {
						new ProductOption() {
							{
								fieldType = "select";
								key = "able";
								name = new HashMap<String, String>() {
									{
										put("en_US", "Able");
									}
								};
								optionId = Long.valueOf(
									System.getProperty("optionId"));
								required = true;
								skuContributor = true;
							}
						}
					};
					productType = "simple";
					skus = new Sku[] {
						new Sku() {
							{
								published = true;
								purchasable = true;
								sku = "SKU-01";
								skuOptions = new SkuOption[] {
									new SkuOption() {
										{
											key = "able";
											value = "Baker";
										}
									}
								};
							}
						},
						new Sku() {
							{
								published = true;
								purchasable = true;
								sku = "SKU-02";
								skuOptions = new SkuOption[] {
									new SkuOption() {
										{
											key = "able";
											value = "Charlie";
										}
									}
								};
							}
						}
					};
				}
			}));
}

This class invokes the REST service using only three lines of code:

Line (abbreviated) Description
ProductResource.Builder builder = ... Gets a Builder for generating a ProductResource service instance.
ProductResource productResource = builder.authentication(...).build(); Specifies basic authentication and generates a ProductResource service instance.
productResource.postProduct(...); Calls the productResource.postProduct method and passes the data to post.

Note that the project includes the com.liferay.headless.commerce.admin.catalog.client.jar file as a dependency. You can find client JAR dependency information for all REST applications in the API explorer in your installation at /o/api.

note

The main method’s comment demonstrates running the class.

Reviewing the Payload

This is the example payload used to create one product with two active SKUs.

{
   "active": true,
   "catalogId": 1234,
   "name": {
     "en_US": "Foo"
   },
   "productOptions":[
      {
         "fieldType": "select",
         "key": "able",
         "name": {
            "en_US": "Able"
         },
         "optionId": 5678,
         "required": true,
         "skuContributor": true
      }
   ],
   "productType": "simple",
   "skus": [
      {
         "published": true,
         "purchasable": true,
         "sku": "SKU-01",
         "skuOptions":[{
            "key": "able",
            "value": "Baker"
         }]
      },
      {
         "published": true,
         "purchasable": true,
         "sku": "SKU-02",
         "skuOptions":[{
            "key": "able",
            "value": "Charlie"
         }]
      }
   ]
}

There are a total of 6 fields in the JSON.

Field Description
active Set it to true or false to change the product’s visibility.
catalogId ID of the product’s catalog.
name The name of the product.
productOptions An array of product options. See ProductOption
productType The type of the product (simple, grouped, virtual or diagram).
skus An array of product SKUs. See Sku

The productOptions field contains information about the option that is linked to the product.

Field Description
fieldType The option field’s type. Can be one of "text", "select", "radio", "checkbox_multiple", "date", "numeric", or "checkbox".
key The option’s key.
name The option’s name.
optionId The option’s ID.
required When true, you must select an option before checking out.
skuContributor When true, each option is linked to a SKU. This is mandatory for products with multiple SKUs.

The skus field contains information about the SKUs of a product.

Field Description
published When true, the SKU is visible in the storefront.
purchasable When true, the SKU is purchasable.
sku The name of the SKU.
skuOptions An array of sku options. See SkuOption. The key is the key of the option template and the value specifies one of the values of the option.
note

You can substitute the key and value inside skuOptions with optionId and optionValueId.

Capability: