Documentation Index
Fetch the complete documentation index at: https://docs.oneclickdz.com/llms.txt
Use this file to discover all available pages before exploring further.
Vue d’ensemble
Le flux de paiement est simple :- Le client crée une commande → Sauvegardez comme
PENDING - Créez un lien de paiement → Obtenez
paymentRef - Sauvegardez
paymentRefavec la commande (important !) - Redirigez le client vers la page de paiement
- Le client paie et revient
- Vérifiez le statut du paiement et mettez à jour la commande
Implémentation complète
Étape 1 : Création de la commande
Lorsqu’un client passe une commande, sauvegardez-la avec le statutPENDING :
async function createOrder(customerData, items, total) {
// Générer un ID de commande unique
const orderId = generateUniqueId(); // ex. "ORD-2025-001234"
// Sauvegarder la commande en base de données
const order = await db.orders.create({
id: orderId,
customerId: customerData.id,
items: items,
totalAmount: total,
status: "PENDING", // Important : commencer par PENDING
paymentRef: null, // Sera défini après la création du lien de paiement
createdAt: new Date(),
updatedAt: new Date(),
});
return order;
}
Critique : Chaque commande doit avoir un ID unique et doit commencer avec le statut
PENDINGÉtape 2 : Créer un lien de paiement
const express = require("express");
const fetch = require("node-fetch");
const app = express();
app.use(express.json());
// 1. Créer la commande et rediriger vers le paiement
app.post("/checkout", async (req, res) => {
const { items, total, customerId } = req.body;
try {
// Créer la commande en base de données
const orderId = generateOrderId();
await db.orders.create({
id: orderId,
customerId: customerId,
items: items,
total: total,
status: "PENDING",
});
// Créer le lien de paiement
const response = await fetch(
"https://api.oneclickdz.com/v3/ocpay/createLink",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Access-Token": process.env.ONECLICK_API_KEY,
},
body: JSON.stringify({
productInfo: {
title: `Order ${orderId}`,
amount: total,
},
redirectUrl: `https://yoursite.com/orders/${orderId}`,
}),
}
);
const data = await response.json();
// IMPORTANT : Sauvegarder paymentRef avec la commande
await db.orders.update(orderId, {
paymentRef: data.data.paymentRef,
});
// Rediriger vers la page de paiement
res.redirect(data.data.paymentUrl);
} catch (error) {
console.error("Checkout error:", error);
res.status(500).json({ error: "Checkout failed" });
}
});
// 2. Page de statut de commande
app.get("/orders/:orderId", async (req, res) => {
const { orderId } = req.params;
try {
const order = await db.orders.findOne({ id: orderId });
if (!order) {
return res.status(404).send("Order not found");
}
// Check payment if still pending
if (order.status === "PENDING" && order.paymentRef) {
const statusResponse = await fetch(
`https://api.oneclickdz.com/v3/ocpay/checkPayment/${order.paymentRef}`,
{
headers: { "X-Access-Token": process.env.ONECLICK_API_KEY },
}
);
const statusData = await statusResponse.json();
if (statusData.data.status === "CONFIRMED") {
await db.orders.update(orderId, { status: "PAID" });
order.status = "PAID";
} else if (statusData.data.status === "FAILED") {
await db.orders.update(orderId, { status: "FAILED" });
order.status = "FAILED";
}
}
res.render("order-status", { order });
} catch (error) {
console.error("Error:", error);
res.status(500).send("Error loading order");
}
});
// 3. Endpoint de vérification manuelle du paiement
app.post("/orders/:orderId/check", async (req, res) => {
const { orderId } = req.params;
try {
const order = await db.orders.findOne({ id: orderId });
if (!order || !order.paymentRef) {
return res.status(404).json({ error: "Order not found" });
}
const response = await fetch(
`https://api.oneclickdz.com/v3/ocpay/checkPayment/${order.paymentRef}`,
{
headers: { "X-Access-Token": process.env.ONECLICK_API_KEY },
}
);
const data = await response.json();
// Mettre à jour le statut de la commande
if (data.data.status === "CONFIRMED") {
await db.orders.update(orderId, { status: "PAID" });
} else if (data.data.status === "FAILED") {
await db.orders.update(orderId, { status: "FAILED" });
}
res.json({ status: data.data.status });
} catch (error) {
console.error("Check error:", error);
res.status(500).json({ error: "Check failed" });
}
});
function generateOrderId() {
return `ORD-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
app.listen(3000);
Frontend : Page de statut de commande
Page HTML simple avec bouton de vérification manuelle :<!DOCTYPE html>
<html>
<head>
<title>Statut de la commande</title>
<style>
.status-pending { color: #f59e0b; }
.status-paid { color: #10b981; }
.status-failed { color: #ef4444; }
</style>
</head>
<body>
<h1>Commande #<span id="orderId"></span></h1>
<h2>Statut : <span id="status" class="status-pending">PENDING</span></h2>
<button id="checkBtn" onclick="checkPayment()">Check Payment Status</button>
<p id="message"></p>
<script>
const orderId = window.location.pathname.split("/").pop();
document.getElementById("orderId").textContent = orderId;
async function checkPayment() {
const btn = document.getElementById("checkBtn");
const msg = document.getElementById("message");
btn.disabled = true;
msg.textContent = "Vérification...";
try {
const response = await fetch(`/orders/${orderId}/check`, {
method: "POST",
});
const data = await response.json();
const statusEl = document.getElementById("status");
statusEl.textContent = data.status;
statusEl.className = `status-${data.status.toLowerCase()}`;
if (data.status === "CONFIRMED") {
msg.textContent = "✅ Paiement confirmé ! Actualisation...";
setTimeout(() => location.reload(), 2000);
} else if (data.status === "FAILED") {
msg.textContent = "❌ Paiement échoué";
} else {
msg.textContent = "⏳ Paiement toujours en attente";
}
} catch (error) {
msg.textContent = "Erreur lors de la vérification";
} finally {
btn.disabled = false;
}
}
// Vérification automatique au chargement de la page
if (document.getElementById("status").textContent === "PENDING") {
checkPayment();
}
</script>
</body>
</html>
Schéma de base de données
Schéma simple pour les commandes :CREATE TABLE orders (
id VARCHAR(50) PRIMARY KEY,
customer_id VARCHAR(50) NOT NULL,
total INTEGER NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
payment_ref VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_payment_ref (payment_ref),
INDEX idx_status (status)
);
Points clés
Important : - Sauvegardez toujours
paymentRef avec votre commande - Vérifiez le statut du paiement au retour du client - Ne traitez les commandes qu’avec le statut CONFIRMED - Les liens de paiement expirent après 20 minutesProchaines étapes
Continuer vers le suivi du statut
Apprenez à automatiser la vérification du statut avec des tâches cron

