Merged in feature/IO-3056-Enhanced-Lightbox-Logging (pull request #2014)
Feature/IO-3056 Enhanced Lightbox Logging Approved-by: Patrick Fic
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||
const path = require("path");
|
||||
const queries = require("../graphql-client/queries");
|
||||
const Dinero = require("dinero.js");
|
||||
@@ -6,7 +5,6 @@ const qs = require("query-string");
|
||||
const axios = require("axios");
|
||||
const moment = require("moment");
|
||||
const logger = require("../utils/logger");
|
||||
const InstanceManager = require("../utils/instanceMgr").default;
|
||||
const { sendTaskEmail } = require("../email/sendemail");
|
||||
const generateEmailTemplate = require("../email/generateTemplate");
|
||||
const { getEndpoints } = require("../email/tasksEmails");
|
||||
@@ -53,14 +51,19 @@ const getShopCredentials = async (bodyshop) => {
|
||||
};
|
||||
|
||||
exports.lightbox_credentials = async (req, res) => {
|
||||
logger.log("intellipay-lightbox-credentials", "DEBUG", req.user?.email, null, null);
|
||||
logger.log("intellipay-lightbox-credentials", "DEBUG", req.user?.email, null, {
|
||||
iPayData: req.body.iPayData,
|
||||
bodyshop: req.body.bodyshop
|
||||
});
|
||||
|
||||
const shopCredentials = await getShopCredentials(req.body.bodyshop);
|
||||
|
||||
if (shopCredentials.error) {
|
||||
logger.log("intellipay-credentials-error", "ERROR", req.user?.email, null, { message: shopCredentials.error });
|
||||
res.json(shopCredentials);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const options = {
|
||||
method: "POST",
|
||||
@@ -74,26 +77,39 @@ exports.lightbox_credentials = async (req, res) => {
|
||||
|
||||
const response = await axios(options);
|
||||
|
||||
logger.log("intellipay-lightbox-success", "DEBUG", req.user?.email, null, {
|
||||
responseData: response.data,
|
||||
requestOptions: options
|
||||
});
|
||||
|
||||
res.send(response.data);
|
||||
} catch (error) {
|
||||
//console.log(error);
|
||||
logger.log("intellipay-lightbox-credentials-error", "ERROR", req.user?.email, null, {
|
||||
error: JSON.stringify(error)
|
||||
});
|
||||
res.json({ error });
|
||||
logger.log("intellipay-lightbox-error", "ERROR", req.user?.email, null, { message: error.message });
|
||||
res.json({ message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
exports.payment_refund = async (req, res) => {
|
||||
logger.log("intellipay-refund", "DEBUG", req.user?.email, null, null);
|
||||
logger.log("intellipay-refund-request-received", "DEBUG", req.user?.email, null, {
|
||||
bodyshop: req.body.bodyshop,
|
||||
paymentid: req.body.paymentid,
|
||||
amount: req.body.amount
|
||||
});
|
||||
|
||||
const shopCredentials = await getShopCredentials(req.body.bodyshop);
|
||||
|
||||
if (shopCredentials.error) {
|
||||
logger.log("intellipay-refund-credentials-error", "ERROR", req.user?.email, null, {
|
||||
credentialsError: shopCredentials.error
|
||||
});
|
||||
res.status(400).json({ error: shopCredentials.error });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/x-www-form-urlencoded" },
|
||||
|
||||
data: qs.stringify({
|
||||
method: "payment_refund",
|
||||
...shopCredentials,
|
||||
@@ -103,132 +119,216 @@ exports.payment_refund = async (req, res) => {
|
||||
url: `https://${domain}.cpteller.com/api/26/webapi.cfc?method=payment_refund`
|
||||
};
|
||||
|
||||
logger.log("intellipay-refund-options-prepared", "DEBUG", req.user?.email, null, {
|
||||
options
|
||||
});
|
||||
|
||||
const response = await axios(options);
|
||||
|
||||
logger.log("intellipay-refund-success", "DEBUG", req.user?.email, null, {
|
||||
responseData: response.data
|
||||
});
|
||||
|
||||
res.send(response.data);
|
||||
} catch (error) {
|
||||
//console.log(error);
|
||||
logger.log("intellipay-refund-error", "ERROR", req.user?.email, null, {
|
||||
error: JSON.stringify(error)
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
requestOptions: {
|
||||
paymentid: req.body.paymentid,
|
||||
amount: req.body.amount
|
||||
}
|
||||
});
|
||||
res.json({ error });
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
exports.generate_payment_url = async (req, res) => {
|
||||
logger.log("intellipay-payment-url", "DEBUG", req.user?.email, null, null);
|
||||
logger.log("intellipay-generate-payment-url-received", "DEBUG", req.user?.email, null, {
|
||||
bodyshop: req.body.bodyshop,
|
||||
amount: req.body.amount,
|
||||
account: req.body.account,
|
||||
comment: req.body.comment,
|
||||
invoice: req.body.invoice
|
||||
});
|
||||
|
||||
const shopCredentials = await getShopCredentials(req.body.bodyshop);
|
||||
|
||||
if (shopCredentials.error) {
|
||||
logger.log("intellipay-generate-payment-url-credentials-error", "ERROR", req.user?.email, null, {
|
||||
credentialsError: shopCredentials.error
|
||||
});
|
||||
res.status(400).json({ error: shopCredentials.error });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/x-www-form-urlencoded" },
|
||||
//TODO: Move these to environment variables/database.
|
||||
data: qs.stringify({
|
||||
...shopCredentials,
|
||||
//...req.body,
|
||||
amount: Dinero({ amount: Math.round(req.body.amount * 100) }).toFormat("0.00"),
|
||||
account: req.body.account,
|
||||
comment: req.body.comment,
|
||||
invoice: req.body.invoice,
|
||||
createshorturl: true
|
||||
//The postback URL is set at the CP teller global terminal settings page.
|
||||
}),
|
||||
url: `https://${domain}.cpteller.com/api/custapi.cfc?method=generate_lightbox_url`
|
||||
};
|
||||
|
||||
logger.log("intellipay-generate-payment-url-options-prepared", "DEBUG", req.user?.email, null, {
|
||||
options
|
||||
});
|
||||
|
||||
const response = await axios(options);
|
||||
|
||||
logger.log("intellipay-generate-payment-url-success", "DEBUG", req.user?.email, null, {
|
||||
responseData: response.data
|
||||
});
|
||||
|
||||
res.send(response.data);
|
||||
} catch (error) {
|
||||
//console.log(error);
|
||||
logger.log("intellipay-payment-url-error", "ERROR", req.user?.email, null, {
|
||||
error: JSON.stringify(error)
|
||||
logger.log("intellipay-generate-payment-url-error", "ERROR", req.user?.email, null, {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
requestOptions: {
|
||||
amount: req.body.amount,
|
||||
account: req.body.account,
|
||||
comment: req.body.comment,
|
||||
invoice: req.body.invoice
|
||||
}
|
||||
});
|
||||
res.json({ error });
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
//Reference: https://intellipay.com/dist/webapi26.html#operation/fee
|
||||
exports.checkfee = async (req, res) => {
|
||||
// Requires amount, bodyshop.imexshopid, and state? to get data.
|
||||
logger.log("intellipay-fee-check", "DEBUG", req.user?.email, null, null);
|
||||
logger.log("intellipay-checkfee-request-received", "DEBUG", req.user?.email, null, {
|
||||
bodyshop: req.body.bodyshop,
|
||||
amount: req.body.amount
|
||||
});
|
||||
|
||||
//If there's no amount, there can't be a fee. Skip the call.
|
||||
if (!req.body.amount || req.body.amount <= 0) {
|
||||
logger.log("intellipay-checkfee-skip", "DEBUG", req.user?.email, null, {
|
||||
message: "Amount is zero or undefined, skipping fee check."
|
||||
});
|
||||
res.json({ fee: 0 });
|
||||
return;
|
||||
}
|
||||
|
||||
const shopCredentials = await getShopCredentials(req.body.bodyshop);
|
||||
|
||||
if (shopCredentials.error) {
|
||||
logger.log("intellipay-checkfee-credentials-error", "ERROR", req.user?.email, null, {
|
||||
credentialsError: shopCredentials.error
|
||||
});
|
||||
res.status(400).json({ error: shopCredentials.error });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/x-www-form-urlencoded" },
|
||||
//TODO: Move these to environment variables/database.
|
||||
data: qs.stringify(
|
||||
{
|
||||
method: "fee",
|
||||
...shopCredentials,
|
||||
amount: req.body.amount,
|
||||
paymenttype: `CC`,
|
||||
cardnum: "4111111111111111", //Not needed per documentation, but incorrect values come back without it.
|
||||
cardnum: "4111111111111111", // Required for compatibility with API
|
||||
state:
|
||||
req.body.bodyshop?.state && req.body.bodyshop.state?.length === 2
|
||||
req.body.bodyshop?.state && req.body.bodyshop.state.length === 2
|
||||
? req.body.bodyshop.state.toUpperCase()
|
||||
: "ZZ" //Same as above
|
||||
: "ZZ"
|
||||
},
|
||||
{ sort: false } //ColdFusion Query Strings depend on order. This preserves it.
|
||||
{ sort: false } // Ensure query string order is preserved
|
||||
),
|
||||
url: `https://${domain}.cpteller.com/api/26/webapi.cfc`
|
||||
};
|
||||
|
||||
logger.log("intellipay-checkfee-options-prepared", "DEBUG", req.user?.email, null, {
|
||||
options
|
||||
});
|
||||
|
||||
const response = await axios(options);
|
||||
|
||||
if (response.data?.error) {
|
||||
logger.log("intellipay-checkfee-api-error", "ERROR", req.user?.email, null, {
|
||||
apiError: response.data.error
|
||||
});
|
||||
res.status(400).json({ error: response.data.error });
|
||||
} else if (response.data < 0) {
|
||||
logger.log("intellipay-checkfee-negative-fee", "ERROR", req.user?.email, "Fee amount returned is negative.");
|
||||
res.json({ error: "Fee amount negative. Check API credentials & account configuration." });
|
||||
} else {
|
||||
logger.log("intellipay-checkfee-success", "DEBUG", req.user?.email, null, {
|
||||
fee: response.data
|
||||
});
|
||||
res.json({ fee: response.data });
|
||||
}
|
||||
} catch (error) {
|
||||
//console.log(error);
|
||||
logger.log("intellipay-fee-check-error", "ERROR", req.user?.email, null, {
|
||||
error: error.message
|
||||
logger.log("intellipay-checkfee-error", "ERROR", req.user?.email, null, {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
amount: req.body.amount
|
||||
});
|
||||
res.status(400).json({ error });
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
exports.postback = async (req, res) => {
|
||||
try {
|
||||
logger.log("intellipay-postback", "DEBUG", req.user?.email, null, req.body);
|
||||
const { body: values } = req;
|
||||
|
||||
const comment = Buffer.from(values?.comment, "base64").toString();
|
||||
logger.log("intellipay-postback-received", "DEBUG", req.user?.email, null, {
|
||||
iprequest: values,
|
||||
base64Comment: values?.comment || null
|
||||
});
|
||||
|
||||
if ((!values.invoice || values.invoice === "") && !comment) {
|
||||
// Decode the base64 comment, if it exists
|
||||
const decodedComment = values?.comment ? Buffer.from(values.comment, "base64").toString() : null;
|
||||
|
||||
logger.log("intellipay-postback-decoded-comment", "DEBUG", req.user?.email, null, {
|
||||
decodedComment
|
||||
});
|
||||
|
||||
if ((!values.invoice || values.invoice === "") && !decodedComment) {
|
||||
//invoice is specified through the pay link. Comment by IO.
|
||||
logger.log("intellipay-postback-ignored", "DEBUG", req.user?.email, null, req.body);
|
||||
logger.log("intellipay-postback-ignored", "DEBUG", req.user?.email, null, {
|
||||
reason: "No invoice or comment provided",
|
||||
iprequest: values
|
||||
});
|
||||
res.sendStatus(200);
|
||||
return;
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
if (decodedComment) {
|
||||
//Shifted the order to have this first to retain backwards compatibility for the old style of short link.
|
||||
//This has been triggered by IO and may have multiple jobs.
|
||||
const parsedComment = JSON.parse(comment);
|
||||
const parsedComment = JSON.parse(decodedComment);
|
||||
|
||||
logger.log("intellipay-postback-parsed-comment", "DEBUG", req.user?.email, null, {
|
||||
parsedComment
|
||||
});
|
||||
|
||||
//Adding in the user email to the short pay email.
|
||||
//Need to check this to ensure backwards compatibility for clients that don't update.
|
||||
|
||||
const partialPayments = Array.isArray(parsedComment) ? parsedComment : parsedComment.payments;
|
||||
|
||||
// Fetch jobs by job IDs
|
||||
const jobs = await gqlClient.request(queries.GET_JOBS_BY_PKS, {
|
||||
ids: partialPayments.map((p) => p.jobid)
|
||||
});
|
||||
|
||||
logger.log("intellipay-postback-jobs-fetched", "DEBUG", req.user?.email, null, {
|
||||
jobs
|
||||
});
|
||||
|
||||
// Insert new payments
|
||||
const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, {
|
||||
paymentInput: partialPayments.map((p) => ({
|
||||
amount: p.amount,
|
||||
@@ -250,13 +350,12 @@ exports.postback = async (req, res) => {
|
||||
}
|
||||
}))
|
||||
});
|
||||
logger.log("intellipay-postback-app-success", "DEBUG", req.user?.email, JSON.stringify(jobs), {
|
||||
iprequest: values,
|
||||
|
||||
logger.log("intellipay-postback-payment-success", "DEBUG", req.user?.email, null, {
|
||||
paymentResult
|
||||
});
|
||||
|
||||
if (values.origin === "OneLink" && parsedComment.userEmail) {
|
||||
//Send an email, it was a text to pay link.
|
||||
try {
|
||||
const endPoints = getEndpoints();
|
||||
sendTaskEmail({
|
||||
@@ -275,20 +374,23 @@ exports.postback = async (req, res) => {
|
||||
})
|
||||
});
|
||||
} catch (error) {
|
||||
logger.log("intellipay-postback-app-email-error", "DEBUG", req.user?.email, JSON.stringify(jobs), {
|
||||
iprequest: values,
|
||||
paymentResult,
|
||||
error: error.message
|
||||
logger.log("intellipay-postback-email-error", "ERROR", req.user?.email, null, {
|
||||
error: error.message,
|
||||
jobs,
|
||||
paymentResult
|
||||
});
|
||||
}
|
||||
}
|
||||
res.sendStatus(200);
|
||||
} else if (values.invoice) {
|
||||
//This is a link email that's been sent out.
|
||||
const job = await gqlClient.request(queries.GET_JOB_BY_PK, {
|
||||
id: values.invoice
|
||||
});
|
||||
|
||||
logger.log("intellipay-postback-invoice-job-fetched", "DEBUG", req.user?.email, null, {
|
||||
job
|
||||
});
|
||||
|
||||
const paymentResult = await gqlClient.request(queries.INSERT_NEW_PAYMENT, {
|
||||
paymentInput: {
|
||||
amount: values.total,
|
||||
@@ -300,6 +402,10 @@ exports.postback = async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
logger.log("intellipay-postback-invoice-payment-success", "DEBUG", req.user?.email, null, {
|
||||
paymentResult
|
||||
});
|
||||
|
||||
const responseResults = await gqlClient.request(queries.INSERT_PAYMENT_RESPONSE, {
|
||||
paymentResponse: {
|
||||
amount: values.total,
|
||||
@@ -313,18 +419,17 @@ exports.postback = async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
logger.log("intellipay-postback-link-success", "DEBUG", req.user?.email, values.invoice, {
|
||||
iprequest: values,
|
||||
responseResults,
|
||||
paymentResult
|
||||
logger.log("intellipay-postback-invoice-response-success", "DEBUG", req.user?.email, null, {
|
||||
responseResults
|
||||
});
|
||||
res.sendStatus(200);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("intellipay-postback-total-error", "ERROR", req.user?.email, null, {
|
||||
error: JSON.stringify(error),
|
||||
body: req.body
|
||||
logger.log("intellipay-postback-error", "ERROR", req.user?.email, null, {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
iprequest: req.body
|
||||
});
|
||||
res.status(400).json({ succesful: false, error: error.message });
|
||||
res.status(400).json({ successful: false, error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user