I'm looking for a payment gateway that supports INR, that I can use with a nodejs app. Can't find anything that works. Any suggestions and pointers would be helpful.
I think citruspay is a good choice. The following links show integrations with node js.
Merchant Hosted Checkout (Citrus.js)
var crypto = require('crypto');
function generateSignature(merchantTxnId, request) {
//Need to change with your Secret Key
var secret_key = "***SEcRETKey***";
//Need to change with your Access Key
var accesskey = "***Access Key***";
//Should be unique for every transaction
var txn_id = merchantTxnId;
//Need to change with your Order Amount
var amount = "1.00";
var data = 'merchantAccessKey=' + accesskey + '&transactionId=' + txn_id + '&amount=' + amount;
// generate hmac
var hmac = crypto.createHmac('sha1', secret_key);
hmac.update(data);
return hmac.digest('hex');
}
Now include this signature in PaymentObject
Then listen for post on the Return URL
You have to generate signature and compare with the signature sent in the post data from citrus to make sure data is not tampered in the way.
var http = require("http");
var qs = require('querystring');
var crypto = require('crypto');
var secret_key = "MERCHANT_SECRET_KEY";
http.createServer(function(request, response) {
var body = "";
if (request.method = "POST") {
request.on("data", function(data) { body += data; });
request.on("end", function() {
var post = qs.parse(body);
var data_string = post['TxId'] + post['TxStatus'] + post['amount']
+ post['pgTxnNo'] + post['issuerRefNo'] + post['authIdCode']
+ post['firstName'] + post['lastName'] + post['pgRespCode']
+ post['addressZip'];
var signature = crypto.createHmac('sha1',
secret_key).update(data_string).digest('hex');
if (signature == post['signature']) {
response.writeHead(200, {"Content-Type": "application/json"});
console.log(post);
response.write(JSON.stringify(post));
}
else {
response.writeHead(403, {"Content-Type": "application/json"});
var error = {error : 'Transaction Failed', message: 'Signature Verification Failed'};
response.write(JSON.stringify(error));
}
response.end();
});
}
}).listen(3000);
Related
Mandrill webhook authentication-verify signature
For node js
example verify signature
please check the code below
But its working only for event types like send, reject. Not working for event types like open, click & others
function generateSignature(webhook_key, url, params) {
var signed_data = url;
const param_keys = Object.keys(params);
param_keys.sort();
param_keys.forEach(function (key) {
signed_data += key + params[key];
});
hmac = crypto.createHmac('sha1', webhook_key);
hmac.update(signed_data);
return hmac.digest('base64');
}
let url = "https://your-app-domain.com/default/MandrillXP-new";
let key = "abcd1234"; //your mandrill webhook api key
let bodyPayload;
if(event.isBase64Encoded){
bodyPayload = Buffer.from(event.body, 'base64').toString()
}else{
bodyPayload = event.body
}
let splitData = req.body.split("=")
let decodeData = decodeURIComponent(splitData[1]);
var generatedSignature = generateSignature(key, url, { "mandrill_events": decodeData })
if (req.headers["x-mandrill-signature"]!== generatedSignature) {
console.log("signature mismatch")
}else{
console.log("signature matched")
}
replace '+' with ' '(space) in string before encode
var decodeData = decodeData .replace(/[+]/g, ' ');
I know it is possible in .net, i can see the reference over here https://learn.microsoft.com/en-us/azure/notification-hubs/notification-hubs-send-push-notifications-scheduled. But I want to know how to do that in node. Can any one guide me on this.
You can send a scheduled notification in Node using the REST API. Use the specification for sending a normal notification and replace /messages with /schedulednotifications. You will also need to add a header specifying the datetime named ServiceBusNotification-ScheduleTime.
For an example using the template schema:
var CryptoJS = require("crypto-js");
var axios = require("axios");
var getSelfSignedToken = function(targetUri, sharedKey, keyName,
expiresInMins) {
targetUri = encodeURIComponent(targetUri.toLowerCase()).toLowerCase();
// Set expiration in seconds
var expireOnDate = new Date();
expireOnDate.setMinutes(expireOnDate.getMinutes() + expiresInMins);
var expires = Date.UTC(expireOnDate.getUTCFullYear(), expireOnDate
.getUTCMonth(), expireOnDate.getUTCDate(), expireOnDate
.getUTCHours(), expireOnDate.getUTCMinutes(), expireOnDate
.getUTCSeconds()) / 1000;
var tosign = targetUri + '\n' + expires;
// using CryptoJS
var signature = CryptoJS.HmacSHA256(tosign, sharedKey);
var base64signature = signature.toString(CryptoJS.enc.Base64);
var base64UriEncoded = encodeURIComponent(base64signature);
// construct autorization string
var token = "SharedAccessSignature sr=" + targetUri + "&sig="
+ base64UriEncoded + "&se=" + expires + "&skn=" + keyName;
// console.log("signature:" + token);
return token;
};
var keyName = "<mykeyName>";
var sharedKey = "<myKey>";
var uri = "https://<mybus>.servicebus.windows.net/<myhub>";
var expiration = 10;
var token = getSelfSignedToken(uri, sharedKey, keyName, expiration);
const instance = axios.create({
baseURL: uri,
timeout: 100000,
headers: {
'Content-Type': 'application/octet-stream',
'X-WNS-Type': 'wns/raw',
'ServiceBusNotification-Format' : 'template',
'ServiceBusNotification-ScheduleTime': '2019-07-19T17:13',
'authorization': token}
});
var payload = {
"alert" : " This is my test notification!"
};
instance.post('/schedulednotifications?api-version=2016-07', payload)
.then(function (response) {
console.log(response);
}).catch(function (error) {
// handle error
console.log(error);
});
I am new to node.js and AWS Lambda. I have the following code that should return a 401 error code if the payload is coming from an untrusted source. However, I am not sure how to return a message with non-200 status code with AWS Lambda.
Any help shall be greatly appreciated!
'use strict';
var https = require('https');
var querystring = require('querystring');
exports.handler = (request, context) => {
var statusCode, errMessage;
statusCode = 401;
errMessage = 'error';
try {
const API_KEY = "API_KEY_GOES_HERE";
const ALLOWED_HOURS = 1;
var theHook = request;
var event_type = theHook.meta.event_type;
// verify that the incoming payload is from the trusted source
var pToken1, pToken2, pSig, crypto, algorithm, hmac, cSig;
pToken1 = theHook.token1;
pToken2 = theHook.token2;
pSig = theHook.sig;
crypto = require('crypto');
algorithm = 'sha1';
hmac = crypto.createHmac(algorithm, API_KEY);
hmac.setEncoding('hex');
hmac.write(pToken1 + pToken2);
hmac.end();
cSignature = hmac.read();
// if cSig does not equal to pSig, then this is an invalid source
if (cSig !== pSig) throw ("Invalid signature");
// TODO: this is a valid JSON, save it in the DB
statusCode = 200;
errMessage = 'success';
} catch (e) {
// this is not a JSON, or a JSON we expect, return an error
console.log(e);
}
// response.writeHead(statusCode, {'Content-Type': 'text/json'});
// response.write(JSON.stringify({"message": errMessage}));
// response.end();
console.log(errMessage);
};
Thank you!
I'm trying to create a simple client for Lync using Nodejs.
Base on http://ucwa.lync.com/documentation/KeyTasks-CreateApplication I've made someting like this.
It works until last step #9 when I should register my app with UCWA. Server responds with code 500 and silly explanation
There is a problem with the resource you are looking for, and it cannot be displayed
And headers
x-ms-diagnostics': '28032;source="mysource";reason="The web ticket is invalid."'
var http = require('request-promise');
var lync = {};
lync.setup = function(email, password){
var self = this;
var hostname = email.split('#');
this.username = email;
//discover urls
return http.get('http://lyncdiscover.'+hostname[1])
.then(function(d) {
var parsed = JSON.parse(d);
self.urls = {
self: parsed._links.self.href,
user: parsed._links.user.href,
xframe: parsed._links.xframe.href
};
return http.get(self.urls.user);
}).catch(function(err){
if(err.statusCode == 401){
var toParse = err.response.headers['www-authenticate'];
var Oauth = toParse.match(/https:\/\/[\d\w\./_-]*/i)[0];
var loginPost = {
grant_type: 'password',
username: email,
password: password
};
return http.post(Oauth, {form:loginPost});
}
return false
}).then(function(data){
var parsed = JSON.parse(data);
//setup authorization
http = http.defaults({
headers: {Authorization: parsed.token_type + ' ' + parsed.access_token}
});
//console.log(self.urls.user);
//console.log('Authorization:'+ parsed.token_type + ' ' + parsed.access_token);
return http.get(self.urls.user);
}).then(function(data){
var parsed = JSON.parse(data);
self.urls.applications = parsed._links.applications.href;
var registerApp = {
culture : "en-us",
endpointId : "2d9dc28d-4673-4035-825c-feb64be28e4e",
userAgent : "Test"
};
var r = "{'userAgent': 'NodeJs', 'endpointId' : '2d9dc28d-4673-4035-825c-feb64be28e4e', 'culture': 'en-US'}";
return http.post(self.urls.applications, {body: registerApp, json:true});
})
.then(function(data){
console.log(data);
})
.catch(function(err){
console.log(err);
return false;
});
};
//run app
lync.setup('login#domain.com', 'password').then(function(ret){
});
One key point here. It's not my server. I just have an account over there and I can login with official Lync client or Pidgin plugin.
Are there some extra steps to "allow" my app to work with UCWA?
#ShelbyZ
I can easily authorize using Oauth. I'm receiving authorization token so I'm logged in.
I'm receiving json similar to
"_links":{
"self":{"href":"link"},
"applications":{"href":"i need this"},
"xframe":{"href":"link"}
} }
Now. I need to "register my application" doing POST.
In this last step I get 500 code response.
I hope It's not related with that #Matthew Proctor said..
becouse I cannot simple administrate the server
Thank you #ShelbyZ
You were right, it was split-domain scenario. Now authorization works, and I can register my app. Also example for future generations
var http = require('request-promise');
var lync = {};
lync._authorize = function(){
var self = this;
var orgDomain = self.urls.user.match(/https:\/\/([\w\d\.]+)/i)[0];
//console.log(orgDomain);
http.get(self.urls.user).catch(function(err){
if(err.statusCode == 401){
var toParse = err.response.headers['www-authenticate'];
var Oauth = toParse.match(/https:\/\/[\d\w\./_-]+/i)[0];
var loginPost = {
grant_type: 'password',
username: self.username,
password: self.password
};
return http.post(Oauth, {form:loginPost});
}
}).then(function(data){
if(data) {
var parsed = JSON.parse(data);
//setup authorization
http = http.defaults({
headers: {Authorization: parsed.token_type + ' ' + parsed.access_token}
});
return http.get(self.urls.user);
}
}).then(function(data){
//check for split-domain scenario
var parsed = JSON.parse(data);
var domain = parsed._links.self.href.match(/https:\/\/([\w\d\.]+)/i)[0];
console.log('[1] '+orgDomain);
console.log('[2] '+domain);
if(domain!== orgDomain){
//split domain scenario
self.urls.user = self.urls.user.replace(orgDomain, domain);
http = http.defaults({
headers: {Authorization: null}
});
self._authorize();
} else { //create app
var parsed = JSON.parse(data);
self.urls.applications = parsed._links.applications.href;
var registerApp = {
culture : "en-us",
endpointId : "2d9dc28d-4673-4035-825c-feb64be28e4e",
userAgent : "NodeJs client"
};
return http.post(self.urls.applications, {body: registerApp, json:true});
}
}).then(function(app){
console.log(app);
});
};
lync.setup = function(email, password){
var self = this;
var hostname = email.split('#');
this.username = email;
this.password = password;
//discover urls
return http.get('http://lyncdiscover.'+hostname[1])
.then(function(d) {
var parsed = JSON.parse(d);
self.urls = {
self: parsed._links.self.href,
user: parsed._links.user.href,
xframe: parsed._links.xframe.href
};
return self._authorize();
});
};
//run app
lync.setup('username#domain.com', 'password');
I was getting the same error before I added my test domain to the list of Allowed Domains.
This can be updated via PowerShell, full details below:
Enabling UCWA and Configuring Allowed Domains
I've had clients see similar errors when running my code from http://localhost/, their fix was to test their code on a FQDN (ie http://testmyucwacode.mydomain.com/).
I am using nodejs with socket.io-client to connect to the MtGox Streaming API described here: https://en.bitcoin.it/wiki/MtGox/API/Streaming#Authenticated_commands
The examples are written in php and I tried my best to convert them to JS but I keep getting a response from the server "Invalid call"
var sec_key_buffer = Buffer(secret_key, 'base64');
var hmac = crypto.createHmac('sha512', sec_key_buffer);
var nonce = Date.now() + "";
var id = crypto.createHash('md5').update(nonce).digest('hex');
var query = {
"call": 'private/info',
"id": id,
"nonce": nonce
};
var body = JSON.stringify(query);
var sign = hmac.update(body).digest('binary');
// The 'api_key' field has already stripped of the '-' character
var callBody = new Buffer(api_key + sign + body).toString('base64');
// 'connection' is the socket.io connection to 'https://socketio.mtgox.com/mtgox'
connection.json.send({
"op": "call",
"id": id,
"call": callBody,
"context": 'mtgox.com'
});
Any help would be appreciated.
Here's what seemed to work for me:
var io = require('socket.io-client');
var crypto = require('crypto');
var socket = io.connect('https://socketio.mtgox.com/mtgox');
var MTGOX_API_INFO = {
key: '<YOUR_KEY>',
secret: '<YOUR_SECRET>'
}
var MTGOX_CHANNELS = {
trade: 'dbf1dee9-4f2e-4a08-8cb7-748919a71b21',
depth: '24e67e0d-1cad-4cc0-9e7a-f8523ef460fe',
ticker: 'd5f06780-30a8-4a48-a2f8-7ed181b4a13f'
}
// unsubscribe from depth and trade messages
socket.emit('message', {
op: 'unsubscribe',
channel: MTGOX_CHANNELS.trade
});
socket.emit('message', {
op: 'unsubscribe',
channel: MTGOX_CHANNELS.depth
});
socket.emit('message', {
op: 'unsubscribe',
channel: MTGOX_CHANNELS.ticker
});
var getNonce = function() {
return ((new Date()).getTime() * 1000).toString();
}
var nonce = getNonce();
var requestId = crypto.createHash('md5').update(nonce).digest('hex');
var query = {
id: requestId,
call: 'private/info',
nonce: nonce
// params: {},
// item: 'BTC',
// currency: 'USD'
};
var queryJSON = JSON.stringify(query);
var signedQuery = crypto.createHmac('sha512', new Buffer(MTGOX_API_INFO.secret, 'base64')).update(queryJSON).digest('binary');
var binKey = (new Buffer(MTGOX_API_INFO.key.replace(/-/g, ''), 'hex')).toString('binary');
var buffer = new Buffer(binKey + signedQuery + queryJSON, 'binary');
var call = buffer.toString('base64');
var command = {
op: 'call',
id: requestId,
call: call,
context: 'mtgox.com'
};
console.log("REQUEST:", command);
socket.emit('message', command);
socket.on('message', function(data) {
console.log(data);
});
UPDATE: I've also abstracted it into a simple node module.
You must hex decode the api key to raw bytes before appending the hash and message content.
Not familiar enough with node.js to provide code, but in Java (using Guava) it's:
byte[] apiKey = BaseEncoding.base16().lowerCase().decode(API_KEY.replace("-", ""));