Connect two Salesforce Orgs using REST API

When ever record is created/Updated in Org1 then the same record is get created/Updated in Org2.This is one-way integration, For two way integration we need to do the same in other Org.
Org 1 - Setup
First,We need to create connected App in Org2, Create -> Apps -> Connected App -> New
We need to call the below class in a trigger or other class.
EX: OrderExternalServiceCall.createSales(parameters)
 

    public class OrderExternalServiceCall {
   
   public static  String clientId = label.Org2ClientID;
   public static  String clientSecret = label.Org2ClientSecret;
   public static  String username = label.Org2UserName;
   public static  String password = label.Org2UserPassword;
   public static  String AccessToken;

   // generate access token
    public static void generateAccessToken(){
     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(label.Org2_Endpoint_URL+'/services/oauth2/token');
      HttpResponse res = h.send(req);
      System.debug('respone of AccesToken ..'+res);
      deserializeAccessTokenRes resp1 = (deserializeAccessTokenRes)JSON.deserialize(res.getbody(),deserializeAccessTokenRes.class);
      AccessToken = resp1.access_token;
      System.debug('AccesToken ..'+AccessToken);
    
    }
 public class deserializeAccessTokenRes
      {
      
        public String access_token;
      }
  
    @future(callout=true)       
   public static void createSales(set salid){

//Here I'm using Salesforce custom object Sales__c and change API names according to your requirement

    List<Sales__c> listsal = new List<Sales__c >();
    List<sales__c> sal= [select id,VIN__c,Sales_Channel__c,account__r.Org2_Account_Id__c,Model__c,Dealer_Name__c,Registration_Date__c,Order_Number__c,Date__c,org2_Order_Id__c from Sales__c where id=:salid];
   
       string myJsonString = JSON.serialize(sal);
       
       system.debug('myJsonString---->'+myJsonString);  
       system.debug('sal'+sal); 
       
       Map<string,string> maps = null;
      List<map<string,string> out = new List<map<string,string>>();
       Iterator<sales__c> keys = sal.iterator();
       while(keys.hasNext()){
           maps = new Map<string,string>();
           Sales__c key = keys.next();
           
        //below if condition is used to check either record is update or insert
        //Here Map keys are Org2 API names

           if(key.Org2_Order_Id__c == null){
               maps.put('Org1_Sales_Id__c', key.Id);  //insert logic                                    
           }else{
               maps.put('Id', key.Org2_Order_Id__c);  //Update logic
           }
           maps.put('VIN__c', key.VIN__c);
           
                    
           maps.put('Vehicule_order_class__c',key.Sales_Channel__c);
           maps.put('Model_Sold__c',key.Model__c);
           
           maps.put('Actual_retail_Date__c',string.valueof(key.Registration_Date__c));
         
           maps.put('Order_number__c',string.valueof(key.Order_Number__c));
           
           maps.put('Order_Date__c', string.valueof(key.Date__c).substringBefore('T'));
              
           maps.put( 'Order_Status__c', 'Delivered');
           maps.put('Country__c','United Kingdom (The)');
           maps.put('NB_Of_Vehicles_Sold__c', '1');
           
           maps.put('CurrencyIsoCode', 'GBP');
           out.add(maps);
       }
     
       string finalJsonString = JSON.serialize(out);
       
       system.debug('finalJsonString'+finalJsonString);               
       
       
        
       if(AccessToken==null){
           
           generateAccessToken();
           
       }
       // send response to Org2
       if(AccessToken!=null){
        String endPoint = label.Org2_Endpoint_URL+'/services/apexrest/sfdcCallingOrder/';
       
             
        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.setMethod('GET');
        req1.setEndpoint(endPoint);
        req1.setBody(finalJsonString);
       
        System.debug('request1......'+req1);
        
           HttpResponse res1 = h2.send(req1); 
           
           String trimmedResponse = res1.getBody().unescapeCsv().remove('\\');  
           system.debug('@@@RESPONSE@@'+trimmedResponse); 
           
           JSONParser tparser = JSON.createParser(trimmedResponse);
           
           list<map<string,string>> tlistmap = new list<map<string,string>>();
           Map<string,string> tmapstr = null;
           
           while (tparser.nextToken() != null) {     
               
               system.debug('tpraser'+tparser.getText());         
               if ((tparser.getCurrentToken() == JSONToken.FIELD_NAME) && (tparser.getText() == 'Org1_Sales_Id__c')) {
                   if(null == tmapstr) {
                       tmapstr =  new Map();
                   }
                   tparser.nextToken();
                   string resIdvalue= tparser.getText();  
                   tmapstr.put('Id',resIdvalue);
                   system.debug('resIdvalue @@@@@@@@' +resIdvalue);
                   
               }         
             
               if ((tparser.getCurrentToken() == JSONToken.FIELD_NAME) && (tparser.getText() == 'Id')) {
                   if(null == tmapstr) {
                       tmapstr =  new Map();
                   }
                   tparser.nextToken();
                   string resOrdId= tparser.getText();
                   tmapstr.put('Org2_Order_Id__c',resOrdId);         
                   
                   system.debug('tmapstr'+tmapstr);                          
                   
                   
               } 
               if(null != tmapstr && tmapstr.containsKey('Id') && tmapstr.containsKey('Org2_Order_Id__c')) {
                   tlistmap.add(tmapstr);
                   tmapstr = new Map();
               } 
           }
           
           system.debug('tlistmap'+tlistmap);
           
           string tarJsonString = JSON.serialize(tlistmap);
           system.debug('tarJsonString '+tarJsonString);
           List<sales__c> tOrdObj = (List<sales__c>)JSON.deserialize(tarJsonString ,List<sales__c>.class);
           system.debug('tOrdObj'+tOrdObj );  
           if(TriggerAdministration.canTrigger('Sales.onAfterUpdate')){ //TriggerAdministration is apex class to avoid recursive conditions
               Update tOrdObj;          
           }
           System.debug('tOrdObj......'+tOrdObj);
           
       }
   }
}



Below class is used to avoid recursive conditions as like boolean static variables.
 


public class TriggerAdministration {

private static final Set<string> requiredOnce = new Set<string> {'Sales.onAfterUpdate'}; //List of Apex codes that should run only once. Add any code to the list

    private static Set<string> hasRun = new Set<string>(); //List of Apex code that has already been run. Keep this list empty.
    public static final String PAD_BypassTrigger;//List of triggers that can be bypassed
  
    public static final String userRoleName;  //User Role Name
    public static final String userProfileName;//User Profile Name
    public static Set<string&t; TriggersToBypass = new Set<string>(); //Triggers to ByPass in some cases
 g
    public static boolean canTrigger(String ApexName) { 
         
          //If no bypass
        if (bypassAllTriggers){// If bypass all triggers do not fire anything
            return false;
        }
        if (requiredOnce.contains(ApexName)) { //If it should run Once
            if (hasRun.contains(ApexName))return false; //Already run, should not run
            hasRun.add(ApexName);//Never run, can run only if not bypassed
        }
        if (TriggersToBypass.contains(ApexName) ) {
            return false;
        }
        return true;
    }

  
     private static boolean bypassAllTriggers = false;



}




OrderExternalServiceCall is called from below sample trigger
 


   trigger SalesAfterInsertUpdate on Sales__c (after insert,after update) {
      
   set<id> salesid = new set<id>();
   set<id> salesUpdateid = new set<id>();


      //insertion 
    
    if (Trigger.isInsert){

  for (Sales__c sal:trigger.new){
    if(sal.LMT_Order_Id__c == null){
      salesid.add(sal.id); 
      }                         
  
  }  
    if(salesid.size() >=1){
            
            
    OrderExternalServiceCall.createSales(salesid);
            
        }

    }

   //update operation
            if (Trigger.isUpdate){
     for (Sales__c salUp:trigger.new){
            
               salesUpdateid.add(salUp.id);
               }
   
 if(salesUpdateid != null){
        if(TriggerAdministration.canTrigger('Sales.onAfterUpdate')){ //Recursive check
            OrderExternalServiceCall.createSales(salesUpdateid);
        }

      }
    }
}

  


Test Class:
 

   @IsTest
global class OrderExternalServiceCall_Test {

    global HTTPResponse respond(HTTPRequest req){

        String endpoint = req.getEndpoint();

        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');  
        res.setBody('{"access_token":"8UT28QKGORMivFqne-6PMRLdTYk3AS0mcxdVwRJEwYsTjwZjqGopk1TRzGX7vHSZpFNFL3HOmX3RKZrQkBap3b16j-XVkwArdDbhusArOBGzYsD1cpA8B87N_RedJrd9btvq2i22cAjPvyJLSVMc297U0V9YZ9rJ3tM429G8mglnsUNUVJJi_nnTJAN6-H038B4Y1aQeRQZVdU72Nr942eYZ3fXv1HXfxwYUZgWyYO5juVaVnoq_ZJHcrFGXfNp5LVrNlnEibHhJ2RGeD-MYKhyVjfkTrATGQhYY--OVCOemUyWKTlwgwBFjgzfpQfOq79raEglOTgEF3Qx78RY2-nBNvgOTRMET4B2fT17Q8EN4UCQLxGZTGq1ACN5j2B3YKT7isjzwAgysloYGJsL4j4D8dCGKgWBO0rTXwx7MfkNsX5TjAYRNCip5vTSRXeSBqhjM_TtwbKCA0HexikSz-XryZT7pKGYhjfRCXtWudd7OUjFYoDRfKTiAhjNk5yJj","token_type":"bearer","expires_in":86400,"userName":"te123st@gmail.com",".issued":"Thu, 25 Jun 2015 12:56:23 GMT",".expires":"Fri, 26 Jun 2015 12:56:23 GMT"}');
        res.setStatusCode(200);
        return res;
        }


     @isTest static void testCallout(){
           
           Test.setMock(HttpcalloutMock.class, new MockHttpResponseGenerator());
              Account acc = new Account();
              acc.Name='Test Account1' ;
     acc.Type ='customer1';
              acc.BillingCity = 'United kingdom(the)';
     acc.BillingPostalCode ='3433455';
     acc.BillingStreet ='chenna';
     acc.Business_Sector__c = 'Construction';
     acc.Phone ='+9947555595';
              insert acc;
         
           list<sales__c> salList = new list<sales__c>();
           Sales__c sal=new Sales__c();
           sal.Date__c=Date.today(); 
           sal.Account__c=acc.id;
           sal.VIN__c='VNVM1F4SE55360044';
           sal.Sales_Channel__c='S';
           sal.Model__c='NV400';
           sal.Dealer_Name__c='test';
           sal.Registration_Date__c='09/02/2017';
           sal.Order_Number__c=45;
           sal.Date__c=Date.today();
           salList.add(sal);
            Insert salList;
                 
              Set<id> SalIDs = new set<id>();
                                        
              for(sales__c sal1 : salList){
                  SalIDs.add(sal1.id);
              }
              
             OrderExternalServiceCall.createSales(SalIDs ); 
           
       }
    
    global class MockHttpResponseGenerator implements HttpCalloutMock {
       // Implement this interface method
        global HTTPResponse respond(HTTPRequest req) {
            // Optionally, only send a mock response for a specific endpoint
            // and method.
            
            // Create a fake response
            HttpResponse res = new HttpResponse();
            res.setHeader('Content-Type', 'application/json');
            res.setBody('{"access_token":"8UT28QKGORMivFqne-6PMRLdTYk3AS0mcxdVwRJEwYsTjwZjqGopk1TRzGX7vHSZpFNFL3HOmX3RKZrQkBap3b16j-XVkwArdDbhusArOBGzYsD1cpA8B87N_RedJrd9btvq2i22cAjPvyJLSVMc297U0V9YZ9rJ3tM429G8mglnsUNUVJJi_nnTJAN6-H038B4Y1aQeRQZVdU72Nr942eYZ3fXv1HXfxwYUZgWyYO5juVaVnoq_ZJHcrFGXfNp5LVrNlnEibHhJ2RGeD-MYKhyVjfkTrATGQhYY--OVCOemUyWKTlwgwBFjgzfpQfOq79raEglOTgEF3Qx78RY2-nBNvgOTRMET4B2fT17Q8EN4UCQLxGZTGq1ACN5j2B3YKT7isjzwAgysloYGJsL4j4D8dCGKgWBO0rTXwx7MfkNsX5TjAYRNCip5vTSRXeSBqhjM_TtwbKCA0HexikSz-XryZT7pKGYhjfRCXtWudd7OUjFYoDRfKTiAhjNk5yJj"}');
            res.setStatusCode(200);
            return res;
        }
    }
    
}


Org 2 - Setup
Below class is used to get the details from Org1
 

    @RestResource(urlMapping='/sfdcCallingOrder/*')
   Global class GetSalesFromCPM {
     // getting JSON from ORG1
   @HttpPost
    global static String insertSales()
    {
    System.debug('entered..'+RestContext.request.requestBody.toString().trim());
 
    String jsonBody = RestContext.request.requestBody.toString().trim();
    System.debug('jsonBody'+jsonBody );
 
       List<order__c> OrdObj = (List<order__c>)JSON.deserialize(jsonBody,List<order__c>.class);
       System.debug('OrdObj #########'+OrdObj );
       Set<order__c> OrdObjInsert = new Set<order__c>();
       Set<order__c> OrdObjUpdate = new Set<order__c>();
       set<id> AcID=new set<id>();  
      
       Iterator<order__c> keys = OrdObj.iterator();
        while(keys.hasNext()){
            Order__c key = keys.next();
            System.debug('jsonBody11991'+key );
            if(key.Id != null){
                OrdObjUpdate.addAll(Ordobj);
            }else {
                OrdObjInsert.addAll(OrdObj);
            }
        }
                                            
       list<order__c> lstordObjInsert = new list<order__c>(OrdObjInsert);
       list<order__c> lstordObjUpdate = new list<order__c>(OrdObjUpdate);
    
    try{
     
     if(lstordObjUpdate != null){
      
      update lstordObjUpdate;
     }
     if(lstordObjInsert != null){
      
      insert lstordObjInsert;
      return JSON.serialize(lstordObjInsert);
     }
    }
       catch(Exception e){
     
     return JSON.serialize(e);
    }
         return 'success';    
 } 
   } 
 



Test Class:
 

@isTest()
public class GetSalesFromCPM_Test {
 Static Testmethod void GetSalesFromCPMMethod1(){
     // insert account
      Account acc=new Account();
       acc.name='ACTest';
       acc.AccountNumber='1232332';
       acc.Local_ID_code__c = '12443455';
       acc.Site='site';
       acc.Industry = 'waste';
       acc.Address_line_1__c= 'chennai';
       acc.City__c= 'Chennai';
       acc.Country__c= 'United kingdom (The)';
       acc.Post_code__c= '345567';
       acc.Website='cloudyworlds.blospot.in';
       insert acc;
       
  // insert order
     Order__c ord=new Order__c();
     ord.Order_Date__c=Date.today();
     ord.Order_Status__c='Delivered'; 
     ord.CPM_account__c=acc.id;
     ord.Country__c='United Kingdom (The)';
     
     //ADD required fields
     
     list<order__c> ordlist=new list<order__c>();
     ordlist.add(ord);
     RestRequest req=new RestRequest();
     RestResponse res=new RestResponse();
     req.requestURI='/services/apexrest/sfdcCalling';
     req.httpMethod='POST';
     req.requestBody=Blob.valueof(JSON.serialize(ordlist));
     RestContext.request = req;
 
     String resp= GetSalesFromCPM.insertSales();
     
        
 }
  
}


Comments