I have website on React
and trying to intergrate the payment engine. The payment engine page is added using iframe
, so I can not add onClick
event to handle the "Pay" button click when a user pay for the product and then use axios to handle it. For example, when I use axios
or fetch
in my frontend, it fires before the user submits the payment form.
Instead, the payment engine sends a post request to a serviceUrl
which I provided whenever a user submits their form.
So, I got the post request from them:
app.post("/api/payment-status", (req, res) => {
console.log("Payment status received");
const {transactionStatus, reason, reasonCode} = JSON.parse(Object.keys(req.body)[0]);
console.log("transactionStatus: ", transactionStatus, "reason: ", reason, "reasonCode: ", reasonCode);
let paymentData = {};
if (transactionStatus === webConfig.wfpTransactionStatus && reason === webConfig.wfpReason && reasonCode === Number(webConfig.wfpReasonCode)) {
console.log("Success!!!");
paymentData = {
isSuccess: true,
wfpStatus: transactionStatus,
wfpReason: reason,
msg: "Success.",
wfpReasonCode: reasonCode
};
} else {
console.log("Failed!!!!");
paymentData = {
isSuccess: false,
wfpStatus: transactionStatus,
wfpReason: reason,
msg: `Failed: ${reasonCode}!`,
wfpReasonCode: reasonCode
};
}
res.status(200).send("Payment status received.");
});
I must send paymentData
object to frontend.
So, I deciced to use the socket.io
to transfer data from backend to a client.
Backend code:
const socketIO = require("socket.io");
const io = socketIO(server, {
cors: {
origin: "https://www.my-domain.com",
methods: ["GET", "POST"]
}
});
io.on("connection", (socket) => {
console.log("A client connected: ", socket.id);
socket.on("paymentClientID", (offerID) => {
console.log("Client ID on backend: ", offerID);
});
socket.on("disconnect", () => {
console.log("A client disconnected: ", socket.id);
socket.close();
socket.disconnect();
});
});
app.post("/api/payment-status", (req, res) => {
console.log("Payment status received");
const {transactionStatus, reason, reasonCode, orderReference} = JSON.parse(Object.keys(req.body)[0]);
console.log("transactionStatus: ", transactionStatus, "reason: ", reason, "reasonCode: ", reasonCode, "orderReference: ", orderReference);
let paymentData = {};
if (transactionStatus === webConfig.wfpTransactionStatus && reason === webConfig.wfpReason && reasonCode === Number(webConfig.wfpReasonCode) && orderReference) {
console.log("Success!!!");
paymentData = {
isSuccess: true,
wfpOrderReference: orderReference,
wfpStatus: transactionStatus,
wfpReason: reason,
msg: "Success.",
wfpReasonCode: reasonCode
};
} else {
console.log("Failed!!!!");
paymentData = {
isSuccess: false,
wfpOrderReference: orderReference,
wfpStatus: transactionStatus,
wfpReason: reason,
msg: `Failed: ${reasonCode}!`,
wfpReasonCode: reasonCode
};
}
io.emit("paymentStatus", paymentData);
res.status(200).send("Статус платежу отримано");
});
Frontend code:
import io from "socket.io-client";
const socket = io("https://www.my-domain.com");
useEffect(() => {
const wfpPaymentStatusSocket = () => {
socket.emit("paymentClientID", offerID);
socket.on("paymentStatus", (data) => {
console.log("Data: ", data);
alert(data);
socket.emit("disconnect");
console.log("Disconnecting....");
});
};
wfpPaymentStatusSocket();
}, [socket]);
From server logs, I see only:
A client connected: NUDCr7GnZclJuNYBAAAi
Client ID on backend: 16132880
A client connected: ex9Kg5g-Bejn6oncAAAk
Client ID on backend: 16132880
For some reason it does not receive the following data:
socket.on("paymentStatus", (data) => {
console.log("Data: ", data);
alert(data);
socket.emit("disconnect");
console.log("Disconnecting....");
});
Any ideas why it does not receive paymentStatus data on a client (frontend)?
So, I fixed this issue by adding:
app.emit("paymentStatusReceived", paymentData);
app.post("/api/payment-status", (req, res) => {
console.log("Payment status received");
const {transactionStatus, reason, reasonCode, orderReference} = JSON.parse(Object.keys(req.body)[0]);
console.log("transactionStatus: ", transactionStatus, "reason: ", reason, "reasonCode: ", reasonCode, "orderReference: ", orderReference);
let paymentData = {};
if (transactionStatus === webConfig.wfpTransactionStatus && reason === webConfig.wfpReason && reasonCode === Number(webConfig.wfpReasonCode) && orderReference) {
console.log("Success!!!");
paymentData = {
isSuccess: true,
wfpOrderReference: orderReference,
wfpStatus: transactionStatus,
wfpReason: reason,
msg: "Success.",
wfpReasonCode: reasonCode
};
} else {
console.log("Failed!!!!");
paymentData = {
isSuccess: false,
wfpOrderReference: orderReference,
wfpStatus: transactionStatus,
wfpReason: reason,
msg: `Failed: ${reasonCode}!`,
wfpReasonCode: reasonCode
};
}
app.emit("paymentStatusReceived", paymentData);
res.status(200).send("Статус платежу отримано");
});
This will trigger the event to indicate that payment status is received.
Then I created the route to handle the Axios
request from the frontend using GET
method.
app.get("/api/get-payment-data", (req, res) => {
// Listen for the paymentStatusReceived event
app.once("paymentStatusReceived", (paymentData) => {
// Send the payment data to the frontend
res.json(paymentData);
});
});
Now, it displays the "pending" status for the Axios
GET
request from React
and waits until the callback is received from the payment engine. After I get the callback it sends the paymentData
to the frontend (React
). The issue is resolved.