Guide
Node.js (Express) guide for exposing a safe backend route that runs the YKNPG flow.
Node.js (Express) guide for exposing a safe backend route that runs the YKNPG flow.
Prerequisites
- Node.js 18+, npm.
.envwithYKNPG_API_TOKEN.
- Init project
mkdir -p demo-node && cd demo-nodenpm init -ynpm install express axios dotenv
- Add environment file
- File:
.env
YKNPG_API_TOKEN=replace-with-your-token
YKNPG_BASE_URL=https://yknpg.ngoul.com/api/v1
PORT=3000
- Create server
- File:
server.js
import express from "express";
import dotenv from "dotenv";
import axios from "axios";
dotenv.config();
const { YKNPG_API_TOKEN, YKNPG_BASE_URL = "https://yknpg.ngoul.com/api/v1", PORT = 3000 } =
process.env;
if (!YKNPG_API_TOKEN) throw new Error("Set YKNPG_API_TOKEN in .env");
const client = axios.create({
baseURL: YKNPG_BASE_URL,
headers: { Authorization: `Bearer ${YKNPG_API_TOKEN}` },
timeout: 10000,
});
const app = express();
app.use(express.json());
app.post("/pay", async (req, res) => {
try {
const { amount, phone } = req.body;
const payload = {
amount,
provider: "ORANGE_MONEY",
user_infos: { number: phone },
callback_url: "http://example.com",
callback_method: "POST",
your_message: "pay this",
your_order_ref: "demo-1",
provider_fees_on_customer: true,
};
const { data: created } = await client.post("/transactions/", payload);
const { data: paid } = await client.post(`/transactions/${created.uuid}/pay/`);
let status = paid.status;
while (status === "new" || status === "paying") {
await new Promise((r) => setTimeout(r, 5000));
const { data } = await client.get(`/transactions/${created.uuid}/`);
status = data.status;
}
res.json({
instructions: created.instructions,
post_pay_instructions: paid.instructions,
final_status: status,
});
} catch (err) {
console.error(err.response?.data || err.message);
res.status(500).json({ error: err.response?.data || err.message });
}
});
app.listen(PORT, () => {
console.log(`Server listening on http://localhost:${PORT}`);
});
- Run
node server.js- POST to
http://localhost:3000/paywith JSON{"phone": "...", "amount": 1000}.
Notes
- This backend keeps the token private and can be consumed by any web/mobile client.