Gpay payment-gateway integration in NodeJS - node.js

I tried it in Html and Javascript it's working perfect in web (mobile's browser).I am using angular for frontend and node for backend but not getting any proper solution for redirect Playstore or Gpay for mobile browser. Basically I want to implement for mobile browser.
this is my node for backend code & for frontend I already paste static. So, request you that please check & get back to me proper resolution or tutorial. Thanks & Regards--
const canMakePaymentCache = 'canMakePaymentCache';
onBuyClicked();
function readSupportedInstruments() {
let formValue = {};
formValue['pa'] = keys.GPAY_MERCHANT_ID;//merchantId
formValue['pn'] = `Test_Gpay_Name`;//transactionId
formValue['tn'] = 'Testing Messages ';//message
formValue['mc'] = 'merchant Code';//
formValue['tr'] = 'Transaction Reference';
formValue['tid'] = 'Transaction id';
formValue['url'] = 'http://localhost.co/';
return formValue;
}
function readAmount() {
//const pay_amount = parseInt(req.body.amount) * 100;
return parseInt(req.body.amount) * 100;
}
function onBuyClicked() {
// if (!window.PaymentRequest) {
// console.log('Web payments are not supported in this browser.');
// return;
// }
let formValue = readSupportedInstruments();
const supportedInstruments = [
{
supportedMethods: ['https://pwp-server.appspot.com/pay-dev'],
data: formValue,
},
{
supportedMethods: ['https://tez.google.com/pay'],
data: formValue,
},
];
const details = {
total: {
label: 'Total',
amount: {
currency: 'INR',
value: readAmount(),
},
},
displayItems: [
{
label: 'Original amount',
amount: {
currency: 'INR',
value: readAmount(),
},
},
],
};
const options = {
requestShipping: false,
requestPayerName: false,
requestPayerPhone: false,
requestPayerEmail: false,
shippingType: 'shipping',
};
let request = null;
try {
//const PaymentRequest = {};
//request = PaymentRequest(supportedInstruments, details, options);
request ={supportedInstruments, details, options};
} catch (e) {
return;
}
if (!request) {
console.log('Web payments are not supported in this browser.');
return;
}
var canMakePaymentPromise = checkCanMakePayment(request);
canMakePaymentPromise
.then((result) => {
showPaymentUI(request, result);
})
.catch((err) => {
console.log('Error calling checkCanMakePayment: ' + err);
});
}
function checkCanMakePayment(request) {
//if (sessionStorage.hasOwnProperty(canMakePaymentCache)) {
//return Promise.resolve(JSON.parse(sessionStorage[canMakePaymentCache]));
//}
var canMakePaymentPromise = Promise.resolve(true);
if (request.canMakePayment) {
canMakePaymentPromise = request.canMakePayment();
}
return canMakePaymentPromise
.then((result) => {
canMakePaymentCache = result;
return result;
})
.catch((err) => {
console.log('Error calling canMakePayment: ' + err);
});
}
function showPaymentUI(request, canMakePayment) {
if (!canMakePayment) {
redirectToPlayStore();
return;
}
let paymentTimeout = window.setTimeout(function () {
window.clearTimeout(paymentTimeout);
request.abort()
.then(function () {
console.log('Payment timed out after 20 minutes.');
})
.catch(function () {
console.log('Unable to abort, user is in the process of paying.');
});
}, 20 * 60 * 1000); /* 20 minutes */
request.show()
.then(function (instrument) {
window.clearTimeout(paymentTimeout);
processResponse(instrument); // Handle response from browser.
})
.catch(function (err) {
console.log(err);
});
}
function processResponse(instrument) {
var instrumentString = instrumentToJsonString(instrument);
console.log(instrumentString);
fetch('/buy', {
method: 'POST',
headers: new Headers({ 'Content-Type': 'application/json' }),
body: instrumentString,
credentials: 'include',
})
.then(function (buyResult) {
if (buyResult.ok) {
return buyResult.json();
}
console.log('Error sending instrument to server.');
})
.then(function (buyResultJson) {
completePayment(
instrument, buyResultJson.status, buyResultJson.message);
})
.catch(function (err) {
console.log('Unable to process payment. ' + err);
});
}
function completePayment(instrument, result, msg) {
instrument.complete(result)
.then(function () {
console.log('Payment completes.');
console.log(msg);
document.getElementById('inputSection').style.display = 'none'
document.getElementById('outputSection').style.display = 'block'
document.getElementById('response').innerHTML =
JSON.stringify(instrument, undefined, 2);
})
.catch(function (err) {
console.log(err);
});
}
console.log(`in line 448....`);
function redirectToPlayStore() {
//if (confirm('Tez not installed, go to play store and install?')) {
//window.location.href = 'https://play.google.com/store/apps/details?id=com.google.android.apps.nbu.paisa.user.alpha'
//res.writeHead( "https://play.google.com/store/apps/details?id=com.google.android.apps.nbu.paisa.user.alpha" );
const response_data = axios
.post(
'https://play.google.com/store/apps/details?id=com.google.android.apps.nbu.paisa.user.alpha',
)
console.log(`in line no. 459... ${response_data}`);
return response_data;
//};
}
function instrumentToJsonString(instrument) {
var instrumentDictionary = {
methodName: instrument.methodName,
details: instrument.details,
shippingAddress: addressToJsonString(instrument.shippingAddress),
shippingOption: instrument.shippingOption,
payerName: instrument.payerName,
payerPhone: instrument.payerPhone,
payerEmail: instrument.payerEmail,
};
return JSON.stringify(instrumentDictionary, undefined, 2);
}

Related

display questions based on user type MERN

I have two collections from one questions for admin comes and from other questions for user comes.
I am unable to show the questions in React using redux store.
store/action
import { QUESTIONS } from '../../constants/actionTypes';
import * as api from '../../services/api';
import * as paths from '../../constants/apiPaths';
const TOTAL_QUESTIONS = 60;
export const fetcQuestions = (router) => async (dispatch) => {
try {
const user = await api.get(paths.FETCH_USER);
const userType = user.type;
console.log(userType + "userType");
if((userType === "Student") || (userType === "STUDENT"))
{
const {questions, assessment, options} = await api.get(paths.FETCH_QUESTIONS);
console.log(api.get(paths.FETCH_QUESTIONS) + "Question path");
dispatch({ type: QUESTIONS, questions, assessment, options });
if(assessment.responded === TOTAL_QUESTIONS) {
router.push('/advice');
}
}
else
if((userType === "Admin") || (userType === "ADMIN"))
{
console.log(userType + "type of user");
const {questions, assessment, options} = await api.get(paths.FETCH_QUESTIONS);
console.log(api.get(paths.FETCH_QUESTIONS) + "Question path");
dispatch({ type: QUESTIONS, questions, assessment, options });
if(assessment.responded === TOTAL_QUESTIONS) {
console.log("thank you");
}
}
} catch (error) {
console.log(error);
}
};
export const postAssessment = (data, router) => async (dispatch) => {
try {
const {questions, assessment, options} = await api.post(paths.POST_ASSESSMENT, data);
console.log(paths.POST_ASSESSMENT + "assessment");
dispatch({ type: QUESTIONS, questions, assessment, options });
if(assessment.responded === TOTAL_QUESTIONS) {
console.log("Thank you");
}
} catch (error) {
console.log(error);
}
};
please help me looking out whats wrong I am doing here. Thank You.
Reducer:
import * as actionType from '../../constants/actionTypes';
const assessmentReducer = (state = { questions: null, assessment: null, options: null }, action) => {
switch (action.type) {
case actionType.QUESTIONS:
return { ...state, questions: action?.questions, assessment: action?.assessment, options: action?.options, loading: false, errors: null };
default:
return state;
}
};
export default assessmentReducer;
NodeJS controller:
const TOTAL_QUESTIONS = 120;
export const fetchQuestions = async (req, res) => {
try {
const user = await db.findOne('USER', { _id: req.userId});
console.log(user + "user data");
let answerdQuestions = [];
let nextQuestions;
let assessment;
if (user.assessment) {
assessment = await db.findOne('ASSESSMENT', { user: req.userId });
answerdQuestions = assessment.responses.map(response => response.number)
}
nextQuestions = getNextQuestions(answerdQuestions);
if ((user.type === "STUDENT") || (user.type === "student")) {
console.log(user.type + "type");
const questions = await db.find('QUESTIONG', { number: { $in: nextQuestions } });
console.log(questions.number + "quesstudent");
res.status(200).json({ questions, assessment: { id: assessment?._id, responded: answerdQuestions.length }, options: options });
return answerdQuestions;
}
else {
console.log(user.type + "typegh");
const questions = await db.find('QUESTION', {number: { $in: nextQuestions }});
console.log(questions.question + "quesdata");
res.status(200).json({ questions, assessment: { id: assessment?._id, responded: answerdQuestions.length }, options: options });
return answerdQuestions;
}
} catch (err) {
console.log(err)
res.status(500).json({ message: "Something went wrong" });
}
};
export const postResponses = async (req, res) => {
try {
let responses = req.body.responses;
let assessmentId = req.body.id;
responses = responses.map(response => {
return {
score: Number(response.value),
number: response.number,
category: response.category,
question: response._id
}
});
const user = await db.findOne('USER', {_id: req.userId});
console.log( user.type + "typeofuser");
let assessment = await db.findOne('ASSESSMENT', { _id: assessmentId });
if (assessment?.responses.length === TOTAL_QUESTIONS) {
res.status(200).json("completed");
}
if (!assessment) {
//
let response = {
user: req.userId,
responses: responses,
responded: responses.length
}
assessment = await db.create('ASSESSMENT', response);
await db.findOneAndUpdate('USER', { _id: req.userId }, { assessment: assessment._id });
} else {
assessment = await db.findOneAndUpdate('ASSESSMENT', { _id: assessment._id }, { $push: { responses: { $each: responses } } });
}
let answerdQuestions = assessment.responses.map(response => response.number);
const nextQuestions = getNextQuestions(answerdQuestions);
if (answerdQuestions.length === TOTAL_QUESTIONS) {
console.log("You win");
]
}
if((user.type === "STUDENT") || (user.type==="student") ){
console.log("type" + user.type);
const questions = await db.find('QUESTIONG', { number: { $in: nextQuestions } });
res.status(200).json({ questions, assessment: { id: assessment?._id, responded: answerdQuestions.length }, options: options });
} else
{
console.log(user.type + "typeg");
const questions = await db.find('QUESTION', { number: { $in: nextQuestions } });
res.status(200).json({ questions, assessment: { id: assessment?._id, responded: answerdQuestions.length }, options: options });
}
}catch (err) {
console.log(err)
res.status(500).json({ message: "Something went wrong" });
}
};
//export default fetchQuestions;
I have added reducer and NodeJS controller also, Based on user type the questions are to be shown. Please help. If type is student then the questions are not getting displayed else condition the questions are getting displayed
What I can see is, you have mentioned wrong database when you are trying to fetch data for usertype student. Here is your code:
if (user.type === 'STUDENT' || user.type === 'student') {
console.log(user.type + 'type');
const questions = await db.find('QUESTIONG', { number: { $in: nextQuestions } });
You need to correct the database name, and everything will work fine:
const questions = await db.find('QUESTION', { number: { $in: nextQuestions } });
Hope this works!!!

Discord button only works once discord.js

I have posted a button but it only works once
but after that when I use it again
Also
How can I reply to message if I use deferUpdate it shows
Code
client.on('ready', () => {
client.user.setActivity('people and managing the server', {
type: 'WATCHING',
});
const channel = client.channels.cache.get('894171605608042496');
const row = new MessageActionRow().addComponents(
new MessageButton()
.setCustomId('openTicket')
.setLabel('Create ticket')
.setEmoji('📩')
.setStyle('SECONDARY')
);
channel
.send({
embeds: [
{
title: 'SGAS Tickets',
color: '#388e3c',
description: 'To create a ticket react with 📩',
},
],
components: [row],
})
.then(() => {
const filter = () => {
return true;
};
const collector = channel.createMessageComponentCollector({
filter,
time: 15 * 1000,
});
collector.on('collect', (i) => {
i.deferUpdate().then(() => {
Ticket.count({}, (err, result) => {
if (err) {
console.log(err);
} else {
const ticketNumber = result + 1;
const ticketString = convertNumber(ticketNumber);
const ticket = new Ticket({
tickedId: ticketString,
});
ticket.save((err) => {
if (err) {
console.log(err);
} else {
const myguild = client.guilds.cache.get('887277806386565150');
if (!myguild) {
console.log('guild not found');
return;
}
const category = myguild.channels.cache.find(
(c) =>
c.id === '887277807279947826' &&
c.type == 'GUILD_CATEGORY'
);
if (!category) {
console.log('category not found');
return;
}
myguild.channels
.create(`Ticket#${ticketString}`, {
type: 'GUILD_TEXT',
})
.then(async (myc) => {
myc.setParent(category).then(() => {
myc.send(
`Hello <#${i.user.id}>, your question will be solved here shortly`
);
i.reply({
content: `Go to <#${myc.id}>, for your question`,
ephemeral: true,
});
});
});
}
});
}
});
});
});
});
});
you are using a component collector - which expires in 15 seconds, as seen in your code. That means after 15 seconds your bot stops listening for button clicks. My recommendation is to use the interactionCreate event to listen for that button: see docs https://discord.js.org/#/docs/main/stable/class/ButtonInteraction
Example:
client.on("interactionCreate", (interaction) => {
if(!interaction.isButton()) return;
if(interaction.customId === "openTicket") {
// your ticket code here
}
});

Asynchronicity issue: why does the second part of my function run before a loop event finishes?

I have a route on an Express server that updates a User profile. The User profile is updated before I have finished to parse the data to update. How so?
I want to update two const: newProfilePicture & newOtherPictures. They are correctly updated, but after the user has been updated, so it's useless. How to fix this asynchronicity issue?
Here is the function:
router.post("/upload-images", upload.array("image"), async (req, res) => {
const { userId } = req.body;
try {
if (req.files) {
let newProfilePicture = null;
let newOtherPictures = [];
req.files.forEach(({ path, originalname }) => {
cloudinary.uploader.upload(
path,
{
resource_type: "image",
public_id: `myapp/users/${userId}/${originalname}`,
crop: "scale",
quality: "auto",
},
(err, res) => {
if (err) {
return fs.unlinkSync("./" + path);
}
fs.unlinkSync("./" + path);
if (originalname === "main") {
return (newProfilePicture = res.secure_url);
}
return newOtherPictures.push({
id: originalname,
url: res.secure_url,
});
}
);
});
// THIS PART IS COMPLETE BEFORE THE req.files.forEach IS DONE
const user = await User.findById(userId);
const { otherPictures, profilePicture } = updatePictures(
newProfilePicture,
newOtherPictures,
user
);
User.findByIdAndUpdate(
userId,
{ profilePicture, otherPictures },
{ new: true }
);
res.send("upload images success");
}
} catch (err) {
console.log("err", err);
return res.status(500).send("upload images failed");
}
});
It happens because cloudinary.uploader.upload() runs asynchronously. Since you mentioned it doesn't have promise interface, you can convert the callback to promise using NodeJS's util.promise function as it's error first callback.
const { promisify } = require("util");
const fs = require("fs");
const cloudinaryUpload = promisify(cloudinary.uploader.upload.bind(cloudinary.uploader))
router.post("/upload-images", upload.array("image"), async (req, res) => {
try {
if (!req.files) {
return res.send("no images in the request body");
}
let newProfilePicture = null;
let newOtherPictures = [];
for (const { path, originalName } of req.files) {
try {
const response = await cloudinaryUpload(path, {
resource_type: "image",
public_id: `myapp/users/${userId}/${originalName}`,
crop: "scale",
quality: "auto",
});
await fs.promises.unlink("./" + path);
if (originalname === "main") {
newProfilePicture = response.secure_url;
continue;
}
newOtherPictures.push({
id: originalName,
url: response.secure_url,
});
} catch (error) {
//do what you want if there is an error
//throw error if you want
await fs.promises.unlink("./" + path);
}
}
const user = await User.findById(userId);
const { otherPictures, profilePicture } = updatePictures(
newProfilePicture,
newOtherPictures,
user
);
//use User.updateOne() as you don't need the doc back
await User.findByIdAndUpdate(
userId,
{ profilePicture, otherPictures },
{ new: true }
);
return res.send("upload images success");
} catch (error) {
console.log("err", err);
return res.status(500).send("upload images failed");
}
});

How to send selected files to a node server using react native fs?

I am using https://github.com/itinance/react-native-fs to upload files from a react-native client, but it's not getting received in my nodejs server. By the way, I have used react-native-document-picker https://github.com/Elyx0/react-native-document-picker to select the files from the Android file system. Here is my client app's code;
async uploadToNode() {
let testUrl = this.state.multipleFile[0].uri; //content://com.android.providers.media.documents/document/image%3A7380
const split = testUrl.split('/');
const name = split.pop();
const setFileName = "Img"
const inbox = split.pop();
const realPath = `${RNFS.TemporaryDirectoryPath}${inbox}/${name}`;
const uploadUrl = "http://localhost:8082/uploadToIpfs";
var uploadBegin = (response) => {
const jobId = response.jobId;
console.log('UPLOAD HAS BEGUN! JobId: ' + jobId);
};
var uploadProgress = (response) => {
const percentage = Math.floor((response.totalBytesSent/response.totalBytesExpectedToSend) * 100);
console.log('UPLOAD IS ' + percentage + '% DONE!');
};
RNFS.uploadFiles({
toUrl: uploadUrl,
files: [{
name: setFileName,
filename:name,
filepath: realPath,
}],
method: 'POST',
headers: {
'Accept': 'application/json',
},
begin: uploadBegin,
beginCallback: uploadBegin, // Don't ask me, only way I made it work as of 1.5.1
progressCallback: uploadProgress,
progress: uploadProgress
})
.then((response) => {
console.log(response,"<<< Response");
if (response.statusCode == 200) { //You might not be getting a statusCode at all. Check
console.log('FILES UPLOADED!');
} else {
console.log('SERVER ERROR');
}
})
.catch((err) => {
if (err.description) {
switch (err.description) {
case "cancelled":
console.log("Upload cancelled");
break;
case "empty":
console.log("Empty file");
default:
//Unknown
}
} else {
//Weird
}
console.log(err);
});
}
I'm not sure if the nodejs code is correct to get the files from the client app. And here is my Server code;
app.post('/uploadToIpfs', (req, res) => {
// network.changeCarOwner(req.body.key, req.body.newOwner)
// .then((response) => {
// res.send(response);
// });
// var fileName = "Img";
// if(req.name == fileName){
// console.log(req.filename);
// res.send("Passed")
// }else{
// res.send("failed")
// }
console.log(req.files[0].filename);
res.send("Passed")
});
app.listen(process.env.PORT || 8082);

Nodejs promise all not running as expected

I have a series of promises which I have chained in testCard. This method takes a stripe card number, get the token from stripe and then talks to a third party API which tries to perform purchases with that card.
I need to run testCard by looping through an array of card numbers. To do this I have a controller object with a method testAllCards which takes the array of numbers. The array is stored in a config file.
I then run the code from the command line with node cli.js testAllCards.
However when I run it, I get testAllCards has been run before all most promises have resolved.
I am obviously missing something here, but can't seem to figure out what it is.
cli.js
const testAllCards = () => {
return controller.testAllCards(config.get('CARD_NUMBERS'))
.then((obj) => {
console.log('testAllCards has been run');
})
.catch((e) => {
console.log('testCards has been run with an error!');
const _err = new ErrHandler(e, eTopicName, eSnsSubject);
_err.handle()
.then(() => {
console.log('Error has been sent with success to sns');
});
});
};
switch(process.argv[2]) {
case 'testAllCards':
testAllCards();
break;
default:
console.log('Please run with `testAllCards`');
controller.js
//Tests response from API for different cards
const testCard = (cardNum) => {
return new Promise((resolve, reject) => {
const expMonth = new Date().getMonth() + 1;
const expYear = new Date().getFullYear() + 2;
const cardObj = {
cardNum: cardNum,
expMonth: expMonth,
expYear: expYear
};
let apiCardItem = '';
return testRequestToApi('getStripeToken', 200, 299, cardObj)
.then((cardItem) => {
return testRequestToApi('postNewCard', 200, 299, JSON.parse(cardItem.body));
})
.then((apiCard) => {
apiCardItem = apiCard.body;
try {
apiCardItem = JSON.parse(apiCardItem);
} catch(e) {
console.log(e);
}
return testRequestToApi('sampleAddToCart', 200, 299);
})
.then(() => {
return testRequestToApi('useFailingStripeCards', 400, 499, apiCardItem.id);
})
.then(() => {
return testRequestToApi('deleteCard', 200, 299, apiCardItem.id);
})
.then(() => {
resolve();
})
.catch((e) => {
reject(e);
});
});
};
//Loops through the card numbers and runs the test command against them
Controller.testAllCards = (cardsArray) => {
const items = cardsArray.map((cardNum) => {
return testCard(cardNum);
});
return Promise.all(items);
};
module.exports = Controller;
test-request-to-api.js
'use strict';
const checkStatus = require('./../utils/status-code-checker');
const formHeaders = require('./../utils/form-req-headers');
const request = require('request');
const expObj = {};
//#requestType {string} - defines which headers and function name to use
//#item {object} - defines item that is being used
expObj.testRequestToApi = (requestType, lowerLimit, upperLimit, item) => {
return new Promise((resolve, reject) => {
const reqOps = formHeaders[requestType](item);
request(reqOps, (err, response, body) => {
if (err) {
const badRequest = {
ErrorMessage: err,
FuncName: requestType,
InternalError: true
};
return reject(badRequest);
}
if (!checkStatus.checkRangeStatusCode(response.statusCode, lowerLimit, upperLimit)) {
console.log(JSON.stringify(body, null, 2));
// Set a bad Status error object
let badStatus = {
StatusCode: response.statusCode,
ErrorMessage: body,
FuncName: requestType,
InternalError: false
};
return reject(badStatus);
}
// console.log(response.headers);
// console.log(body);
const resObj = {
headers: response.headers,
body: body
};
// console.log(`******** ${requestType} *********`);
// console.log(resObj);
// console.log('----------------------------------');
return resolve(resObj);
});
});
};
module.exports = expObj;
Understanding that new Promise() is used only ever necessary when promisifying a callback based API, changing to request-promise and returning my promises in cli.js solved my issue. The execution flow was correctly maintained in this manner.
Changes to the following files are as followed:
cli.js
const testAllCards = () => {
return controller.testAllCards(config.get('CARD_NUMBERS'))
.then((obj) => {
console.log('testAllCards has been run');
})
.catch((e) => {
console.log(e)
console.log('testCards has been run with an error!');
const _err = new ErrHandler(e, eTopicName, eSnsSubject);
return _err.handle()
.then(() => {
console.log('Error has been sent with success to sns');
})
.catch((e) => {
console.log('Failed to publish to sns');
console.log(e);
});
});
};
test-request-to-api
'use strict';
const checkStatus = require('./../utils/status-code-checker');
const formHeaders = require('./../utils/form-req-headers');
const rqp = require('request-promise');
const expObj = {};
//#requestType {string} - defines which headers and function name to use
//#item {object} - defines item that is being used
expObj.testRequestToApi = (requestType, lowerLimit, upperLimit, item) => {
const reqOps = formHeaders[requestType](item);
return rqp(reqOps)
.then((response) => {
if (!checkStatus.checkRangeStatusCode(response.statusCode, lowerLimit, upperLimit)) {
console.log(JSON.stringify(response.body, null, 2));
// Set a bad Status error object
return {
StatusCode: response.statusCode,
ErrorMessage: response.body,
FuncName: requestType,
InternalError: false
};
}
// console.log(response.headers);
// console.log(response.body);
const resObj = {
headers: response.headers,
body: response.body,
previousItem: item
};
// console.log(`******** ${requestType} *********`);
// console.log(resObj);
// console.log('----------------------------------');
return resObj;
})
.catch((e) => {
return {
ErrorMessage: e,
FuncName: requestType,
InternalError: true
};
});
};
module.exports = expObj;
controller.js
//Tests response from API for different cards
Controller.testCard = (cardNum) => {
const expMonth = new Date().getMonth() + 1;
const expYear = new Date().getFullYear() + 2;
const cardObj = {
cardNum: cardNum,
expMonth: expMonth,
expYear: expYear
};
let apiCardItem = '';
return testRequestToApi('getStripeToken', 200, 299, cardObj)
.then((cardItem) => {
return testRequestToApi('postNewCard', 200, 299, JSON.parse(cardItem.body));
})
.then((apiCard) => {
apiCardItem = apiCard.body;
try {
apiCardItem = JSON.parse(apiCardItem);
} catch(e) {
console.log('Already a JSON object -----> Moving on');
}
return testRequestToApi('sampleAddToCart', 200, 299);
})
.then(() => testRequestToApi('useFailingStripeCards', 400, 499, apiCardItem.id))
.then(() => testRequestToApi('deleteCard', 200, 299, apiCardItem.id));
};
//Loops through the card numbers and runs the test command against them
Controller.testAllCards = (cardsArray) => {
return Promise.all(cardsArray.map((cardNum) => {
return Controller.testCard(cardNum);
}));
};
module.exports = Controller;
I rewrote your "testCard" function (controller.js)
//Tests response from API for different cards
const testCard = (cardNum) => {
return new Promise((resolve, reject) => {
let apiCardItem = '';
const expDate = new Date();
const cardObj = {
cardNum: cardNum,
expMonth: expDate.getMonth() + 1,
expYear: expDate.getFullYear() + 2
};
testRequestToApi('getStripeToken', 200, 299, cardObj)
.then((cardItem) => testRequestToApi('postNewCard', 200, 299, JSON.parse(cardItem.body)))
.then((apiCard) => {
apiCardItem = apiCard.body;
try {
apiCardItem = JSON.parse(apiCardItem);
} catch(e) {
console.log(e);
}
return testRequestToApi('sampleAddToCart', 200, 299);
})
.then(() => testRequestToApi('useFailingStripeCards', 400, 499, apiCardItem.id))
.then(() => testRequestToApi('deleteCard', 200, 299, apiCardItem.id))
.then(resolve)
.catch(reject);
});
};
And your "testRequestToApi" (test-request-to-api.js)
expObj.testRequestToApi = (requestType, lowerLimit, upperLimit, item) => {
return new Promise((resolve, reject) => {
const reqOps = formHeaders[requestType](item);
request(reqOps, (err, response, body) => {
let badStatus = {};
let badRequest = {};
let resObj = {};
if (err) {
badRequest = {
ErrorMessage: err,
FuncName: requestType,
InternalError: true
};
reject(badRequest);
return false;
}
if (!checkStatus.checkRangeStatusCode(response.statusCode, lowerLimit, upperLimit)) {
console.log(JSON.stringify(body, null, 2));
// Set a bad Status error object
badStatus = {
StatusCode: response.statusCode,
ErrorMessage: body,
FuncName: requestType,
InternalError: false
};
reject(badStatus);
return false;
}
resObj = {
headers: response.headers,
body: body
};
resolve(resObj);
});
});
};
I think the problem is when you return from a promise before a resolve/reject is getting called.
Also check that in nested promises you can pass resolve/reject to .then/catch for brevity.

Resources