How to Integrate Paytm Payment Gateway?
Subham
Posted on April 8, 2023
In this article, I will show you how to integrate Paytm Payment Gateway into your website or app using Node.js and Express. Paytm Payment Gateway is a secure and easy way to accept online payments from your customers. You can use Paytm Payment Gateway to accept payments from various sources, such as debit/credit cards, UPI, Netbanking, Paytm Wallet, and EMI. You can also benefit from the features and offers that Paytm Payment Gateway provides, such as high success rates, dedicated support, analytics, affordability products, and more
Github Code : here
Now just follow these steps:
Create a new folder and open it in VS Code.
-
npm init -y
(this will create package.json file) -
npm i express nodemon
(this will install express and nodemon) - Open the paytm website here a > Login with your paytm account
- Go to Developer Settings
-
Click on API Keys
or,
- Go to [here](https://business.paytm.com/integration-builder/account-setup)
- Copy the Merchant ID and Merchant Key
-
Change the script in package.json to
"start": "nodemon index.js"
"scripts": { "start": "nodemon index.js" },
Create a file named
index.js
and paste the following code.
const express = require("express");
const https = require("https");
const qs = require("querystring");
const app = express();
const parseUrl = express.urlencoded({ extended: false });
const parseJson = express.json({ extended: false });
const PORT = process.env.PORT || 4000;
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.post("/paynow", [parseUrl, parseJson], (req, res) => {
// Route for making payment
var paymentDetails = {
amount: req.body.amount,
customerId: req.body.name,
customerEmail: req.body.email,
customerPhone: req.body.phone,
};
if (
!paymentDetails.amount ||
!paymentDetails.customerId ||
!paymentDetails.customerEmail ||
!paymentDetails.customerPhone
) {
res.status(400).send("Payment failed");
} else {
var params = {};
params["MID"] = config.PaytmConfig.mid;
params["WEBSITE"] = config.PaytmConfig.website;
params["CHANNEL_ID"] = "WEB";
params["INDUSTRY_TYPE_ID"] = "Retail";
params["ORDER_ID"] = "TEST_" + new Date().getTime();
params["CUST_ID"] = paymentDetails.customerId;
params["TXN_AMOUNT"] = paymentDetails.amount;
params["CALLBACK_URL"] = "http://localhost:3000/callback";
params["EMAIL"] = paymentDetails.customerEmail;
params["MOBILE_NO"] = paymentDetails.customerPhone;
checksum_lib.genchecksum(
params,
config.PaytmConfig.key,
function (err, checksum) {
var txn_url =
"https://securegw-stage.paytm.in/theia/processTransaction"; // for staging
// var txn_url = "https://securegw.paytm.in/theia/processTransaction"; // for production
var form_fields = "";
for (var x in params) {
form_fields +=
"<input type='hidden' name='" + x + "' value='" + params[x] + "' >";
}
form_fields +=
"<input type='hidden' name='CHECKSUMHASH' value='" + checksum + "' >";
res.writeHead(200, { "Content-Type": "text/html" });
res.write(
'<html><head><title>Merchant Checkout Page</title></head><body><center><h1>Please do not refresh this page...</h1></center><form method="post" action="' +
txn_url +
'" name="f1">' +
form_fields +
'</form><script type="text/javascript">document.f1.submit();</script></body></html>'
);
res.end();
}
);
}
});
app.post("/callback", (req, res) => {
// Route for verifiying payment
var body = "";
req.on("data", function (data) {
body += data;
});
req.on("end", function () {
var html = "";
var post_data = qs.parse(body);
// received params in callback
console.log("Callback Response: ", post_data, "n");
// verify the checksum
var checksumhash = post_data.CHECKSUMHASH;
// delete post_data.CHECKSUMHASH;
var result = checksum_lib.verifychecksum(
post_data,
config.PaytmConfig.key,
checksumhash
);
console.log("Checksum Result => ", result, "n");
// Send Server-to-Server request to verify Order Status
var params = { MID: config.PaytmConfig.mid, ORDERID: post_data.ORDERID };
checksum_lib.genchecksum(
params,
config.PaytmConfig.key,
function (err, checksum) {
params.CHECKSUMHASH = checksum;
post_data = "JsonData=" + JSON.stringify(params);
var options = {
hostname: "securegw-stage.paytm.in", // for staging
// hostname: 'securegw.paytm.in', // for production
port: 443,
path: "/merchant-status/getTxnStatus",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": post_data.length,
},
};
// Set up the request
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("S2S Response: ", response, "n");
var _result = JSON.parse(response);
if (_result.STATUS == "TXN_SUCCESS") {
res.send("payment sucess");
} else {
res.send("payment failed");
}
});
});
// post the data
post_req.write(post_data);
post_req.end();
}
);
});
});
app.listen(PORT, () => {
console.log(`App is listening on Port ${PORT}`);
});
- Create a file named
index.html
and paste the following code.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<title>Paytm-Nodejs</title>
</head>
<body style="background-color:#f5f3ef">
<div class="row my-5">
<div class="col-md-4 offset-md-4">
<div class="card">
<div class="card-body">
<form class="" action="/paynow" method="post">
<div class="form-group">
<label for="">Name: </label>
<input class="form-control" type="text" name="name" value="">
</div>
<div class="form-group">
<label for="">Email: </label>
<input class="form-control" type="text" name="email" value="">
</div>
<div class="form-group">
<label for="">Phone: </label>
<input class="form-control" type="text" name="phone" value="">
</div>
<div class="form-group">
<label for="">Amount: </label>
<input class="form-control" type="text" name="amount" value="">
</div>
<div class="form-group">
<button class="btn form-control btn-primary">Pay Now</button>
</div>
</form>
</div>
</div>
</div>
</div>
</body>
</html>
- Hit
npm start
to start the server.
- The browser will display a form "name email phone number.".
If you simple open the html file you will see in the form action is
/paynow
and method ispost
so it will send the data to the server and the server will send the data to the paytm server and the paytm server will send the response to the server and the server will send the response to the browser.
- And now you need to make the
Paytm
folder and inside it you need to create thechecksum.js
file and copy the following code
Paytm/checksum.js
"use strict";
var crypt = require('./crypt');
var util = require('util');
var crypto = require('crypto');
//mandatory flag: when it set, only mandatory parameters are added to checksum
function paramsToString(params, mandatoryflag) {
var data = '';
var tempKeys = Object.keys(params);
tempKeys.sort();
tempKeys.forEach(function (key) {
var n = params[key].includes("REFUND");
var m = params[key].includes("|");
if(n == true )
{
params[key] = "";
}
if(m == true)
{
params[key] = "";
}
if (key !== 'CHECKSUMHASH' ) {
if (params[key] === 'null') params[key] = '';
if (!mandatoryflag || mandatoryParams.indexOf(key) !== -1) {
data += (params[key] + '|');
}
}
});
return data;
}
function genchecksum(params, key, cb) {
var data = paramsToString(params);
crypt.gen_salt(4, function (err, salt) {
var sha256 = crypto.createHash('sha256').update(data + salt).digest('hex');
var check_sum = sha256 + salt;
var encrypted = crypt.encrypt(check_sum, key);
cb(undefined, encrypted);
});
}
function genchecksumbystring(params, key, cb) {
crypt.gen_salt(4, function (err, salt) {
var sha256 = crypto.createHash('sha256').update(params + '|' + salt).digest('hex');
var check_sum = sha256 + salt;
var encrypted = crypt.encrypt(check_sum, key);
var CHECKSUMHASH = encodeURIComponent(encrypted);
CHECKSUMHASH = encrypted;
cb(undefined, CHECKSUMHASH);
});
}
function verifychecksum(params, key, checksumhash) {
var data = paramsToString(params, false);
//TODO: after PG fix on thier side remove below two lines
if (typeof checksumhash !== "undefined") {
checksumhash = checksumhash.replace('n', '');
checksumhash = checksumhash.replace('r', '');
var temp = decodeURIComponent(checksumhash);
var checksum = crypt.decrypt(temp, key);
var salt = checksum.substr(checksum.length - 4);
var sha256 = checksum.substr(0, checksum.length - 4);
var hash = crypto.createHash('sha256').update(data + salt).digest('hex');
if (hash === sha256) {
return true;
} else {
util.log("checksum is wrong");
return false;
}
} else {
util.log("checksum not found");
return false;
}
}
function verifychecksumbystring(params, key,checksumhash) {
var checksum = crypt.decrypt(checksumhash, key);
var salt = checksum.substr(checksum.length - 4);
var sha256 = checksum.substr(0, checksum.length - 4);
var hash = crypto.createHash('sha256').update(params + '|' + salt).digest('hex');
if (hash === sha256) {
return true;
} else {
util.log("checksum is wrong");
return false;
}
}
function genchecksumforrefund(params, key, cb) {
var data = paramsToStringrefund(params);
crypt.gen_salt(4, function (err, salt) {
var sha256 = crypto.createHash('sha256').update(data + salt).digest('hex');
var check_sum = sha256 + salt;
var encrypted = crypt.encrypt(check_sum, key);
params.CHECKSUM = encodeURIComponent(encrypted);
cb(undefined, params);
});
}
function paramsToStringrefund(params, mandatoryflag) {
var data = '';
var tempKeys = Object.keys(params);
tempKeys.sort();
tempKeys.forEach(function (key) {
var m = params[key].includes("|");
if(m == true)
{
params[key] = "";
}
if (key !== 'CHECKSUMHASH' ) {
if (params[key] === 'null') params[key] = '';
if (!mandatoryflag || mandatoryParams.indexOf(key) !== -1) {
data += (params[key] + '|');
}
}
});
return data;
}
module.exports.genchecksum = genchecksum;
module.exports.verifychecksum = verifychecksum;
module.exports.verifychecksumbystring = verifychecksumbystring;
module.exports.genchecksumbystring = genchecksumbystring;
module.exports.genchecksumforrefund = genchecksumforrefund;
- Now you need to create the
config.js
file inside thePaytm
folder and copy the following code
var PaytmConfig = {
mid: "####yourmid#####",
key: "###yourkey#####",
website: "##yourwebsite##",
};
module.exports.PaytmConfig = PaytmConfig;
Note: You need to replace the
mid
andkey
with your ownmid
andkey
andwebsite
with your ownwebsite
- Now you need to create the
crypt.js
file inside thePaytm
folder and copy the following code
"use strict";
var crypto = require('crypto');
var util = require('util');
var crypt = {
iv: '@@@@&&&&####$$',
encrypt: function (data,custom_key) {
var iv = this.iv;
var key = custom_key;
var algo = '256';
switch (key.length) {
case 16:
algo = '128';
break;
case 24:
algo = '192';
break;
case 32:
algo = '256';
break;
}
var cipher = crypto.createCipheriv('AES-' + algo + '-CBC', key, iv);
//var cipher = crypto.createCipher('aes256',key);
var encrypted = cipher.update(data, 'binary', 'base64');
encrypted += cipher.final('base64');
return encrypted;
},
decrypt: function (data,custom_key) {
var iv = this.iv;
var key = custom_key;
var algo = '256';
switch (key.length) {
case 16:
algo = '128';
break;
case 24:
algo = '192';
break;
case 32:
algo = '256';
break;
}
var decipher = crypto.createDecipheriv('AES-' + algo + '-CBC', key, iv);
var decrypted = decipher.update(data, 'base64', 'binary');
try {
decrypted += decipher.final('binary');
} catch (e) {
util.log(util.inspect(e));
}
return decrypted;
},
gen_salt: function (length, cb) {
crypto.randomBytes((length * 3.0) / 4.0, function (err, buf) {
var salt;
if (!err) {
salt = buf.toString("base64");
}
//salt=Math.floor(Math.random()*8999)+1000;
cb(err, salt);
});
},
/* one way md5 hash with salt */
md5sum: function (salt, data) {
return crypto.createHash('md5').update(salt + data).digest('hex');
},
sha256sum: function (salt, data) {
return crypto.createHash('sha256').update(data + salt).digest('hex');
}
};
module.exports = crypt;
(function () {
var i;
function logsalt(err, salt) {
if (!err) {
console.log('salt is ' + salt);
}
}
if (require.main === module) {
var enc = crypt.encrypt('One97');
console.log('encrypted - ' + enc);
console.log('decrypted - ' + crypt.decrypt(enc));
for (i = 0; i < 5; i++) {
crypt.gen_salt(4, logsalt);
}
}
}());
- Now if you enter the name and email and click on the
Pay Now
button you will be redirected to thePaytm
payment gateway and you can pay using thePaytm
app or using thePaytm
website.
Posted on April 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 29, 2024