We have been working the last few months on an experiment with Salesforce.com. The code is some of our first to be written almost purely using CFScript and Hibernate. One of our challenges was communicating with Salesforce, in particular, their fairly new REST API. Their API documentation is pretty good, but the one area that was somewhat lacking at the time was how to log in. Once we figured it out, the solution was rather simple, it just took a little while to find the right combination of parameters.
We hope to eventually release our entire CFC for talking with Salesforce, which has a lot of convenience methods to get, set, upsert, and describe Salesforce objects, but for now, here is our code to log in and get an object.
public boolean function logIn() {
if (variables.token EQ '' OR arguments.force) {
local.http = new Http(url=variables.salesforceInstance & '/services/oauth2/token',method='post');
local.http.addParam(type='formField',name='grant_type', value='password');
local.http.addParam(type='formField',name='client_id', value=variables.CLIENTID);
local.http.addParam(type='formField',name='client_secret', value=variables.CLIENTSECRET);
local.http.addParam(type='formField',name='username', value=variables.USERNAME);
local.http.addParam(type='formField',name='password', value=variables.PASSWORD);
local.http.addParam(type='formField',name='format', value='json');
local.httpSendResult = local.http.send();
local.httpResult = httpSendResult.getPrefix();
if (StructKeyExists(local.httpResult, "responseHeader")
&& StructKeyExists(local.httpResult.responseHeader, "status_code")
&& local.httpResult.responseHeader.status_code EQ 200) {
local.stringResult = gatherResponseString(local.httpResult);
//variables.json is an in-house wrapper around 'org.json.simple.JSONValue'. DeserializeJSON may work for you as well
local.json = variables.json.toObject(local.stringResult);
variables.token = local.json.access_token;
} else {
variables.token = '';
local.errorString = gatherResponseString(local.httpResult);
if (StructKeyExists(local.httpResult, "ErrorDetail")) {
local.errorString &= ", detail: " & local.httpResult.ErrorDetail;
}
throw (message='Unable to authenticate to SalesForce: ' & local.errorString, type='lampo.salesforce.loginerror');
}
}
}
public any function getObject(required string sfid, required string type, array fields) {
local.url=variables.salesforceInstance & '/services/data/v' & variables.apiVersion &'/sobjects/'&arguments.type&'/' & arguments.sfid;
if (NOT isNull(fields) AND ArrayLen(fields) GT 0) {
local.url = local.url & '?fields=' & ArrayToList(fields);
}
return makeJsonGetCall(url=local.url,errorMessage='Unable to find ' & arguments.type & ' with sfid ' & arguments.sfid);
}
/*************** HELPER FUNCTIONS ********************/
private function gatherResponseString(required any httpresult) {
if (IsBinary(httpResult.FileContent)) {
return CharsetEncode(httpResult.FileContent, httpResult.CharSet);
} else {
return trim(httpResult.FileContent);
}
}
private any function makeJsonGetCall(required string url, required string errorMessage) {
local.httpResult = makeCall(arguments.url,'GET',{});
if (local.httpResult.responseHeader.status_code EQ 200) {
local.fromJson = variables.json.toObject(gatherResponseString(local.httpResult));
return local.fromJson;
} else {
throw (message=arguments.errorMessage & ' (status: '& local.httpResult.responseHeader.status_code &')',type='lampo.salesforce.objectNotFound') ;
}
}
private any function makeCall(required string url, required string method,required struct params) {
local.http = new Http(url=arguments.url,method=arguments.method);
for (paramType in params) {
for (paramKey in params[paramType]) {
if (paramType NEQ 'header' or paramType neq 'Authorization') {
local.http.addParam(type=paramType,name=paramKey,value=params[paramType][paramKey]);
}
}
}
local.http.addParam(type='header',name='Authorization',value='OAuth ' & variables.token);
local.httpSendResult = local.http.send().getPrefix();
if (local.httpSendResult.responseHeader.status_code EQ 401) {
throw (message = 'Unable to log into SalesForce: ' & local.httpSendResult.responseHeader.status_code & '('&gatherResponseString(local.httpSendResult)&')',detail=gatherResponseString(local.httpSendResult),type='lampo.salesforce.loginFailure');
} else {
return local.httpSendResult;
}
}
September 2, 2011 at 12:13 pm
Hey, this is pretty cool. Thanks for sharing!
September 6, 2011 at 4:26 pm
Nice code.. I’m trying to figure out the salesforce stuff myself so this is great timing. I look forward to seeing more
February 13, 2012 at 9:11 pm
Hey guys, are you gonna release the full CFC soon? I’m stuck on upserting and would like to see some code. Thanks!