Intégrer Stripe dans un SaaS français : TVA, factures, webhooks
Guide complet pour intégrer Stripe dans un SaaS B2B français, gestion de la TVA, factures conformes, webhooks sécurisés et abonnements.
Stripe en France : ce qui change
Intégrer Stripe dans un SaaS français n'est pas juste "copier-coller la doc US". Il y a la TVA à 20%, les factures conformes à générer, et des règles spécifiques pour les abonnements B2B.
Étape 1 : Configuration Stripe
// src/lib/stripe.ts
import Stripe from "stripe";
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2025-02-24.acacia",
typescript: true,
});Produits et prix
Créez vos plans dans le dashboard Stripe avec les bons taux de TVA :
// Exemple de création programmatique
const product = await stripe.products.create({
name: "HeartCo Pro",
tax_code: "txcd_10103001", // SaaS - Software as a Service
});
const price = await stripe.prices.create({
product: product.id,
unit_amount: 3400, // 34€ HT
currency: "eur",
recurring: { interval: "month" },
tax_behavior: "exclusive", // TVA ajoutée en plus
});Étape 2 : Checkout Session
// src/server/api/routers/billing.ts
export const billingRouter = createTRPCRouter({
createCheckout: staffProcedure
.input(z.object({ priceId: z.string() }))
.mutation(async ({ ctx, input }) => {
const session = await stripe.checkout.sessions.create({
customer_email: ctx.session.user.email,
mode: "subscription",
line_items: [{ price: input.priceId, quantity: 1 }],
automatic_tax: { enabled: true },
tax_id_collection: { enabled: true },
success_url: `${env.NEXT_PUBLIC_APP_URL}/dashboard/billing?success=true`,
cancel_url: `${env.NEXT_PUBLIC_APP_URL}/dashboard/billing`,
metadata: {
organizationId: ctx.session.user.organizationId,
},
});
return { url: session.url };
}),
});Points clés pour la France
automatic_tax: { enabled: true }, Stripe calcule la TVA automatiquement selon le pays du clienttax_id_collection: Permet au client de saisir son numéro de TVA intracommunautairemetadata: Toujours inclure l'organizationIdpour le webhook
Étape 3 : Webhooks sécurisés
Le webhook est le point critique. C'est lui qui met à jour votre base de données quand un paiement est confirmé.
// src/app/api/webhooks/stripe/route.ts
import { headers } from "next/headers";
import crypto from "crypto";
export async function POST(req: Request) {
const body = await req.text();
const headersList = await headers();
const signature = headersList.get("stripe-signature")!;
// Vérification HMAC — OBLIGATOIRE
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!,
);
} catch {
return new Response("Invalid signature", { status: 400 });
}
switch (event.type) {
case "checkout.session.completed": {
const session = event.data.object;
const orgId = session.metadata?.organizationId;
if (!orgId) break;
await db.subscription.update({
where: { organizationId: orgId },
data: {
plan: "PRO",
stripeSubscriptionId: session.subscription as string,
status: "ACTIVE",
},
});
break;
}
case "customer.subscription.deleted": {
// Downgrade vers FREE
const sub = event.data.object;
await db.subscription.updateMany({
where: { stripeSubscriptionId: sub.id },
data: { plan: "FREE", status: "CANCELED" },
});
break;
}
}
return new Response("OK", { status: 200 });
}Règle de sécurité critique
Ne jamais comparer les signatures avec === :
// ❌ VULNÉRABLE — timing attack
if (computedSignature === receivedSignature) { ... }
// ✅ SÉCURISÉ — comparaison en temps constant
crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(receivedSignature),
);Stripe SDK le fait pour vous via constructEvent, mais si vous vérifiez manuellement, utilisez toujours timingSafeEqual.
Étape 4 : Factures conformes
Pour un SaaS B2B français, vos factures doivent inclure :
- Numéro séquentiel (FACT-2026-001)
- TVA ventilée (HT + TVA + TTC)
- Mentions légales (SIRET, numéro TVA)
- Date d'émission et de paiement
Stripe génère des factures automatiquement pour les abonnements. Activez Stripe Invoicing et configurez vos informations légales dans le dashboard.
Checklist Stripe France
-
automatic_taxactivé sur toutes les Checkout Sessions -
tax_id_collectionactivé pour les clients B2B - Webhook vérifié par signature HMAC
- Informations légales dans Stripe Dashboard (SIRET, TVA)
- Gestion du downgrade à l'expiration de l'abonnement
- Emails de confirmation configurés (Stripe ou custom)
- Mode test validé avant passage en production
Le paiement est la partie la plus sensible de votre SaaS. Prenez le temps de bien le configurer : vos clients (et votre comptable) vous remercieront.
Articles connexes
RGPD pour SaaS B2B français, checklist complète sans mythes
Ce que vous devez vraiment faire pour être conforme RGPD en tant que SaaS B2B français, et ce que les agences de conseil vous vendent inutilement.
LireLancer un SaaS sans coder en 2026, la stack hybride no-code + code
Comment passer de l'idée au SaaS en production sans écrire une ligne de Stripe ou de NextAuth, avec un assistant no-code qui génère le code pour vous.
LireMistral AI dans un SaaS B2B : 5 use-cases concrets en TypeScript
Intégrer une IA souveraine française dans votre SaaS, extraction de données, résumés clients, classification d'emails, génération de contenu et search sémantique.
Lire