Skip to main content

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
Ces deux packages sont essentiels :
– `@stripe/stripe-js` : SDK JavaScript de Stripe
– `@stripe/react-stripe-js` : Composants React officiels

 

Configuration du Provider Stripe

La première étape consiste à configurer le `StripeProvider` qui englobera votre application :

 

// 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>
  );
}

 

Important : Utilisez toujours `NEXT_PUBLIC_` pour les variables d’environnement côté client dans Next.js.

 

Créer un formulaire de paiement avec Stripe Elements

Stripe Elements fournit des composants UI pré-construits et sécurisés :

 

// 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

Voici comment fonctionne le flux de paiement avec Stripe :
  • 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

Dans votre API Next.js :
// 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

Ne faites jamais confiance aux montants envoyés par le frontend :
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

 

Ne vous fiez pas uniquement à la redirection après paiement. Les webhooks sont essentiels pour une confirmation fiable.

 

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

Stripe fournit des numéros de carte de test :

 

| 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

L’intégration de Stripe dans une application React/Next.js est relativement simple grâce aux composants Stripe Elements. Les points clés à retenir :
  • 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

Prochaine étape recommandée :

[Chapitre 2 – Les webhooks Stripe](/blog/chapitre-2-webhooks-stripe-nodejs) pour sécuriser la confirmation de vos paiements.