For this post, I will offer a simple explanation of the complex, yet interesting areas essential for the complete understanding of Salesforce Integration’s capabilities. The business scenario quoted, along with the working code samples, will be a good starting point for entering into the world of non-declarative ways for integrating with Salesforce. Here’s what I’ll cover:
Understanding authentication and its prerequisites
OAuth authentication flows for REST API calls
Apex triggers and callouts
REST API, REST web services, and Apex web services
1) Authentication and Its Prerequisites
Authenticating a client application is the first and foremost step while building an interface.
The authentication method depends on your chosen call type (REST or SOAP). Let’s see how to do it using REST.
Before moving any further, let’s frame a business scenario. We’ll use two Salesforce instances that exchange Account details. When a new Account is created in one org, it will flow down to the other Salesforce org, and in return the source org will get the Salesforce Record ID of the created record. These two orgs are:
Source Salesforce org (used for callout) – Source
Target Salesforce org (used for receiving requests) – Target
Following our business scenario, we can say that authentication is a collection of the following sub-steps. Though actual authentication calls a trigger from the Apex code, consider these steps as the prerequisites because without them being completed first, the authentication calls won’t work.
Choosing OAuth Endpoint (to be invoked from Source org)
Choosing OAuth Authentication flow (to be used by Source org)
Remote Site Setting in Source Org.
Understanding authentication and its prerequisites
OAuth authentication flows for REST API calls
Apex triggers and callouts
REST API, REST web services, and Apex web services
1) Authentication and Its Prerequisites
Authenticating a client application is the first and foremost step while building an interface.
The authentication method depends on your chosen call type (REST or SOAP). Let’s see how to do it using REST.
Before moving any further, let’s frame a business scenario. We’ll use two Salesforce instances that exchange Account details. When a new Account is created in one org, it will flow down to the other Salesforce org, and in return the source org will get the Salesforce Record ID of the created record. These two orgs are:
Source Salesforce org (used for callout) – Source
Target Salesforce org (used for receiving requests) – Target
Following our business scenario, we can say that authentication is a collection of the following sub-steps. Though actual authentication calls a trigger from the Apex code, consider these steps as the prerequisites because without them being completed first, the authentication calls won’t work.
Choosing OAuth Endpoint (to be invoked from Source org)
Choosing OAuth Authentication flow (to be used by Source org)
Remote Site Setting in Source Org.
Connected App enables Salesforce to recognize and authenticate an external application as a new entry point. OAuth is used for this authentication. We need to create a Connected App record in Target org. Below is an illustration.
Connected App in Target Org.
callback url should be specified in the remote site setting
Once after saving the record the client id and clientSecret are generated.
Create a Trigger to make an asynchronous call from source org to target org
Trigger on account Object:
1 2 3 4 5 6 | trigger SendAccount on Account(after insert) { for(Account a : Trigger.new){ SendAccountFromSource.createAccount(a.Name, a.Id); } } |
Apex Class to make a callout :
Replace the clientid,secret,username and password's of your org.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2 | public class SendAccountFromSource { private final String clientId = 'Clent Id from App'; private final String clientSecret = 'clientSecretfrom app'; private final String username = 'username'; private final String password = 'passwordwithsecuritytoken'; public class deserializeResponse { public String id; public String access_token; } public String ReturnAccessToken (SendAccountFromSource acount) { String reqbody = 'grant_type=password&client_id='+clientId+'&client_secret='+clientSecret+'&username='+username+'&password='+password; Http h = new Http(); HttpRequest req = new HttpRequest(); req.setBody(reqbody); req.setMethod('POST'); req.setEndpoint('https://ap2.salesforce.com/services/oauth2/token'); HttpResponse res = h.send(req); deserializeResponse resp1 = (deserializeResponse)JSON.deserialize(res.getbody(),deserializeResponse.class); return resp1.access_token; } @future(callout=true) public static void createAccount(String accName, String accId) { SendAccountFromSource acount = new SendAccountFromSource(); String accessToken = acount.ReturnAccessToken (acount); if(accessToken != null) { String endPoint = 'https://ap2.salesforce.com/services/data/v32.0/sobjects/Account/'; String jsonstr = '{"Name" : "' + accName + '"}'; Http h2 = new Http(); HttpRequest req1 = new HttpRequest(); req1.setHeader('Authorization','Bearer ' + accessToken); req1.setHeader('Content-Type','application/json'); req1.setHeader('accept','application/json'); req1.setBody(jsonstr); req1.setMethod('POST'); req1.setEndpoint(endPoint); HttpResponse res1 = h2.send(req1); deserializeResponse resp2 = (deserializeResponse)JSON.deserialize(res1.getbody(),deserializeResponse.class); Account a = [SELECT Id FROM Account WHERE Id = :accId]; a.externalId__c = resp2.id; update a; } } } |
Explanation –
1 Setting the REST API resource to create an Account (sObject)
2 Creating the JSON string to be sent as the input
3 Setting the Header to include the access token
4 Querying the Account record in Source Org so it can be updated
5 Setting the custom foreign key field on Account in Source Org with the extracted Account ID from the response.
Till here we have worked with Rest API.
REST Webservices
When working with rest webservices we need to change the code in the createAccount method in SendAccountFromSource class . Which looks like
1 Setting the REST API resource to create an Account (sObject)
2 Creating the JSON string to be sent as the input
3 Setting the Header to include the access token
4 Querying the Account record in Source Org so it can be updated
5 Setting the custom foreign key field on Account in Source Org with the extracted Account ID from the response.
Till here we have worked with Rest API.
REST Webservices
When working with rest webservices we need to change the code in the createAccount method in SendAccountFromSource class . Which looks like
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | if(accessToken != null) { String endPoint = 'https://ap2.salesforce.com/services/apexrest/v1/createAccount/'; String jsonstr = '{"AccName" : "' + accName + '"}'; Http h2 = new Http(); HttpRequest req1 = new HttpRequest(); req1.setHeader('Authorization','Bearer ' + accessToken); req1.setHeader('Content-Type','application/json'); req1.setHeader('accept','application/json'); req1.setBody(jsonstr); req1.setMethod('POST'); req1.setEndpoint(endPoint); HttpResponse res1 = h2.send(req1); String trimmedResponse = res1.getBody().unescapeCsv().remove('\\'); deserializeResponse resp2 = (deserializeResponse)JSON.deserialize(trimmedResponse, deserializeResponse.class); Account a = [SELECT Id FROM Account WHERE Id = :accId]; a.externalId__c= resp2.id; update a; } |
Here in this example we need to change the endpoint url that is pointing to createAccount class in the target org. Create a new rest web service class createAccount in target org.
1 2 3 4 5 6 7 8 9 10 11 12 13 | @RestResource(urlMapping='/v1/createAccount/*') global with sharing class createAccount { @HttpPost global static String createAccount(String AccName) { Account a = new Account(); a.Name = AccName; insert a; String returnResponse = JSON.serialize(a); return returnResponse; } } |
Explanation –
1 Exposing the web service using the @RestResource annotation
2 Exposing method as REST resource to be called when HTTP Post request is made to this web service
3 Creating a new Account in Target org and setting the name as passed from Source org
4 Serializing the response (Account details) before sending
5 Sending the response.
Apex Web Service
Finally, the third option is the Apex Web Service that uses SOAP to handle integration. The class written at the target needs to be exposed as a global Web Service.
1 Exposing the web service using the @RestResource annotation
2 Exposing method as REST resource to be called when HTTP Post request is made to this web service
3 Creating a new Account in Target org and setting the name as passed from Source org
4 Serializing the response (Account details) before sending
5 Sending the response.
Apex Web Service
Finally, the third option is the Apex Web Service that uses SOAP to handle integration. The class written at the target needs to be exposed as a global Web Service.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | global class CreateAccountApexWS { global class sAccount { webservice String name; } webservice static String createAccount(sAccount sAcct) { Account acct = new Account(); acct.Name = sAcct.name; insert acct; String returnResponse = JSON.serialize(acct); return returnResponse; } } |
Explanation –
1 Creating a Global class that can be accessed from anywhere
2 Using the webservice keyword to expose class variable as an input to the web service
3 Using the webservice keyword to expose the class method as a custom SOAP Web Service
1 Creating a Global class that can be accessed from anywhere
2 Using the webservice keyword to expose class variable as an input to the web service
3 Using the webservice keyword to expose the class method as a custom SOAP Web Service
0 Comments