Salesforce.com interface to directly access Salesforce.com

Dependencies:   HTTPClient-SSL MbedJSONValue

Dependents:   df-2014-salesforce-hrm-k64f

Fork of SalesforceInterface by Doug Anson

Revision:
0:518b1ca956fc
Child:
1:a7dca096e47d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SalesforceInterface.cpp	Wed Sep 17 21:36:19 2014 +0000
@@ -0,0 +1,223 @@
+/* Copyright C2014 ARM, MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+ * and associated documentation files the "Software", to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+  
+ // Tuneables
+ #define  SF_OAUTH_TOKEN_URL    "https://login.salesforce.com/services/oauth2/token"
+ #define  SF_OAUTH_REQUEST_BODY "grant_type=password&client_id=%s&client_secret=%s&username=%s&password=%s"
+ #define  SF_HTTP_AUTH_HEADER   "Authorization: Bearer %s"
+ #define  MAX_BUFFER_LENGTH     1024
+ 
+ // convenience macros
+ #define  ALLOC_BUFFER(x)       char x[MAX_BUFFER_LENGTH+1];memset(x,0,MAX_BUFFER_LENGTH+1);
+ 
+ // include class definition
+ #include "SalesforceInterface.h"
+ 
+ // Supported DataTypes for HTTPClient
+ #include "HTTPMap.h"
+ #include "HTTPJson.h"
+ 
+ // default constructor
+ SalesforceInterface::SalesforceInterface(ErrorHandler *logger,HTTPClient *http) {
+     this->m_logger = logger;
+     this->m_http = http;
+     this->m_username = NULL;
+     this->m_password = NULL;
+     this->m_client_id = NULL;
+     this->m_client_secret = NULL;
+     this->m_have_creds = false;
+ }
+ 
+ // destructor
+ SalesforceInterface::~SalesforceInterface() {
+ }
+ 
+ // set credentials
+ void SalesforceInterface::setCredentials(char *username,char *password,char *client_id,char *client_secret) {
+     this->m_username = NULL;
+     this->m_password = NULL;
+     this->m_client_id = NULL;
+     this->m_client_secret = NULL;
+     this->m_have_creds = false;
+     
+     if (username != NULL) {
+        this->m_username = username;
+        if (password != NULL) {
+            this->m_password = password;
+            if (client_id != NULL) {
+                this->m_client_id = client_id;
+                if (client_secret != NULL) {
+                    this->m_client_secret = client_secret;
+                    this->m_have_creds = true;
+                }
+            }
+        }
+     }
+ }
+ 
+ // convenience accessors
+ ErrorHandler *SalesforceInterface::logger() { return this->m_logger; }
+ HTTPClient *SalesforceInterface::http() { return this->m_http; }
+ bool SalesforceInterface::haveCreds() { return this->m_have_creds; }
+ 
+ //
+ // get OAUTH2 Token - taken from here: 
+ // https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Obtaining_a_Token_in_an_Autonomous_Client_.28Username_and_Password_Flow.29
+ //
+ char *SalesforceInterface::getOauthToken(char *output_buffer,int output_buffer_length) {
+     if (this->haveCreds()) {
+         ALLOC_BUFFER(body);
+         
+         // construct the OAUTH2 Token request body
+         HTTPMap input;
+         
+         //
+         // FORMAT: Taken from URL above method signature:
+         //
+         // grant_type=password&client_id=<your_client_id>&client_secret=<your_client_secret>&username=<your_username>&password=<your_password>
+         //
+         // ContentType: application/x-www-form-urlencoded
+         //
+         input.put("grant_type","password");
+         input.put("client_id",this->m_client_id);
+         input.put("client_secret",this->m_client_secret);
+         input.put("username",this->m_username);
+         input.put("password",this->m_password);
+        
+         // prepare the output buffer
+         HTTPText output(output_buffer,output_buffer_length);
+         
+         // HTTP POST call to gett he token 
+         DEBUG("getOauthToken: Calling %s...",SF_OAUTH_TOKEN_URL);
+         HTTPResult status = this->http()->post(SF_OAUTH_TOKEN_URL,input,&output);
+         
+         // check the result and return the token
+         DEBUG("getOauthToken: status(%d) response: %s",status,output_buffer);
+         if (status == 0) return output_buffer;
+     }
+     else {
+         // no credentials
+         this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to acquire OAUTH2 token...");
+     }
+     return NULL;
+ }
+ 
+ // Salesforce.com Invoke: defaults to GET
+ char *SalesforceInterface::invoke(char *url,char *output_buffer,int output_buffer_len) { 
+    return this->invoke(url,NUM_TYPES,NULL,0,output_buffer,output_buffer_len,GET); 
+ }
+ 
+ // Salesforce.com Invoke: defaults to POST with JSON input data type                                                  
+ char *SalesforceInterface::invoke(char *url,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len) { 
+    return this->invoke(url,JSON,input_data,input_data_len,output_buffer,output_buffer_len); 
+ }
+ 
+ // Salesforce.com Invoke: defaults to POST with variable input data type                                                  
+ char *SalesforceInterface::invoke(char *url,InputDataTypes input_type,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len) { 
+    return this->invoke(url,input_type,input_data,input_data_len,output_buffer,output_buffer_len,POST); 
+ }
+ 
+ // Salesforce.com Invoke: full fidelity method
+ char *SalesforceInterface::invoke(char *url,InputDataTypes input_type,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len,HttpVerb verb) {     
+     // initialize our invocation status
+     HTTPResult status = HTTP_ERROR;
+            
+     if (this->haveCreds() && output_buffer != NULL && output_buffer_len > 0) {
+        // first we have to get our OAUTH2 Token
+        ALLOC_BUFFER(token_buffer);
+     
+        // get the OAUTH2 token
+        char *token = this->getOauthToken(token_buffer,sizeof(token_buffer));
+        if (token != NULL) {
+            // Parse the OAUTH2 token
+            MbedJSONValue parsed_token;
+            parse(parsed_token,token);
+            
+            // extract the OAUTH2 token
+            string access_token = parsed_token["access_token"].get<std::string>();
+            
+            // DEBUG
+            this->logger()->log("OAUTH: %s",access_token.c_str());
+            
+            // use OAUTH headers
+            this->http()->oauthToken(access_token.c_str());
+            
+            // create our output/response buffer
+            HTTPText output(output_buffer,output_buffer_len);
+            
+            // now make the HTTP(S) request
+            switch(verb) {
+                case GET:
+                    status = this->http()->get(url,&output);
+                    break;
+                case DELETE:
+                    status = this->http()->del(url,&output);
+                    break;
+                case POST:
+                    if (input_data != NULL && input_data_len > 0) {
+                        if (input_type == JSON) {
+                            HTTPJson input_json(input_data,input_data_len);
+                            status = this->http()->post(url,input_json,&output);
+                        }
+                        else {
+                            HTTPText input_text(input_data,input_data_len);
+                            status = this->http()->post(url,input_text,&output);
+                        }
+                    }
+                    else {
+                        // no input buffer!
+                        this->logger()->log("invoke: ERROR HTTP(POST) requested but no input data provided... returning NULL");
+                    }
+                    break;
+                case PUT:
+                    if (input_data != NULL && input_data_len > 0) {
+                        if (input_type == JSON) {
+                            HTTPJson input_json(input_data,input_data_len);
+                            status = this->http()->put(url,input_json,&output);
+                        }
+                        else {
+                            HTTPText input_text(input_data,input_data_len);
+                            status = this->http()->put(url,input_text,&output);
+                        }
+                    }
+                    else {
+                        // no input buffer!
+                        this->logger()->log("invoke: ERROR HTTP(PUT) requested but no input data provided... returning NULL");
+                    }
+                    break;
+                default:
+                    // invalid HTTP verb
+                    this->logger()->log("invoke: ERROR invalid HTTP verb (%d) provided... returning NULL",verb);
+                    break;
+            }
+        }
+     }
+     else {
+         // no credentials
+         this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to invoke API...");
+     }
+     
+     // DEBUG
+     if (status == 0) this->logger()->log("invoke: SUCCESS!");
+     else this->logger()->log("invoke: FAILURE (%d)",status);
+     
+     // return the response in the output buffer
+     if (status == 0) return output_buffer;
+     return NULL;
+ }
+ 
\ No newline at end of file