Introduction
L'intégration Stripe constitue une étape déterminante pour tout système nécessitant des paiements en ligne et une facturation automatisée. Stripe offre une API RESTful complète, des webhooks temps réel et un tableau de bord robuste pour gérer l'ensemble du cycle de vie transactionnel.
Ce guide couvre la connexion de Stripe à un système existant, la gestion des paiements, la configuration des webhooks et l'automatisation de la facturation — de l'authentification initiale jusqu'aux erreurs courantes à éviter.
Prérequis à l'intégration Stripe
Avant de débuter, plusieurs éléments doivent être en place :
- Un compte Stripe (mode test activé par défaut)
- Une clé API disponible dans le tableau de bord (Dashboard → Developers → API keys)
- Un serveur backend capable d'effectuer des requêtes HTTPS vers l'API Stripe
- Un certificat SSL/TLS valide (Stripe refuse les connexions non sécurisées)
Stripe fournit deux paires de clés :
| Type | Usage |
|---|---|
sk_test_… |
Clé secrète de test (jamais côté client) |
pk_test_… |
Clé publique de test (côté frontend) |
sk_live_… |
Clé secrète de production |
pk_live_… |
Clé publique de production |
Les clés secrètes ne doivent jamais être exposées dans le code frontend. Elles transitent exclusivement par le serveur backend.
Authentification et configuration initiale
L'authentification Stripe repose sur le Bearer Token. Chaque requête vers l'API inclut la clé secrète dans l'en-tête Authorization.
curl https://api.stripe.com/v1/charges \
-u sk_test_VOTRE_CLE: \
-d amount=2000 \
-d currency=eur \
-d description="Paiement commande #1234" \
-d source=tok_visa
En Node.js, le SDK officiel simplifie l'initialisation :
const Stripe = require('stripe');
const stripe = Stripe('sk_test_VOTRE_CLE');
// Vérification de la connexion
const balance = await stripe.balance.retrieve();
console.log(balance.available);
En Python :
import stripe
stripe.api_key = "sk_test_VOTRE_CLE"
balance = stripe.Balance.retrieve()
print(balance['available'])
Créer un paiement avec Stripe API
Payment Intents : l'approche recommandée
Stripe recommande l'utilisation de Payment Intents pour tous les nouveaux projets. Ce flux gère nativement l'authentification forte (SCA), les paiements différés et la gestion des erreurs.
Le flux se déroule en trois étapes :
1. Création du Payment Intent côté serveur :
const paymentIntent = await stripe.paymentIntents.create({
amount: 5000, // en centimes
currency: 'eur',
metadata: {
order_id: 'CMD-2026-0042',
customer_reference: 'REF-ABC'
}
});
2. Confirmation côté client avec Stripe.js :
const { error } = await stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: cardElement,
billing_details: {
name: 'Jean Dupont'
}
}
});
3. Vérification côté serveur :
const intent = await stripe.paymentIntents.retrieve(paymentIntent.id);
if (intent.status === 'succeeded') {
// Mettre à jour la commande en base de données
await updateOrderStatus(orderId, 'paid');
}
Gérer les statuts de paiement
Un Payment Intent traverse plusieurs états :
| Statut | Signification |
|---|---|
requires_payment_method |
Aucune méthode de paiement fournie |
requires_confirmation |
Prêt à être confirmé |
requires_action |
Authentification supplémentaire requise (SCA) |
processing |
Paiement en cours de traitement |
succeeded |
Paiement validé |
requires_capture |
Autorisé mais non capturé |
canceled |
Paiement annulé |
Chaque transition de statut déclenche un événement webhook — un point crucial pour maintenir la synchronisation entre Stripe et le système interne.
Configurer les Stripe Webhooks
Les webhooks constituent le mécanisme central pour recevoir les événements de Stripe en temps réel. Sans eux, le système doit interroger l'API périodiquement (polling), ce qui est peu fiable et coûteux en ressources.
Enregistrement d'un endpoint webhook
Depuis le Dashboard Stripe (Developers → Webhooks) ou via l'API :
const webhook = await stripe.webhookEndpoints.create({
url: 'https://votre-domaine.com/api/stripe/webhook',
enabled_events: [
'payment_intent.succeeded',
'payment_intent.payment_failed',
'invoice.paid',
'invoice.payment_failed',
'customer.subscription.created',
'customer.subscription.deleted'
]
});
Vérification de la signature webhook
Chaque événement envoyé par Stripe inclut une signature dans l'en-tête Stripe-Signature. La vérification empêche les attaques par falsification :
const sig = request.headers['stripe-signature'];
const endpointSecret = 'whsec_VOTRE_SECRET';
let event;
try {
event = stripe.webhooks.constructEvent(
request.rawBody,
sig,
endpointSecret
);
} catch (err) {
response.status(400).send(`Webhook Error: ${err.message}`);
return;
}
// Traitement de l'événement
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
await fulfillOrder(paymentIntent);
break;
case 'invoice.paid':
const invoice = event.data.object;
await generateInvoicePDF(invoice);
break;
}
Événements essentiels à écouter
Pour un système de facturation complet, ces événements sont indispensables :
payment_intent.succeeded— Confirmer le paiement et déclencher la livraisonpayment_intent.payment_failed— Notifier et proposer un nouveau moyen de paiementinvoice.paid— Marquer la facture comme payée, archiverinvoice.payment_failed— Tenter une relance automatiquecustomer.subscription.updated— Synchroniser le plan d'abonnementcustomer.subscription.deleted— Révoquer les accès
Connecter Stripe à un système de facturation
Création de factures programmées
Stripe Billing automatise entièrement le cycle de facturation récurrente. La configuration passe par la création de produits et de prix :
// Création d'un produit
const product = await stripe.products.create({
name: 'Plan Professionnel',
description: 'Accès complet à la plateforme'
});
// Création d'un prix récurrent
const price = await stripe.prices.create({
product: product.id,
unit_amount: 4900,
currency: 'eur',
recurring: {
interval: 'month'
}
});
Abonnements clients
Un client Stripe regroupe les informations de paiement réutilisables :
const customer = await stripe.customers.create({
email: 'client@exemple.com',
name: 'Entreprise ABC',
metadata: {
internal_id: 'CLI-0042'
}
});
// Création de l'abonnement
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: price.id }],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent']
});
Gestion des factures
Chaque abonnement génère automatiquement des factures. La récupération se fait via l'API :
const invoices = await stripe.invoices.list({
customer: customer.id,
limit: 12,
status: 'paid'
});
// Génération du PDF de facture
const invoicePdf = await stripe.invoices.retrievePDF(invoice.id);
Stripe permet aussi la facturation ponctuelle (one-off) :
const invoiceItem = await stripe.invoiceItems.create({
customer: customer.id,
amount: 15000,
currency: 'eur',
description: 'Services de consulting - Mars 2026'
});
const invoice = await stripe.invoices.create({
customer: customer.id,
auto_advance: true // génère et envoie automatiquement
});
await stripe.invoices.finalizeInvoice(invoice.id);
await stripe.invoices.sendInvoice(invoice.id);
Automatisation et bonnes pratiques
Idempotency Keys
Chaque mutation de l'API Stripe devrait inclure une clé d'idempotence. Cette clé empêche la double exécution en cas de timeout ou de retry réseau :
const paymentIntent = await stripe.paymentIntents.create({
amount: 5000,
currency: 'eur',
}, {
idempotencyKey: `order-${orderId}-${Date.now()}`
});
Retry logique avec exponential backoff
Les appels API peuvent échouer temporairement (rate limit, timeout). Une stratégie de retry avec backoff exponentiel est recommandée :
async function stripeCall(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (err) {
if (err.statusCode === 429 || err.statusCode >= 500) {
const delay = Math.pow(2, i) * 1000 + Math.random() * 1000;
await new Promise(r => setTimeout(r, delay));
continue;
}
throw err;
}
}
throw new Error('Max retries exceeded');
}
Journalisation structurée
Chaque interaction avec Stripe devrait être journalisée avec les identifiants pertinents :
logger.info('Payment intent created', {
payment_intent_id: paymentIntent.id,
amount: paymentIntent.amount,
currency: paymentIntent.currency,
order_id: orderId,
timestamp: new Date().toISOString()
});
Gestion des échecs de paiement
Pour les abonnements, Stripe propose un mécanisme de relance automatique (Smart Retries) configurable :
await stripe.subscriptions.update(subscription.id, {
days_until_due: 14,
collection_method: 'send_invoice',
payment_settings: {
payment_method_types: ['card', 'sepa_debit']
}
});
Un webhook invoice.payment_failed déclenche la logique métier : notification email, suspension temporaire des accès, relance manuelle.
Tests et mode sandbox
Stripe fournit un ensemble de numéros de carte de test :
| Carte | Résultat |
|---|---|
4242 4242 4242 4242 |
Paiement réussi |
4000 0000 0000 0002 |
Paiement refusé |
4000 0025 0000 3155 |
Authentification 3D Secure requise |
4000 0000 0000 9995 |
Perte de carte |
L'utilisation du CLI Stripe permet de simuler des webhooks en local :
stripe listen --forward-to localhost:3000/api/stripe/webhook
stripe trigger payment_intent.succeeded
Migration de test à production
Le passage en production nécessite plusieurs vérifications :
- Remplacer les clés de test par les clés live (
sk_live_…/pk_live_…) - Activer le endpoint webhook en production avec un certificat SSL valide
- Configurer les méthodes de paiement activées pour chaque devise
- Activer Radar (anti-fraude) et définir les règles métier
- Configurer les notifications email (reçus, relances)
- Vérifier la conformité RGPD et PCI-DSS
Stripe gère la majeure partie de la conformité PCI-DSS (niveau 1), mais la gestion des données sensibles côté serveur reste de la responsabilité de l'intégrateur.
FAQ
Quels langages de programmation sont supportés par Stripe ?
Stripe propose des SDK officiels pour Ruby, Python, PHP, Java, Node.js, Go, .NET et Java. Une API REST est disponible pour tout autre langage. La documentation inclut des exemples pour chaque SDK.
Comment gérer les remboursements via l'API ?
Les remboursements s'effectuent via l'endpoint dédié :
const refund = await stripe.refunds.create({
payment_intent: 'pi_3AbcDefGhiJkl',
amount: 2500 // remboursement partiel (en centimes)
});
Un remboursement total se fait en omettant le paramètre amount. Le webhook charge.refunded notifie le système.
Stripe supporte-t-il les paiements SEPA ?
Oui. Stripe supporte SEPA Direct Debit pour les prélèvements en euros dans les 36 pays de la zone SEPA. La configuration nécessite l'activation dans le Dashboard et l'utilisation du type de paiement sepa_debit. Le cycle de confirmation est plus long que pour les cartes (2-4 jours ouvrés).
Que faire en cas de webhook manqué ?
Stripe propose un mécanisme de retry automatique pendant 72 heures avec un backoff exponentiel. En cas d'échec définitif, l'événement apparaît dans la section "Failed webhooks" du Dashboard. Une API permet de relister les événements récents :
const events = await stripe.events.list({
type: 'payment_intent.succeeded',
created: { gte: Math.floor(Date.now() / 1000) - 86400 }
});
Comment sécuriser l'intégration Stripe ?
Les bonnes pratiques incluent : validation côté serveur de tous les montants, utilisation systématique des clés d'idempotence, vérification des signatures webhook, activation de Radar pour la détection de fraude, restriction des méthodes de paiement aux seules devises supportées, et audit régulier des logs Stripe.