Salesforce.com interface to directly access Salesforce.com

Dependencies:   HTTPClient-SSL MbedJSONValue

Dependents:   df-2014-salesforce-hrm-k64f

Fork of SalesforceInterface by Doug Anson

Committer:
ansond
Date:
Wed Sep 17 21:36:19 2014 +0000
Revision:
0:518b1ca956fc
Child:
1:a7dca096e47d
updates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:518b1ca956fc 1 /* Copyright C2014 ARM, MIT License
ansond 0:518b1ca956fc 2 *
ansond 0:518b1ca956fc 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
ansond 0:518b1ca956fc 4 * and associated documentation files the "Software", to deal in the Software without restriction,
ansond 0:518b1ca956fc 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
ansond 0:518b1ca956fc 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
ansond 0:518b1ca956fc 7 * furnished to do so, subject to the following conditions:
ansond 0:518b1ca956fc 8 *
ansond 0:518b1ca956fc 9 * The above copyright notice and this permission notice shall be included in all copies or
ansond 0:518b1ca956fc 10 * substantial portions of the Software.
ansond 0:518b1ca956fc 11 *
ansond 0:518b1ca956fc 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
ansond 0:518b1ca956fc 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ansond 0:518b1ca956fc 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
ansond 0:518b1ca956fc 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ansond 0:518b1ca956fc 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
ansond 0:518b1ca956fc 17 */
ansond 0:518b1ca956fc 18
ansond 0:518b1ca956fc 19 // Tuneables
ansond 0:518b1ca956fc 20 #define SF_OAUTH_TOKEN_URL "https://login.salesforce.com/services/oauth2/token"
ansond 0:518b1ca956fc 21 #define SF_OAUTH_REQUEST_BODY "grant_type=password&client_id=%s&client_secret=%s&username=%s&password=%s"
ansond 0:518b1ca956fc 22 #define SF_HTTP_AUTH_HEADER "Authorization: Bearer %s"
ansond 0:518b1ca956fc 23 #define MAX_BUFFER_LENGTH 1024
ansond 0:518b1ca956fc 24
ansond 0:518b1ca956fc 25 // convenience macros
ansond 0:518b1ca956fc 26 #define ALLOC_BUFFER(x) char x[MAX_BUFFER_LENGTH+1];memset(x,0,MAX_BUFFER_LENGTH+1);
ansond 0:518b1ca956fc 27
ansond 0:518b1ca956fc 28 // include class definition
ansond 0:518b1ca956fc 29 #include "SalesforceInterface.h"
ansond 0:518b1ca956fc 30
ansond 0:518b1ca956fc 31 // Supported DataTypes for HTTPClient
ansond 0:518b1ca956fc 32 #include "HTTPMap.h"
ansond 0:518b1ca956fc 33 #include "HTTPJson.h"
ansond 0:518b1ca956fc 34
ansond 0:518b1ca956fc 35 // default constructor
ansond 0:518b1ca956fc 36 SalesforceInterface::SalesforceInterface(ErrorHandler *logger,HTTPClient *http) {
ansond 0:518b1ca956fc 37 this->m_logger = logger;
ansond 0:518b1ca956fc 38 this->m_http = http;
ansond 0:518b1ca956fc 39 this->m_username = NULL;
ansond 0:518b1ca956fc 40 this->m_password = NULL;
ansond 0:518b1ca956fc 41 this->m_client_id = NULL;
ansond 0:518b1ca956fc 42 this->m_client_secret = NULL;
ansond 0:518b1ca956fc 43 this->m_have_creds = false;
ansond 0:518b1ca956fc 44 }
ansond 0:518b1ca956fc 45
ansond 0:518b1ca956fc 46 // destructor
ansond 0:518b1ca956fc 47 SalesforceInterface::~SalesforceInterface() {
ansond 0:518b1ca956fc 48 }
ansond 0:518b1ca956fc 49
ansond 0:518b1ca956fc 50 // set credentials
ansond 0:518b1ca956fc 51 void SalesforceInterface::setCredentials(char *username,char *password,char *client_id,char *client_secret) {
ansond 0:518b1ca956fc 52 this->m_username = NULL;
ansond 0:518b1ca956fc 53 this->m_password = NULL;
ansond 0:518b1ca956fc 54 this->m_client_id = NULL;
ansond 0:518b1ca956fc 55 this->m_client_secret = NULL;
ansond 0:518b1ca956fc 56 this->m_have_creds = false;
ansond 0:518b1ca956fc 57
ansond 0:518b1ca956fc 58 if (username != NULL) {
ansond 0:518b1ca956fc 59 this->m_username = username;
ansond 0:518b1ca956fc 60 if (password != NULL) {
ansond 0:518b1ca956fc 61 this->m_password = password;
ansond 0:518b1ca956fc 62 if (client_id != NULL) {
ansond 0:518b1ca956fc 63 this->m_client_id = client_id;
ansond 0:518b1ca956fc 64 if (client_secret != NULL) {
ansond 0:518b1ca956fc 65 this->m_client_secret = client_secret;
ansond 0:518b1ca956fc 66 this->m_have_creds = true;
ansond 0:518b1ca956fc 67 }
ansond 0:518b1ca956fc 68 }
ansond 0:518b1ca956fc 69 }
ansond 0:518b1ca956fc 70 }
ansond 0:518b1ca956fc 71 }
ansond 0:518b1ca956fc 72
ansond 0:518b1ca956fc 73 // convenience accessors
ansond 0:518b1ca956fc 74 ErrorHandler *SalesforceInterface::logger() { return this->m_logger; }
ansond 0:518b1ca956fc 75 HTTPClient *SalesforceInterface::http() { return this->m_http; }
ansond 0:518b1ca956fc 76 bool SalesforceInterface::haveCreds() { return this->m_have_creds; }
ansond 0:518b1ca956fc 77
ansond 0:518b1ca956fc 78 //
ansond 0:518b1ca956fc 79 // get OAUTH2 Token - taken from here:
ansond 0:518b1ca956fc 80 // 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
ansond 0:518b1ca956fc 81 //
ansond 0:518b1ca956fc 82 char *SalesforceInterface::getOauthToken(char *output_buffer,int output_buffer_length) {
ansond 0:518b1ca956fc 83 if (this->haveCreds()) {
ansond 0:518b1ca956fc 84 ALLOC_BUFFER(body);
ansond 0:518b1ca956fc 85
ansond 0:518b1ca956fc 86 // construct the OAUTH2 Token request body
ansond 0:518b1ca956fc 87 HTTPMap input;
ansond 0:518b1ca956fc 88
ansond 0:518b1ca956fc 89 //
ansond 0:518b1ca956fc 90 // FORMAT: Taken from URL above method signature:
ansond 0:518b1ca956fc 91 //
ansond 0:518b1ca956fc 92 // grant_type=password&client_id=<your_client_id>&client_secret=<your_client_secret>&username=<your_username>&password=<your_password>
ansond 0:518b1ca956fc 93 //
ansond 0:518b1ca956fc 94 // ContentType: application/x-www-form-urlencoded
ansond 0:518b1ca956fc 95 //
ansond 0:518b1ca956fc 96 input.put("grant_type","password");
ansond 0:518b1ca956fc 97 input.put("client_id",this->m_client_id);
ansond 0:518b1ca956fc 98 input.put("client_secret",this->m_client_secret);
ansond 0:518b1ca956fc 99 input.put("username",this->m_username);
ansond 0:518b1ca956fc 100 input.put("password",this->m_password);
ansond 0:518b1ca956fc 101
ansond 0:518b1ca956fc 102 // prepare the output buffer
ansond 0:518b1ca956fc 103 HTTPText output(output_buffer,output_buffer_length);
ansond 0:518b1ca956fc 104
ansond 0:518b1ca956fc 105 // HTTP POST call to gett he token
ansond 0:518b1ca956fc 106 DEBUG("getOauthToken: Calling %s...",SF_OAUTH_TOKEN_URL);
ansond 0:518b1ca956fc 107 HTTPResult status = this->http()->post(SF_OAUTH_TOKEN_URL,input,&output);
ansond 0:518b1ca956fc 108
ansond 0:518b1ca956fc 109 // check the result and return the token
ansond 0:518b1ca956fc 110 DEBUG("getOauthToken: status(%d) response: %s",status,output_buffer);
ansond 0:518b1ca956fc 111 if (status == 0) return output_buffer;
ansond 0:518b1ca956fc 112 }
ansond 0:518b1ca956fc 113 else {
ansond 0:518b1ca956fc 114 // no credentials
ansond 0:518b1ca956fc 115 this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to acquire OAUTH2 token...");
ansond 0:518b1ca956fc 116 }
ansond 0:518b1ca956fc 117 return NULL;
ansond 0:518b1ca956fc 118 }
ansond 0:518b1ca956fc 119
ansond 0:518b1ca956fc 120 // Salesforce.com Invoke: defaults to GET
ansond 0:518b1ca956fc 121 char *SalesforceInterface::invoke(char *url,char *output_buffer,int output_buffer_len) {
ansond 0:518b1ca956fc 122 return this->invoke(url,NUM_TYPES,NULL,0,output_buffer,output_buffer_len,GET);
ansond 0:518b1ca956fc 123 }
ansond 0:518b1ca956fc 124
ansond 0:518b1ca956fc 125 // Salesforce.com Invoke: defaults to POST with JSON input data type
ansond 0:518b1ca956fc 126 char *SalesforceInterface::invoke(char *url,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len) {
ansond 0:518b1ca956fc 127 return this->invoke(url,JSON,input_data,input_data_len,output_buffer,output_buffer_len);
ansond 0:518b1ca956fc 128 }
ansond 0:518b1ca956fc 129
ansond 0:518b1ca956fc 130 // Salesforce.com Invoke: defaults to POST with variable input data type
ansond 0:518b1ca956fc 131 char *SalesforceInterface::invoke(char *url,InputDataTypes input_type,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len) {
ansond 0:518b1ca956fc 132 return this->invoke(url,input_type,input_data,input_data_len,output_buffer,output_buffer_len,POST);
ansond 0:518b1ca956fc 133 }
ansond 0:518b1ca956fc 134
ansond 0:518b1ca956fc 135 // Salesforce.com Invoke: full fidelity method
ansond 0:518b1ca956fc 136 char *SalesforceInterface::invoke(char *url,InputDataTypes input_type,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len,HttpVerb verb) {
ansond 0:518b1ca956fc 137 // initialize our invocation status
ansond 0:518b1ca956fc 138 HTTPResult status = HTTP_ERROR;
ansond 0:518b1ca956fc 139
ansond 0:518b1ca956fc 140 if (this->haveCreds() && output_buffer != NULL && output_buffer_len > 0) {
ansond 0:518b1ca956fc 141 // first we have to get our OAUTH2 Token
ansond 0:518b1ca956fc 142 ALLOC_BUFFER(token_buffer);
ansond 0:518b1ca956fc 143
ansond 0:518b1ca956fc 144 // get the OAUTH2 token
ansond 0:518b1ca956fc 145 char *token = this->getOauthToken(token_buffer,sizeof(token_buffer));
ansond 0:518b1ca956fc 146 if (token != NULL) {
ansond 0:518b1ca956fc 147 // Parse the OAUTH2 token
ansond 0:518b1ca956fc 148 MbedJSONValue parsed_token;
ansond 0:518b1ca956fc 149 parse(parsed_token,token);
ansond 0:518b1ca956fc 150
ansond 0:518b1ca956fc 151 // extract the OAUTH2 token
ansond 0:518b1ca956fc 152 string access_token = parsed_token["access_token"].get<std::string>();
ansond 0:518b1ca956fc 153
ansond 0:518b1ca956fc 154 // DEBUG
ansond 0:518b1ca956fc 155 this->logger()->log("OAUTH: %s",access_token.c_str());
ansond 0:518b1ca956fc 156
ansond 0:518b1ca956fc 157 // use OAUTH headers
ansond 0:518b1ca956fc 158 this->http()->oauthToken(access_token.c_str());
ansond 0:518b1ca956fc 159
ansond 0:518b1ca956fc 160 // create our output/response buffer
ansond 0:518b1ca956fc 161 HTTPText output(output_buffer,output_buffer_len);
ansond 0:518b1ca956fc 162
ansond 0:518b1ca956fc 163 // now make the HTTP(S) request
ansond 0:518b1ca956fc 164 switch(verb) {
ansond 0:518b1ca956fc 165 case GET:
ansond 0:518b1ca956fc 166 status = this->http()->get(url,&output);
ansond 0:518b1ca956fc 167 break;
ansond 0:518b1ca956fc 168 case DELETE:
ansond 0:518b1ca956fc 169 status = this->http()->del(url,&output);
ansond 0:518b1ca956fc 170 break;
ansond 0:518b1ca956fc 171 case POST:
ansond 0:518b1ca956fc 172 if (input_data != NULL && input_data_len > 0) {
ansond 0:518b1ca956fc 173 if (input_type == JSON) {
ansond 0:518b1ca956fc 174 HTTPJson input_json(input_data,input_data_len);
ansond 0:518b1ca956fc 175 status = this->http()->post(url,input_json,&output);
ansond 0:518b1ca956fc 176 }
ansond 0:518b1ca956fc 177 else {
ansond 0:518b1ca956fc 178 HTTPText input_text(input_data,input_data_len);
ansond 0:518b1ca956fc 179 status = this->http()->post(url,input_text,&output);
ansond 0:518b1ca956fc 180 }
ansond 0:518b1ca956fc 181 }
ansond 0:518b1ca956fc 182 else {
ansond 0:518b1ca956fc 183 // no input buffer!
ansond 0:518b1ca956fc 184 this->logger()->log("invoke: ERROR HTTP(POST) requested but no input data provided... returning NULL");
ansond 0:518b1ca956fc 185 }
ansond 0:518b1ca956fc 186 break;
ansond 0:518b1ca956fc 187 case PUT:
ansond 0:518b1ca956fc 188 if (input_data != NULL && input_data_len > 0) {
ansond 0:518b1ca956fc 189 if (input_type == JSON) {
ansond 0:518b1ca956fc 190 HTTPJson input_json(input_data,input_data_len);
ansond 0:518b1ca956fc 191 status = this->http()->put(url,input_json,&output);
ansond 0:518b1ca956fc 192 }
ansond 0:518b1ca956fc 193 else {
ansond 0:518b1ca956fc 194 HTTPText input_text(input_data,input_data_len);
ansond 0:518b1ca956fc 195 status = this->http()->put(url,input_text,&output);
ansond 0:518b1ca956fc 196 }
ansond 0:518b1ca956fc 197 }
ansond 0:518b1ca956fc 198 else {
ansond 0:518b1ca956fc 199 // no input buffer!
ansond 0:518b1ca956fc 200 this->logger()->log("invoke: ERROR HTTP(PUT) requested but no input data provided... returning NULL");
ansond 0:518b1ca956fc 201 }
ansond 0:518b1ca956fc 202 break;
ansond 0:518b1ca956fc 203 default:
ansond 0:518b1ca956fc 204 // invalid HTTP verb
ansond 0:518b1ca956fc 205 this->logger()->log("invoke: ERROR invalid HTTP verb (%d) provided... returning NULL",verb);
ansond 0:518b1ca956fc 206 break;
ansond 0:518b1ca956fc 207 }
ansond 0:518b1ca956fc 208 }
ansond 0:518b1ca956fc 209 }
ansond 0:518b1ca956fc 210 else {
ansond 0:518b1ca956fc 211 // no credentials
ansond 0:518b1ca956fc 212 this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to invoke API...");
ansond 0:518b1ca956fc 213 }
ansond 0:518b1ca956fc 214
ansond 0:518b1ca956fc 215 // DEBUG
ansond 0:518b1ca956fc 216 if (status == 0) this->logger()->log("invoke: SUCCESS!");
ansond 0:518b1ca956fc 217 else this->logger()->log("invoke: FAILURE (%d)",status);
ansond 0:518b1ca956fc 218
ansond 0:518b1ca956fc 219 // return the response in the output buffer
ansond 0:518b1ca956fc 220 if (status == 0) return output_buffer;
ansond 0:518b1ca956fc 221 return NULL;
ansond 0:518b1ca956fc 222 }
ansond 0:518b1ca956fc 223