Next.js est le framework React le plus utilisé pour les projets web en 2026. Voici comment intégrer MonCash dans une app Next.js moderne avec l'App Router — que ce soit avec des Server Actions ou des API Routes classiques.
Architecture : ce qui va côté serveur vs client
- Côté serveur (Server Action ou API Route) : créer la session de paiement, stocker l'orderId en base
- Côté client : déclencher l'action, récupérer le paymentUrl, rediriger avec window.location.href
- Webhook handler (API Route) : recevoir la confirmation MonCash, vérifier la signature HMAC, créditer le client
Option A — Server Action Next.js (App Router)
// app/actions/payment.ts
"use server";
export async function createPayment(amount: number, orderId: string) {
const res = await fetch("https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MONCASH_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount,
orderId,
description: "Commande " + orderId,
returnUrl: process.env.NEXT_PUBLIC_URL + "/success",
cancelUrl: process.env.NEXT_PUBLIC_URL + "/cancel",
}),
});
if (!res.ok) throw new Error("Échec création paiement");
const { paymentUrl } = await res.json();
return paymentUrl;
}// Composant React qui déclenche le paiement
"use client";
import { createPayment } from "@/app/actions/payment";
export function CheckoutButton({ amount, orderId }: { amount: number; orderId: string }) {
async function handlePay() {
const paymentUrl = await createPayment(amount, orderId);
window.location.href = paymentUrl; // Redirection vers MonCash
}
return (
<button onClick={handlePay} className="btn-primary">
Payer {amount} HTG avec MonCash
</button>
);
}Option B — API Route classique
// app/api/pay/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function POST(req: NextRequest) {
const { amount, orderId } = await req.json();
const res = await fetch("https://hvlmeoqyxaguzcujpmit.supabase.co/functions/v1/pay-create", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.MONCASH_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount,
orderId,
returnUrl: `${process.env.NEXT_PUBLIC_URL}/success`,
cancelUrl: `${process.env.NEXT_PUBLIC_URL}/cancel`,
}),
});
const data = await res.json();
return NextResponse.json({ paymentUrl: data.paymentUrl });
}Recevoir le webhook de confirmation
// app/api/webhook/moncash/route.ts
import { NextRequest, NextResponse } from "next/server";
import crypto from "node:crypto";
export async function POST(req: NextRequest) {
const rawBody = await req.text();
const sig = req.headers.get("x-moncashconnect-signature") ?? "";
const expected = crypto
.createHmac("sha256", process.env.WEBHOOK_SECRET!)
.update(rawBody)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig))) {
return NextResponse.json({ error: "Signature invalide" }, { status: 401 });
}
const event = JSON.parse(rawBody);
if (event.type === "payment.completed") {
const { orderId, amount } = event.data;
// Marquer la commande comme payée en base
await db.orders.update({ where: { id: orderId }, data: { status: "paid", amount } });
}
return NextResponse.json({ received: true });
}Variables d'environnement à configurer
# .env.local
MONCASH_SECRET_KEY=sk_proj_xxxxxxxxxxxxxxxxxxxxx
WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_URL=https://votresite.comPage de succès et annulation
Créez les routes /success et /cancel dans votre app. Important : ne marquez pas la commande comme payée sur la page de succès — basez-vous uniquement sur le webhook. L'URL de retour peut être manipulée ; seul le webhook signé est fiable.
Les exemples de code complets pour Next.js et React sont disponibles dans la documentation MonCashConnect.
Consulter la documentation →