Paiements Stripe : connecte, sync et gère tes produits
Crée ton compte Stripe, configure clés, SDK serveur, et synchronise produits Prisma en un clic dans React Router. Maîtrise paiements et tarifs sans stress.
Crée un compte Stripe dans sa propre organisation
- Connecte-toi sur
https://dashboard.stripe.com. Settings → Accounts → Create a new account.- Renseigne : • Nom : Shop Router • Pays : France • Business type : Services numériques
- Décoche Tax collection pour éviter des frais superflus.
Stripe génère immédiatement un tableau de bord test et live.
Ajoute les clés API à .env
1# mode test - ne jamais pousser en prod2STRIPE_PUBLISHABLE_KEY=pk_test_xxx3STRIPE_SECRET_KEY=sk_test_xxx
Gardes-les hors Git : .env figure déjà dans .gitignore.
Installe et configure le SDK côté serveur
1npm add stripe
1import Stripe from "stripe";23export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {4apiVersion: "2023-10-16",5});
Pourquoi ? – instance unique ; – version figée ➜ pas de breaking change surprise.
Synchronise un produit Prisma → Stripe
1import { prisma } from "~/server/db.server";2import { stripe } from "./stripe.server";34export async function syncProductWithStripe(productId: string) {5const product = await prisma.product.findUnique({6where: { id: productId },7include: { images: { take: 1 } },8});9if (!product) throw new Error("Product not found");1011/* 1 - Produit Stripe */12const stripeProduct =13product.stripeProductId14? await stripe.products.retrieve(product.stripeProductId)15: await stripe.products.create({16name: product.name,17description: product.description ?? "",18images: product.images.map((i) => i.url),19active: product.isActive,20});2122/* 2 - Prix Stripe */23await syncStripePrice({ product, stripeProductId: stripeProduct.id });2425/* 3 - Sauvegarde en DB */26await prisma.product.update({27where: { id: product.id },28data: { stripeProductId: stripeProduct.id },29});30}3132async function syncStripePrice({33product,34stripeProductId,35}: {36product: { priceCents: number; stripePriceId?: string };37stripeProductId: string;38}) {39const amount = product.priceCents;4041/* Stripe interdit la modif direct d'un prix */42if (product.stripePriceId) {43await stripe.prices.update(product.stripePriceId, { active: false });44}4546const price = await stripe.prices.create({47product: stripeProductId,48unit_amount: amount,49currency: "eur",50});5152await prisma.product.update({53where: { stripeProductId },54data: { stripePriceId: price.id },55});56}
Explications brèves :
- Si l’ID Stripe existe :
retrieve, sinoncreate. - Un changment de montant ➜ ancien prix archivé, nouveau créé.
- On stocke les IDs Stripe dans Prisma (
stripeProductId,stripePriceId).
Ajoute le bouton “Synchroniser Stripe” dans l’admin
1import { syncProductWithStripe } from "~/server/stripe-products.server";23export const action = async ({ params }: Route.ActionArgs) => {4await syncProductWithStripe(params.productSlug);5return redirect(`/admin/products/${params.productSlug}`);6};
1<fetcher.Form method="POST">2<Button3name="intent"4value="sync-stripe"5isLoading={fetcher.state === "submitting"}6>7Synchroniser Stripe8</Button>9</fetcher.Form>
Le spinner affiche fetcher.state === "submitting" ; l’UI reste sur place.
Synchronisation en masse depuis la liste
1export async function action() {2const ids = await prisma.product.findMany({ select: { id: true } });3for (const { id } of ids) await syncProductWithStripe(id);4return redirect("/admin/products");5}
1<fetcher.Form method="POST">2<Button isLoading={fetcher.state==="submitting"}>Sync catalogue</Button>3</fetcher.Form>
Supprime aussi le produit côté Stripe
1export async function deleteStripeProduct(stripeProductId?: string) {2if (!stripeProductId) return;34const prices = await stripe.prices.list({ product: stripeProductId });5for (const p of prices.data) await stripe.prices.update(p.id, { active: false });67await stripe.products.update(stripeProductId, { active: false });8}
Appel :
1await deleteStripeProduct(product.stripeProductId);2await prisma.product.delete({ where: { id: product.id } });
Ce que tu viens d’accomplir
- Création d’un compte Stripe dédié à l’appli.
- Stockage sécurisé des clés dans
.env. - SDK Stripe typé côté serveur.
- Synchronisation produit ↔ prix ↔ image en un clic.
- Archivage automatique des anciens prix (historique préservé).
- Nettoyage Stripe lors d’une suppression produit.
Ton catalogue est désormais miroir de Stripe ; prêt à lancer une session Checkout et encaisser tes premiers paiements. 🚀
Comprendre les concepts fondamentaux
Quelle est la principale différence entre les composants client et serveur dans React ?
Optimisation des performances
Quelle technique est recommandée pour éviter les rendus inutiles dans React ?
Architecture des données
Quel hook permet de gérer les effets de bord dans un composant React ?