Salesforce to Salesforce Integration using Rest API Callouts

Salesforce to Salesforce Integration using Rest API Callouts

"Integration" itself is a vast topic, though with a bit of understanding and practise one can master any skill whatsoever. Answering the question posted here is what I think is the best solution for Salesforce to Salesforce Integration using Rest API Callouts:

Don’t forget to check out: Apex Web Services and callouts

For the reason of integrating two Salesforce Orgs which in our case, between two separate Salesforce Orgs, we have to assume one Org as Client or Source and another as Server or Destination or Target, so here whenever an Account record is created in the Source Org, data automatically will be pushed in Account object at Destination Org.

Let's start our journey now.

Prerequisites:

  • Source org endpoint: https://akashmishra-dev-ed.my.salesforce.com/ (Don’t get confused as this is the custom URL I used, you can use the Instance URL for your org like https://ap5.salesforce.com).
  • Destination Org URL: https://ap4.salesforce.com

First, we talk about what we have to do in the Destination org:

Step 1.

Create a Connected App in Destination org giving the callback URL with the details as mentioned in the image below.

ConnectedApp
Create a Connected App on Destination Org

Now don’t forget to copy the Consumer Key (Client id) and Consumer Secret (Client Secret) we’ll need these in Source org Rest Callout Class.

Step 2.

Create a Rest Webservice with @httpPost & @httpGet verb, though it’s not required in our case.

Find the class below.

/*********************************************************************
* Description – Apex REST service with GET and POST methods
* Author – AP
Json format
{
    “name” : “Akash”,
    “phone” : “8826031286”,
    “website” : “www.akashmishra.co.in”

}
***********************************************************************/
@RestResource(urlMapping=’/v3/accounts/*’)
global with sharing class REST_AccountService_V4 {
    @HttpPost
    global static AccountWrapper doPost(String name, String phone, String website) {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        AccountWrapper response = new AccountWrapper();
        Account acct = new Account();
        acct.Name = name;
        acct.Phone = phone;
        acct.Website = website;
        insert acct;
        response.acctList.add(acct);
        response.status = ‘Success’;
        response.message = ‘Your Account was created successfully.’;
        return response;
    }
    @HttpGet
    global static AccountWrapper doGet() {
        RestRequest req = RestContext.request;
        RestResponse res = RestContext.response;
        AccountWrapper response = new AccountWrapper();
        String accountId = req.requestURI.substring(req.requestURI.lastIndexOf(‘/’)+1);
        if(doSearch(accountId)){
            searchAccounts(req, res, response);
        }
        else{
            findAccount(res, response, accountId);
        }
        return response;
    }
    // If the item to the right of the last forward slash is “accounts”, the request went to
    //v3/accounts?Name=Akash
    // Else the request went to v3/accounts/<something>, which is not a search, but a specific
    //entity
    private static boolean doSearch(String accountId) {
        if(accountId == ‘accounts’) {
            return true;
        }
        return false;
    }
    //If the request came to /v3/accounts, then we want to execute a search
    Public static void searchAccounts(RestRequest req, RestResponse res,
    AccountWrapper response) {
        //Use the RestRequest’s params to fetch the Name parameter
        String searchTerm = req.params.get(‘Name’);
        if(searchTerm == null || searchTerm == ”) {
            response.status = ‘Error’;
            response.message = ‘You must provide a Name for your search term.’;
            res.StatusCode = 400;
        }
        else {
            String searchText = ‘%’+searchTerm+’%’;
            List<Account> searchResults =
            [SELECT Id, Name, Phone, Website FROM Account WHERE Name LIKE : searchText];
            if(searchResults != null && searchResults.size() > 0) {
                response.acctList = searchResults;
                response.status = ‘Success’;
                response.message = searchResults.size()
                + ‘ Accounts were found that matched your search term.’;
            }
            else {
                response.status = ‘Error’;
                response.message =
                ‘No Accounts were found based on that Name, please search again.’;
            }
        }
    }
    //If the request came to v3/accounts/sometext then we want
    //to find a specific account
    Public static void findAccount(RestResponse res, AccountWrapper response,
    String accountId) {
        // Provided we recevied an External Id, perform the search and return the results
        if(accountId != null && accountId != ”) {
            List<Account> result = [SELECT Id, Name, Phone, Website FROM Account
            WHERE External_Id__c =: accountId];
            if(result != null && result.size() > 0) {
                response.acctList.add(result[0]);
                response.status = ‘Success’;
            }
            else {
                response.status = ‘Error’;
                response.message = ‘This account could not be found, please try again.’;
                res.StatusCode = 404;
            }
        }
        // If the request came to /v3/accounts/ (without an Account Id),
        //return an error
        else {
            response.status = ‘Error’;
            response.message = ‘You must specify an External Id.’;
            res.StatusCode = 400;
        }
    }
    global class AccountWrapper {
        public List<Account> acctList;
        public String status;
        public String message;
        public AccountWrapper(){
            acctList = new List<Account>();
        }
    }
}

Note: Please ignore the Naming conventions as they may look funny.

Now is the time to configure the Source org:

Step 1.

Create Remote site in Source like in my case I created the below one.

Remote Site
Create a Remote Site in Source Org

Step 2.

Create a class for Rest Callout in the Source org.
Goto: Create==>Apex Class==>Click New
/*******************************************************************
*Description: Rest Callout
*Owner: AP
********************************************************************/
public class SendAccount {
    //Use your Client Id 
    String clientId =3MVG9YDQS5WtC11o4mAP_I******************************         OoLrKY3FUrb6221Ms9hjkqhZo_oTNbjKu2LJBHN_tFmZ1.’;
    //Use your Client Secret
    String clientsecret=’314426******97831′;
    //Your Destination org username
    String username=’[email protected]’;
    //Your Destination orgPassword+Security Token
    String password=’Qwerty@10064OMwL3ZNSh6WP5lVqRxapaHUK’;
    String accesstoken_url=’https://login.salesforce.com/services/oauth2/token’;
    String authurl=’https://login.salesforce.com/services/oauth2/authorize’;
    public class deserializeResponse {
        public String id;
        public String access_token;
    }
    public String ReturnAccessToken(SendAccount Acc){
        String reqbody = ‘grant_type=password&client_id=’+clientId+’&client_secret=’
        +clientSecret+’&username=’+username+’&password=’+password;
        // 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’);
        //Change “ap4” in url to your Destination Org Instance
        req.setEndpoint(‘https://ap4.salesforce.com/services/oauth2/token’);
        HttpResponse res=h.send(req);
        System.debug(res.getBody()+’By-AP-1986-Response’);
        deserializeResponse resp1=
        (deserializeResponse)JSON.deserialize(res.getBody(),deserializeResponse.class);
        System.debug(resp1+’By-AP-deserializeresponse’);
        return resp1.access_token;
    }
    @future(callout=true)
    public static void createAccount(String Accname, String Phone, String Website){
        SendAccount acc1= new SendAccount();
        String accessToken=acc1.ReturnAccessToken(acc1);
        System.debug(accessToken+’###AP’);
        if(accessToken!=null){
            //Change “ap4” in url to your Destination Org
            String endPoint=’https://ap4.salesforce.com/services/data/v32.0/sobjects/Account’;  
            String jsonstr='{“Name”:”‘+ Accname +'”,”Phone”:”‘+ Phone +'”,”Website”:”‘+ Website +'”}’;
            Http h2= new Http();
            HttpRequest req2= new HttpRequest();
            req2.setHeader(‘Authorization’,’Bearer ‘ + accessToken);
            req2.setHeader(‘Content-Type’,’application/json’);
            req2.setHeader(‘accept’,’application/json’);
            req2.setBody(jsonstr);
            req2.setMethod(‘POST’);
            req2.setEndpoint(endPoint);
            HttpResponse res2=h2.send(req2);
            System.debug(res2+’###Akash###’);
            deserializeResponse deresp=                         (deserializeResponse)System.JSON.deserialize(res2.getBody(),deserializeResponse.class);
            System.debug(‘### Deserialized Response ###’+deresp);
        }
    }

}

 

Now Create a Trigger to make callout when some data is inserted in the Account Object.

Try This:

Trigger SendMyAccount on Account (after insert)
{for(Account a:Trigger.new) {SendAccount.createAccount(a.name, a.Phone, a.Website); } }

Now save and start testing by creating a record on Account Object in Source Org. I hope you got it right.

Thanks, everyone,

"Don't let the tiny bit of Doubt today be a road-blocker Tomorrow", so keep on asking friends.

"Happy Learning"

Responses

  1. In the Org, which we do the callout (Ap4)...

    The end point you set is 'https://ap4.salesforce.com/services/data/v32.0/sobjects/Account';

    if you are making callout to the Org in which you defined the webservices...

    But,  the last part should be  "services/apexrest/v3/accounts/" right??

     

  2. Nice Blog Akash. It is really helpful to understand the concept of REST Integration.

    Thank you for your efforts.

    Amit

Comments are closed.

Popular Salesforce Blogs