Getting a Session ID in APEX using the Login Partner API Call.

Salesforce is great at allowing access to itself through the many possible APIs.  The first step in most cases is to do a Login to the Partner or Enterprise APIs so that a session ID can be returned.  Once you have this session ID you will be able to make subsequent API calls as needed.

But what if I want to log into another Salesforce instance or my current Salesforce instance so that the Salesforce APIs can be used?  Maybe I want to log into a few of my sandboxes from my production org to collect data about how many rows of contacts exist in each sandbox.  The first step before making such a query is to log into the other org or your current org to get the session ID.  You could download the entire Partner API and then make modifications to the WSDL so that the ‘WSDL to APEX’ functionality can be used.  For example, there are certain reserved words like ‘Update’ that need to be changed to something like ‘Update2’ before the WSDL can be imported.  But even once it is imported there are so many extra function calls that you are never going to use.  Let me show you how to log into Salesforce using the HTTP objects that APEX provides.

We need to construct the XML that will be sent in the SOAP message for logging in.  The way that I like to see the XML structure is to build my API call in VB.NET, run the call and then capture the XML as it is sent with a tool like Fiddler at http://www.fiddler2.com  Thi.s fiddler Web Debugging Proxy will capture the XML that is both sent and received.  You can then build that XML string yourself in APEX and send it the same way.  Here is some code that does just this for calling the Partner API Login method.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//Beginning of XML Generation for Partner API SOAP Login Call
string bodyToSendLogin;
string outCallResultLogin;
string sessionID;
string userName = 'Me@Me.com';  //A great place to keep these values is in a custom object with an encrypted field for the password.
string password = 'MyPassword';
//This beginning piece of XML can be re-used for the subsequent calls
private final string SOAP_START = '<?xml version="1.0" encoding="utf-8"?><soap:envelope '="" +="" 'xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 'xmlns:xsd="http://www.w3.org/2001/XMLSchema">';
bodyToSendLogin = SOAP_START + '<soap:body><login xmlns="urn:partner.soap.sforce.com"><username>' + userName +
            '</username><password>' + password + '</password></login></soap:body></soap:envelope><p>';<br>
            <br>
if (true){ //Keep the setting on whether this is a production or sandbox in a custom object.<br>
}else{<br>
}</p>
<p>outCallResultLogin = makeHTTPCall(loginURL,bodyToSendLogin);<br>
system.debug('outCallResultLogin Output: ' + outCallResultLogin);   <br>
        <br>
sessionID = getValueFromXMLString(outCallResultLogin, 'sessionId');</p>
<p>//End of XML Generation for Partner API SOAP Login Call</p>
<p>private string makeHTTPCall(string endPoint, string soapBody){<br>
        Http hLLogin = new Http();<br>
        HttpRequest reqLLogin = new HttpRequest();<br>
        reqLLogin.setTimeout(60000);<br>
        reqLLogin.setEndpoint(endPoint);  <br>
        reqLLogin.setMethod('POST');<br>
        reqLLogin.setHeader('SFDC_STACK_DEPTH', '1');<br>
        reqLLogin.setHeader('SOAPAction','DoesNotMatter'); <br>
        //reqLLogin.setHeader('User-Agent', 'SFDC-Callout/22.0');<br>
        reqLLogin.setHeader('Accept','text/xml');  <br>
        reqLLogin.setHeader('Content-type','text/xml');    <br>
        reqLLogin.setHeader('charset','UTF-8'); <br>
        system.debug('Request: ' + reqLLogin);<br>
                <br>
        reqLLogin.setBody(soapBody);    <br>
        HttpResponse resLLogin = hLLogin.send(reqLLogin);<br>
        string outCallResultLogin = '';<br>
        outCallResultLogin = resLLogin.getBody();<br>
        return outCallResultLogin;<br>
}</p>
<p>private string getValueFromXMLString(string xmlString, string keyField){<br>
        string valueFound = '';<br>
        if(xmlString.contains('</p><' + keyField + '>') && xmlString.contains('<!--' + keyField + '--><p>')){<br>
            try{<br>
                valueFound = xmlString.substring(xmlString.indexOf('</p><' + keyField + '>') + keyField.length() + 2, xmlString.indexOf('<!--' + keyField + '--><p>'));   <br>
            }catch (exception e){<br>
                system.debug('Error in getValueFromXMLString.  Details: ' + e.getMessage() + ' keyfield: ' + keyfield);<br>
            }            <br>
        }<br>
        return valueFound;<br>
}</p>

I hope that some of this code can kick-start some of your integration projects.  You can now log into any Salesforce Org.  To make any subsequent calls like doing a query or an insert just make those same calls in Java or .NET and intercept the XML using fiddler.  Then you can build that same XML and then using the session ID it should be easy to make that next call.

Happy Integrating!

This entry was posted in Technology and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>