Salesforce Snippet
This snippet can be used by copy-pasting to the neqto.js script.
neqto: Bridge | SPRESENSE |
---|---|
v00.00.30+ | v01.00.00+ |
This snippet provides a function to send IoT data to Salesforce.
Details
The send_salesforce
function can be used to POST the passed object 'payload' to the specified 'object' on Salesforce using the Session ID, over HTTPS. The Session ID can be retrieved by the getSessionId
function using the user credentials. The result (error/response) is then passed to the callback function.
To start using this snippet, USERNAME
(Salesforce username), PASSWORD
(Salesforce password), REST_VERSION
(Salesforce REST API version), SOAP_VERSION
(Salesforce SOAP API version), and CA
are required to be configured by the user.
NOTE: The provided function only allows payloads up to size of 4KB. For bigger sized payloads, please refer to the sample for divided writing in neqto.js docs for neqto: Bridge and Sony Spresense.
The following CA can be used (as of 2020-07-30),
/* DigiCert Global Root CA - 083be056904246b1a1756ac95991c74a */
var CA = "-----BEGIN CERTIFICATE-----\nMIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\nMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\nd3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\nQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\nMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\nb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\nCSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\nnh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\nT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\ngdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\nBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\nTLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\nDQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\nhMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\nPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\nYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\nCAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n-----END CERTIFICATE-----";
//=================================================================
// SALESFORCE SNIPPET
//=================================================================
//=================================================================
// The following configuration are MANDATORY. Set by user.
//=================================================================
// The Username for authorization.
var USERNAME = '<YOUR_USERNAME>';
// The Password for authorization.
var PASSWORD = '<YOUR_PASSWORD>';
// Salesforce REST API version.
// Find Salesforce Edition and API version - https://help.salesforce.com/articleView?siteLang=en_us&id=000334996&language=en_us&type=1&mode=1
// eg. xx.x
var REST_VERSION = '<REST_API_VERSION>';
// Salesforce SOAP API version.
// eg. xx.x
var SOAP_VERSION = '<SOAP_API_VERSION>';
// Public certificate of the certificate authority that signed the Salesforce server certificate for SSL/TLS handshake.
// eg. '-----BEGIN CERTIFICATE-----\n...<CA>...\n-----END CERTIFICATE-----'
var CA = '<YOUR_CA>';
//=================================================================
/**
* Get Session ID and Hostname from Salesforce using user credentials.
* @function getSessionId
* @param {object} sessionInfo - Session info object to hold a session's information, as an Object.
* @param {function} callback - User callback to return the result (error/response).
* @returns {undefined}
*/
var getSessionId = function (sessionInfo, callback) {
var body = '<?xml version="1.0" encoding="utf-8" ?> ' +
'<env:Envelope ' +
'xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' +
'xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" ' +
'xmlns:urn="urn:partner.soap.sforce.com"> ' +
'<env:Header> ' +
'<urn:CallOptions> ' +
'<urn:client>RestForce</urn:client> ' +
'<urn:defaultNamespace>sf</urn:defaultNamespace> ' +
'</urn:CallOptions> ' +
'</env:Header> ' +
'<env:Body> ' +
'<n1:login xmlns:n1="urn:partner.soap.sforce.com"> ' +
'<n1:username>' + USERNAME + '</n1:username> ' +
'<n1:password>' + PASSWORD + '</n1:password> ' +
'</n1:login> ' +
'</env:Body> ' +
'</env:Envelope>';
var options = {
"method": 'POST',
"host": 'login.salesforce.com',
"path": `/services/Soap/u/${SOAP_VERSION}`,
"headers": {
"Content-Type": 'text/xml',
"Content-Length": body.length.toString(),
"SOAPAction": '""'
},
"ca": CA
};
var request = https.request(options, function (response) {
response.on('end', function () {
var resBody = response.read();
if (response.statusCode == 200) { // 200 - OK
var session = resBody.match(/<sessionId>([^<]+)<\/sessionId>/);
sessionInfo.sessionId = session && session[1];
sessionInfo.host = resBody.match("<serverUrl>(.*?)<\/serverUrl>")[1].split('/')[2];
}
callback(null, { "statusCode": response.statusCode, "statusMessage": response.statusMessage, "body": resBody });
});
});
request.on('error', function () {
callback({ "errCode": request.errCode }, null);
});
request.end(body.toString(), function () {
print("[request] SUCCESS");
});
};
/**
* Post data to Salesforce using Session ID.
* @function send_salesforce
* @param {object} sessionInfo - Information about the session, as an Object.
* @param {string} object - Name of the object to be put, as a String.
* @param {string} payload - Data/meta-data to be sent to Salesforce, as an Object.
* @param {function} callback - User callback to return the result (error/response).
* @returns {undefined}
*/
var send_salesforce = function (sessionInfo, object, payload, callback) {
var body = JSON.stringify(payload);
var options = {
"method": 'POST',
"host": sessionInfo.host,
"path": `/services/data/v${REST_VERSION}/sobjects/${object}`,
"headers": {
"Content-Type": 'application/json',
'Content-Length': body.length.toString(),
'Authorization': `Bearer ${sessionInfo.sessionId}`
},
"ca": CA
};
var request = https.request(options, function (response) {
response.on('end', function () {
callback(null, { "statusCode": response.statusCode, "statusMessage": response.statusMessage, "body": response.read() });
});
});
request.on('error', function () {
callback({ "errCode": request.errCode }, null);
});
request.end(body.toString(), function () {
print("[request] SUCCESS");
});
}
Function Usage Example
The following example script uses the send_salesforce
function to continuously send data to Salesforce at regular intervals, and re-fetches the Session ID using the getSessionID
function when it expires.
/*
<INSERT ABOVE SNIPPET HERE WITH SET CONFIGURATIONS>
*/
//=================================================================
log.setLevel(-1); //-1:NONE 0:ERROR 1:WARNING 2:DEBUG 3:TRACE
log.printLevel(2); //0:DISABLE 1:LOG 2:CONSOLE 3:BOTH
//=================================================================
// MAIN SCENARIO
//=================================================================
/**
* Callback to fetch error/response from the request.
* @function callback
* @param {object} err - Error returned in case of a failed request. Has one property - `errCode`.
* @param {object} data - Response returned by a successfully completed request. Has three properties - `statusCode`, `statusMessage`, and `body`.
*/
var callback = function (err, data) {
if (err) {
print("[error]", err.errCode);
} else {
print("[status]", data.statusCode, data.statusMessage);
print("[response]", data.body);
}
}
/**
* Object to store any session related information.
* @enum sessionInfo
* @property {string} host - Hostname of the server.
* @property {string} sessionId - Session ID to authorize API requests.
*/
var sessionInfo = {
"host": '',
"sessionId": ''
};
var object = "test__c";
var payload = {
"Component__r": {
"external_id__c": 'node-component'
},
"Value__c": 123,
"Thing__r": {
"external_id__c": 'node'
},
"Code__c": 'ERR-01',
"Priority__c": 'High',
"Timestamp__c": new Date().getTime()
};
// A mutex to limit the active HTTP requests.
var lock = false;
while (1) {
if (!lock) { // wait for the lock to release
lock = true; // lock
if (sessionInfo.sessionId) {
print("[info] send_salesforce()");
send_salesforce(sessionInfo, object, payload, function (err, data) {
callback(err, data);
if (data.statusCode == 401) sessionInfo.sessionId = ''; // 401 - Unauthorized
lock = false; // unlock
});
setTimeout(60000).wait(); // wait for 60 seconds
}
else {
print("[info] getSessionId()");
getSessionId(sessionInfo, function (err, data) {
callback(err, data);
lock = false; // unlock
});
setTimeout(10000).wait(); // wait for 10 seconds
}
}
};