nodejs paypal pdt return 302 - node.js

I'm using nodejs and express. This is my code that is run on the return from Paypal. I only get a 302 errors in response from Paypal. I saw a couple examples that use ssl:// instead of https:// but nodejs yells saying that its not a valid protocol for the https module. Does anyone have a working nodejs script for PDT and IPN?
var purchaseID = req.query.tx;
var atoken = MYAuthToken;
var postDataArray = {'cmd':'_notify-synch','tx': purchaseID, 'at': atoken}
var postData = JSON.stringify(postDataArray);
console.log(postData);
var options = {
hostname: 'www.sandbox.paypal.com',
port: 443,
path: '/cgi-bin/webscr',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = https.request(options, function(res) {
console.log('STATUS: '+ res.statusCode);
console.log('HEADERS: '+ JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY: '+chunk);
});
res.on('end', function() {
console.log('No more data in response.')
});
});
req.on('error', function(e) {
console.log('problem with request: '+e.message);
});
req.write(postData);
req.end();
});
This

You're missing Accept: */* header. Also, JSON.stringify is not application/x-www-form-urlencoded. Here is some working code for you to build based on:
var request = require('request');
var endpoint = 'www.sandbox.paypal.com';
var options = {
form: {
cmd: '_notify-synch',
tx: tx,
at: auth
},
headers: {
Accept: '*/*'
}
};
request.post('https://' + endpoint + '/cgi-bin/webscr', options, function(e, r, body) {
return console.log(body);
});

Try just posting without the JSON
var postData = "cmd=_notify-synch,at=" + at + ",tx=" + tx;
I've edited a couple of times as i ran into issues. I'm new to node so just hacking out a solution with trial and error. Your post moved me towards the solution. So here is postData that works with your code. It's nice to see the FAIL ans SUCCESS messages come through. Note .. need the &'s
var postData = "cmd=_notify-synch&at=" + at + "&tx=" + tx;

Related

NodeJS 12.x https version of a curl request on AWS Lambda

curl -d "m_payment_id=m_payment_id-xxxxxxxxxxxxxxxxxyyy&pf_payment_id=990396&payment_status=COMPLETE&item_name=Subscription&item_description=Monthly+Subscription&amount_gross=99.00&amount_fee=-6.74&amount_net=92.26&custom_str1=&custom_str2=&custom_str3=&custom_str4=&custom_str5=&custom_int1=&custom_int2=&custom_int3=&custom_int4=&custom_int5=&name_first=&name_last=&email_address=christo%40g4-ape.co.za&merchant_id=0000000&token=0000000-0000-0000-3a83-25bc733a307b&billing_date=2020-02-21&signature=3895d0769b56862b842da5067af4483f" -X POST https://sandbox.somedomain.co.za/what/something/validate
My attempt:
const https = require("https");
const querystring = "m_payment_id=m_payment_id-xxxxxxxxxxxxxxxxxyyy&pf_payment_id=990396&payment_status=COMPLETE&item_name=Subscription&item_description=Monthly+Subscription&amount_gross=99.00&amount_fee=-6.74&amount_net=92.26&custom_str1=&custom_str2=&custom_str3=&custom_str4=&custom_str5=&custom_int1=&custom_int2=&custom_int3=&custom_int4=&custom_int5=&name_first=&name_last=&email_address=christo%40g4-ape.co.za&merchant_id=0000000&token=0000000-0000-0000-3a83-25bc733a307b&billing_date=2020-02-21&signature=3895d0769b56862b842da5067af4483f";
return new Promise((resolve, reject) => {
const options = {
hostname: 'sandbox.somedomain.co.za',
port: 443,
path: 'what/something/validate',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(querystring)
}
};
const req = https.request(options, (res) => {
console.log('statusCode: ' + res.statusCode);
console.log('headers: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('BODY: ' + data);
});
resolve('Success');
});
req.on('error', (e) => {
console.log('problem with request: ' + e.message);
reject(e.message);
});
// write data to request body
req.write(querystring);
req.end();
});
I keep getting a statusCode 400 on the NodeJS code, the curl works fine. The hostname hs obviously been changed for security.
Can someone please advise me on what I'm doing wrong here?
Content-Length is reqired when you are sending the body while posting. In your case all the info is getting passed as query string parameter so you can get rid of the headers alltogather.
Also, you should be resolving inside res.on('end'. THe way you are doing it will finish the function before it even finishes execution.

How to make https call from Azure function?

I'm trying to create an Azure function using nodeJS, but when I make a call to an https API I get an error message.
Is it possible to make a HTTPS call from azure function?
Here is my code
const https = require('https');
const querystring = require('querystring');
module.exports = async function (context, req) {
if (req.query.accessCode || (req.body && req.body.accessCode)) {
var options = {
host: 'api.mysite.com',
port: 443,
path: '/oauth/access_token',
method: 'POST'
};
var postData = querystring.stringify({
client_id : '1234',
client_secret: 'xyz',
code: req.query.accessCode
});
var req = https.request(options, function(res) {
context.log('STATUS: ' + res.statusCode);
context.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function (chunk) {
context.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
context.log('problem with request: ' + e.message);
});
req.write(postData);
req.end();
context.res = {
status: 200,
body: "Hello " + (req.query.accessCode)
};
} else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
context.done();
};
I get an error but I do not see any error on the console, also if I comment all the https call it works fine and I can see the Hello message on the screen.
Two points to fix
Delete context.done();. See Azure document.
If your function uses the JavaScript async function declaration (available using Node 8+ in Functions version 2.x), you do not need to use context.done(). The context.done callback is implicitly called.
Rename your https.request like var myReq = https.request(options, function(res).
There's a name conflict causing error as function has a built-in req object declared.
It's possible, here is an example of how to make a request to an Azure AD v2 token endpoint (I'd assume you are trying to do something similar):
var http = require('https');
module.exports = function (context, req) {
var body = "";
body += 'grant_type=' + req.query['grant_type'];
body += '&client_id=' + req.query['client_id'];
body += '&client_secret=' + req.query['client_secret'];
body += '&code=' + req.query['code'];
const options = {
hostname: 'login.microsoftonline.com',
port: 443,
path: '/ZZZ920d8-bc69-4c8b-8e91-11f3a181c2bb/oauth2/v2.0/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': body.length
}
}
var response = '';
const request = http.request(options, (res) => {
context.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
response += d;
})
res.on('end', (d) => {
context.res = {
body: response
}
context.done();
})
})
request.on('error', (error) => {
context.log.error(error)
context.done();
})
request.write(body);
request.end();
};
The difference is - the function is not async module.exports = function
I believe your issue is:
You should use the Node.js utility function util.promisify to turn error-first callback-style functions into awaitable functions.
link

getaddrinfo ENOTFOUND when making a post request using node.js

I want to send a POST request to my server using Node.js
function login(email, company_code, password){
var options = {
hostname: '266fd57b.ngrok.io',
path: '/v1/manager/sign_in',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: {
'email': email,
'company_code': company_code,
'password': password
}
};
var req = https.request(options, function(res) {
console.log('Status: ' + res.statusCode);
console.log('Headers: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (body) {
console.log('Body: ' + body);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('{"string": "Hello, World"}');
req.end();
return true;
}
But I keep getting error:
getaddrinfo ENOTFOUND 266fd57b.ngrok.io 266fd57b.ngrok.io:443
I tried all the fixes found on the Internet but nothing worked.
Oh my god this is because I have not entered billing account for google.
Dialogflow needs a credit card number to work.

ECONNRESET error node.js https

Guys I'm having trouble requesting to this URL.. It seems fine, but I always get the error ECONNRESET.
I wrote a little script in ruby and it worked fine. With cURL in the terminal also works.
I tried all the solutions on a lot of issues and stack overflow threads... Like these:
https://github.com/joyent/node/issues/5360
https://github.com/joyent/node/issues/5119
Any idea what it might be?
The url is: https://ecommerce.cielo.com.br/servicos/ecommwsec.do
var https = require('https');
var options = {
host: 'ecommerce.cielo.com.br',
path: '/servicos/ecommwsec.do',
//This is what changes the request to a POST request
method: 'GET',
};
https.globalAgent.options.secureProtocol = 'SSLv3_method';
callback = function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
}
var req = https.request(options, callback);
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
How are you ??
Let's try this solution.
app.js
Change your options:
var options = {
host: 'ecommerce.cielo.com.br',
path:'/servicos/ecommwsec.do',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(body),
'user-agent': 'node.js'
}
};
https.globalAgent.options.secureProtocol = 'SSLv3_method';
try{
var req = https.request(options, function(res)
{
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
}).on('end', function(cieloResponse){
console.log( cieloResponse);
});
console.log('Response:' + res);
});
req.end();
}catch(err){
console.log('ERRO: '+ err);
}

How to use http.client in Node.js if there is basic authorization

As per title, how do I do that?
Here is my code:
var http = require('http');
// to access this url I need to put basic auth.
var client = http.createClient(80, 'www.example.com');
var request = client.request('GET', '/', {
'host': 'www.example.com'
});
request.end();
request.on('response', function (response) {
console.log('STATUS: ' + response.statusCode);
console.log('HEADERS: ' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
You have to set the Authorization field in the header.
It contains the authentication type Basic in this case and the username:password combination which gets encoded in Base64:
var username = 'Test';
var password = '123';
var auth = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');
// new Buffer() is deprecated from v6
// auth is: 'Basic VGVzdDoxMjM='
var header = {'Host': 'www.example.com', 'Authorization': auth};
var request = client.request('GET', '/', header);
From Node.js http.request API Docs
you could use something similar to
var http = require('http');
var request = http.request({'hostname': 'www.example.com',
'auth': 'user:password'
},
function (response) {
console.log('STATUS: ' + response.statusCode);
console.log('HEADERS: ' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
request.end();
var username = "Ali";
var password = "123";
var auth = "Basic " + new Buffer(username + ":" + password).toString("base64");
var request = require('request');
var url = "http://localhost:5647/contact/session/";
request.get( {
url : url,
headers : {
"Authorization" : auth
}
}, function(error, response, body) {
console.log('body : ', body);
} );
An easier solution is to use the user:pass#host format directly in the URL.
Using the request library:
var request = require('request'),
username = "john",
password = "1234",
url = "http://" + username + ":" + password + "#www.example.com";
request(
{
url : url
},
function (error, response, body) {
// Do more stuff with 'body' here
}
);
I've written a little blogpost about this as well.
for what it's worth I'm using node.js 0.6.7 on OSX and I couldn't get 'Authorization':auth to work with our proxy, it needed to be set to 'Proxy-Authorization':auth
my test code is:
var http = require("http");
var auth = 'Basic ' + new Buffer("username:password").toString('base64');
var options = {
host: 'proxyserver',
port: 80,
method:"GET",
path: 'http://www.google.com',
headers:{
"Proxy-Authorization": auth,
Host: "www.google.com"
}
};
http.get(options, function(res) {
console.log(res);
res.pipe(process.stdout);
});
var http = require("http");
var url = "http://api.example.com/api/v1/?param1=1&param2=2";
var options = {
host: "http://api.example.com",
port: 80,
method: "GET",
path: url,//I don't know for some reason i have to use full url as a path
auth: username + ':' + password
};
http.get(options, function(rs) {
var result = "";
rs.on('data', function(data) {
result += data;
});
rs.on('end', function() {
console.log(result);
});
});
I came across this recently.
Which among Proxy-Authorization and Authorization headers to set depends on the server the client is talking to.
If it is a Webserver, you need to set Authorization and if it a proxy, you have to set the Proxy-Authorization header
This code works in my case, after a lot of research. You will require to install the request npm package.
var url = "http://api.example.com/api/v1/?param1=1&param2=2";
var auth = "Basic " + new Buffer(username + ":" + password).toString("base64");
exports.checkApi = function (req, res) {
// do the GET request
request.get({
url: url,
headers: {
"Authorization": auth
}
}, function (error, response, body) {
if(error)
{ console.error("Error while communication with api and ERROR is : " + error);
res.send(error);
}
console.log('body : ', body);
res.send(body);
});
}
For those not using DNS and needs more depth (you can also use request instead of get by simply replacing get with request like so: http.request({ ... })):
http.get({
host: '127.0.0.1',
port: 443,
path: '/books?author=spongebob',
auth: 'user:p#ssword#'
}, resp => {
let data;
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => console.log(data));
}).on('error', err => console.log(err));
This is not well documented in Node.js, but you can use
require("http").get(
{
url: "www.example.com",
username: "username",
password: "mysecret",
},
(resp) => {
let data;
resp.on("data", (chunk) => (data += chunk));
resp.on("end", () => console.log(data));
}
)
.on("error", (err) => console.log(err));
Since the got pacakge inherits it's options object from http.request, username and password is also available there.

Resources