Gérer les commandes et intégrer Stripe pour le paiement
Créez les commandes et connectez Stripe pour des paiements sécurisés et automatisés.
Préparer la gestion des commandes et Stripe
Avant d’intégrer le paiement, assure-toi d’avoir :
- Un panier fonctionnel avec React Context (voir [Le panier d’achat dynamique]).
- Les routes Strapi pour commandes et ligne-de-commandes prêtes (voir module précédent).
- Installé le SDK Stripe :
Terminal1npm install stripe
- Configuré tes variables d’environnement dans
.env:1STRIPE_SECRET_KEY=sk_test_xxx2STRIPE_WEBHOOK_SECRET=whsec_xxx
1. Initialiser Stripe côté serveur
Crée un utilitaire pour réutiliser le client Stripe dans tes actions Loader/Action.
1import Stripe from "stripe";23export const stripe = new Stripe(4process.env.STRIPE_SECRET_KEY!, // ^? clé secrète stockée en env5{ apiVersion: "2022-11-15" }6);
2. Créer la session de paiement
Dans Remix, on va exposer une route d’API pour générer la session Stripe.
Cette action :
- Lit le panier et l’email depuis le
request.json(). - Crée d’abord la commande + lignes dans Strapi (
createOrder). - Prépare les
line_itemspour Stripe. - Crée la session et redirige vers
session.url.
1import type { ActionFunction } from "@remix-run/node";2import { redirect } from "@remix-run/node";3import { stripe } from "~/utils/stripe.server";4import { createOrder } from "~/models/order.server";56export const action: ActionFunction = async ({ request }) => {7const { products, email } = await request.json();89// 1. Création de la commande dans Strapi10const { id: orderId } = await createOrder({ products, email });1112// 2. Construction des line_items Stripe13const line_items = products.map((p) => ({14price_data: {15currency: "usd",16unit_amount: p.price * 100,17product_data: { name: p.name },18},19quantity: p.quantity,20}));2122// 3. Création de la session Stripe23const session = await stripe.checkout.sessions.create({24payment_method_types: ["card"],25line_items,26mode: "payment",27success_url: `${request.headers.get("origin")}/order/${orderId}` +28"?session_id={CHECKOUT_SESSION_ID}",29cancel_url: `${request.headers.get("origin")}/cart`,30metadata: { orderId: String(orderId) }, // pour le webhook31});3233return redirect(session.url!, 303);34};
Tip
On stocke orderId dans metadata pour relier la session Stripe
à la commande Strapi lors du webhook.
3. Gérer le webhook Stripe
Stripe doit informer ton backend quand le paiement est complété.
Tu crées une route api/webhooks/stripe en loader (GET non utilisé).
1import { json } from "@remix-run/node";2import { stripe } from "~/utils/stripe.server";3import { updateOrderStatus } from "~/models/order.server";45export const loader = async ({ request }) => {6const payload = await request.text();7const sig = request.headers.get("stripe-signature")!;89let event: Stripe.Event;10try {11event = stripe.webhooks.constructEvent(12payload,13sig,14process.env.STRIPE_WEBHOOK_SECRET!15);16} catch {17return json({ error: "Invalid signature" }, { status: 400 });18}1920if (event.type === "checkout.session.completed") {21const session = event.data.object as Stripe.Checkout.Session;22const orderId = session.metadata?.orderId!;23await updateOrderStatus(orderId, "paid");24}2526return json({ received: true });27};
Sécurité du webhook
N’expose jamais ta clé STRIPE_WEBHOOK_SECRET. Remix
la lit depuis process.env.
4. Afficher la confirmation de commande
Après paiement, l’utilisateur est redirigé sur /order/:orderId.
On récupère la commande Strapi (avec ses lignes et utilisateur).
1import { LoaderFunction, useLoaderData } from "@remix-run/node";2import { getOrderById } from "~/models/order.server";34export const loader: LoaderFunction = async ({ params }) => {5const order = await getOrderById({ id: params.orderId! });6return { order };7};89export default function OrderDetail() {10const { order } = useLoaderData<typeof loader>();11return (12<main>13<h2>Merci pour ta commande ! 🎉</h2>14<p>Statut : {order.orderStatus}</p>15<ul>16{order.lines.map((line) => (17<li key={line.produit.id}>18{line.quantity}× {line.produit.name} – ${(line.price / 100).toFixed(2)}19</li>20))}21</ul>22<p>Total : ${(order.totalPrice / 100).toFixed(2)}</p>23</main>24);25}
Tip
Pense à formater les montants en cents pour Stripe (multiplicateur × 100).
5. Points clés
- Crée d’abord ta commande et tes lignes dans Strapi avant de lancer Stripe Checkout.
- Passe
metadata.orderIdà Stripe pour lier le paiement à la commande. - Utilise un webhook pour mettre à jour le statut de la commande
(
paid,cancelled, etc.). - Réserve les clés Stripe dans les variables d’environnement et ne les expose jamais au client.
- La redirection success/cancel s’effectue côté Action Remix.
Exercices
- Configure un projet Remix pour ajouter la variable
STRIPE_SECRET_KEYet teste questripese connecte sans erreur. - Implémente la route
/api/create-checkout-sessionet vérifie qu’elle renvoie bien une URL Stripe valide. - Écris un test manuel du webhook : simule l’événement
checkout.session.completedavecstripe-cliet vérifie que Strapi met à jour le statut de ta commande.