Salesforce.com interface to directly access Salesforce.com
Dependencies: HTTPClient-SSL MbedJSONValue
Dependents: df-2014-salesforce-hrm-k64f
Fork of SalesforceInterface by
Revision 0:518b1ca956fc, committed 2014-09-17
- Comitter:
- ansond
- Date:
- Wed Sep 17 21:36:19 2014 +0000
- Child:
- 1:a7dca096e47d
- Commit message:
- updates
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPClient-SSL.lib Wed Sep 17 21:36:19 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/ansond/code/HTTPClient-SSL/#debaeb6006a7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MbedJSONValue.lib Wed Sep 17 21:36:19 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/samux/code/MbedJSONValue/#10a99cdf7846
--- /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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SalesforceInterface.h Wed Sep 17 21:36:19 2014 +0000 @@ -0,0 +1,91 @@ +/* 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. + */ + + #ifndef _SALESFORCE_INTERFACE_H_ + #define _SALESFORCE_INTERFACE_H_ + + // ErrorHandler + #include "ErrorHandler.h" + + // SSL-based HTTP support + #include "HTTPClient.h" + + // JSON parsing support + #include "MbedJSONValue.h" + + // verbose debugging + #if ENABLE_DEBUG_LOGGING + #define DEBUG(...) { this->logger()->logConsole(__VA_ARGS__); } + #else + #define DEBUG(...) + #endif + + + // HTTP Verbs + typedef enum { + GET, + PUT, + POST, + DELETE, + NUM_VERBS + } HttpVerb; + + // Supported input data types for PUT and POST (Defined by HTTPClient-SSL/data support...) + typedef enum { + JSON, // ContentType: application/json + PLAIN_TEXT, // ContentType: plain/text + FORM_MAPPED, // ContentType: application/x-www-form-urlencoded + NUM_TYPES + } InputDataTypes; + + // This class provides an interface into the REST-based Salesforce.com APIs + class SalesforceInterface { + private: + ErrorHandler *m_logger; + HTTPClient *m_http; + char *m_username; + char *m_password; + char *m_client_id; + char *m_client_secret; + bool m_have_creds; + + public: + // construction/destruction + SalesforceInterface(ErrorHandler *logger,HTTPClient *http); + virtual ~SalesforceInterface(); + + // set Salesforce.com credentials + void setCredentials(char *username,char *password,char *client_id,char *client_secret); + + // get our OAUTH Token + char *getOauthToken(char *output_buffer,int output_buffer_length); + + // invoke REST calls into Salesforce.com + char *invoke(char *url,char *output_buffer,int output_buffer_len); // defaults to GET + char *invoke(char *url,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len); // defaults to POST with JSON input data type // defaults to GET + char *invoke(char *url,InputDataTypes input_type,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len); // defaults to POST with variable input data type + char *invoke(char *url,InputDataTypes input_type,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len,HttpVerb verb); // full fidelity method + + private: + // convenience accessors + ErrorHandler *logger(); + HTTPClient *http(); + bool haveCreds(); + }; + + #endif // _SALESFORCE_INTERFACE_H_ \ No newline at end of file