Introduction
L’intégration d’un système de paiement est une étape cruciale pour toute application e-commerce ou SaaS. Stripe s’est imposé comme la solution de référence grâce à son API puissante et sa documentation exhaustive. Dans cet article, nous allons voir comment intégrer Stripe dans une application React avec Next.js.
Prérequis
Avant de commencer, assurez-vous d’avoir :
– Un compte Stripe (mode test disponible gratuitement)
– Une application Next.js fonctionnelle
– Node.js 18+ installé
Installation des dépendances
```bash``` npm install @stripe/stripe-js @stripe/react-stripe-js
Configuration du Provider Stripe
// providers/StripeProvider.tsx
import { Elements } from '@stripe/react-stripe-js';
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!
);
export function StripeProvider({ children }: { children: React.ReactNode }) {
return (
<Elements stripe={stripePromise}>
{children}
</Elements>
);
}
Créer un formulaire de paiement avec Stripe Elements
// components/PaymentForm.tsx
import { PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js';
import { useState } from 'react';
interface PaymentFormProps {
clientSecret: string;
}
export function PaymentForm({ clientSecret }: PaymentFormProps) {
const stripe = useStripe();
const elements = useElements();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!stripe || !elements) {
return; // Stripe.js n'est pas encore chargé
}
setIsLoading(true);
setError(null);
const { error: submitError } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/payment/success`,
},
});
if (submitError) {
setError(submitError.message ?? 'Une erreur est survenue');
}
setIsLoading(false);
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
{error && <div className="error">{error}</div>}
<button type="submit" disabled={!stripe || isLoading}>
{isLoading ? 'Traitement...' : 'Payer'}
</button>
</form>
);
}
Le flux de paiement complet
- 1. Frontend → Backend : Demande de création de PaymentIntent
- 2. Backend → Stripe API : Création du PaymentIntent
- 3. Stripe → Backend : Retour du client_secret
- 4. Backend → Frontend : Transmission du client_secret
- 5. Frontend : Affichage du formulaire avec Stripe Elements
- 6. Utilisateur : Saisie des informations de carte
- 7. Frontend → Stripe : Confirmation du paiement
- 8. Stripe → Backend (webhook) : Notification de succès/échec
Créer le PaymentIntent côté serveur
// app/api/create-payment-intent/route.ts
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2024-12-18.acacia',
});
export async function POST(request: Request) {
try {
const { amount, currency = 'eur' } = await request.json();
// Vérification basique (tu peux ajouter une validation Zod si besoin)
if (!amount || typeof amount !== 'number') {
return Response.json(
{ error: 'Montant invalide ou manquant.' },
{ status: 400 }
);
}
const paymentIntent = await stripe.paymentIntents.create({
amount, // En centimes (ex : 1000 = 10 €)
currency,
automatic_payment_methods: { enabled: true },
});
return Response.json({
clientSecret: paymentIntent.client_secret,
});
} catch (error) {
console.error('Erreur Stripe PaymentIntent :', error);
return Response.json(
{ error: 'Impossible de créer le PaymentIntent.' },
{ status: 500 }
);
}
}
Bonnes pratiques de sécurité
1. Ne jamais exposer la clé secrète
env # .env.local STRIPE_SECRET_KEY=sk_test_... # Côté serveur uniquement NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_... # Côté client
2. Valider les montants côté serveur
typescript // Toujours recalculer le montant côté serveur const amount = calculateOrderTotal(orderId); // Depuis votre base de données
3. Utiliser les webhooks pour confirmer les paiements
Gestion des erreurs courantes
const handlePaymentError = (error: Stripe.StripeError): string => {
switch (error.code) {
case 'card_declined':
return 'Votre carte a été refusée';
case 'expired_card':
return 'Votre carte a expiré';
case 'incorrect_cvc':
return 'Le code CVC est incorrect';
case 'processing_error':
return 'Erreur de traitement, veuillez réessayer';
default:
return 'Une erreur est survenue';
}
};
Tester votre intégration
| Numéro | Résultat | |--------|----------| | 4242 4242 4242 4242 | Paiement réussi | | 4000 0000 0000 0002 | Carte refusée | | 4000 0025 0000 3155 | Authentification 3D Secure |
Conclusion
- Utilisez le `StripeProvider` pour envelopper votre application
- Créez les PaymentIntent côté serveur uniquement
- Implémentez les webhooks pour une gestion fiable des paiements
- Testez toujours en mode test avant de passer en production
📚 Série complète : Maîtriser Stripe avec Node.js et React
-
Chapitre 1 : Configuration initiale (Vous êtes ici) Intégrer Stripe dans React/Next.js Premier formulaire de paiement et installation.
-
Chapitre 2 : Automatisation (Suivant) Gérer les webhooks Stripe dans Node.js Recevoir et traiter les événements de paiement en temps réel.
-
Chapitre 3 : Stratégie de Paiement Stripe Checkout vs Elements : Quel choix pour votre projet ? Comparatif complet pour choisir la meilleure UX.
-
Chapitre 4 : Gestion après-vente Implémenter les remboursements Stripe Gérer les annulations, les remboursements et les litiges.
-
Chapitre 5 : Concepts Avancés PaymentIntent et capture différée Autoriser les paiements et les capturer plus tard.
