How to use set 2Checkout Authentication Headers? - node.js

I'm trying to use 2checkout REST API
https://knowledgecenter.2checkout.com/API-Integration/REST_5.0_Reference#/introduction/authentication/json-encoded-requests
Here's a snippet of how i try to request
const axios = require('axios')
const moment = require('moment')
const saltedMd5 = require('salted-md5');
let now = moment().format('YYYY-MM-DD HH:MM:SS')
let vendorCode = '250207358831'
let toHash = vendorCode.length + vendorCode + now.length + now
let salt = '~0CSl)!M#4rZ|zX5QR&s'
const hash = saltedMd5(toHash, salt)
axios.get('https://api.2checkout.com/rest/5.0/subscriptions/?Email=customer%40email.com&AvangateCustomerReference=1234567&ExternalCustomerReference=abcdefg&Page=1&Limit=10&PurchasedBefore=2015-12-29&PurchasedAfter=2015-01-15&ExpireBefore=2016-05-22&ExpireAfter=2015-07-23&Type=regular&Aggregate=false', {
headers: {
'X-Avangate-Authentication': `code="${vendorCode}" date="${now}" hash="${hash}"`,
'Content-Type': 'application/json',
'Accept': 'application/json'
}
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
It returns status code 500. Does someone know how to retrieve subscriptions using the 2checkout API?

class TwoCheckoutService {
tco: {
domain:string;
apiUrl: string,
apiUser:string,
apiPass:string,
sellerId:string,
privateKey:string,
secretKey:string,
demo:boolean,
};
constructor(private userService: UserService) {
this.tco = {=
apiUrl: 'https://api.2checkout.com/rest/6.0',
apiUser: "=",
apiPass: "=",
sellerId: "=",
privateKey: "=",
secretKey: "=",
demo: true,
// sandbox: false
};
}
private async _getAuthHeaders(): Promise<{[key:string]: string}> {
var code = this.tco.sellerId;
var date = moment().utc().format('YYYY-MM-DD hh:mm:ss');
var stringToHash = code.toString().length + code + date.toString().length + date;
var hmac = crypto.createHmac('md5', this.tco.secretKey);
hmac.update(stringToHash, 'utf8');
var hash = hmac.digest('hex')
var authHeader = `code="${code}" date="${date}" hash="${hash}"`
return {
'X-Avangate-Authentication': authHeader,
'Content-Type': 'application/json',
'Accept': 'application/json'
};
}
async getProducts() {
var url = this.tco.apiUrl + '/products/';
var headers = await this._getAuthHeaders();
console.log(headers);
var res = await Axios.get(url, {
headers: headers,
params: {
'Limit': 10,
'Page': 1,
},
validateStatus: (status)=>true
});
if(res.status === 200) return res.data;
return {
error: true,
data: res.data,
url: url,
headers: headers
}
}
}
#This is an example in typescript nodejs
##requirements
crypto
axios
2checkout api credentials

Related

How do I generate Basic HTTP RFC2617 Authentication code?

My problem is exactly same as this one.
The fact is, it's answer didn't worked for me. It is still showing "wrong code".
{ message: 'Access denied: Invalid token, wrong code' }
headers are
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic bW9oaXRrdW1hcnNpbmdoMTIzNDRAZ21haWwuY29tOjE1NDg3NjY3Njg='
}
Here is the code used
import axios from 'axios';
import base64 from 'base-64';
import utf8 from 'utf8';
import { totp } from 'otplib';
const reqJSON =
{
github_url: GITHUB_URL,
contact_email: EMAIL
}
const stringData = JSON.stringify(reqJSON);
const URL = API_URL;
const sharedSecret = reqJSON.contact_email + "SOME_STRING";
totp.options = { digits: 10, algorithm: "sha512", epoch: 0 }
const myTotp = totp.generate(sharedSecret);
const isValid = totp.check(myTotp, sharedSecret);
console.log("Token Info:", { myTotp, isValid });
const authStringUTF = reqJSON.contact_email + ":" + myTotp;
const bytes = utf8.encode(authStringUTF);
const encoded = base64.encode(bytes);
console.log('encoded ->', encoded);
const createReq = async () => {
try {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': "Basic " + encoded
}
};
console.log("Making req", { URL, reqJSON, config });
const res = await axios.post(URL, stringData, config);
console.log(res.data);
}
catch (err) {
console.error(err.response.data);
}
};
createReq();
EDIT - Added current code for generating Basic HTTP RFC2617 Authentication Code
Thanks you so much!

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

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);
}
}

My express routing not working on different discord servers

So what happens is I am creating a discord bot that access the routes from express and it works if I keep it on a certain server, but if I try to access express on a different server while the server is on I get
Restarting the server removes the "assignments is not a function" So this only works when I try to access these routes endpoints from a completely different server. More information, If I try to do curl requests to these endpoints with different channel or guild id information, I also get that error. So I am assuming thats where a lot of the problem is coming from. I don't know why different information throws off the function.
index.js
import express, { json, query, request, response } from 'express';
import { assignments , announcements , discussions} from "./Fetch/fetchCalls.js";
var app = express();
app.use(express.json());
const PORT = 8080;
app.listen(PORT);
var guild;
var channel;
app.all('/assignments',(request) => {assignments(guild = request.body.guild, channel = request.body.channel);});
app.all('/discussions',(request) => {discussions(guild = request.body.guild,channel = request.body.channel); });
app.all('/announcements', (request) => {announcements(guild = request.body.guild,channel = request.body.channel);});
fetchCalls.js
import fetch from 'node-fetch';
import { createRequire } from "module";
import { getRecord, updateChannelID } from './dbUtil.js';
import { clearData } from './clear.js';
const require = createRequire(import.meta.url);
const config = require("../Canvas Bot/Source/Data/config.json")
var obj;
var course;
var url;
var access_token;
var guildid;
var channelid;
export function discussions(guild,channel) {
guildid = guild;
channelid = channel;
discussionsFunc();
async function discussionsFunc(){
try {
updateChannelID(guildid,channelid);
await getRecord({ guild_id : `${guildid}`}, getFetchData);
const res1 = await fetch(url + `courses/${course}/discussion_topics?scope=unlocked`, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const apiData = await res1.json();
for(discussions of apiData){
const string = ["**TOPIC: "+discussions.title +"**", discussions.message + "\n"];
const res2 = await fetch(
`https://discordapp.com/api/channels/${channelid}/messages`,
{
method: "POST",
headers: {
"Authorization": `Bot ${config.TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
"Connection": "close",
body: JSON.stringify({
content: string.join('\n').replace(/(<([^>]+)>)/gi, "")
}),
}
);
const apiResponse = await res2.json();
}
} catch (err) {
console.log(err);
}
}
clearData();
};
export function announcements(guild,channel) {
guildid = guild;
channelid = channel;
announcementsFunc();
async function announcementsFunc(){
updateChannelID(guildid,channelid);
try {
await getRecord({ guild_id : `${guildid}`}, getFetchData);
const res1 = await fetch(url + `/announcements?context_codes[]=${obj}&latest_only=true`, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}` ,
"Content-Type": "application/json",
},
});
const apiData = await res1.json();
console.log(apiData);
for( announcements of apiData){
const string = [`\`\`\`${announcements.title}\n`, `${announcements.message}\n\`\`\``];
const res2 = await fetch(
`https://discordapp.com/api/channels/${channelid}/messages`,
{
method: "POST",
headers: {
"Authorization": `Bot ${config.TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
"Connection": "close",
body: JSON.stringify({
content: string.join('\n').replace(/(<([^>]+)>)/gi, "")
}),
}
);
const apiResponse = await res2.json();
console.log(apiResponse);
}
} catch (err) {
console.log(err);
}
}
clearData();
}
export function assignments(guild, channel) {
guildid = guild;
channelid = channel;
assignmentsFunc();
async function assignmentsFunc(){
updateChannelID(guildid,channelid);
try {
await getRecord({guild_id : `${guildid}`}, getFetchData);
const res1 = await fetch(url + `/courses/${course}/assignments?order_by=due_at`, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const apiData = await res1.json();
console.log(apiData);
var size = apiData.length-1;
for( assignments of apiData){
const string = [`\`\`\`Name: ${assignments.name}`, `Description:\n ${assignments.description}`,`Due Date: ${assignments.due_at}\n\`\`\``];
const res2 = await fetch(
`https://discordapp.com/api/channels/${channelid}/messages`,
{
method: "POST",
headers: {
"Authorization": `Bot ${config.TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
"Connection": "close",
body: JSON.stringify({
content: string.join('\n').replace(/(<([^>]+)>)/gi, "")
}),
}
);
const apiResponse = await res2.json();
console.log(apiResponse);
}
} catch (err) {
console.log(err);
}
}
clearData();
}
function getFetchData(document) {
obj = 'course_' + document._courseid;
course = document._courseid;
course1 = "_" + course;
url = 'https://' + document.prefix + '.instructure.com/api/v1/';
access_token = document.access_token;
console.log('obj = ' + obj + '\ncourse = ' + course + '\nurl = ' + url + '\naccess_token = ' + access_token);
}
and if necessary
dbUtil.js
import { MongoClient } from 'mongodb';
const uri = 'cluser uri';
const client = new MongoClient(uri)
export async function updateChannelID(guildids, channelids) {
try{
await client.connect();
// db name and collection
const database = client.db("Users");
const docs = database.collection("user_info");
var query = {guild_id: `${guildids}`};
var insert = {$set: {channel_id: `${channelids}`}};
// find the first record matching the given query
docs.updateOne(query,insert);
}
catch(error){
console.log(error);
}
}
The problem lies in the fetchCall.js file. First of all, you are exporting things in the wrong manner. If you are not using tools like babel, syntax export function ... is incorrect, you have to use module.exports to export things from a Node.js module.
So you can change your file in the following manner, for example.
function discussions(guild, channel) {
guildid = guild;
channelid = channel;
discussionsFunc();
async function discussionsFunc() {
try {
updateChannelID(guildid, channelid);
await getRecord({
guild_id: `${guildid}`
}, getFetchData);
const res1 = await fetch(url + `courses/${course}/discussion_topics?scope=unlocked`, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const apiData = await res1.json();
for (discussions of apiData) {
const string = ["**TOPIC: " + discussions.title + "**", discussions.message + "\n"];
const res2 = await fetch(
`https://discordapp.com/api/channels/${channelid}/messages`, {
method: "POST",
headers: {
"Authorization": `Bot ${config.TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
"Connection": "close",
body: JSON.stringify({
content: string.join('\n').replace(/(<([^>]+)>)/gi, "")
}),
}
);
const apiResponse = await res2.json();
}
} catch (err) {
console.log(err);
}
}
clearData();
};
function announcements(guild, channel) {
guildid = guild;
channelid = channel;
announcementsFunc();
async function announcementsFunc() {
updateChannelID(guildid, channelid);
try {
await getRecord({
guild_id: `${guildid}`
}, getFetchData);
const res1 = await fetch(url + `/announcements?context_codes[]=${obj}&latest_only=true`, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const apiData = await res1.json();
console.log(apiData);
for (announcements of apiData) {
const string = [`\`\`\`${announcements.title}\n`, `${announcements.message}\n\`\`\``];
const res2 = await fetch(
`https://discordapp.com/api/channels/${channelid}/messages`, {
method: "POST",
headers: {
"Authorization": `Bot ${config.TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
"Connection": "close",
body: JSON.stringify({
content: string.join('\n').replace(/(<([^>]+)>)/gi, "")
}),
}
);
const apiResponse = await res2.json();
console.log(apiResponse);
}
} catch (err) {
console.log(err);
}
}
clearData();
}
function assignments(guild, channel) {
guildid = guild;
channelid = channel;
assignmentsFunc();
async function assignmentsFunc() {
updateChannelID(guildid, channelid);
try {
await getRecord({
guild_id: `${guildid}`
}, getFetchData);
const res1 = await fetch(url + `/courses/${course}/assignments?order_by=due_at`, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const apiData = await res1.json();
console.log(apiData);
var size = apiData.length - 1;
for (assignments of apiData) {
const string = [`\`\`\`Name: ${assignments.name}`, `Description:\n ${assignments.description}`, `Due Date: ${assignments.due_at}\n\`\`\``];
const res2 = await fetch(
`https://discordapp.com/api/channels/${channelid}/messages`, {
method: "POST",
headers: {
"Authorization": `Bot ${config.TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
},
"Connection": "close",
body: JSON.stringify({
content: string.join('\n').replace(/(<([^>]+)>)/gi, "")
}),
}
);
const apiResponse = await res2.json();
console.log(apiResponse);
}
} catch (err) {
console.log(err);
}
}
clearData();
}
function getFetchData(document) {
obj = 'course_' + document._courseid;
course = document._courseid;
course1 = "_" + course;
url = 'https://' + document.prefix + '.instructure.com/api/v1/';
access_token = document.access_token;
console.log('obj = ' + obj + '\ncourse = ' + course + '\nurl = ' + url + '\naccess_token = ' + access_token);
}
module.exports = {assignments, discussions, announcements}
Also another advice to rename your functions, functions are verbs, not nouns, e.g. instead of assignments name it getAssignments or whatever it is doing.
UPD:
And looks like you are using wrong modules, Node.js uses CommonJS modules, so you have use require to import other modules unless you are using TypeScript or Babel.
Change your index.js file to
const express = require('express');
const{ assignments , announcements , discussions}
= require("./Fetch/fetchCalls.js");
var app = express();
app.use(express.json());
const PORT = 8080;
app.listen(PORT);
var guild;
var channel;
app.all('/assignments',(request) => {assignments(guild = request.body.guild, channel = request.body.channel);});
app.all('/discussions',(request) => {discussions(guild = request.body.guild,channel = request.body.channel); });
app.all('/announcements', (request) => {announcements(guild = request.body.guild,channel = request.body.channel);});

How to correctly handle Params and Querys in Axios?

I'm consuming an API with NODEJS and using the axios to do the "get" ...
In NODEJS we call "params" everything that comes before the "?" Character, and we call the "query" everything that goes after the "?" Character, such as:
https://www.url.com/testing.xsjs?QueryName1='test1,test1'&QueryName2=1
The problem I'm having in Axios is that it does not create the url correctly, which the correct URL should be:
https: //www.url.comho/fatSales.xsjs?Shop='shop1,shop2,shop3'&PeriodoDe=201801&PeriodoAte=201807&Kpi='kp1,kp2,kp3'& Select = NUCOMPETEC
But the url he is creating for me is this:
https://www.apiUrl.com/Shop=shop1, + shop2, + shop3&PeriodoDe=201801&PeriodoAte=201807&Kpi=kp1,+kp2,+kp3&Select=NUCOMPETEC
I have some issues with this URL that it creates that are as follows:
1) Shop and Kpi it creates the "+" character
2) It does not add the parameter (NODEJS) before the "?" Character ...
Remembering that:
Shop and Kpi (It's an array with 1 or * elements)
const axios = require('axios');
const Qs = require('qs');
class ApiDAO {
constructor(xsjs, shoppingId, periodOf, periodUntil, kpi, select){
this.xsjs = xsjs;
this.shoppingId = shoppingId;
this.periodOf = periodOf;
this.periodUntil = periodUntil;
this.kpi = kpi;
this.select = select;
}
configAxios(){
return axios.create({
method: 'GET',
responseType: 'json',
responseEncoding: 'utf8',
headers: {
'Content-Type': "application/json",
'Cache-Control': "no-cache",
Authorization: "",
Apikey: "",
},
params: {
xsjs: this.xsjs,
Shop: this.shoppingId,
PeriodoDe: this.periodOf,
PeriodoAte: this.periodUntil,
Kpi: this.kpi,
Select: this.select
},
});
}
async getResponseAxios(){
return await this.configAxios().get('https://www.apiUrl.com/');
}
}
module.exports = () => { return ApiDAO };
Are you stringifying your params? Can you try the following:
const axios = require('axios');
const Qs = require('qs');
class ApiDAO {
constructor(xsjs, shoppingId, periodOf, periodUntil, kpi, select){
this.xsjs = xsjs;
this.shoppingId = shoppingId;
this.periodOf = periodOf;
this.periodUntil = periodUntil;
this.kpi = kpi;
this.select = select;
}
configAxios(url){
return axios.get({
method: 'GET',
url: url,
responseType: 'json',
responseEncoding: 'utf8',
headers: {
'Content-Type': "application/json",
'Cache-Control': "no-cache",
Authorization: "",
Apikey: "",
},
params: {
xsjs: this.xsjs,
Shop: this.shoppingId,
PeriodoDe: this.periodOf,
PeriodoAte: this.periodUntil,
Kpi: this.kpi,
Select: this.select
},
});
}
async getResponseAxios(){
return await this.configAxios('https://www.apiUrl.com/');
}
}
module.exports = () => { return ApiDAO };
Or if you want to use axios create, pass the URL in earlier as an option field. I don't think it's an error with the other params.

Resources