A complete MonCash checkout flow in Node.js: create, redirect, verify
poze 4 months ago226 gadeen
0
I've read the MonCash docs, but I'm confused about how the pieces connect. Can someone show the whole flow end to end: creating the payment, sending the customer to MonCash, and confirming the payment afterwards?
Anviwònman:Node.js 20Express
Dyagnostik IA
Se IA ki fè l. Se pa yon repons — kominote a anba a konfime oswa korije l. Toujou verifye anvan ou fye l.
poze 4 months ago
Marie Louis 2.2k
1 Repons
3
✓✓ Repons yo aksepte
Three server-side steps, with the customer's browser in the middle:
[your server] CreatePayment ──► payment token
[browser] redirect to MonCash page ──► customer enters phone + PIN on MonCash
[MonCash] redirects to your return URL (?transactionId=…)
[your server] RetrieveTransactionPayment ──► verify amount + status ──► fulfil
// 1. Create the payment (server)
app.post("/checkout/:orderId", async (req, res) => {
const order = await db.order.findUniqueOrThrow({ where: { id: req.params.orderId } });
const token = await moncashToken(); // cached token, see the token-expiry question
const r = await fetch(MONCASH.api + "/v1/CreatePayment", {
method: "POST",
headers: { Authorization: "Bearer " + token, "Content-Type": "application/json" },
body: JSON.stringify({ amount: order.totalHtg, orderId: order.id }),
});
if (!r.ok) return res.status(502).send("MonCash unavailable, please retry");
const { payment_token } = await r.json();
// 2. Send the customer to MonCash
res.redirect(MONCASH.gateway + "/Payment/Redirect?token=" + encodeURIComponent(payment_token.token));
});
// 3. Return URL, configured in the MonCash merchant portal
app.get("/moncash/return", async (req, res) => {
const transactionId = String(req.query.transactionId ?? "");
const token = await moncashToken();
const r = await fetch(MONCASH.api + "/v1/RetrieveTransactionPayment", {
method: "POST",
headers: { Authorization: "Bearer " + token, "Content-Type": "application/json" },
body: JSON.stringify({ transactionId }),
});
const { payment } = await r.json();
const order = await db.order.findUnique({ where: { id: payment?.reference } });
const paid = payment?.message === "successful" && order && Number(payment.cost) === order.totalHtg;
if (!paid) return res.redirect("/orders/payment-failed");
await markPaidOnce(order.id, payment.transaction_id); // idempotent
res.redirect("/orders/" + order.id + "/thank-you");
});
The rules that matter:
- Never trust the return URL alone. Anyone can type
?transactionId=into a browser. Always re-fetch the payment from the API. - Compare the amount with your order. Don't just check that "a payment" exists.
referenceis theorderIdyou sent. Use it to find the order.- Make fulfilment idempotent: a refresh of the return page must not ship twice.
Konekte pou di lòt moun si li te mache.
answered 4 months ago
David Charles 2.9k
Sign in and verify your email to post an answer.