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:
Thu Sep 18 16:50:39 2014 +0000
Revision:
1:a7dca096e47d
Parent:
0:518b1ca956fc
Child:
7:97ea5ef906f7
removed mbed.h from HTTPClient.cpp to enable K64F builds

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 1:a7dca096e47d 83 if (this->haveCreds()) {
ansond 0:518b1ca956fc 84 // construct the OAUTH2 Token request body
ansond 0:518b1ca956fc 85 HTTPMap input;
ansond 0:518b1ca956fc 86
ansond 0:518b1ca956fc 87 //
ansond 0:518b1ca956fc 88 // FORMAT: Taken from URL above method signature:
ansond 0:518b1ca956fc 89 //
ansond 0:518b1ca956fc 90 // grant_type=password&client_id=<your_client_id>&client_secret=<your_client_secret>&username=<your_username>&password=<your_password>
ansond 0:518b1ca956fc 91 //
ansond 0:518b1ca956fc 92 // ContentType: application/x-www-form-urlencoded
ansond 0:518b1ca956fc 93 //
ansond 0:518b1ca956fc 94 input.put("grant_type","password");
ansond 0:518b1ca956fc 95 input.put("client_id",this->m_client_id);
ansond 0:518b1ca956fc 96 input.put("client_secret",this->m_client_secret);
ansond 0:518b1ca956fc 97 input.put("username",this->m_username);
ansond 0:518b1ca956fc 98 input.put("password",this->m_password);
ansond 1:a7dca096e47d 99
ansond 0:518b1ca956fc 100 // prepare the output buffer
ansond 0:518b1ca956fc 101 HTTPText output(output_buffer,output_buffer_length);
ansond 0:518b1ca956fc 102
ansond 0:518b1ca956fc 103 // HTTP POST call to gett he token
ansond 0:518b1ca956fc 104 DEBUG("getOauthToken: Calling %s...",SF_OAUTH_TOKEN_URL);
ansond 0:518b1ca956fc 105 HTTPResult status = this->http()->post(SF_OAUTH_TOKEN_URL,input,&output);
ansond 0:518b1ca956fc 106
ansond 0:518b1ca956fc 107 // check the result and return the token
ansond 0:518b1ca956fc 108 DEBUG("getOauthToken: status(%d) response: %s",status,output_buffer);
ansond 0:518b1ca956fc 109 if (status == 0) return output_buffer;
ansond 0:518b1ca956fc 110 }
ansond 0:518b1ca956fc 111 else {
ansond 0:518b1ca956fc 112 // no credentials
ansond 0:518b1ca956fc 113 this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to acquire OAUTH2 token...");
ansond 0:518b1ca956fc 114 }
ansond 0:518b1ca956fc 115 return NULL;
ansond 0:518b1ca956fc 116 }
ansond 0:518b1ca956fc 117
ansond 0:518b1ca956fc 118 // Salesforce.com Invoke: defaults to GET
ansond 0:518b1ca956fc 119 char *SalesforceInterface::invoke(char *url,char *output_buffer,int output_buffer_len) {
ansond 0:518b1ca956fc 120 return this->invoke(url,NUM_TYPES,NULL,0,output_buffer,output_buffer_len,GET);
ansond 0:518b1ca956fc 121 }
ansond 0:518b1ca956fc 122
ansond 0:518b1ca956fc 123 // Salesforce.com Invoke: defaults to POST with JSON input data type
ansond 0:518b1ca956fc 124 char *SalesforceInterface::invoke(char *url,char *input_data,int input_data_len,char *output_buffer,int output_buffer_len) {
ansond 0:518b1ca956fc 125 return this->invoke(url,JSON,input_data,input_data_len,output_buffer,output_buffer_len);
ansond 0:518b1ca956fc 126 }
ansond 0:518b1ca956fc 127
ansond 0:518b1ca956fc 128 // Salesforce.com Invoke: defaults to POST with variable input data type
ansond 0:518b1ca956fc 129 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 130 return this->invoke(url,input_type,input_data,input_data_len,output_buffer,output_buffer_len,POST);
ansond 0:518b1ca956fc 131 }
ansond 0:518b1ca956fc 132
ansond 0:518b1ca956fc 133 // Salesforce.com Invoke: full fidelity method
ansond 0:518b1ca956fc 134 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 135 // initialize our invocation status
ansond 0:518b1ca956fc 136 HTTPResult status = HTTP_ERROR;
ansond 0:518b1ca956fc 137
ansond 0:518b1ca956fc 138 if (this->haveCreds() && output_buffer != NULL && output_buffer_len > 0) {
ansond 0:518b1ca956fc 139 // first we have to get our OAUTH2 Token
ansond 0:518b1ca956fc 140 ALLOC_BUFFER(token_buffer);
ansond 0:518b1ca956fc 141
ansond 0:518b1ca956fc 142 // get the OAUTH2 token
ansond 0:518b1ca956fc 143 char *token = this->getOauthToken(token_buffer,sizeof(token_buffer));
ansond 0:518b1ca956fc 144 if (token != NULL) {
ansond 0:518b1ca956fc 145 // Parse the OAUTH2 token
ansond 0:518b1ca956fc 146 MbedJSONValue parsed_token;
ansond 0:518b1ca956fc 147 parse(parsed_token,token);
ansond 0:518b1ca956fc 148
ansond 0:518b1ca956fc 149 // extract the OAUTH2 token
ansond 0:518b1ca956fc 150 string access_token = parsed_token["access_token"].get<std::string>();
ansond 0:518b1ca956fc 151
ansond 0:518b1ca956fc 152 // DEBUG
ansond 0:518b1ca956fc 153 this->logger()->log("OAUTH: %s",access_token.c_str());
ansond 0:518b1ca956fc 154
ansond 0:518b1ca956fc 155 // use OAUTH headers
ansond 0:518b1ca956fc 156 this->http()->oauthToken(access_token.c_str());
ansond 0:518b1ca956fc 157
ansond 0:518b1ca956fc 158 // create our output/response buffer
ansond 0:518b1ca956fc 159 HTTPText output(output_buffer,output_buffer_len);
ansond 0:518b1ca956fc 160
ansond 0:518b1ca956fc 161 // now make the HTTP(S) request
ansond 0:518b1ca956fc 162 switch(verb) {
ansond 0:518b1ca956fc 163 case GET:
ansond 0:518b1ca956fc 164 status = this->http()->get(url,&output);
ansond 0:518b1ca956fc 165 break;
ansond 0:518b1ca956fc 166 case DELETE:
ansond 0:518b1ca956fc 167 status = this->http()->del(url,&output);
ansond 0:518b1ca956fc 168 break;
ansond 0:518b1ca956fc 169 case POST:
ansond 0:518b1ca956fc 170 if (input_data != NULL && input_data_len > 0) {
ansond 0:518b1ca956fc 171 if (input_type == JSON) {
ansond 0:518b1ca956fc 172 HTTPJson input_json(input_data,input_data_len);
ansond 0:518b1ca956fc 173 status = this->http()->post(url,input_json,&output);
ansond 0:518b1ca956fc 174 }
ansond 0:518b1ca956fc 175 else {
ansond 0:518b1ca956fc 176 HTTPText input_text(input_data,input_data_len);
ansond 0:518b1ca956fc 177 status = this->http()->post(url,input_text,&output);
ansond 0:518b1ca956fc 178 }
ansond 0:518b1ca956fc 179 }
ansond 0:518b1ca956fc 180 else {
ansond 0:518b1ca956fc 181 // no input buffer!
ansond 0:518b1ca956fc 182 this->logger()->log("invoke: ERROR HTTP(POST) requested but no input data provided... returning NULL");
ansond 0:518b1ca956fc 183 }
ansond 0:518b1ca956fc 184 break;
ansond 0:518b1ca956fc 185 case PUT:
ansond 0:518b1ca956fc 186 if (input_data != NULL && input_data_len > 0) {
ansond 0:518b1ca956fc 187 if (input_type == JSON) {
ansond 0:518b1ca956fc 188 HTTPJson input_json(input_data,input_data_len);
ansond 0:518b1ca956fc 189 status = this->http()->put(url,input_json,&output);
ansond 0:518b1ca956fc 190 }
ansond 0:518b1ca956fc 191 else {
ansond 0:518b1ca956fc 192 HTTPText input_text(input_data,input_data_len);
ansond 0:518b1ca956fc 193 status = this->http()->put(url,input_text,&output);
ansond 0:518b1ca956fc 194 }
ansond 0:518b1ca956fc 195 }
ansond 0:518b1ca956fc 196 else {
ansond 0:518b1ca956fc 197 // no input buffer!
ansond 0:518b1ca956fc 198 this->logger()->log("invoke: ERROR HTTP(PUT) requested but no input data provided... returning NULL");
ansond 0:518b1ca956fc 199 }
ansond 0:518b1ca956fc 200 break;
ansond 0:518b1ca956fc 201 default:
ansond 0:518b1ca956fc 202 // invalid HTTP verb
ansond 0:518b1ca956fc 203 this->logger()->log("invoke: ERROR invalid HTTP verb (%d) provided... returning NULL",verb);
ansond 0:518b1ca956fc 204 break;
ansond 0:518b1ca956fc 205 }
ansond 0:518b1ca956fc 206 }
ansond 0:518b1ca956fc 207 }
ansond 0:518b1ca956fc 208 else {
ansond 0:518b1ca956fc 209 // no credentials
ansond 0:518b1ca956fc 210 this->logger()->log("no/incomplete salesforce.com credentials provided. Unable to invoke API...");
ansond 0:518b1ca956fc 211 }
ansond 0:518b1ca956fc 212
ansond 0:518b1ca956fc 213 // DEBUG
ansond 0:518b1ca956fc 214 if (status == 0) this->logger()->log("invoke: SUCCESS!");
ansond 0:518b1ca956fc 215 else this->logger()->log("invoke: FAILURE (%d)",status);
ansond 0:518b1ca956fc 216
ansond 0:518b1ca956fc 217 // return the response in the output buffer
ansond 0:518b1ca956fc 218 if (status == 0) return output_buffer;
ansond 0:518b1ca956fc 219 return NULL;
ansond 0:518b1ca956fc 220 }
ansond 0:518b1ca956fc 221