Connecting to Salesforce with ThingWorx

One of the great aspects of ThingWorx is the ability to connect disparate data silos to a central IoT hub. Many of these silos are made accessible through Web APIs. RESTful Web APIs enable developers to pull data from an inexhaustible number of sources around the web; often using nothing but a HTTP URI. Salesforce has an extensive REST API that can be accessed through ThingWorx. This blog will introduce you to creating a “Connected App” on Salesforce, authentication using username and password in ThingWorx, adding records to Salesforce, and finally modifying records. For a detailed description of Salesforce’s REST API, visit https://developer.salesforce.com/page/REST_API

 

Step 1 (Optional): Obtain a Developer Environment with Salesforce.com

If you do not already have a Salesforce account, navigate to https://developer.salesforce.com/platform/force.com and sign up for a free developer environment. It only takes a few minutes and you get a fully functioning Salesforce instance that you can freely develop in.

Step 2: Obtain a Security Token

You’ll need a security token to authenticate with a username and password. If you don’t already have one, or can’t dig it up from previous emails, you’ll need to reset the token.

Resetting the Token

1.    In the upper right-hand corner of your Salesforce page, click on your name and select “My Settings”

2.    On the left-hand menu, select “Personal”

3.    Under “Personal,” select “Reset My Security Token”

4.    Follow the directions on the page and you will receive a new security token via email

Step 3: Create a Connected App

To use the REST API, we’ll need to create a connected app that gives us a “Consumer Key” and a “Consumer Secret”.

Creating the Connected App

1.    Click on “Settings” in the upper right of your Salesforce screen

2.    On the left side, navigate to “Build” > “Create” > “Apps”

3.    Under the “Connected Apps” section, select “New”

 

4.    Fill out the fields as shown below. A callback URL is required but we won’t really be referencing it anywhere in ThingWorx. There is a great article on using Postman to test out REST calls with Salesforce at https://blog.mkorman.uk/using-postman-to-explore-salesforce-restful-web-services/ . The callback URL is used in the examples when authenticating in Postman.

 

 

5.    Click “Save.” You will get an alert that your connected app will take 2-10 minutes to take effect.

6.    After you click “Save,” you’ll see the “Consumer Key” and “Consumer Secret.” Copy those somewhere to use in ThingWorx.

 

Step 4: Authenticate Salesforce Session in ThingWorx

In this step, we’ll create a service in ThingWorx that returns a JSON for us to use in our other Salesforce requests.

1.    Create a service inside your Thing called AuthenticateSalesForce. I have a “TestThing” that I’ve created where I can try out new services without disrupting any of my live projects.

 

 

2.    Choose the “STRING” type for the result output, no inputs are needed unless you want to have the end user input their username and password. After we test functionality, we’ll change the output type to “JSON”

3.    Enter the following code, which is just the POST JSON function in the ContentLoaderFunction resource.

var params = {

                 proxyScheme: undefined /* STRING */,
                 headers: undefined /* JSON */,
                 ignoreSSLErrors: undefined /* BOOLEAN */,
                 useNTLM: undefined /* BOOLEAN *
                 workstation: undefined /* STRING */,
                 useProxy: undefined /* BOOLEAN */,
                 withCookies: undefined /* BOOLEAN */,
                 proxyHost: undefined /* STRING */,

url: "https://login.salesforce.com/services/oauth2/token?grant_type=password&client_id=<consumer_key>&client_secret=<consumer_secret>&username=<username> &password=<password_plus_security_token>" /* STRING */,

                 content: undefined /* JSON */,
                 timeout: undefined /* NUMBER */,
                 proxyPort: undefined /* INTEGER */,
                 password: undefined /* STRING */,
                 domain: undefined /* STRING */,
                 username: undefined /* STRING */

};

// result: JSON
var j = Resources["ContentLoaderFunctions"].PostJSON(params);

var result = j.access_token;

4.    Enter the consumer key, consumer secret, username (use %40 for the ‘@’ symbol), and password plus security token (enter your password and security token with no spaces between the two)

5.    Select “Done” on your service, save your Thing, and test the service. You should receive a session token like the one seen below:

 

 

6.    If nothing shows up, either the Salesforce server hasn’t activated the app, or there may be an issue with the URL. If you copy and paste the URL into PostMan, you should get an error message that clarifies the issue.

7.    When you’re getting an access token as the result, edit your service, change the result type to “JSON,” delete the last line (the “var result = j.access_token” line”), and modify the end of the service to now read:

// result: JSON

var result = Resources[“ContentLoaderFunctions”].PostJSON(params);

 

Step 5: Create a record in Salesforce

In this step, we’ll create a new account within salesforce using our new authentication service and a REST call utilizing the ContentLoaderFunctions.

1.    Create another new service in your Thing and call it AddSalesForceAccount. 2.    Create an input and call it AccountName. The type is “STRING” 3.    Type in the following code:

var authJSON = me.AuthenticateSalesForce();

var token = authJSON.access_token;
var instance_url = authJSON.instance_url;

var url = instance_url + "/services/data/v20.0/sobjects/Account/";

var authString = "Bearer " + token;
var headers = {
   "authorization" : authString,
   "content-type" : "application/json"
};

var content = {
 "Name" : AccountName
};

var params = {
                 proxyScheme: undefined /* STRING */,
                 headers: headers /* JSON */,
                 ignoreSSLErrors: undefined /* BOOLEAN */,
                 useNTLM: undefined /* BOOLEAN */,
                 workstation: undefined /* STRING */,
                 useProxy: undefined /* BOOLEAN */,
                 withCookies: undefined /* BOOLEAN */,
                 proxyHost: undefined /* STRING */,
   url: url /* STRING */,
                 content: content /* JSON */,
                 timeout: undefined /* NUMBER */,
                 proxyPort: undefined /* INTEGER */,
                 password: undefined /* STRING */,
                 domain: undefined /* STRING */,
                 username: undefined /* STRING */
};

// result: JSON
var result = Resources["ContentLoaderFunctions"].PostJSON(params);

4. Test the service. Enter a unique account name and verify that it shows up in Salesforce.

 

 

 

 

Step 6: Retrieve a Record ID

To modify a record, the record ID must be used to reference the object of interest. We can make a request to Salesforce to return relevant records using an SOQL query. This example will cover retrieving the record ID of the account we just created in the last step.

1.    Create a new service in your Thing

2.    Create an input and call it AccountName. The type is “STRING”

3.    Type in the following code:

var authJSON = me.AuthenticateSalesForce();


var token = authJSON.access_token;
var instance_url = authJSON.instance_url;

var url = instance_url + "/services/data/v20.0/query/?q=SELECT+name+FROM+Account+WHERE+name+=+'" + AccountName + "'";

var authString = "Bearer " + token;
var headers = {
   "authorization" : authString,
   "content-type" : "application/json"
};




var params = {
                  proxyScheme: undefined /* STRING */,
                  headers: headers /* JSON */,
                  ignoreSSLErrors: undefined /* BOOLEAN */,
                  useNTLM: undefined /* BOOLEAN */,
                  workstation: undefined /* STRING */,
                  useProxy: undefined /* BOOLEAN */,
                  withCookies: undefined /* BOOLEAN */,
                  proxyHost: undefined /* STRING */,
                  url: url /* STRING */,
                  timeout: undefined /* NUMBER */,
                  proxyPort: undefined /* INTEGER */,
                  password: undefined /* STRING */,
                  domain: undefined /* STRING */,
                  username: undefined /* STRING */

};




// result: JSON
var j = Resources["ContentLoaderFunctions"].GetJSON(params);

var result = j.records[0].attributes.url;

 

4. Give the service a name and test it. The output of this service is a url that can be appended to the instance_url that is returned in the response from the Authentication service.

 

 

Step 7: Modify a Record

Using the output from our last service, we can now easily modify the fields of the record ID that we just retrieved. Keep in mind, if you create a custom field and you want to modify its value, add a “__c” to the end of the field name (denotes custom field).

  1. Create a new service in your Thing
  2. Let’s give it a few “STRING” inputs: field, stringValue, and AccountName
  3. Input the following code:
var authJSON = me.AuthenticateSalesForce();

var token = authJSON.access_token;
var instance_url = authJSON.instance_url;

var stringJSON = '{"' + field + '":' + stringValue + "}";


var params = {
                  AccountName: AccountName /* STRING */
};

// result: STRING
var object_url = me.RetrieveSalesForceAccountRecordID(params);

var url = instance_url + object_url + "?_HttpMethod=PATCH";
var authString = "Bearer " + token;
var headers = {
   "authorization" : authString,
   "content-type" : "application/json"
};

var content = JSON.parse(stringJSON);

var params = {
                  proxyScheme: undefined /* STRING */,
                  headers: headers /* JSON */,
                  ignoreSSLErrors: undefined /* BOOLEAN */,
                  useNTLM: undefined /* BOOLEAN */,
                  workstation: undefined /* STRING */
                  useProxy: undefined /* BOOLEAN */,
                  withCookies: undefined /* BOOLEAN */,
                  proxyHost: undefined /* STRING */,
                  url: url /* STRING */,
                  content: content /* JSON */,
                  timeout: undefined /* NUMBER */,
                  proxyPort: undefined /* INTEGER */,
                  password: undefined /* STRING */,
                  domain: undefined /* STRING */,
                  username: undefined /* STRING */
};
// result: JSON
var result = Resources["ContentLoaderFunctions"].PostJSON(params);

 

 

 

 

A Note About Security

Salesforce has a few ways to authenticate your session.  The method described in this blog is the least secure way because ThingWorx has visibility to the username and password of the Salesforce account.  There are two other ways to authenticate and both use callback URLs.  Basically, a user sends a call to the login endpoint and enters user and password information directly into the Salesforce environment.  Salesforce then redirects to a callback URL that is appended with an authorization token.  If you’d like to implement one of the more secure methods, I would suggest using a REST endpoint to a ThingWorx service as your callback URL. More specifically, create a service that has a string input called “code.” Now, change your callback URL in your Salesforce connected app to something like https://<thingworxAddress>/ThingWorx/Things/TestThing/Services/getCode?appKey=<appKey>&x-thingworx-session=true&method=post.  For your authentication, your URL will look like https://login.salesforce.com/services/oauth2/authorize?response_type=code&client_id=<client_id>&redirect_uri=<redirect_uri>.  Now, when you navigate to the login link, it will send your authorization code to your ThingWorx service (this is because it appends “&code=<yourAuthCode>” to the URL).  You’ll need to then send that code via the Content Loader Functions to receive your authorization token.  One thing to note is that the ThingWorx instance must be on HTTPS.  Salesforce does not allow HTTP callback URLs.  More information about Authentication can be found at https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_understanding_authentication.htm

 

If you have any questions about this blog or ThingWorx in general, don’t hesitate to leave a comment or contact EAC Product Development Solutions.