DocuSign API - JavaScript - javascript

Afternoon! I am very new to JavaScript and the DocuSign API. I tried following the sample, but I am getting a ReferenceError.
For testing purposes, I have async.js, fs.js, request.js, and require.js at the root of the folder on my PC along with the test HTML doc
HTML:
<html>
<head>
<script src="require.js"></script>
<script src="example.js"></script>
</head>
<body>
<div id="message"></div>
</body>
</html>
I am getting the following error:
ReferenceError: async is not defined
async.waterfall(
Below is the example.js code I got from the DocuSign website, slighlt adjusted based on another error around the require function:
// Request Signature on a Document (JavaScript)
// To run this sample
// 1. Copy the file to your local machine and give .js extension (i.e. example.js)
// 2. Change "***" to appropriate values
// 3. Install async and request packages
// npm install async
// npm install request
// npm install fs
// 4. execute
// node example.js
//
//var async = require("async"), // async module
// request = require("request"), // request module
// fs = require("fs"); // fs module
require(["request"], function (request){});
require(["async"], function (async){});
require(["fs"], function (fs){});
var email = "email#email", // your account email
password = "apassword", // your account password
integratorKey = "akey", // your Integrator Key
(found on the Preferences -> API page)
recipientName = "Bob", // recipient (signer) name
documentName = "afile", // copy document with this name into same
directory!
baseUrl = ""; // we will retrieve this through the Login call
async.waterfall(
[
/////////////////////////////////////////////////////////////////////////////////////
// Step 1: Login (used to retrieve your accountId and baseUrl)
/////////////////////////////////////////////////////////////////////////////////////
function(next) {
var url = "https://demo.docusign.net/restapi/v2/login_information";
var body = ""; // no request body for login api call
// set request url, method, body, and headers
var options = initializeRequest(url, "GET", body, email, password);
// send the request...
request(options, function(err, res, body) {
if(!parseResponseBody(err, res, body)) {
return;
}
baseUrl = JSON.parse(body).loginAccounts[0].baseUrl;
next(null); // call next function
});
},
/////////////////////////////////////////////////////////////////////////////////////
// Step 2: Request Signature on a PDF Document
/////////////////////////////////////////////////////////////////////////////////////
function(next) {
var url = baseUrl + "/envelopes";
// following request body will place 1 signature tab 100 pixels to the right and
// 100 pixels down from the top left of the document that you send in the request
var body = {
"recipients": {
"signers": [{
"email": email,
"name": recipientName,
"recipientId": 1,
"tabs": {
"signHereTabs": [{
"xPosition": "100",
"yPosition": "100",
"documentId": "1",
"pageNumber": "1"
}]
}
}]
},
"emailSubject": 'DocuSign API - Signature Request on Document Call',
"documents": [{
"name": documentName,
"documentId": 1,
}],
"status": "sent",
};
// set request url, method, body, and headers
var options = initializeRequest(url, "POST", body, email, password);
// change default Content-Type header from "application/json" to "multipart/form-data"
options.headers["Content-Type"] = "multipart/form-data";
// configure a multipart http request with JSON body and document bytes
options.multipart = [{
"Content-Type": "application/json",
"Content-Disposition": "form-data",
"body": JSON.stringify(body),
}, {
"Content-Type": "application/pdf",
'Content-Disposition': 'file; filename="' + documentName + '";
documentId=1',
"body": fs.readFileSync(documentName),
}
];
// send the request...
request(options, function(err, res, body) {
parseResponseBody(err, res, body);
});
} // end function
]);
//***********************************************************************************************
// --- HELPER FUNCTIONS ---
//***********************************************************************************************
function initializeRequest(url, method, body, email, password) {
var options = {
"method": method,
"uri": url,
"body": body,
"headers": {}
};
addRequestHeaders(options, email, password);
return options;
}
///////////////////////////////////////////////////////////////////////////////////////////////
function addRequestHeaders(options, email, password) {
// JSON formatted authentication header (XML format allowed as well)
dsAuthHeader = JSON.stringify({
"Username": email,
"Password": password,
"IntegratorKey": integratorKey // global
});
// DocuSign authorization header
options.headers["X-DocuSign-Authentication"] = dsAuthHeader;
}
///////////////////////////////////////////////////////////////////////////////////////////////
function parseResponseBody(err, res, body) {
console.log("\r\nAPI Call Result: \r\n", JSON.parse(body));
if( res.statusCode != 200 && res.statusCode != 201) { // success statuses
console.log("Error calling webservice, status is: ", res.statusCode);
console.log("\r\n", err);
return false;
}
return true;
}
Again, I am very new to this, so any help would be very appreciated, thanks in advance!
UPDATE - after realizing I could not takw pieces of node.js to use on QuickBase code pages, I attempted the below two coding options, neither worked...any ideas what I am doing wrong?
var xhr = createCORSRequest('GET', urlLoginCall);
xhr.withCredentials = true;
xhr.setRequestHeader('X-DocuSign-Authentication', jsonLoginCall);
xhr.send();
xhr.onload = function() {
var responseText = xhr.responseText;
alert(responseText);
};
xhr.onerror = function() {
alert('There was an error!');
};
and
$.ajax({
type: 'GET',
url: urlLoginCall,
headers: {
'X-DocuSign-Authentication': jsonLoginCall
},
xhrFields: {
withCredentials: true
},
success: function() {
alert("success");
},
error: function() {
alert("failure");
}
});
Via Fidler, I always get this as the request header:
OPTIONS /restapi/v2/login_information HTTP/1.1
Host: demo.docusign.net
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: https://twmts.quickbase.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36
Access-Control-Request-Headers: x-docusign-authentication
Accept: */*
Referer: https://twmts.quickbase.com/db/bhkhmzax6?a=dbpage&pageID=145
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
an this as the response header:
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Mon, 10 Mar 2014 12:15:48 GMT
Content-Length: 0
Strict-Transport-Security: max-age=7776000; includeSubDomains
No XML or JSON returned.
I know it has to besomething simple I am just not getting, but I have spent a lot of time tryig to determine what I am missing and other than not using the node.js, I can't figure it out.

The DocuSign sample code you've referenced uses Node.js modules, more specifically it uses request, async, and the fs module. It looks like you've commented out the three lines where it imports the Node.js libraries that it needs:
//var async = require("async"), // async module
// request = require("request"), // request module
// fs = require("fs"); // fs module
The require statement loads different modules, and when you comment out the above the code it has no idea what the async.waterfall function is since it's not declared anywhere. To resolve try un-commenting the above code so that's it's:
var async = require("async"), // async module
request = require("request"), // request module
fs = require("fs"); // fs module

Related

Invalid protocol: undefined - NodeJS error on POST request -

I'm getting this error coming from my require.post(error)
its a lambda function deployed from a vagrant box. It is a wrapper for an api, the event.body has the properly formatted post json and everything is working perfectly when the post is done from postman. I have seen a roughly similar problem solved by
npm config set proxy http://usr:pwd#host:port
npm config set https-proxy http://usr:pwd#host:port
Please help! : )
Error: Invalid protocol: undefined
at Request.init (/var/task/node_modules/request/request.js:454:31)
at new Request (/var/task/node_modules/request/request.js:127:8)
at request (/var/task/node_modules/request/index.js:53:10)
at Function.post (/var/task/node_modules/request/index.js:61:12)
at module.exports.startVerifyProcess (/var/task/handler.js:83:13)
my Code:
module.exports.startVerifyProcess = (event, context, callback) => {
var body = JSON.parse(event.body);
const params = querystring.parse(event.body);
console.warn(body);
var Re;
var post_options = {
host: 'api.demo.veri.com',
path: '/api/v1/verify/requests',
port: 443,
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// 'Content-Length': Buffer.byteLength(event.body),
"Authorization": "myValidAuth",
},
}
request.post(post_options, body, function(err, res, resBody) {
if (err){
console.error(err);
}
console.warn("RESPONSE " + resBody);
});
callback(null, {
statusCode: 200,
body: JSON.stringify({
body: Re
})
});
}
The issue here is that request should not take the body as the second parameter.
request.post(post_options, function(err, res, resBody) is correct and the body should be in the post_options object. While your at it chose either camelCase or snake_case for everything in that project. Also check out node-fetch I would consider it a solid upgrade from using request.

Node JS and making external web calls successfully?

Hi I am trying to start learning NodeJS now and am in the middle of creating an application. The goal currently is to call a website through node, get an authentication token, then call that website again now with a POST payload which includes my login info and the auth token.
I have created the same program using python and i get a 200 response where in nodeJS i am getting a 302.
I believe thats a quick solution, the main meat of the problem I guess is my lack of understanding in NodeJS where:
1. If I am supposed to nest these requests calls into one another because they are supposed to be a part of the same 'session' and
2. If so how do I go to the last url which is, example.com/poll and be able to store/modify that information (which is just a json) because/if i go to example.com/poll url using a browser, the browser automatically downloads a file which it contains is a JSON format and doesnt just display it, which is what i need. so that i can either save that data in a string or etc. and not download it
In python I do this (Create a session than make the two calls)
url = "https://example.com/"
session = requests.session()
first_req = session.get(url)
auth_token_str = re.search(XXX, first_req.text)
login_url = 'https://example.com/sessions'
payload = { 'session[username_or_email]' : 'username', 'session[password]' : 'password', 'redirect_after_login':'/', 'authenticity_token': authenticity_token }
login_req = session.post(login_url, data=payload, headers=user_agent)
print "login_req response: ", login_req.status_code //gets me 200
then in Node JS:
var initLoad = {
method: 'GET',
url: 'https://example.com/',
headers: {
'User-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36'
}
};
request(initLoad, function(error, response, body) {
if (error) throw new Error(error);
var $ = cheerio.load(body, {xmlMode: false});
var authenticityToken = $("input[name=authenticity_token]").val();
console.log(authenticityToken);
var options = {
method: 'POST',
url: 'https://example.com/sessions',
headers: response.headers,
form: {
'session[username_or_email]': 'someUsername',
'session[password]': 'somePassword',
redirect_after_login: '/',
authenticity_token: authenticityToken
}
};
request(options, function(error, response2, body2) {
if (error) throw new Error(error);
console.log(response2.statusCode); //gets me 302 not 200
var analytics_url = 'https://example.com/poll';
var tripleload = {
method: 'GET',
url: analytics_url,
headers: response2.headers
};
request(tripleload, function(error, response3, body3) {
if (error) throw new Error(error);
res.end(body3);
});
});
});
302 means temporarily moved redirection which you get due error page being displayed to you (or served to your server in this case). There is something with this call that you are doing wrong, maybe url is wrong if generated like this.
Your code is messy due you being newbie in node and due the fact you use request which is barebone and offers little to no comfort in writing this stuff.
Use something like Axios: https://github.com/mzabriskie/axios to make it easier to write requests like this.

Get all public github repostories of user with javascript/node js

I want to get all public github repositories of given user from github.
I tried to make it with GET request I read from here. When i try it with curl or in the browser everything is fine, but when I run this code is gives me http 403 status code
var request = require('request');
request.get("https://api.github.com/users/:user")
.on('response', function (response) {
console.log(response.statusCode);
console.log(JSON.stringify(response));
});
I tried using this github api library, but couldn't work around the authetication
var GithubApi = require("github");
var github = new GithubApi({});
github.authenticate({
type: "oauth",
token: "GIT_TOKEN"
});
var getUsersRepos = function (user) {
github.repos.getAll({
username: user
}, function (err, res) {
res.forEach(function (element) {
console.log(`${element.name} - language: ${element.language} - issues: ${element.open_issues} - url: ${element.url}`);
}, this);
});
}
module.exports = {
getRepos: getUsersRepos
};
But when I enter my token I can get only my user information.
Any ideas what I am doing wrong or some better idea will be appreciated
The Github API requires requests to have a valid User-Agent header:
If you provide an invalid User-Agent header, you will receive a 403
Forbidden response.
Github requests that you use your GitHub username, or the name of your application, for the User-Agent header value:
var request = require('request');
options = {
url: "https://api.github.com/users/:user",
headers: {
"User-Agent": "tabula" // Your Github ID or application name
}
}
request.get(options)
.on('response', function (response) {
console.log(response.statusCode);
console.log(JSON.stringify(response));
});

How to use the node.js 'request' library with this http request?

I was trying to make a simple request to site. it should get html text, but it gets ' '
NPM module here: github.com/request/request
Code:
var fs = require('fs');
var request = require('request');
var options = {
url:'https://sample.site/phpLoaders/getInventory/getInventory.php',
encoding : 'utf8',
gzip : true,
forever: true,
headers: {
'Host': 'sample.site',
'Connection': 'keep-alive',
'Content-Length': '58',
'Cache-Control': 'max-age=0',
'Accept': '*/*',
'Origin': 'https://csgosell.com',
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': 'https://sample.site/',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
'Cookie': 'my-cookies from browser'
},
form: {
stage:'bot',
steamId:76561198284997423,
hasBonus:false,
coins:0
}
};
request.post(options,
function(error, response, body){
console.log(response.statusCode);
if (!error) {
fs.writeFileSync('site.html', body);
}
else{
console.log(error);
}
}
);
Chrome request: https://i.stack.imgur.com/zKQo5.png
Nodejs request:https://i.stack.imgur.com/yH9U3.png
the difference is in headers:
:authority:csgosell.com
:method:POST :path:/phpLoaders/getInventory/getInventory.php :scheme:https
after some googling, I anderstood that it is http2, and tried to put it inow another agent's options, but nothing changed.
var spdy = require('spdy');
var agent = spdy.createAgent({
host: 'sample.site',
port: 443,
spdy: {
ssl: true,
}
}).once('error', function (err) {
this.emit(err);
});
options.agent = agent;
To answer your question i will copy/paste a part of my code that enable you to receive a post request from your frontend application(angularJS) to your backend application (NodeJS), and another function that enable you to do the inverse send a post request from nodeJS to another application (that might consume it):
1) receive a request send from angularJS or whatever inside your nodeJS app
//Import the necessary libraries/declare the necessary objects
var express = require("express");
var myParser = require("body-parser");
var app = express();
// we will need the following imports for the inverse operation
var https = require('https')
var querystring = require('querystring')
// we need these variables for the post request:
var Vorname ;
var Name ;
var e_mail ;
var Strasse ;
app.use(myParser.urlencoded({extended : true}));
// the post request is send from http://localhost:8080/yourpath
app.post("/yourpath", function(request, response ) {
// test the post request
if (!request.body) return res.sendStatus(400);
// fill the variables with the user data
Vorname =request.body.Vorname;
Name =request.body.Name;
e_mail =request.body.e_mail;
Strasse =request.body.Strasse;
response.status(200).send(request.body.title);
});
2) Do the inverse send a POST request from a nodeJS application to another application
function sendPostRequest()
{
// prepare the data that we are going to send to anymotion
var jsonData = querystring.stringify({
"Land": "Land",
"Vorname": "Vorname",
"Name": "Name",
"Strasse": Strasse,
});
var post_options = {
host: 'achref.gassoumi.de',
port: '443',
method: 'POST',
path: '/api/mAPI',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': jsonData.length
}
};
// request object
var post_req = https.request(post_options, function(res) {
var result = '';
res.on('data', function (chunk) {
result += chunk;
console.log(result);
});
res.on('end', function () {
// show the result in the console : the thrown result in response of our post request
console.log(result);
});
res.on('error', function (err) {
// show possible error while receiving the result of our post request
console.log(err);
})
});
post_req.on('error', function (err) {
// show error if the post request is not succeed
console.log(err);
});
// post the data
post_req.write(jsonData);
post_req.end();
// ps : I used a https post request , you could use http if you want but you have to change the imported library and some stuffs in the code
}
So finally , I hope this answer will helps anyone who is looking on how to get a post request in node JS and how to send a Post request from nodeJS application.
For further details about how to receive a post request please read the npm documentation for body-parser library : npm official website documentation

Verifiy iOS Receipt with Node.js

After struggling a few days trying to get something to work and getting no where, I was wondering if someone has gotten iOS Receipt Validation working on Node.js. I have tried the node module iap_verifier found here but I could not get it to work properly for me. the only response I received back form Apples servers is 21002, data was malformed.
One thing that has worked for me was a client side validation request to apples servers that I got directly from the tutorials provided by Apple here, with the code shown below.
// The transaction looks ok, so start the verify process.
// Encode the receiptData for the itms receipt verification POST request.
NSString *jsonObjectString = [self encodeBase64:(uint8_t *)transaction.transactionReceipt.bytes
length:transaction.transactionReceipt.length];
// Create the POST request payload.
NSString *payload = [NSString stringWithFormat:#"{\"receipt-data\" : \"%#\", \"password\" : \"%#\"}",
jsonObjectString, ITC_CONTENT_PROVIDER_SHARED_SECRET];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
// Use ITMS_SANDBOX_VERIFY_RECEIPT_URL while testing against the sandbox.
NSString *serverURL = ITMS_SANDBOX_VERIFY_RECEIPT_URL;
// Create the POST request to the server.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverURL]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:payloadData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
I have a bunch of different code I have been using to send a wide array of things to my node server. and all of my different attempts have failed. I have even tried just funneling the "payloadData" I constructed in the client side validation example above to my server and sending that to Apples servers with the following code:
function verifyReceipt(receiptData, responder)
{
var options = {
host: 'sandbox.itunes.apple.com',
port: 443,
path: '/verifyReceipt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(receiptData)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
});
req.write(receiptData);
req.end();
}
Where the function is passed the payloadData. The response received from Apple is always 21002. I'm still basically a node novice,so I can't figure out what exactly is going wrong. I think there might be some data corruption happening when I am sending the data from ObjC to my Node server, so perhaps I am not transmitting right.
If anyone can point me in the right direction, or provide some example of how they got receipt validation to work in node for them, it would be a great help. It would be great if anyone has had any experience with the iap_verifier module, and exactly what data it requires. I'll provide any code example I need to, as I have been fighting this process for a few days now.
Thanks!
For anyone using the npm library "request", here's how to avoid that bothersome 21002 error.
formFields = {
'receipt-data': receiptData_64
'password': yourAppleSecret
}
verifyURL = 'https://buy.itunes.apple.com/verifyReceipt' // or 'https://sandbox.itunes.apple.com/verifyReceipt'
req = request.post({url: verifyURL, json: formFields}, function(err, res, body) {
console.log('Response:', body);
})
This is my working solution for auto-renewable subscriptions, using the npm request-promise library.
Without JSON stringify-ing the body form, I was receiving 21002 error (The data in the receipt-data property was malformed or missing)
const rp = require('request-promise');
var verifyURL = 'https://sandbox.itunes.apple.com/verifyReceipt';
// use 'https://buy.itunes.apple.com/verifyReceipt' for production
var options = {
uri: verifyURL,
method: 'POST',
headers: {
'User-Agent': 'Request-Promise',
'Content-Type': 'application/x-www-form-urlencoded',
},
json: true
};
options.form = JSON.stringify({
'receipt-data': receiptData,
'password': password
});
rp(options).then(function (resData) {
devLog.log(resData); // 0
}).catch(function (err) {
devLog.log(err);
});
Do you have composed correctly receiptData? Accordlying with Apple specification it should have the format
{"receipt-data": "your base64 receipt"}
Modifying your code wrapping the base64 receipt string with receipt-data object the validation should works
function (receiptData_base64, production, cb)
{
var url = production ? 'buy.itunes.apple.com' : 'sandbox.itunes.apple.com'
var receiptEnvelope = {
"receipt-data": receiptData_base64
};
var receiptEnvelopeStr = JSON.stringify(receiptEnvelope);
var options = {
host: url,
port: 443,
path: '/verifyReceipt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(receiptEnvelopeStr)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
cb(true, chunk);
});
res.on('error', function (error) {
console.log("error: " + error);
cb(false, error);
});
});
req.write(receiptEnvelopeStr);
req.end();
}

Categories

Resources