Issue With Paytm payment gateway integration(Custom checkout) in nodejs environment - node.js

I am using the nodejs environment to integrate PayTm payment gateway with Custom Checkout approach as mentioned in the link and on this process I need to use the Initiate Transaction API. Now the issue is, whenever I am calling the Initiate Transaction API from nodejs the paytm server server is responding as bellow-
{"head":{"requestId":null,"responseTimestamp":"1607066431489","version":"v1"},"body":{"extraParamsMap":null,"resultInfo":{"resultStatus":"U","resultCode":"00000900","resultMsg":"System error"}}}
So it has become hard to make out if I am missing out something on my code or the integration process mentioned in the document has missed something either. Please suggest. My code base is already mentioned below-
`
const https = require('https');
/* import checksum generation utility */
var PaytmChecksum = require("paytmchecksum");
//FOR TEST/STAGING OF APPLICATION
const MERCHANT_ID = 'XXXXXXXXXXXXXXXXXXX';
const MERCHANT_KEY = 'XXXXXXXXXXXXXXX';
function initPayProcess(orderId, payVal, custId, custMobile, custEmail) {
var paytmParams = {};
paytmParams.body = {
"requestType": "Payment",
"mid": MERCHANT_ID,
"websiteName": "WEBSTAGING",
"orderId": orderId,
"callbackUrl": "",
"txnAmount": {
"value": payVal,
"currency": "INR",
},
"userInfo": {
"custId": custId,
"mobile": custMobile,
"email": custEmail,
},
"enablePaymentMode": {
"mode": "BALANCE",
}
};
/*
* Generate checksum by parameters we have in body
* Find your Merchant Key in your Paytm Dashboard at https://dashboard.paytm.com/next/apikeys 
*/
return PaytmChecksum.generateSignature(JSON.stringify(paytmParams.body), MERCHANT_KEY)
.then(function (checksum) {
paytmParams.head = {
"signature": checksum
};
var post_data = JSON.stringify(paytmParams);
var options = {
/* for Staging */
hostname: 'securegw-stage.paytm.in',
port: 443,
path: '/theia/api/v1/initiateTransaction?mid=' + MERCHANT_ID + '&orderId=' + orderId,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
var response = "";
var post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
console.log('Response: ', response);
//return response;
});
});
post_req.write(post_data);
post_req.end();
return post_data;
});
}
module.exports = { getCheckSum, initPayProcess };
`

I have also stumbled across this issue few months back and fortunately paytm devs replied to my email, had a few email discussions and found below code to be working for me.
Do remember to import Paytm from its node js library as shown in below code.
const Paytm = require("paytmchecksum");
var paytmParams = {};
paytmParams = {
body: {
requestType: "Payment",
mid: config.PaytmConfig.stag.mid,
orderId: "ORDS" + new Date().getTime(),
websiteName: config.PaytmConfig.stag.website,
txnAmount: {
value: paymentDetails.amount.toString(),
currency: "INR",
},
userInfo: {
custId: paymentDetails.customerId,
},
disablePaymentMode: [
{
mode: "CREDIT_CARD",
},
],
callbackUrl: process.env.HOST_URL + "/callbackfun",
},
};
/*
* Generate checksum by parameters we have in body
* Find your Merchant Key in your Paytm Dashboard at https://dashboard.paytm.com/next/apikeys
*/
const checksum = await Paytm.generateSignature(
JSON.stringify(paytmParams.body),
config.PaytmConfig.stag.key
);
// .then(function (checksum) {
paytmParams.head = {
channelId: "WAP",
signature: checksum,
};
var post_data = JSON.stringify(paytmParams);
var options = {
/* for Staging */
hostname: "securegw-stage.paytm.in",
/* for Production */ // hostname: 'securegw.paytm.in',
port: 443,
path: `/theia/api/v1/initiateTransaction?mid=${config.PaytmConfig.stag.mid}&orderId=${paytmParams.body.orderId}`,
method: "POST",
headers: {
"Content-Type": "application/json",
"Content-Length": post_data.length,
},
};
const responsePaytm = await doRequest(options, post_data);
const https = require("https");
/**
* Do a request with options provided.
*
* #param {Object} options
* #param {Object} data
* #return {Promise} a promise of request
*/
function doRequest(options, data) {
return new Promise((resolve, reject) => {
const req = https.request(options, (res) => {
res.setEncoding("utf8");
let responseBody = "";
res.on("data", (chunk) => {
responseBody += chunk;
});
res.on("end", () => {
resolve(JSON.parse(responseBody));
});
});
req.on("error", (err) => {
reject(err);
});
req.write(data);
req.end();
});
}

Related

Paytm Payment Gateway - Returning Invalid payment mode for UPI

I'm trying to integrate Paytm's Payment gateway [Custom Checkout]. However, while UPI Integration, after sending the request i'm getting Invalid payment mode response code on the callback url.
As suggested in documentation,
First i'm calling the Initiate Transaction API for token.
initialise(order, res, next) {
const paytmParams = {};
paytmParams.body = {
requestType: 'Payment',
mid: paytm.mid,
websiteName: paytm.website,
orderId: order.orderId,
callbackUrl: paytm.callbackUrl,
txnAmount: {
value: order.amount,
currency: 'INR',
},
userInfo: {
custId: order.custId,
},
};
const paytmChecksum = PaytmChecksum.generateSignature(paytmParams.body, paytm.merchantKey);
paytmChecksum.then(function (checksum) {
paytmParams.head = {
signature: checksum,
};
const post_data = JSON.stringify(paytmParams);
const options = {
hostname: paytm.host,
port: 443,
path: `/theia/api/v1/initiateTransaction?mid=${paytm.mid}&orderId=${order.orderId}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length,
},
};
let response = '';
const post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
const result = JSON.parse(response);
if (result.body.resultInfo.resultStatus === 'S') {
res.status(200).json({ token: result.body.txnToken, orderId: order.orderId });
} else {
next(new ApiError(httpStatus.EXPECTATION_FAILED, result.body.resultInfo.resultMsg));
}
});
});
post_req.write(post_data);
post_req.end();
});
}
After this i'm taking the user's vpa and validating that via Validate VPA API.
validateUpi(data, res, next) {
const paytmParams = {};
paytmParams.body = {
vpa: data.upiId,
};
paytmParams.head = {
tokenType: 'TXN_TOKEN',
token: data.token,
};
const post_data = JSON.stringify(paytmParams);
const options = {
hostname: paytm.host,
port: 443,
path: `/theia/api/v1/vpa/validate?mid=${paytm.mid}&orderId=${data.orderId}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length,
},
};
let response = '';
const post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
const result = JSON.parse(response);
if (result.body.resultInfo.resultStatus === 'S') {
res.status(200).json({
action: `https://${paytm.host}/theia/api/v1/processTransaction?mid=${paytm.mid}&orderId=${data.orderId}`,
params: {
mid: paytm.mid,
orderId: data.orderId,
txnToken: data.token,
paymentMode: 'UPI',
payerAccount: data.upiId,
},
});
} else {
next(new ApiError(httpStatus.EXPECTATION_FAILED, result.body.resultInfo.resultMsg));
}
});
});
post_req.write(post_data);
post_req.end();
}
After the successfull response, i'm returning the action URL and the params to the front end to create the form and post it in front end.
const res = await paymentAPI.validateUpiId(body);
paymentHelpers.createFormAndSubmit(res.action, res.params, 'redirect');
export const createFormAndSubmit = (url: string, data: any, type = "") => {
const form = document.createElement("form");
form.method = "POST";
form.action = url;
form.type = type;
Object.keys(data).forEach((key) => {
const input = document.createElement("input");
input.type = "text";
input.name = key;
input.value = data[key];
form.appendChild(input);
});
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
};
But after this form is being submitted, i'm getting redirected to callbackUrl with error message
http://localhost:3000/callback/paytm?retryAllowed=false&errorMessage=Invalid%20payment%20mode&errorCode=317

AWS Node.js Lambda HTTPS Request Not Sending Data To Facebook Conversions API

I am attempting to send data to Facebook Conversion API via an AWS Lambda function written in node.js. Documentation here.
All data is passed successfully to the function via API gateway and external GET requests.
However when the function executes, there's no indication the data was actually sent, as there is no response logged from Facebook.
The current code is as follows:
const https = require('https');
let path = '/v15.0/' + pixelId +'/events?access_token='+ access_token;
var options = {
'method': 'POST',
'hostname': 'graph.facebook.com',
'path': path
,
'headers': {
'port': '443',
'Content-Type': 'application/json'
}};
var body = [{
"data": [
{
"event_name": conversionEvent,
"event_time": current_timestamp,
"action_source": "website",
"event_source_url": site,
"event_id": current_timestamp * Math.floor(Math.random() * 10),
"user_data": {
"em": email,
"phone": phone,
"fn": fName,
"ln": lName,
"client_ip_address": userIp,
"st": userState,
"zp": userZip,
"ct": userCity,
"fbc": clickId
}
}
]
}];
console.log(JSON.stringify(body));
var req = https.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function (chunk) {
var body = Buffer.concat(chunks);
console.log(body.toString());
console.log("END");
response.statusCode = 200;
response.body = JSON.stringify("Success");
});
res.on("error", function (error) {
console.error(error);
response.body = JSON.stringify("Error Posting Data to Facebook " + JSON.stringify(error));
})
});
req.write(JSON.stringify(body));
req.end();
I've also modified the lambda function to timeout at 30 seconds, rather than 3. Also note the function is NOT operating within a private VPC.
Here's a screenshot of the log output:
Any guidance would be greatly appreciated.
Try this:
const https = require('https');
exports.handler = async (event) => {
let path = '/v15.0/' + pixelId +'/events?access_token='+ access_token;
var options = {
'method': 'POST',
'hostname': 'graph.facebook.com',
'path': path
,
'headers': {
'port': '443',
'Content-Type': 'application/json'
}};
var body = [{
"data": [
{
"event_name": conversionEvent,
"event_time": current_timestamp,
"action_source": "website",
"event_source_url": site,
"event_id": current_timestamp * Math.floor(Math.random() * 10),
"user_data": {
"em": email,
"phone": phone,
"fn": fName,
"ln": l

Keep getting pending request when trying to call endpoint, what's wrong?

I have made an endpoint to get token for paytm payment integration. In backend when i'm calling api i'm getting reqdata json but in frontend when i'm logging await transactionAPI, i'm getting only pending promise. i've tried using then in backend in PaytmChecksum.generateSignature method & in frontend in fetch but nothing is working. Keep getting the same result. Pls help.
Frontend code:
const makePayment = async () => {
const data = {
oid: String(new Date().valueOf()),
amount: '1.00',
email: 'abc#gmail.com',
};
let transactionAPI = fetch('http://localhost:3000/api/pretransact', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
console.log(await transactionAPI);
}
Backend code:
const https = require('https');
const PaytmChecksum = require('./PaytmChecksum');
export default async function handler(req, res) {
if (req.method == 'POST') {
const { oid, amount, email } = req.body;
let mid = process.env.PAYTM_MID;
let paytmParams = {};
paytmParams.body = {
requestType: 'Payment',
mid,
websiteName: process.env.WEBSITE,
orderId: oid,
callbackUrl: 'http://localhost:3000/api/callback',
txnAmount: {
value: amount,
currency: 'INR',
},
userInfo: {
custId: email,
},
};
const checksum = await PaytmChecksum.generateSignature(
JSON.stringify(paytmParams.body),
process.env.MERCHANT_KEY
);
paytmParams.head = {
signature: checksum,
};
var post_data = JSON.stringify(paytmParams);
const requestAsync = () => {
return new Promise((resolve, reject) => {
var options = {
hostname: 'securegw-stage.paytm.in',
// hostname: 'securegw.paytm.in',
port: 443,
path: `/theia/api/v1/initiateTransaction?mid=${mid}&orderId=${oid}`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length,
},
};
var response = '';
var post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
resolve(response);
});
});
post_req.write(post_data);
post_req.end();
});
};
const reqdata = await requestAsync();
res.send(200).json(reqdata);
}
}

One Signal Push Notification

How to include small icon and big icon url while creating a push notification in node js, I know that we need to send image url while sending push notification, i need code sample in node js.. I have this code..
sendNotificationToSpecific =function (token,messages) {
var sendNotification = function (data) {
var headers = {
"Content-Type": "application/json; charset=utf-8",
"Authorization": "Basic MDNlMTNjYWMTgy"
};
var options = {
host: "onesignal.com",
port: 443,
path: "/api/v1/notifications",
method: "POST",
headers: headers
};
var https = require('https');
var req = https.request(options, function (res) {
res.on('data', function (data) {
console.log("Response:");
console.log(JSON.parse(data));
});
});
req.on('error', function (e) {
console.log("ERROR:");
console.log(e);
});
req.write(JSON.stringify(data));
req.end();
};
var message = {
app_id: "awer342-d744-4787-b59a-f55c6215c491",
contents: {"en": messages},
include_player_ids: [token],
};
sendNotification(message);
};
As you can see in the docs https://documentation.onesignal.com/reference#section-appearance you can simply extend your message object like
var message = {
app_id: "xxxx",
contents: {"en": messages},
include_player_ids: [token],
small_icon: "resource_name", // can not be an url
large_icon: "http://url/ or resource_name"
}

Implementation of Box View API in Node.js gives 202

I'm currently building a node implementation of the new Box View API and I'm getting a 202 everytime I upload a document and retrieve a session. However, if I do a curl call, I dont get a 202. Is there anyone else experiencing this issue?
Here is my Ember Implementation:
export default Ember.View.extend({
document: null,
documentID: null,
session: null,
sessionID: null,
getDocument: function() {
var self = this;
return Ember.$.ajax({
url: 'http://localhost:3000/doc',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({ "docURL": this.textField.value })
}).then(function(response){
self.set('document', response);
self.set('documentID', response.document_id);
});
},
getSession: function() {
var self = this;
return Ember.$.ajax({
url: 'http://localhost:3000/sess/',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({ "docID": this.get('documentID') })
}).
then(function(response) {
self.set('session', response);
self.set('sessionID', response.session_id);
});
}.observes('documentID'),
actions: {
upload: function() {
this.getDocument();
}
}
});
Here is my node implementation:
var https = require('https');
var requestCount = 0;
exports.doc = function(req, res) {
var docURL = req.body.docURL;
var httpReq;
var opts = {
hostname: 'view-api.box.com',
path: '/1/documents',
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Token <my token>' }
};
res.header('Access-Control-Allow-Origin', '*');
httpReq = https.request(opts, function(preq, pres) {
var output = '';
preq.on('data', function(chunk) {
output += chunk;
});
preq.on('end', function() {
output = JSON.parse(output);
output.document_id = output.id;
delete output.id;
res.json(output);
});
});
httpReq.write(JSON.stringify({ "url": docURL }));
httpReq.end();
};
exports.sess = getSession;
function getSession(req, res) {
var docID = req.body.docID;
var httpReq;
var opts = {
hostname: 'view-api.box.com',
path: '/1/sessions',
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Token <my token>' }
};
res.header('Access-Control-Allow-Origin', '*');
httpReq = https.request(opts, function(preq, pres) {
var output = '';
if(preq.statusCode === 202) {
setTimeout(function() {
console.log('Retrying Request :: Count(' + requestCount + ')');
if (requestCount >= 3) {
res.json({ 'error': "Retry Again.", 'time': preq.headers['retry-after'] });
return;
}
getSession(req, res);
requestCount += 1;
}, 2000);
return;
}
preq.on('data', function(chunk) {
output += chunk;
});
preq.on('end', function() {
console.log('Successful Request!');
requestCount = 0;
output = JSON.parse(output);
output.session_id = output.id;
delete output.id;
res.json(output);
});
});
httpReq.write(JSON.stringify({ "document_id": docID, "duration": 60 }));
httpReq.end();
}
But now I'm getting this error. Is there a UI that can help me remove the uploaded documents?
{
"message": "You have exceeded your document upload rate-limit.",
"type": "error",
"request_id": "49f8b480b304496987b8cf21f5850c90"
}
You have the correct approach with retry-after for sessions.
The rate limiting you're seeing is actually due to the 2-document rate limit in place for the View API beta. See the FAQ for more info.
You can use webhooks to be notified when your documents finish converting (allowing you to upload another), so you don't have to poll the /documents endpoint for status.

Resources