Configure a custom order submit integration job

  • Updated

The following walk-through will help you create an Order Submit integration job. This Order Submit job will take orders placed in Optimizely Configured Commerce and submit them to the ERP. From there, the ERP typically handles fulfillment of the order.

Many submission jobs will use an API provided by an ERP, so it is crucial that you know how to use the API before continuing. If you are unfamiliar, you should consult with somebody more familiar with the ERP API.

This job will use the GenericSubmit preprocessor, a custom integration processor, and the ProcessSubmitResponse post processor. The GenericSubmit preprocessor retrieves a customer order and related data from the Configured Commerce database using an order number. The custom integration processor will submit that customer order to the ERP via the API. The integration processor will also create a result data set that contains the ERP order number, which is returned from the ERP after submitting the customer order. The ERP order number will link the customer order in Configured Commerce with the customer order in the ERP. The ProcessSubmitResponse post processor will take the ERP order number from the result data set and update the customer order in the Configured Commerce database. For simplicity, this walk-through uses a separate application to represent the ERP, rather than use a full-blown ERP.

Preconditions

Before you start, make sure you've completed the following tasks.

Create the fake ERP application

First, you will create the FakeERP application. This application will have an API with an endpoint for submitting an order. This endpoint will be available at /api/order using a POST request. This application will be an ASP.NET Web API application. You do not need to know how this type of application works. You just need to know how to run it within Visual Studio.

  1. Open Visual Studio.
  2. Create a new ASP.NET Web Application named "FakeERP".
  3. Select the Web API template.
  4. In the Controllers directory, add a new, empty Web API controller named "OrderController".
  5. Add the following code to the file. As mentioned before, you do not need to worry about the implementation. The application just needs to run and respond to the order submission endpoint.
    public class OrderController : ApiController{    [Route(Name = "GetOrder")]    public HttpResponseMessage Get([FromUri] string id)    {        var response = this.Request.CreateResponse(HttpStatusCode.OK, new Order());        return response;    }     public HttpResponseMessage Post([FromBody] Order order)    {        // ERP processing for order         order.ErpOrderNumber = Guid.NewGuid().ToString();         var response = this.Request.CreateResponse(HttpStatusCode.Created, order);        response.Headers.Location = new Uri(this.Url.Link("GetOrder", new { id = order.ErpOrderNumber }));         return response;    }} public class Order{    public string OrderNumber { get; set; }     public string CustomerNumber { get; set; }     public string ErpOrderNumber { get; set; }}
  6. Build the solution and run the application. This can usually be done in the Debug menu by selecting Start Debugging.
  7. When the browser opens, copy the URL in the address bar. You will need this when you set up the integration connection.
  8. Stop running the application. Click the "stop" icon button in the header menu in Visual Studio.

That's it! The FakeERP application is complete. It does not store the customer order anywhere because that does not matter for this walk-through. In a production environment, you will be submitting the customer order to a real ERP. For simplicity, this application returns a new Guid value as the ERP order number. You will need to run this application again later, so keep track of it.

Now that the FakeERP application is complete, you can start configuring the integration connection to the FakeERP application.

Create the integration connection to the FakeERP application

The integration connection is used to specify the URL used to connect to the FakeERP application.

  1. Start up your Configured Commerce application.
  2. Log into the Admin Console. You can go to /admin to get there.
  3. Go to Administration > Jobs > Connections.
  4. Click Add Integration Connection.
  5. In the Name field, type "FakeERP API".
  6. In the Type Name drop-down, select "WebService".
  7. In the Source Server Time Zone drop-down, select the appropriate time zone.
  8. In the Url field, type the URL you copied from the FakeERP application and append "api". You should end up with something like "http://localhost:24443/api". This is the URL you use to make API requests to the FakeERP application.
  9. Click Save in the top right corner.

If the API requires you to be authenticated, you could specify those credentials using the Log On and Password fields. Then, within your custom integration processor, you could authenticate with the API using those credentials.

Below is an image of the integration connection configuration.

Now that the connection is configured, you need to configure the WIS you installed.

Configure the WIS

Before continuing, you need to configure the WIS with the integration connection that you just created. This will allow you to select an integration processor for the integration job and also allow the job to be executed.

Next, you can create the job that actually does the work of submitting the customer order to the ERP.

Create the order submit integration job

This integration job uses standard processors and a single job step to specify the OrderNumber parameter. First, you need to configure the job details.

Configure the job details

  1. In the Admin Console, go to Administration > Jobs > Job Definitions.
  2. Click Add Job Definition.
  3. Select the Details finger tab.
  4. In the Job Name field, type "Order Submit". This name can be different, but the name "Order Submit" helps indicate what type of job it is and which Configured Commerce object is being affected.
  5. In the Job Type drop-down, select "Submit".
  6. In the Connection drop-down, select the "FakeERP API" integration connection you just created. This will allow the integration processor to connect to the ERP using the connection.

Below is an image of the job details up to this point.

The Preprocessor, Integration Processor, and Post Processor fields are used to indicate what type of work will actually be completed by the integration job. These processors operate in the order the fields appear in the form. The preprocessor does any preprocessing required for the job. This can include aggregating data or constructing a query for the integration processor to use. The integration processor builds on the work done by the preprocessor, usually operating on the data or objects retrieved or constructed by the preprocessor. The post processor processes the response from the integration processor. This can include consuming data retrieved from the ERP by the integration processor. You can read more about the other preprocessors, integration processors, and post processors and what purpose they serve.

  1. For the Preprocessordrop-down, select "GenericSubmit". This preprocessor retrieves a customer order and related data from the Configured Commerce database using an order number.
  2. For the Integration Processordrop-down, select "None" for now. You will come back to configure this later after you have created the custom integration processor.
  3. For the Post Processordrop-down, select "ProcessSubmitResponse". This post processor will take the ERP order number from the result data set returned by the integration processor and update the customer order in the Configured Commerce database.
  4. For the Standard Job Namedrop-down, select "Order Submit". This setting is how Configured Commerce determines which job to use when submitting a customer order to the ERP.
  5. Click Save in the top right corner.

Below is an image of the processor configuration. For now, you can ignore the Notifications, Run Options, and Recurrence sections.

Now that the processors and integration connection have been configured, you can create the integration job step. This job step is expected by the GenericSubmit preprocessor.

Create the job step

Integration job steps provide a way to order work within a job. Each job step will be executed once during the job execution. The job steps are executed in ascending order using the Sequence number. For this job, you only need one job step to specify a parameter to hold an order number. This order number will be used by the GenericSubmit preprocessor to retrieve the customer order within the Configured Commerce database. The customer order will eventually be submitted to the ERP.

  1. Select the Steps finger tab.
  2. Click the Add Job Definition Step button.
  3. In the Sequence field, type "1". This is the first and only integration job step in this job.
  4. In the Step Name field, type "Submit Order". This is a friendly name for the job step. It can help others understand the responsibility of each job step.
  5. In the Target Object drop-down, select "Cart". Cart is the same as customer order. This is the type of object that will be retrieved from the Configured Commerce database. Using the OrderNumber parameter, the GenericSubmit preprocessor will retrieve a customer order object.
  6. Click Save in the top right corner.

Below is an image of the job step configuration up to this point.

You can ignore the Delete Behavior and query clause fields (such as Select Clause, From Clause). The processors used by this job will not use these fields.

Now that the Target Object is configured, you can add the OrderNumber parameter.

Configure the OrderNumber parameter

The GenericSubmit preprocessor expects the parameters to be natural key properties on the Target Object.

  1. Select the Parameters finger tab.
  2. Click Add Job Definition Step Parameter.
  3. In the Name field, type "OrderNumber". The casing for this name does not matter. This is the name of the natural key property for the customer order (Cart) object.
  4. For the Value Type drop-down, select "String". The OrderNumber property is a string.
  5. Click Save in the top right corner.

You should leave the Default Value field blank. This is the value used when the integration job is executed and the OrderNumber parameter value is not specified (it is blank). Leaving this field blank is a precautionary measure. If the default value is an actual order number and the integration job is executed without specifying a value for the OrderNumber parameter, the customer order linked to the default value could be submitted multiple times.

The Prompt field is used to configure instructional text for this parameter. This instructional text is displayed as a form label when a user schedules this integration job manually. Leave the Prompt field blank for now. You can always come back to configure it. Below is an image of the form displayed. The Prompt text is "Please provide an order number".

Below is an image of the OrderNumber parameter configuration.

After you have configured the parameter, you need to create the custom integration processor. This integration processor will actually submit a customer order to the ERP via the API.

Create the custom integration processor

The integration processor will know how to communicate with the ERP in order to submit a customer order. This custom integration processor will be communicating with the FakeERP application you created earlier.

  1. In Visual Studio, open your Configured Commerce solution.
  2. The Configured Commerce solution comes with an "Extensions" project. This is where you can place custom preprocessors and post processors. However, custom integration processors should not be placed here because they run in the WIS installed on your computer, not within the context of the Configured Commerce application. There is a bit more to the reasoning, but for now you can use a separate project for the custom integration processor. Add a new Class Library project to your solution named "Extensions.Integration".
  3. In the Extensions.Integration project, add a new class named "IntegrationProcessorFakeERPSubmitAPI". If you preprend the class name with "IntegrationProcessor", that bit will be removed from the name when displaying the processor in the drop-down field in the integration job configuration.

    public class IntegrationProcessorFakeERPSubmitAPI{}
  4. Implement the IIntegrationProcessor interface. To be used as an integration processor, the class MUST implement this interface. You may need to reference the Insite.WIS.Broker library.

    public class IntegrationProcessorFakeERPSubmitAPI : IIntegrationProcessor{    public DataSet Execute(SiteConnection siteConnection, IntegrationJob integrationJob, JobDefinitionStep jobStep)    {        throw new NotImplementedException();    }}
  5. Within the Execute method, create a new IntegrationJobLogger. The job logger is used to log information to the job logs during the job execution. The job logger can log informational statements, warnings, and errors. You can view these job logs in the Admin Console at Administration > Jobs > Job Definitions > Order Submit > History. After you create the job logger, log an informational message stating that the order submission is starting.

    public DataSet Execute(SiteConnection siteConnection, IntegrationJob integrationJob, JobDefinitionStep jobStep){    var jobLogger = new IntegrationJobLogger(siteConnection, integrationJob);     jobLogger.Info("Starting OrderSubmit to FakeERP API.");}
  6. Get the initial data set created by the GenericSubmit preprocessor and validate the expected data. The preprocessor should have included a table named "CustomerOrder" in the data set to hold the customer order. You are going to use the "OrderNumber" and "CustomerNumber" from this table. There is an object named "Data" located in the Insite.WIS.Broker.Plugins.Constants namespace. This object includes values for all the data set tables and columns used during integration. You can use the Data.CustomerOrderTable value instead of directly typing "CustomerOrder" to retrieve the table.

    public DataSet Execute(SiteConnection siteConnection, IntegrationJob integrationJob, JobDefinitionStep jobStep){    // ...     // You may need to reference Insite.Common to use the XmlDatasetManager.    var initialDataset = XmlDatasetManager.ConvertXmlToDataset(integrationJob.InitialData);     if (initialDataset == null        || !initialDataset.Tables.Contains(Data.CustomerOrderTable)        || initialDataset.Tables[Data.CustomerOrderTable].Rows.Count == 0)    {        // The Fatal method does not halt execution. It simply logs the information        // specifying a log type of "Fatal". This can make it easier to find important        // issues when viewing the job logs.        jobLogger.Fatal("The initial dataset is empty and OrderSubmit cannot proceed. Please verify that the GenericSubmit preprocessor is being used for this job.");        throw new ArgumentException("Invalid initial dataset");    }}
  7. Retrieve the "OrderNumber" and "CustomerNumber" from the "CustomerOrder" table. These two values are stored in separate columns in the first row of the table. These column names are also included in the Data object, so you do not have to type the name.

    public DataSet Execute(SiteConnection siteConnection, IntegrationJob integrationJob, JobDefinitionStep jobStep){    // ...     var dataRowCustomerOrder = initialDataset.Tables[Data.CustomerOrderTable].Rows[0];     var customerNumber = dataRowCustomerOrder[Data.CustomerNumberColumn].ToString();    var orderNumber = dataRowCustomerOrder[Data.OrderNumberColumn].ToString();}
  8. For this walk-through, you have the information you need to submit the order to the ERP (you may need more depending on your specific ERP). Communication with the API will involve the JSON data type. Some of the work requires a third-party library called "Newtonsoft.Json". You can install it using the Package Manager Console and the command below.

    install-package Newtonsoft.Json

    After you have installed the package, you can create the request objects to send to the ERP API. This involves creating a separate Order class to hold the ERP response object. You can also create a variable to hold the ERP order number returned in the ERP response.

    public class Order{    public string OrderNumber { get; set; }     public string CustomerNumber { get; set; }     public string ErpOrderNumber { get; set; }}
    public DataSet Execute(SiteConnection siteConnection, IntegrationJob integrationJob, JobDefinitionStep jobStep){    // ...     var orderRequestObject = new Order { OrderNumber = orderNumber, CustomerNumber = customerNumber };    var orderRequestJson = JsonConvert.SerializeObject(orderRequestObject);     // This will hold the ERP order number returned from the API.    var erpOrderNumber = string.Empty;}
  9. Now you need to create a client to communicate with the API. This can be done using any standard API library, like RestSharp. In this case, you can use the .NET HttpClient so you do not need to download and include another Nuget package. After you create the client, you can send the request to the /order endpoint. You can use the integration connection URL to create the absolute URL.

    using (var httpClient = new HttpClient()){    var result = httpClient.PostAsync(integrationJob.JobDefinition.IntegrationConnection.Url + "/order", new StringContent(orderRequestJson, Encoding.UTF8, "application/json")).Result;    var contentString = result.Content.ReadAsStringAsync().Result;    var updatedOrder = JsonConvert.DeserializeObject<Order>(contentString);     erpOrderNumber = updatedOrder.ErpOrderNumber;}
  10. Create the data set that will be returned. The ProcessSubmitResponse post processor expects an "OrderSubmit" table when processing a submitted customer order. The table needs to include the Configured Commerce order number and the ERP order number in separate columns, named "OrderNumber" and "ErpOrderNumber". This allows Configured Commerce to find the matching customer order and update the ERP order number. The table and columns names are also included in the Data object so you do not have to type the names.

    public DataSet Execute(SiteConnection siteConnection, IntegrationJob integrationJob, JobDefinitionStep jobStep){    // ...     var resultDataSet = new DataSet();    var orderSubmitTable = resultDataSet.Tables.Add(Data.OrderSubmitTable);    orderSubmitTable.Columns.Add(Data.OrderNumberColumn);    orderSubmitTable.Columns.Add(Data.ErpOrderNumberColumn);     var orderNumberRow = orderSubmitTable.NewRow();    orderNumberRow[Data.OrderNumberColumn] = orderNumber;    orderNumberRow[Data.ErpOrderNumberColumn] = erpOrderNumber;     orderSubmitTable.Rows.Add(orderNumberRow);     jobLogger.Info($"Finished OrderSubmit for order #{orderNumber}.");     return resultDataSet;}

    Now the integration processor is complete. However, it needs to be accessible to the WIS.

  11. Build your solution.
  12. Go to the Extensions.Integration debug directory in the file system and find the "Extensions.Integration.dll" file.
  13. Copy the DLL and paste it into the DLL folder where the WIS will be looking to load custom integration processors. This DLL folder is configured in the SiteConnections.config file in the install directory of the WIS. On my computer, this is located at C:\Program Files\Optimizely\Commerce Integration Service V4.3\SiteConnections.config. If the WIS is already running, make sure to stop it before copying over the DLL.
  14. Back in the Extensions.Integration debug directory, find the "Newtonsoft.Json.dll" file.
  15. Copy the "Newtonsoft.Json.dll" file to the install location of the WIS. You will need to copy all the third-party library DLLs used by the integration processor.
  16. After you copy over the DLLs, start the WIS.
  17. In the same directory as the SiteConnections.config file, find the log.txt file.
  18. Open the log.txt file and verify your custom integration processor is found and loaded. The log file appends new logs, so look near the bottom of the file.

If the integration processor is not found or loaded, check for errors in the log.txt file. Also, verify the site connection in the SiteConnections.config file is configured correctly. If you need to, go back and verify you configured the WIS correctly.

Now that the integration processor is complete and loaded into the WIS, you need to configure the Order Submit integration job to use it.

Configure the order submit job with the integration processor

  1. Back in the Admin Console, go to Administration > Jobs > Job Definitions > Order Submit > Details.
  2. If everything was configured correctly up to this point, the Integration Processor drop-down should now have an entry for "FakeERPSubmitAPI", your custom integration processor. Select your custom integration processor.
  3. Click Save in the top right corner.

Now that the Order Submit job has been configured with the integration processor, you can run the job manually to verify it works.

Run the order submit job manually

Before you can run the job manually, you need to make sure the FakeERP application is running. Once that is up and running, you need to get an order number for an order so you can submit it to the ERP. Remember, you created an OrderNumber parameter earlier. To get an order number, checkout on the Storefront. On the Order Confirmation page, copy the order number. Now you are ready to run the job.

  1. Back in the Admin Console, go to Administration > Jobs > Job Definitions > Order Submit.
  2. In the top right corner, click More Actions.
  3. Select "Schedule Job". A dialog will display with a form that has a field for an order number.
  4. For the Order Number field, use the order number you copied earlier.
  5. Click Schedule Job.

You can check the status of the job while it is running.

  1. Select the History finger tab. Here you can see a list of the past executions of this job.
  2. Find the most recent execution and click the View button. Here you can see the status of the execution, the parameters used by the job, and the job logs.

If the job fails, you can select the Job Logs finger tab. Here you can see the various logs that were recorded. If you notice an error log, you can click the View button again to view the error description. If you do not find an obvious error, walk back through the steps to make sure you configured the job correctly. If the job is configured correctly, but still fails, you can read about advanced troubleshooting steps to diagnose the problem.

If the job succeeds, you can verify the ERP order number was updated for the customer order. Go to Sales > Cart History and find the customer order you just submitted. On the details page, the ERP Order Number should have a new Guid value assigned to it. This order submit process will also create a copy of the customer order and use it to create an entry in the order history. This means that the order history will also have the ERP Order Number sent back from the ERP. The customer order and order history are separate objects, but may contain the same data. You can find the order history entry in the Admin Console by going to Sales > Order History. If the job fails, there may not be an entry in the order history.

The job now executes successfully. However, in many cases you may want the order submission to the ERP to happen automatically. When a user completes checkout in Configured Commerce, that order can be submitted to the ERP without your intervention. You can enable this by modifying a system setting.

Modify order submit settings

The system setting named "Submit Orders to ERP" dictates whether or not Configured Commerce customer orders are submitted to the ERP after checkout. If the setting is set to "Yes", the Order Submit integration job you just created will be executed after a user completes checkout on the Storefront. To modify the setting, go to Administration > System > Settings > Integration > Order Submit.

In order for this to work, the Order Submit integration job MUST be assigned the Order Submit standard job name. This is how Configured Commerce finds the correct job to use in order to submit the customer order to the ERP. If you followed the steps for creating the integration job, this job name is already configured so you do not need to worry. This is just a reminder of the required configuration.

Submit order through checkout

Now, you should be able to see the entire workflow in action. A user submits an order on the Configured Commerce Storefront, the Order Submit job is scheduled, the customer order is submitted to the ERP, the customer order in Configured Commerce is updated with an ERP order number. Below are a few things you can do during the workflow to verify each step is executing correctly.

  • After the order is submitted on the Storefront, go back to the Admin Console to verify the Order Submit job is scheduled. The job will not have a date scheduled, but there will be an entry in the History finger tab.
  • After the job completes, verify the status in the History finger tab.
  • If the job failed, check the Job Logs finger tab. The job logs may show an error that is preventing a successful execution.
  • Finally, you can check the customer order within Configured Commerce. In the Admin Console, go to Sales > Cart History and find the order. The ErpOrderNumber should be updated with a Guid value. Again, this order submit process will also create a copy of the customer order and use it to create an entry in the order history. This means that the order history will also have the ERP Order Number sent back from the ERP.

Resources