Salesforce B2B Commerce Lightning Flows

Salesforce makes changes to backend code execution easy

Imagine you have an application that needs to change some specific execution logic at runtime but cannot be opened modified and recompiled. At first it would seem impossible right?. After all, the logic in a program is based on code. If you want to change the direction an application runs after it has been compiled you need open the code and change it then recompile and deploy. That is exactly the problem my colleague Dan Madoni and I faced some time ago – and it is coincidentally exactly the same problem that Salesforce Lightning Flows has solved in a fantastically elegant manner.

In 2006 Dan Madoni and I worked on a .NET framework called PathNET . This framework allowed us to change the logic flow of an application at runtime without redeploying code. We accomplished this by using .NET reflection, a database table and some IoC - before anyone in the .NET world had heard the term IoC.  To be specific, our code would invoke action result classes via reflection based on a db table that listed the class names that could be used.  Long story short – by changing the action result class name listed in a db table we literally changed the path of execution of the application at runtime. Instead of class A it would instantiate class B.  Hence, we could drastically alter the flow without recompiling and redeploying code. Our tagline was “PathNET allows decision makers and business user to change the execution of an application without programming “.  Sound familiar?  Substitute the word Salesforce for PathNET and you have something that you might hear in a Lightning Flow video. 

Lightning Flows are very nice indeed

As you may already know, Lightning Flows are a replacement for the Cloud Flow Designer. According to Salesforce, Lightning Flows provide the following advantages:

  • Lightning Flow Components. Leverage reusable Lightning components to design rich flow screens and guided, visual processes.
  • Integrated Processes. Orchestrate workflows and 3rd party services with Platform Events, External Services, and Local Actions.
  • Process-Driven Apps. Embed Lightning Flow processes into every customer and employee app experience using Lightning App Builder and Community Builder

In the following paragraphs we will show an example substituting a given class at runtime in a Lightning Flow.  From the perspective of a B2B Commerce application this solution provides a great structure to maintainany number of integrations between B2B Commerce and external services, while offering the ability to quickly swap out code and change the logic of the flow. Or in the words of Salesforce’s documentation “ …orchestrate 3rd party services with Platform Events and External  Services…” 

If you have worked with Salesforce B2B Commerce before, you know already that integration is a considerable part of any implementation.  The commerce system doesn’t live in a vacuum. It exchanges data with ERP’s, payment processors and tax services just to name a few.

In order to wire up a new service call within a Lightning Flow we need to execute the following steps : 

  1. Copy the existing lightning flow or sub-flow that needs modifications
  2. Write an apex class that implements the respective interface needed
  3. Insert the apex class into the RegisteredExternalServices object 
  4. Insert the Registered External Service reference into the StoreIntegratedService object 
  5. Connect the previously copied flow’s action to the service class

Here is a screenshot of the Flow shipping with Lightning B2B Commerce implementation, found at Setup > Flows > Checkout Flow Template

B2B Checkout Flow

Notice the branches dealing with subflows. Each subflow can optionally contain custom code.

Copy the flow you want to modify
Its simply a best practice – plus as far as I know you cannot just arbitrarily alter an original base flow. Hence the first step is copying and working on your own version of a flow (or sub-flow)

Create a tax service apex class 
We are interested in looking at the Calculate Taxes Action where we would like to run some custom code that calls an external tax service like Avalara or Vertex. As previously covered, in order to do that we need to substitute our own class here. By the way, before making changes it may be a good idea to clone the Flow first.  

The sample B2B Store should ship with a sample tax implementation.  When you modify this to create your own version you will need to implement checkout.CartTaxCalculations passing the cart Id and an instance of jobInfo. 

implements sfdc_checkout.CartTaxCalculations {
global sfdc_checkout.IntegrationStatus startCartProcessAsync(sfdc_checkout.IntegrationInfo jobInfo, Id cartId)

It might be easiest just to copy the class and modify its contents.

The actual implementation decisions in the body of the class are wide open. You can look at a local object, an external commercial web service like Avalara or a call to some custom code in your ERP (via web service). Whatever your desired solution, you will need bits of information - the DeliveryGroup being used in this checkout and the Cart Items.  You will also want to delete any existing CartTaxEntries, since your class is replacing this data with new calculations.  Tax data is persisted at the line item level, so make sure you write code that deals with it at that level instead of trying to pull together the total tax for the cart in one shot.  The checkout display will automatically show the total for line item tax data that had been persisted in this class, so you don’t have to worry about it.  

If you are used to working with the managed package version of B2B Commerce you will notice immediately the flexibility of this approach. It falls in line with other aspects of coding Salesforce. You can use DML directly as you please without having to work through the former CloudCraze API of the managed package. Nice. 

Add the service class to RegisterExtendedService Object 
This is typically done using Workbench. The screenshot below shows the results of several classes having been registered. Be sure to select version 49 of the API. 


Add the RegisteredExternalService to the StoreIntegratedObject
Again using Workbench you will need to insert the service id similarly to the screenshot below. Start by identifying the RegisteredeExternalService ID .


When done inserting the record, the StoreIntegratedService will look like similar to the example below.


Connect the Action of the flow to the service class. 
Lastly add an Action to the subflow in order to pick the tax integration service you just created


That’s all there is to it. 

To summarize, Salesforce provides Lightning Flows that enable users to associate actions with custom code at runtime, without recompiling anything. It’s an elegant way to alter the execution of logic within Salesforce. This particular approach lends itself especially to B2B Commerce implementations which always have integration points related to ERP’s, payment processors and other services (e.g. taxes, shipping etc)