Using Salesforce Omnichannel Inventory with Salesforce Commerce APIs

Salesforce Omnichannel Inventory is an inventory solution that delivers near real-time inventory availability at the location level across all your fulfillment channels.

I’d like to explain how to use Omnichannel Inventory APIs with Salesforce Commerce APIs (aka B2C Commerce API) for Salesforce Order Management solutions. Once we set up our inventory integration, it will be used in the Order Fulfillment stage for allocation of the order items to the available location based on the items’ inventory availability.

There is one prerequisite before we start which is having a program that creates certificates (crypto library). If you don’t have any program installed, you can install OpenSSL. It’s an open source crypto library which I’ll show how to do it.

Using Commerce APIs will require a series of steps and the first one is configuring the environment.
If you already have an environment ready to use, then you can skip Setup Environment step and move to Create Certificate step.

Setup Environment

I’ll create a scratch org with minimum features & settings to have an environment ready for the next steps.

Create an Empty SFDX project and replace project-scratch-def.json file content with the content at below. The new scratch definition file content has the necessary settings & features for the environment we will use.

{
  "edition": "Enterprise",
  "language": "en_US",
  "features": [
    "OrderManagement", 
    "OmnichannelInventory"
  ],
  "settings": {
    "orderSettings": {
      "enableOrders": true,
      "enableOrderEvents": true,
      "enableNegativeQuantity": true,
      "enableZeroQuantity": true,
      "enableEnhancedCommerceOrders": true
    },
    "orderManagementSettings": {
        "enableOrderManagement": true
    },
    "inventorySettings": {
      "enableOmniChannelInventory": true
    }
  }
}

After replacing the content of the file, execute the following SF CLI command to create the scratch org.

sf org create scratch --alias commerceapi --definition-file config/project-scratch-def.json

Validate Omnichannel Inventory Provisioning

After creating the scratch org, be sure you received an email with the title Sandbox: Omnichannel Inventory Tenant Provisioning Succeeded.

If you receive an email saying that Sandbox: Omnichannel Inventory Tenant Provisioning Failed, delete the scratch org and re-create it until you receive a successful email. (You will most likely get the success email)

You can delete the scratch org with the following SF CLI command.

sf org delete scratch --target-org commerceapi

Certificate

Using Salesforce Commerce APIs for Salesforce Omnichannel Inventory will require OAuth 2.0 JWT Bearer Flow. Therefore, we will need a Connected App that uses a digital signature and for that, we will create a certificate and upload to Salesforce.

Install OpenSSL

If you already have a cryptography library installed on your computer, you can skip this step and move to Create Certificate step.

Download OpenSSL

Download OpenSSL (openssl-1.0.2j-fips-x86_64)

No installation is required, unzipping the folder into any location is enough i.e. C:\Users\OpenSSL

Set OpenSSL Path to Environment Variables

Simultaneously press Windows + R and type sysdm.cpl

Windows Command for Environment Variables

Go to Advanced > Environment Variables

System Properties

You’ll see two types of variables: User Variables & System Variables. We’ll go with User Variables.

  1. Double click on variable Path
  2. Select New
  3. Add the path of OpenSSL (extracted) folder including bin directory

Validate OpenSSL Setup

Open any CLI or terminal application you have installed on your machine and execute the following command and you should see a similar response.

openssl version

OpenSSL Version

Create Certificate

Create a new certificate folder on the desktop to organize the certificate and its related files. After, open the folder in a terminal.

Certificate Folder

1. Generate a private key

openssl genpkey -des3 -algorithm RSA -pass pass:commerceapi -out server.pass.key -pkeyopt rsa_keygen_bits:2048

2. Store it in a file called server.key

openssl rsa -passin pass:commerceapi -in server.pass.key -out server.key

You can delete the server.pass.key file because it is no longer needed.

3. Generate a certificate signing request using the server.key file. Store the certificate signing request in a file called server.csr. Enter information about your company when prompted

openssl req -new -key server.key -out server.csr

4. Generate a self-signed digital certificate from the server.key and server.csr files. Store the certificate in a file called server.crt

openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt

5. Generate the public.key file which will be used for JWT debugging & validation

openssl rsa -in server.key -pubout > public.key

Create Custom Scopes

Authorization for Omnichannel Inventory APIs requires scopes. These inventory scopes will be created in Salesforce and later, will be used in the Connected App.

Go to Setup > Identity > OAuth Custom Scopes > New Custom Scope

For each of the scope, enter Name & Description and then, save it (Leave Include on well known endpoint option as unchecked).

NameDescription
sfcc_inventory_impex_graphsExport location graphs
sfcc_inventory_impex_inventory_rwImport inventory records
sfcc_inventory_impex_inventoryExport inventory records
sfcc_inventory_availabilityGet inventory availability data
sfcc_inventory_availability_rwUpdate inventory availability data
sfcc_inventory_reservationsGet inventory reservation information
sfcc_inventory_reservations_rwUpdate inventory reservations
Total: 7

After adding the OAuth custom scopes, the page will look like this:

Create Connected App

The Connected App will be used to the get access token from Salesforce which will be used for Commerce API authorization.

Go to Setup > Apps > App Manager > New Connected App

  1. Enter Connected App Name
  2. Enter Contact Email
  3. Check Enable OAuth Settings
  4. Check Enable for Device Flow
  5. Enter Callback URL
    • For production: https://login.salesforce.com/services/oauth2/success
    • For the others: https://test.salesforce.com/services/oauth2/success
  6. Check Use digital signatures & click Choose File. Upload server.crt file (from the certificates folder that we created before)
  7. Add Selected OAuth Scopes
    • Manage user data via APIs (api)
    • Perform requests at any time (refresh_token, offline_access)
  8. Check Require Secret for Web Server Flow
  9. Check Require Secret for Refresh Token Flow & click Save & Continue.

After creating the connected app, we’ll copy the consumer secret and consumer key of the connected app which will be used later for authorization.

Click Manage Consumer Details (Salesforce will ask you to verify your identity).

  1. Copy Consumer Key (store somewhere temporarily)
  2. Copy Consumer Secret (store somewhere temporarily)
  3. Click Cancel or close the page

Navigate to the Connected App and click Manage > Edit Policies where we’ll configure OAuth policies.

  1. Select Admin approved users are pre-authorized for Permitted Users setting
  2. Select Relax IP retrictions for IP Relaxation setting
  3. Click Save

Now, let’s set the profile associated with this app. Click Manage Profiles and set the profile you desire. Since my user is admin, I’ll associate System Administrator with the connected app.

  1. Selected the profile for association
  2. Click Save

Now, we’ll add the custom Oauth scope we’ve created for the Connected App. Click Manage OAuth Custom Scopes button below to the Manage Profiles button. Select all the custom scopes (1) we created and click Save (2).

Connected App & Authorization via Salesforce CLI

So far we’ve created the certificate, the connected app and then we used the certificate in that connected app. Let’s use Salesforce CLI to validate our steps. Open any terminal or CLI app or Visual Studio Code to run the sf command.

This is the sf command we’ll execute to authorize:

sf org login jwt --username [username] --jwt-key-file [path] --client-id [consumerKey]

--username
The username of the organization.

--jwt-key-file

The path to the server.key file.

--client-id

The consumer key of the connected app.

Sf command with parameters with my details look like this:
sf org login jwt --username test-dagkpcprnyie@example.com --jwt-key-file "C:\Users\firat\Desktop\blog\certificate\server.key" --client-id 3MVG9od6vNol.eBhQ7Qs0Oe.9UNNAf6.ODNsQDdfFQnqAjfsNp4Im..sxBVumdCm6Lqi6qG_WD1PBG72AkKIM

Generate JWT

We’ve everything we need to create a JWT (JSON Web Token) which will be used for Salesforce Omnichannel Inventory APIs.

To generate JWT, I’ll be using the free website https://jwt.io/

1. Select RS256 as Algorithm
2. Build the payload data
{
"iss":"[consumer key of the connected app]",
"aud": "[instance url login/test.salesforce.com]",
"sub": "[username of the org user]",
"exp": [numericDate]
}

The payload for me will look like this:
{
"iss":"3MVG9od6vNol.eBhQ7Qs0Oe.9UNNAf6.ODNsQDdfFQnqAjfsNp4Im..sxBVumdCm6Lqi6qG_WD1PBG72AkKIM",
"aud": "test.salesforce.com",
"sub": "test-dagkpcprnyie@example.com",
"exp": 1714239022
}

3. Paste the content of public.key file (open it with any text editor)
4. Paste the content of server.key file (open it with any text editor)
5. Click Share JWT (somewhere temporarily)

Get Access Token From Salesforce By Using JWT

Before the final step, which is using Commerce APIs and updating inventory, we’ll need the access token from Salesforce by using JWT. For this step, I’ll use Postman to send HTTP requests but any API platform or client would work.

  1. Select POST
  2. Set the endpoint login/test.salesforce.com
  3. Click Body and select x-www-form-urlencoded
  4. Set param key grant_type and the value as urn:ietf:params:oauth:grant-type:jwt-bearer
  5. Set param key assertion and the value as the JWT we generated and stored somewhere temporarily
  6. Click Send
  7. If everything goes well, you’ll see a similar response. Copy access_token and store somewhere temporarily

Send Requests to Salesforce Omnichannel Inventory

Finally, we are here to send some requests to Salesforce Omnichannel Inventory and update some numbers. In this step, I’ll use the Get Availability API by using the access token we grabbed previously, just to see if our approach works.

Base URL
https://{{shortCode}}.api.commercecloud.salesforce.com/{{apiFamily}}/{{apiName}}/v1/organizations/{{organizationId}}/

Get Availability URL
https://{shortCode}.api.commercecloud.salesforce.com/inventory/availability/v1/organizations/{organizationId}/availability-records/actions/get-availability

shortCode and organizationId values are org related. Therefore, we’ll navigate back to org to grab those values.

Go to Setup > Omnichannel Inventory

  • organizationId can be found in Tenant Group ID
  • shortCode can be found in Base URL for Inventory API Calls

After puting the values, the Get Availability endpoint will look like this:
https://GB.api.commercecloud.salesforce.com/inventory/availability/v1/organizations/d8dbf810-64c5-4bf3-aa87-83a0831ad18e/availability-records/actions/get-availability

  1. Select POST
  2. Set the endpoint URL
  3. Click Authorization tab, select Bearer Token and as the value paste the access token we grabbed from Salesforce (see Get Access Token From Salesforce By Using JWT)
    • Select Authorization tab
    • Select Bearer Token
    • Set the access token we grabbed from Salesforce as token (see Get Access Token From Salesforce By Using JWT)
  4. Select Body, for body raw and paste this JSON content
    {"sku":"ProductSku1","group":"Warehouse"}
  5. Click Send

As you can see, we received an error saying “there is no location group as Warehouse” which is correct. Our goal was to accomplish the authorization & authentication which is working. The next steps will be using Commerce APIs directly to update our inventory data.

You can also download the Postman collection which we built along the way.

Leave a Comment

Your email address will not be published. Required fields are marked *