Stripe + Next.js Commerce Sans Tête : Le Guide d'Intégration 2026
J'ai intégré Stripe à des projets Next.js plus de fois que je ne peux les compter. À chaque fois, le paysage change un peu — nouvelles versions d'API, nouvelles méthodes de paiement, nouveaux cas limites qui vous mordent à 2 h du matin quand un webhook échoue silencieusement. Ce guide est tout ce que j'aurais souhaité avoir la première fois que j'ai construit une pile de commerce sans tête. Nous couvrirons Checkout Sessions, Payment Intents, webhooks, abonnements, Apple Pay, Google Pay, Link, et checkout en un clic. Pas de contournements. Code réel, décisions architecturales réelles, pièges réels.
Au milieu de 2026, l'API de Stripe est à la version 2025-12-18.acacia, Next.js 15.x est stable avec App Router par défaut, et les paquets @stripe/stripe-js et @stripe/react-stripe-js ont mûri considérablement. Si vous construisez sur des versions plus anciennes, la plupart de cela s'applique toujours, mais certains motifs d'actions serveur différeront.
Table des matières
- Pourquoi Stripe + Next.js pour le Commerce Sans Tête
- Aperçu de l'Architecture
- Configurer Stripe dans un Projet Next.js 15
- Checkout Sessions : Le Chemin Rapide
- Payment Intents : Mode Contrôle Total
- Gestion des Webhooks Qui Fonctionne Réellement
- Abonnements et Facturation Récurrente
- Apple Pay, Google Pay, et Link
- Checkout en Un Clic avec Link
- Sécurité, Tests, et Mise en Production
- Considérations de Performance
- FAQ

Pourquoi Stripe + Next.js pour le Commerce Sans Tête
Stripe traite plus de 1 billion de dollars de volume de paiement annuellement. Next.js alimente une part croissante des vitrines de commerce électronique — Vercel rapporte que plus de 40 % des nouveaux projets Next.js en 2025 avaient une forme quelconque de fonctionnalité commerciale. La combinaison a du sens pour quelques raisons concrètes :
- Server Components et Server Actions vous permettent d'appeler le SDK Stripe côté serveur sans construire une couche API séparée.
- Déploiement Edge et serverless sur Vercel, Netlify, ou AWS signifie que vos points de terminaison de paiement se mettent à l'échelle automatiquement.
- React Server Components gardent votre clé secrète Stripe sur le serveur où elle appartient, sans acrobaties supplémentaires.
- App Router vous donne des layouts, des états de chargement, et des limites d'erreur qui correspondent bien aux flux de checkout.
Si vous évaluez des architectures de commerce sans tête, nous avons construit des dizaines de celles-ci chez Social Animal — consultez nos capacités de développement Next.js et développement de CMS sans tête pour plus de contexte sur la façon dont ces pièces s'assemblent.
Aperçu de l'Architecture
Avant d'écrire du code, assurons-nous que l'architecture est correcte. Voici comment les pièces se connectent dans une configuration de commerce sans tête typique :
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Next.js App │────▶│ API Stripe │────▶│ Webhooks │
│ (App Router) │◀────│ (Côté serveur) │ │ Endpoint │
└─────────────────┘ └──────────────────┘ └──────┬──────┘
│ │
│ ▼
▼ ┌─────────────┐
┌─────────────────┐ │ Base de │
│ CMS Sans Tête │ │ données / │
│ (Produits) │ │ Gestion │
└─────────────────┘ │ Commandes │
└─────────────┘
La décision critique est de savoir s'il faut utiliser Checkout Sessions (hébergées ou intégrées par Stripe) ou Payment Intents (interface utilisateur entièrement personnalisée). Voici quand utiliser chacune :
| Fonctionnalité | Checkout Sessions | Payment Intents |
|---|---|---|
| Vitesse de développement | Rapide — jours | Plus lent — semaines |
| Personnalisation de l'UI | Limitée (thème Stripe) | Contrôle total |
| Portée de conformité PCI | SAQ A (la plus simple) | SAQ A-EP |
| Prise en charge des méthodes de paiement | Automatique (40+ méthodes) | Manuel par méthode |
| Prise en charge des abonnements | Intégrée | Nécessite du code supplémentaire |
| Apple Pay / Google Pay | Automatique | Manuel via Payment Request API |
| Optimisation de la conversion | Optimisée par Stripe | Vous êtes responsable |
| Impact sur les tarifs | Mêmes frais Stripe | Mêmes frais Stripe |
Ma recommandation honnête : commencez avec Checkout Sessions sauf si vous avez une raison spécifique de ne pas le faire. Vous pouvez toujours migrer vers Payment Intents plus tard, et le checkout intégré de Stripe s'est considérablement amélioré en 2025-2026.
Configurer Stripe dans un Projet Next.js 15
Configurons les fondations. Je suppose que vous avez un projet Next.js 15 avec App Router.
npm install stripe @stripe/stripe-js @stripe/react-stripe-js
Créez vos variables d'environnement :
# .env.local
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
Configurez une instance Stripe côté serveur. Je la mets toujours dans un fichier lib/stripe.ts :
// lib/stripe.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2025-12-18.acacia',
typescript: true,
});
Et un chargeur côté client :
// lib/stripe-client.ts
import { loadStripe } from '@stripe/stripe-js';
export const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
Une chose qui pose problème aux gens : ne jamais importer lib/stripe.ts dans un composant client. Le paquet stripe npm inclut votre clé secrète et ne doit s'exécuter que côté serveur. Next.js 15 lèvera une erreur de construction si vous l'importez accidentellement dans un fichier 'use client', ce qui est en fait une bonne garde-fou.

Checkout Sessions : Le Chemin Rapide
Les Checkout Sessions sont le moyen le plus rapide d'accepter des paiements. Stripe héberge le formulaire de paiement (ou vous l'intégrez), gère la conformité PCI, et supporte automatiquement des dizaines de méthodes de paiement incluant Apple Pay, Google Pay, et Link.
Créer une Checkout Session avec Server Actions
// app/actions/checkout.ts
'use server';
import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
export async function createCheckoutSession(formData: FormData) {
const priceId = formData.get('priceId') as string;
const quantity = Number(formData.get('quantity')) || 1;
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [
{
price: priceId,
quantity,
},
],
success_url: `${process.env.NEXT_PUBLIC_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/checkout/canceled`,
automatic_tax: { enabled: true },
// Activez toutes les méthodes de paiement pertinentes
payment_method_types: undefined, // Laisser Stripe détecter automatiquement
});
redirect(session.url!);
}
Checkout Intégré (Approche Recommandée 2026)
Le checkout intégré de Stripe garde les utilisateurs sur votre domaine. Cela a de meilleures taux de conversion — les propres données de Stripe de 2025 montrent une amélioration de 10-15 % par rapport au checkout basé sur redirection pour les clients récurrents.
// app/checkout/embedded/page.tsx
'use client';
import { useCallback } from 'react';
import { loadStripe } from '@stripe/stripe-js';
import {
EmbeddedCheckoutProvider,
EmbeddedCheckout,
} from '@stripe/react-stripe-js';
const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
export default function CheckoutPage() {
const fetchClientSecret = useCallback(async () => {
const res = await fetch('/api/checkout/embedded', {
method: 'POST',
body: JSON.stringify({ priceId: 'price_xxx', quantity: 1 }),
});
const { clientSecret } = await res.json();
return clientSecret;
}, []);
return (
<div className="max-w-lg mx-auto py-12">
<EmbeddedCheckoutProvider
stripe={stripePromise}
options={{ fetchClientSecret }}
>
<EmbeddedCheckout />
</EmbeddedCheckoutProvider>
</div>
);
}
Et l'itinéraire API :
// app/api/checkout/embedded/route.ts
import { stripe } from '@/lib/stripe';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
const { priceId, quantity } = await req.json();
const session = await stripe.checkout.sessions.create({
mode: 'payment',
line_items: [{ price: priceId, quantity }],
ui_mode: 'embedded',
return_url: `${process.env.NEXT_PUBLIC_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
});
return NextResponse.json({ clientSecret: session.client_secret });
}
Payment Intents : Mode Contrôle Total
Quand vous avez besoin d'une interface utilisateur de paiement entièrement personnalisée — peut-être que vous construisez un checkout d'une page, ou que votre équipe de design a des exigences spécifiques — Payment Intents vous donnent un contrôle total.
Le compromis est réel : vous écrirez plus de code, traiterez plus de cas limites, et prendrez un fardeau de conformité PCI légèrement plus élevé. Mais pour certains produits, cela en vaut la peine.
Côté Serveur : Créer des Payment Intents
// app/api/payment-intent/route.ts
import { stripe } from '@/lib/stripe';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
const { amount, currency = 'usd', metadata } = await req.json();
const paymentIntent = await stripe.paymentIntents.create({
amount, // en centimes
currency,
metadata,
automatic_payment_methods: {
enabled: true, // Ceci active Apple Pay, Google Pay, Link, etc.
},
});
return NextResponse.json({
clientSecret: paymentIntent.client_secret,
});
}
Côté Client : Le Formulaire de Paiement
// components/PaymentForm.tsx
'use client';
import { useState } from 'react';
import {
PaymentElement,
useStripe,
useElements,
} from '@stripe/react-stripe-js';
export function PaymentForm() {
const stripe = useStripe();
const elements = useElements();
const [error, setError] = useState<string | null>(null);
const [processing, setProcessing] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!stripe || !elements) return;
setProcessing(true);
setError(null);
const { error: submitError } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/checkout/success`,
},
});
if (submitError) {
setError(submitError.message ?? 'Payment failed');
setProcessing(false);
}
// Si pas d'erreur, Stripe redirige automatiquement
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement
options={{
layout: 'accordion',
wallets: {
applePay: 'auto',
googlePay: 'auto',
},
}}
/>
{error && <p className="text-red-500 mt-2">{error}</p>}
<button
type="submit"
disabled={!stripe || processing}
className="mt-4 w-full bg-black text-white py-3 rounded-lg disabled:opacity-50"
>
{processing ? 'Traitement...' : 'Payer maintenant'}
</button>
</form>
);
}
Notez le automatic_payment_methods: { enabled: true } côté serveur. C'est la façon 2025-2026 de gérer la prise en charge des méthodes de paiement. Stripe affichera automatiquement les bonnes méthodes de paiement en fonction de l'appareil, de l'emplacement et de la devise du client. Plus besoin de lister manuellement payment_method_types.
Gestion des Webhooks Qui Fonctionne Réellement
Les webhooks sont où la plupart des intégrations Stripe se cassent. J'ai vu des systèmes de production perdre des commandes parce que quelqu'un a oublié de vérifier la signature du webhook, ou parce que le gestionnaire a levé une erreur avant d'envoyer un 200.
Voici mon gestionnaire de webhook éprouvé :
// app/api/webhooks/stripe/route.ts
import { stripe } from '@/lib/stripe';
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';
import type Stripe from 'stripe';
export async function POST(req: Request) {
const body = await req.text();
const headersList = await headers();
const signature = headersList.get('stripe-signature');
if (!signature) {
return NextResponse.json({ error: 'Missing signature' }, { status: 400 });
}
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
} catch (err) {
console.error('Webhook signature verification failed:', err);
return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });
}
try {
switch (event.type) {
case 'checkout.session.completed': {
const session = event.data.object as Stripe.Checkout.Session;
await handleCheckoutComplete(session);
break;
}
case 'payment_intent.succeeded': {
const paymentIntent = event.data.object as Stripe.PaymentIntent;
await handlePaymentSuccess(paymentIntent);
break;
}
case 'payment_intent.payment_failed': {
const paymentIntent = event.data.object as Stripe.PaymentIntent;
await handlePaymentFailure(paymentIntent);
break;
}
case 'customer.subscription.created':
case 'customer.subscription.updated':
case 'customer.subscription.deleted': {
const subscription = event.data.object as Stripe.Subscription;
await handleSubscriptionChange(subscription);
break;
}
case 'invoice.payment_failed': {
const invoice = event.data.object as Stripe.Invoice;
await handleInvoiceFailure(invoice);
break;
}
default:
console.log(`Unhandled event type: ${event.type}`);
}
} catch (err) {
console.error(`Error processing ${event.type}:`, err);
// Toujours renvoyer 200 pour empêcher Stripe de réessayer
// Enregistrer l'erreur pour investigation manuelle
}
return NextResponse.json({ received: true });
}
Les Pièges des Webhooks Que J'ai Appris à la Dure
Toujours renvoyer 200, même si votre traitement échoue. Sinon Stripe réessaye, et vous pourriez traiter le même événement plusieurs fois. Enregistrez l'erreur et gérez-la de façon asynchrone.
Rendez les gestionnaires idempotents. Stripe peut et va envoyer le même événement plus d'une fois. Utilisez l'ID d'événement ou les métadonnées de l'objet pour vérifier si vous l'avez déjà traité.
Utilisez
req.text()et nonreq.json()pour la vérification de signature. La signature est calculée sur la chaîne du corps brut. Si vous l'analysez d'abord, la vérification échouera toujours.Configurez la CLI Stripe pour les tests locaux. C'est non-négociable.
stripe listen --forward-to localhost:3000/api/webhooks/stripe
- Sur Vercel, les itinéraires webhook nécessitent une configuration spécifique. Assurez-vous que votre itinéraire n'est pas derrière un middleware qui modifie le corps de la demande. Dans Next.js 15, les itinéraires API dans App Router gèrent cela correctement par défaut, mais vérifiez si vous avez un middleware personnalisé.
Abonnements et Facturation Récurrente
Les abonnements ajoutent un niveau de complexité. Vous ne traitez pas juste un paiement ponctuel — vous gérez un cycle de vie : essais, mises à niveau, réductions, annulations, paiements échoués, dunning.
Créer un Abonnement via Checkout
L'approche la plus facile :
// app/actions/subscribe.ts
'use server';
import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
export async function createSubscriptionCheckout(
customerId: string,
priceId: string
) {
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
customer: customerId,
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.NEXT_PUBLIC_URL}/account/billing?success=true`,
cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
subscription_data: {
trial_period_days: 14,
metadata: {
plan: 'pro', // Vos propres métadonnées
},
},
allow_promotion_codes: true,
tax_id_collection: { enabled: true },
});
redirect(session.url!);
}
Gérer les Abonnements
Pour le portail client (mise à niveau, réduction, annulation, mise à jour du mode de paiement), le Customer Portal de Stripe est véritablement excellent en 2026 :
// app/actions/billing.ts
'use server';
import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
export async function createBillingPortalSession(customerId: string) {
const session = await stripe.billingPortal.sessions.create({
customer: customerId,
return_url: `${process.env.NEXT_PUBLIC_URL}/account/billing`,
});
redirect(session.url);
}
Événements de Webhook d'Abonnement Clés
| Événement | Quand C'est Envoyé | Quoi Faire |
|---|---|---|
customer.subscription.created |
Nouvel abonnement | Provisionner l'accès |
customer.subscription.updated |
Changement de plan, renouvellement | Mettre à jour le niveau d'accès |
customer.subscription.deleted |
Annulation (fin de période) | Révoquer l'accès |
invoice.payment_succeeded |
Renouvellement réussi | Mettre à jour les dossiers de facturation |
invoice.payment_failed |
Renouvellement échoué | Envoyer e-mail de dunning, marquer le compte |
customer.subscription.trial_will_end |
3 jours avant fin d'essai | Envoyer e-mail de rappel |
Ne vous fiez pas uniquement au statut de l'abonnement à partir de l'appel API. Les webhooks sont la source de vérité pour les changements d'état d'abonnement. J'ai vu des équipes sonder l'API Stripe au lieu d'utiliser des webhooks et c'est à la fois plus lent et plus fragile.
Apple Pay, Google Pay, et Link
La beauté du Payment Element de Stripe 2025-2026 est que les paiements par portefeuille fonctionnent en grande partie automatiquement. Mais il y a quelques exigences de configuration que les gens oublient.
Configuration d'Apple Pay
La vérification de domaine est requise. Vous devez héberger un fichier
.well-known/apple-developer-merchantid-domain-associationà la racine de votre domaine. Stripe fournit ce fichier dans votre Dashboard sous Paramètres → Méthodes de Paiement → Apple Pay.Dans Next.js, placez le fichier à
public/.well-known/apple-developer-merchantid-domain-association.Enregistrez votre domaine dans le Dashboard Stripe.
Apple Pay n'apparaît que sur Safari/iOS. Ne soyez pas alarmé s'il n'apparaît pas dans Chrome lors des tests.
Configuration de Google Pay
Google Pay nécessite moins de configuration — il fonctionne automatiquement avec le Payment Element tant que votre compte Stripe est correctement configuré. Il apparaît dans Chrome et sur les appareils Android.
Link (Checkout Stripe en Un Clic)
Link est la réponse de Stripe à Shop Pay. Les clients sauvegardent leurs informations de paiement une fois et peuvent faire un achat en un clic chez tout commerçant Stripe utilisant Link.
Au 2026, Link est activé par défaut sur les nouveaux comptes Stripe. L'amélioration de conversion est réelle — Stripe rapporte une amélioration de 7 % de la complétude du checkout quand Link est disponible. Pour les utilisateurs Link récurrents, c'est beaucoup plus élevé.
Avec le Payment Element, Link apparaît automatiquement. Avec les Checkout Sessions, c'est aussi automatique. Vous n'avez rien à faire de spécial.
// Link est automatique avec Payment Element, mais vous pouvez le personnaliser :
<PaymentElement
options={{
wallets: {
applePay: 'auto',
googlePay: 'auto',
},
// Link apparaît dans le champ email automatiquement
}}
/>
Checkout en Un Clic avec Link
Link mérite sa propre section car il est devenu un véritable moteur de conversion. Voici comment ça fonctionne :
- Le client entre son email dans votre formulaire de checkout.
- S'il a un compte Link, il reçoit un code de vérification par SMS.
- Après vérification, son adresse enregistrée et sa méthode de paiement sont remplies automatiquement.
- Il clique sur « Payer » — terminé.
L'idée clé : Link fonctionne entre commerçants. Si votre client a utilisé Link sur un site complètement différent, il obtiendra l'expérience en un clic sur le vôtre aussi. L'effet réseau de Stripe est réel — ils rapportent plus de 100 millions d'utilisateurs Link au début de 2026.
Pour maximiser l'adoption de Link, assurez-vous que le champ email est la première chose avec laquelle les clients interagissent dans votre flux de checkout. Le Payment Element gère cela bien avec la disposition accordion.
Si vous voulez aller plus loin, vous pouvez utiliser l'Express Checkout Element pour afficher les boutons Apple Pay, Google Pay, et Link de manière proéminente au-dessus de votre formulaire :
// components/ExpressCheckout.tsx
'use client';
import { ExpressCheckoutElement } from '@stripe/react-stripe-js';
export function ExpressCheckout() {
return (
<ExpressCheckoutElement
onConfirm={async (event) => {
// Gérer la confirmation du paiement express
console.log('Express checkout confirmed:', event);
}}
options={{
buttonType: {
applePay: 'buy',
googlePay: 'buy',
},
}}
/>
);
}
Sécurité, Tests, et Mise en Production
Liste de Vérification de Sécurité
- La clé secrète Stripe n'est utilisée que côté serveur
- Les signatures de webhooks sont vérifiées à chaque demande
- HTTPS est appliquée en production
- Les calculs de montant se font côté serveur (ne jamais faire confiance aux montants envoyés par le client)
- Les itinéraires API ont une limitation de débit
- Les données client sont gérées selon votre politique de confidentialité
- Les en-têtes CSP permettent les domaines de Stripe (
js.stripe.com,api.stripe.com)
Tests
Le mode test de Stripe est excellent. Utilisez ces numéros de carte de test :
| Numéro de Carte | Scénario |
|---|---|
4242 4242 4242 4242 |
Paiement réussi |
4000 0000 0000 3220 |
3D Secure requis |
4000 0000 0000 9995 |
Refusé |
4000 0025 0000 3155 |
Authentification requise |
4000 0000 0000 0341 |
Attacher échoue (pour les cartes enregistrées) |
Pour les tests d'abonnement, utilisez les horloges de test de Stripe pour simuler le passage du temps sans réellement attendre.
Mise en Production
- Changez vos clés de
sk_test_àsk_live_et depk_test_àpk_live_. - Configurez votre point de terminaison webhook en direct dans le Dashboard Stripe.
- Vérifiez votre domaine Apple Pay pour la production.
- Activez les méthodes de paiement que vous souhaitez dans le Dashboard Stripe.
- Assurez-vous que votre compte Stripe est complètement activé (vérification d'identité, compte bancaire, etc.).
Considérations de Performance
Stripe.js fait environ 40 KB gzippé. Ce n'est pas rien. Voici quelques conseils :
Chargez Stripe.js en différé. Ne le chargez pas sur chaque page — uniquement sur les pages liées au checkout. La fonction
loadStripegère cela bien ; elle ne récupérera le script que lorsque vous l'appellerez.Utilisez
@stripe/stripe-js/puresi vous voulez contrôler exactement quand le script se charge :
import { loadStripe } from '@stripe/stripe-js/pure';
// Le script ne se chargera pas tant que loadStripe() n'est pas appelé
Server Components pour les pages de produits. Gardez le code client Stripe hors de vos pages de listing et de détail de produits. Ne le mettez en place que quand l'utilisateur initie réellement le checkout.
Runtime Edge pour les itinéraires API. Le SDK Node.js de Stripe fonctionne sur le runtime Edge à partir de 2025. Vous pouvez ajouter
export const runtime = 'edge'à vos itinéraires API Stripe pour une latence plus faible.
Pour les équipes construisant des vitrines haute performance sans tête, des frameworks comme Astro peuvent aussi être un excellent ajustement pour les pages riches en contenu tandis que Next.js gère les flux de checkout dynamiques. Nous avons fait cette approche hybride pour plusieurs clients — nos équipes développement Astro et développement Next.js collaborent sur ces architectures régulièrement.
FAQ
Quels sont les frais de transaction de Stripe en 2026 ?
La tarification standard de Stripe est 2,9 % + 0,30 $ par charge de carte réussie aux États-Unis. Pour les cartes européennes, c'est 1,5 % + 0,25 €. Des réductions de volume sont disponibles pour les entreprises traitant plus de 1 M$ annuellement. Il n'y a pas de frais de configuration, frais mensuels, ou frais cachés sur le plan standard. Stripe facture 0,5 % supplémentaires pour les cartes saisies manuellement et 1 % pour les cartes internationales.
Devrais-je utiliser Checkout Sessions ou Payment Intents ?
Utilisez Checkout Sessions pour la plupart des cas. Elles sont plus rapides à implémenter, supportent automatiquement 40+ méthodes de paiement, gèrent la conformité PCI, et Stripe optimise continuellement le taux de conversion. Utilisez Payment Intents quand vous avez besoin d'une interface utilisateur de checkout entièrement personnalisée qui ne peut pas être réalisée avec Checkout intégré, ou quand vous avez besoin d'un contrôle fin du flux de paiement (comme les paiements fractionné ou la capture manuelle).
Comment gérer les échecs de webhooks en production ?
Toujours renvoyer un statut 200 du gestionnaire de webhooks, même si votre logique métier échoue. Enregistrez l'erreur et traitez-la de manière asynchrone. Rendez vos gestionnaires idempotents en vérifiant l'ID d'événement par rapport à votre base de données avant de traiter. Stripe réessaye les webhooks pendant jusqu'à 3 jours avec backoff exponentiel. Configurez les alertes d'échec webhook dans le Dashboard Stripe, et envisagez d'utiliser une file d'attente (comme AWS SQS ou Inngest) pour traiter les charges webhook de manière asynchrone.
Puis-je utiliser Stripe avec un CMS sans tête comme Sanity ou Contentful ?
Absolument. Le motif typique est : stocker les informations de produit et de contenu dans votre CMS sans tête, stocker les données de prix et de paiement dans Stripe, et les connecter via un ID ou SKU de produit partagé. Votre frontend Next.js récupère le contenu du CMS et crée des Checkout Sessions ou Payment Intents Stripe quand le client est prêt à acheter. Nous couvrons ce motif extensively dans notre travail de développement de CMS sans tête.
Comment tester Apple Pay localement ?
Vous ne pouvez pas facilement tester Apple Pay sur localhost car il nécessite HTTPS et la vérification de domaine. La meilleure approche est d'utiliser le mode test de Stripe avec la carte de test 4242 dans le Payment Element — cela simule le flux de paiement. Pour le test réel d'Apple Pay, déployez sur un environnement de staging avec HTTPS. La CLI Stripe supporte aussi le transfert des événements webhook pour les transactions Apple Pay.
Link Stripe vaut-il la peine d'être activé ?
Oui. Link est gratuit pour les commerçants — Stripe ne facture pas supplémentaire pour cela. Il apparaît automatiquement dans le Payment Element et les Checkout Sessions. Stripe rapporte que Link augmente la complétude du checkout jusqu'à 7 % en moyenne, avec des chiffres plus élevés pour les utilisateurs Link récurrents. Il n'y a pas d'inconvénient à l'activer, et avec 100M+ utilisateurs Link en 2026, l'effet réseau est significatif.
Comment gérer les abonnements avec facturation au compteur dans Next.js ?
Créez un abonnement avec un prix mesuré dans Stripe. Ensuite, utilisez l'API Usage Records pour signaler l'utilisation depuis votre backend. À la fin de chaque période de facturation, Stripe calcule automatiquement le total et facture le client. Votre gestionnaire de webhooks doit écouter les événements invoice.payment_succeeded et invoice.payment_failed pour garder votre système synchronisé. Signalez l'utilisation côté serveur en utilisant une tâche cron ou une architecture pilotée par des événements.
Quelle est la meilleure façon de gérer la devise et la tarification pour les clients internationaux ?
Stripe Adaptive Pricing (lancé 2025) convertit automatiquement les prix dans la devise locale du client lors du checkout. Vous définissez les prix dans votre devise de base, et Stripe gère la conversion, l'affichage, et le règlement. Alternatively, vous pouvez créer plusieurs prix par produit dans différentes devises dans Stripe pour plus de contrôle. Utilisez l'IP ou la locale du navigateur du client pour déterminer quelle devise afficher sur vos pages de produits.
Combien coûte la construction d'une intégration de commerce sans tête avec Stripe ?
Cela dépend de la portée. Une intégration basique de Checkout Sessions peut être faite en quelques jours. Une configuration complète avec abonnements, portail client, webhooks, et interface personnalisée prend généralement 2-6 semaines de temps de développement. Si vous voulez discuter de vos besoins spécifiques, consultez notre page de tarification ou contactez-nous — nous avons construit ces intégrations dans une large gamme d'industries et pouvons vous donner une estimation réaliste.