Sunday, January 6, 2019

Salesforce to Salesforce Rest API Integration using Username-Password flow

Let say I have two Salesforce org say ORG A and ORG B. Our requirement is to fetch data from ORG B and display it in ORG A.

Let's start,

ACTIVITIES WE NEED TO DO IN ORG B.

1) Create a Connected App in ORG B.

2) Create a Webservice in ORG B which will be invoked from ORG A to get the data.

Create A Connected App In ORG B:

Configure a connected app as shown below in ORG B and Click Save.

Salesforce rest api integration to fetch a record from external system
Salesforce REST API integration example

Salesforce rest api

Salesforce REST API integration example

Note down the Consumer key, Consumer secret (We need to provide it ORG A for authentication purpose along with username, password, security token of the user from ORG B which ORG A will be using for authentication).

A callback URL is the URL that is invoked after OAuth authorization for the consumer (connected app). In some contexts, the URL must be a real URL that the client’s web browser is redirected to. In others, the URL isn’t actually used, but the value between your client app and the server (the connected app definition) must be the same. Here we are providing the URL of ORG A in the format as asked in comment for Callback URL.

Salesforce rest api integration to fetch a record from external system

Create A Webservice As Shown Below In ORG B:

Now, create a Webservice as shown below in ORG B.

The below Webservice is expecting email and phone number of the contact in request and is returning the associated contact record back.

@RestResource(urlMapping='/getContactFromEmailAndPhone/*')

   global with sharing class getContactRecord {

        @Httpget

      global static Contact fetchContact(){

        Contact obj=new Contact();

        RestRequest req = RestContext.request;

        RestResponse res = Restcontext.response;

        Map<String, String> requestParam = req.params;

        String conEmail=requestParam.get('email');

        String conPhone=requestParam.get('phone');

        obj=[Select id,lastname,email,phone from contact where email=:conEmail and phone=:conPhone];

       /***Modify the HTTP status code that will be returned to external system***/

        res.statuscode=201;

       /***Modify the HTTP status code that will be returned to external system***/

        return obj;

      }

   }

ACTIVITIES WE NEED TO DO IN ORG A.

1) Create an Apex controller which will call Webservice in ORG B.

2) Create a Visualforce page to display the contact information received from ORG B.

3) Create a remote site setting for the URL of System B.

Let’s start,

To store the Username, Password, Consumer key, Consumer secret provided by ORG B, create a custom metadata as shown below in ORG A.

Note: The password will be combination of password and security token of the user from ORG B without any space.

Salesforce rest api integration to fetch a record from external system

Now, create a record under the above custom metadata as shown below.

Salesforce rest api integration to fetch a record from external system

CREATE AN APEX CONTROLLER:

Now, create an Apex controller which will call Webservice in ORG B. This apex controller method will be invoked from Visualforce Page to get the necessary data from ORG B. As of now, for explanation we are hardcoding the email and phone number of the contact as shown in below class to get the contact associated with this email and phone from ORG B. This can be made dynamic as per the requirement.

public class restApiTofetchSingleRecord {

    private string cKey;

    private string cSecret;

    private string uName;

    private string passwd;

    public string instanceURL;

    public static list < resultWrapper > listWrap {

        get;

        set;

    }

    public restApiTofetchSingleRecord() {

        listWrap = new list < resultWrapper > ();

    }

    public class responseWrapper {

        public string id;

        public string access_token;

        public string instance_url;

    }

    public responseWrapper getRequestToken() {

 

        List < Store_Cred__mdt > connectionParam = [SELECT Id, MasterLabel, client_id__c, client_secret__c, username__c, password__c from Store_Cred__mdt];

        if(connectionParam.size() >0){

        cKey=connectionParam[0].client_id__c;

        cSecret=connectionParam[0].client_secret__c;

        uName=connectionParam[0].username__c;

        passwd=connectionParam[0].password__c ;

        }

        System.debug('Store_Cred__mdt' + connectionParam);

        string reqBody = 'grant_type=password&client_id=' + cKey + '&client_secret=' + cSecret + '&username=' + uName + '&password=' + passwd;

        Http h = new Http();

        HttpRequest req = new HttpRequest();

        req.setBody(reqBody);

        req.setMethod('POST');

        req.setEndpoint('https://login.salesforce.com/services/oauth2/token');

        HttpResponse hresp = h.send(req);

        responseWrapper wResp = (responseWrapper) JSON.deserialize(hresp.getBody(), responseWrapper.class);

        system.debug('reqBody '+reqBody );

        system.debug('wResp'+wResp );

        system.debug('Instance url' + wResp.instance_url);

        system.debug('session id' + wResp.access_token);

        return wResp;

    }

    public void getConList() {

 

        string integration1 = 'Testing integration';

        list < account > accList1 = new list < account > ();

        String accToken;

        String instanceUrl;

        string responseBody;

        string email = 'testemail123@gmail.com';

        string phone = '123';

        restApiTofetchSingleRecord obj = new restApiTofetchSingleRecord();

        responseWrapper obj1= obj.getRequestToken();

        accToken = obj1.access_token;

        instanceUrl = obj1.instance_url;

        string endPoint = instanceURL+'/services/apexrest/getContactFromEmailAndPhone/?' + 'email=' + email + '&phone=' + phone;

        system.debug('endPoint'+endPoint );

        system.debug('access token' + accToken);

        if (accToken != '') {

            Http h1 = new Http();

            HttpRequest req1 = new HttpRequest();

            req1.setHeader('Authorization', 'Bearer ' + accToken);

            req1.setHeader('Content-Type', 'application/json');    

            req1.setMethod('GET');

            req1.setEndpoint(endPoint);

            HttpResponse hresp1 = h1.send(req1);

            system.debug('hresp1'+hresp1 );

            system.debug('hresp1.getStatusCode()'+hresp1.getStatusCode());

             system.debug('hresp1.getBody()'+hresp1.getBody());

 

            if (hresp1.getStatusCode() == 201) {

                resultWrapper wResp1 = (resultWrapper) JSON.deserialize(hresp1.getBody(), resultWrapper.class);

                listWrap.add(wResp1);

            }

        }

    }

    public class resultWrapper {

        public string id {

            get;

            set;

        }

        public string LastName{

            get;

            set;

        }

        public string Email{

            get;

            set;

        }

        public string Phone{

            get;

            set;

        }

    }

}

CREATE A VISUALFORCE PAGE:

<apex:page controller="restApiTofetchSingleRecord">

<apex:form >

<apex:pageBlock >

 <apex:pageblockButtons >

 <apex:commandButton value="TEST" action="{!getConList}"/>

 </apex:pageblockButtons>

<apex:pageblocktable value="{!listWrap}" var="a" >

 <apex:column value="{!a.LastName}"/>

 <apex:column value="{!a.Email}"/>

 <apex:column value="{!a.Phone}"/>

 </apex:pageBlockTable>

 </apex:pageBlock>

 </apex:form>

</apex:page>

 

Remote Site URL:

The remote site url here is nothing but the instance URL of ORG B.

Salesforce rest api

Now, we are done with complete setup of customization and configuration needed in ORG A and ORG B.

Before testing try to ensure that the contact with email “testemail123@gmail.com” and phone “123” exist in ORG B as we are trying to get contact associated with this information from ORG B.

Now, Lets preview the Visualforce page, click the “TEST” button.

Salesforce REST API integration example

13 comments:

  1. How to we do the same if we need to display any Images?

    ReplyDelete
    Replies
    1. Sorry for the late reply. I have not checked yet, but I will update here if i try the same.

      Delete
  2. If its using Named Credentials, what changes we need to make on Apex controller?

    ReplyDelete
  3. Hi, after login is success how can we open SYSTEM B's home page? Thanks

    ReplyDelete
  4. How can we hide username, password, client secret etc from the apex class?

    ReplyDelete
    Replies
    1. You can use custom labels or custom settings or custom metadata to store username, password, client secret etc and than refer them in apex class.

      Delete
    2. Just use Named Credentials

      Delete
  5. Hello, the response of the oauth call is "access_token":"SESSION_ID_REMOVED"?
    How fix this?

    ReplyDelete
    Replies
    1. In debug log you will not be able to see it. however in class you can access it.

      Delete
  6. Hi, How to I include composite data in request body?

    ReplyDelete
  7. Hello, Iam not able to see connected app under create apps? can anyone help me please

    ReplyDelete
  8. Cleared 90% of my doubts... Thanks a lot for the resource

    ReplyDelete