# Utiliser Stripe pour accepter des paiements avec SCA

> Formspree Docs · Plugins · 28 février 2026

#### Disponible avec les plans : Free (mode test), Professional, Business

Stripe est une plateforme de traitement des paiements qui permet aux marchands d'accepter des paiements par carte bancaire sur leurs applications et sites web. Lorsque vous connectez votre formulaire à un compte Stripe, vous pouvez effectuer des prélèvements et recevoir des paiements depuis votre site web.

**Quoi de nouveau ?**  
Le plugin Stripe (V2) prend désormais en charge la validation côté serveur des paiements, les montants variables pour les dons et l'[authentification forte du client](https://stripe.com/docs/strong-customer-authentication) (SCA) optionnelle.

L'Authentification Forte du Client (SCA) est une réglementation entrée en vigueur le 14 septembre 2019. Elle impose des changements dans la façon dont les clients européens authentifient les paiements en ligne. Cette réglementation s'[applique](https://stripe.com/docs/strong-customer-authentication#impact) uniquement aux paiements en ligne où la banque du client et l'entreprise sont toutes deux situées dans l'[Espace Économique Européen](https://en.wikipedia.org/wiki/European_Economic_Area) (EEE).

Vous pouvez savoir si vous utilisez le nouveau plugin Stripe V2 si les paramètres de votre plugin affichent une Stripe Publishable Key. Si vous ne voyez pas la Publishable Key, vous pouvez mettre à jour votre plugin vers la dernière version en le supprimant et en le reconnectant. Aucune donnée ne sera perdue.

## Étape 1 : Connexion à Stripe

### Mode Test vs Mode Live

Le mode test et le mode live fonctionnent de manière presque identique, avec quelques différences nécessaires :

-   En mode test, les paiements ne sont pas traités par les réseaux de cartes ou les prestataires de paiement, et seules nos [informations de paiement de test](https://stripe.com/docs/testing) peuvent être utilisées.
-   Certaines méthodes de paiement utilisant des [Sources](https://stripe.com/docs/sources) ont un flux plus nuancé en mode live, avec plus d'étapes requises qu'en mode test.
-   Les litiges ont également un flux plus nuancé en mode live, et un [processus de test](https://stripe.com/docs/testing#disputes) plus simple.
-   En mode test, les [webhooks](https://stripe.com/docs/webhooks) non acquittés avec succès sont réessayés trois fois sur quelques heures (contre 72 heures en mode live).

Pour voir les prélèvements de test, accédez à votre tableau de bord Stripe et cliquez sur View Test Data.

![mceclip0.png](/images/zendesk/9479210aa8c1e005.png)

_**Attention : si vous souhaitez passer du Mode Test au Mode Live, vous devrez supprimer et recréer le plugin pour obtenir de nouvelles identifiants valides via Stripe OAuth.**_

_Nous vous suggérons de connecter un formulaire de développement/staging au mode test et un formulaire de production au mode live._

### Configurer le plugin Stripe

Une fois votre formulaire ajouté dans Formspree, vous pouvez vous connecter à Stripe via le plugin Stripe. Pour ce faire, rendez-vous d'abord dans l'onglet Plugins de votre formulaire. Cliquez ensuite sur le bouton du plugin Stripe.

![mceclip0.png](/images/zendesk/e61d8f0b2e0b9e6c.png)

Après avoir cliqué sur le bouton du plugin Stripe, vous pourrez vous connecter en mode Test ou Live.  
Le **mode Test** est disponible pour tous les plans. Le **mode Live** est disponible uniquement pour les plans payants.

![mceclip4.png](/images/zendesk/ac89283388ab406b.png)

Sélectionnez le mode souhaité et cliquez sur Connexion. Une fois connecté avec votre identifiant et mot de passe Stripe, vous serez invité à définir les informations de prélèvement Stripe pour ce formulaire. Définissez la devise et le prix qui sera facturé à chaque soumission du formulaire.

Cliquer sur **allow variable price** permettra au développeur ou au visiteur du site de définir le prix côté client. Cela permet à un formulaire de facturer un montant variable, par exemple pour un don. Cela peut également être utilisé pour permettre à un même formulaire de facturer des prix différents selon d'autres facteurs, comme un produit sélectionné. Une fois **allow variable price** activé, le prix sera lu depuis le champ de formulaire **price**.

_**Attention : si la tarification variable est activée, tout client peut modifier cette valeur directement, ou en décompilant votre code, et créer des prélèvements pour n'importe quel montant. Assurez-vous de vérifier les prélèvements envoyés à votre compte Stripe. Nous ne validons pas cette valeur.**_

![mceclip0.png](/images/zendesk/f97e2f49dac06df8.png)

Une fois la configuration terminée, cliquez sur **Connect** pour activer le plugin.

À l'avenir, si vous souhaitez modifier la description et le prix ou désactiver entièrement le plugin, vous pouvez le faire en cliquant à nouveau sur le bouton Stripe pour ajuster ses paramètres.

Une fois la configuration et la connexion de votre plugin Stripe terminées, vous verrez ce message :

![mceclip1.png](/images/zendesk/e07fed14e1716088.png)

Copiez la **Publishable Key**. Nous l'utiliserons pour construire notre flux de paiement.

## Étape 2 : Construire votre flux de paiement avec Stripe Elements (sans SCA)

**REMARQUE** : Si vous utilisez React, consultez notre tutoriel sur [Comment créer un formulaire de paiement React personnalisé avec Stripe](https://formspree.io/blog/custom-payment-stripe/).

Maintenant que vous avez configuré votre formulaire Formspree avec le plugin Stripe, il est temps de construire votre flux de paiement. Pour effectuer des prélèvements, vous devez tokeniser une carte bancaire afin de l'envoyer en toute sécurité à Formspree.

Une façon simple de le faire est d'utiliser [Stripe Elements](https://stripe.com/payments/elements). C'est un ensemble de composants d'interface utilisateur préconstruits, tels que des champs et des boutons, pour construire votre flux de paiement. Il est disponible comme fonctionnalité de Stripe.js. Stripe.js _tokenise_ les informations sensibles contenues dans un Element sans qu'elles ne transitent jamais par vos serveurs ou les nôtres.

Il vous suffit ensuite d'envoyer la méthode de paiement tokenisée à Formspree, qui créera et facturera le paiement.

Voici un exemple inspiré de la [documentation Stripe](https://stripe.com/docs/payments/accept-a-payment-synchronously) :

**Fichier HTML**

```html
<head>
  <title>Checkout</title>
  <script src="https://js.stripe.com/v3/"></script>
  <script src="https://code.jquery.com/jquery-latest.min.js"></script>
 </head>

 <body>
   <form id="payment-form" action="">
     <div id="card-element">
       <!-- Elements will create input elements here -->
     </div>

     <!-- We'll put the error messages in this element -->
     <div id="card-errors" role="alert"></div>

     <button id="submit">Pay</button>
   </form>
 </body>
```

**Fichier JS**

```javascript
$(document).ready(function () {
  // Stripe settings
  var stripe = Stripe("YOUR_PUBLISHABLE_KEY_COPIED_FROM_DASHBOARD");
  var elements = stripe.elements();
  var style = {
    base: {
      color: "#32325d",
    },
  };
  var card = elements.create("card", {
    style: style,
  });

  card.mount("#card-element");
  card.on("change", ({ error }) => {
    const displayError = document.getElementById("card-errors");
    if (error) {
      displayError.textContent = error.message;
    } else {
      displayError.textContent = "";
    }
  });
  // end stripe

  var form = document.getElementById("payment-form");
  form.addEventListener("submit", function (event) {
    event.preventDefault();
    // Tokenize card info
    stripe
      .createPaymentMethod({
        type: "card",
        card: card,
        billing_details: {
          // Include any additional collected billing details.
          name: "Jenny Rosen",
          email: "jenny@rosen.com",
        },
      })
      .then(stripePaymentMethodHandler);
  });

  function stripePaymentMethodHandler(result) {
    if (result.error) {
      // Show error to user
      console.log(result.error);
    } else {
      // Otherwise send payment method to your server
      fetch("https://formspree.io/f/FORM_ID", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          // Send the tokenized card
          paymentMethod: result.paymentMethod.id,
          email: "jenny@rosen.com",
          // add here any data that you want to send to Formspree
        }),
      }).then(function (result) {
        // Handle server response
        result.json().then(function (json) {
          handleServerResponse(json);
        });
      });
    }
  }

  function handleServerResponse(response) {
    if (response.error) {
      // Display errors on the payment form
      console.log(response.error);
    } else {
      // Display a success message
      console.log("Payment finished successfully");
    }
  }
});
```

Pour styliser vos éléments Stripe, consultez [cet exemple](https://gist.github.com/colevscode/9cf19623e157cbe6822ffb8bd6e707fb), ou nos exemples de styles de réinitialisation de formulaire [ici](https://gist.github.com/colevscode/ce67075b62f843b7e95b1d5a1370035b).

À ce stade, vous disposez d'un formulaire fonctionnel capable d'effectuer des prélèvements pour les titulaires de cartes hors UE.

## Étape 3 : (Optionnel) Prendre en charge les paiements SCA

Après avoir terminé l'étape 2, votre formulaire devrait soumettre correctement et créer des prélèvements dans Stripe. Cependant, si la SCA est requise par la banque du soumissionnaire, le formulaire générera une erreur. Pour prendre en charge la SCA, nous devons ajouter une étape supplémentaire au flux précédent.

Lors de la première requête, le serveur Formspree tentera de créer un [Payment Intent](https://stripe.com/docs/payments/payment-intents) et de le débiter. Si la carte nécessite une action supplémentaire comme la SCA, le prélèvement échouera et le payment intent retournera un statut `requires_action`.

Le serveur Formspree retournera un statut HTTP 402 avec les informations suivantes :

-   L'identifiant du payment intent créé
-   Un secret client du payment intent qui sera utilisé pour faire une requête à Stripe afin de valider le paiement
-   Un `resubmit_key` qui sera utilisé pour renvoyer la requête à Formspree une fois le paiement validé

#### **Exemple de corps de réponse**

```javascript
{
  "message": "requires_action",
  "resubmitKey": <key_generated_by_formspree>,
  "stripe": {
    "paymentIntentId": <id_from_the_payment_intent>,
    "paymentIntentClientSecret": <secret_generated_by_stripe>,
    "requiresAction": true
  }
}
```

Nous pouvons maintenant valider le paiement en appelant la fonction [handleCardAction](https://stripe.com/docs/js/payment_intents/handle_card_action) de Stripe, en envoyant le `payment_intent_client_secret`. Cela effectuera toute validation côté client requise, comme l'ouverture du [Modal 3DS](https://stripe.com/docs/payments/3d-secure) pour compléter la SCA.

L'exemple suivant montre comment mettre à jour la fonction `handleServerResponse()` créée à l'étape précédente pour intercepter toutes les actions requises. Elle renvoie ensuite le formulaire avec le payment intent et le nouveau `resubmit_key`.

**Exemple JS**

```javascript
function handleServerResponse(response) {
  if (response.error) {
    // Show error from server on payment form
    console.log(response.error);
  } else if (response && response.stripe.requiresAction) {
    // Stripe require additional actions to charge this card
    // Use Stripe.js to handle required card action and open 3DS
    stripe
      .handleCardAction(response.stripe.paymentIntentClientSecret)
      .then(function (stripeResult) {
        // TODO: implement this function to resubmit the form
        resubmitForm(stripeResult, response.resubmitKey);
      });
  } else {
    console.log("Payment finished successfully");
  }
}
```

#### **Modal Stripe 3DS**

![mceclip2.png](/images/zendesk/dcb1c309939d07c1.png)

Si la fonction [handleCardAction](https://stripe.com/docs/js/payment_intents/handle_card_action) réussit, vous pouvez maintenant renvoyer le formulaire à Formspree en incluant le `resubmit_key` et le `paymentIntent` reçus précédemment après la première tentative échouée.

**Exemple de renvoi du formulaire :**

```javascript
function resubmitForm(result, resubmitKey) {
  console.log("handle Stripe SCA result");
  if (result.error) {
    // Show error in payment form
    console.log("Stripe SCA error");
  } else {
    // The card action has been handled
    // The PaymentIntent can be confirmed again on the server
    fetch('https://formspree.io/f/', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ 
        paymentIntent: result.paymentIntent.id ,
        resubmitKey: resubmitKey,
        email: 'jenny@rosen.com',
      })
    }).then(function(result) {
      return result.json();
    }).then(handleServerResponse);
  }
}
```

Lorsque Formspree reçoit la deuxième soumission, il tentera à nouveau de débiter le payment intent avec les informations de carte qui devraient avoir été validées côté client via le flux SCA de Stripe. Vous pouvez renvoyer les mêmes champs que ceux de la soumission initiale. Toute modification de ces champs mettra à jour les données du formulaire.

Sachez que le `resubmit_key` expirera s'il n'est pas utilisé dans un délai raisonnable. Dans ce cas, Formspree retournera un code de statut HTTP 404.

## Récapitulatif

En résumé, les étapes sont :

1.  Tentez de débiter la carte. Si la SCA est requise, une réponse 402 est retournée avec les données du payment intent et le resubmit key.
2.  Appelez handleCardAction de Stripe avec le secret client du payment intent retourné lors de la première tentative et effectuez le [3DS](https://stripe.com/docs/payments/3d-secure).
3.  Renvoyez le formulaire en incluant le resubmit key, l'identifiant du payment intent et l'e-mail. Formspree retentera le prélèvement pour finaliser la soumission.

Consultez le flux de paiement complet avec SCA :

**Fichier JS (SCA)**

```javascript
$(document).ready(function () {
  // Stripe settings
  var stripe = Stripe("YOUR_PUBLISHABLE_KEY_COPIED_FROM_DASHBOARD");
  var elements = stripe.elements();
  var style = {
    base: {
      color: "#32325d",
    },
  };
  var card = elements.create("card", {
    style: style,
  });

  card.mount("#card-element");
  card.on("change", ({ error }) => {
    const displayError = document.getElementById("card-errors");
    if (error) {
      displayError.textContent = error.message;
    } else {
      displayError.textContent = "";
    }
  });
  // end stripe

  var form = document.getElementById("payment-form");
  form.addEventListener("submit", function (ev) {
    event.preventDefault();

    stripe
      .createPaymentMethod({
        type: "card",
        card: card,
        billing_details: {
          // Include any additional collected billing details.
          name: "Jenny Rosen",
          email: "jenny@rosen.com",
        },
      })
      .then(stripePaymentMethodHandler);
  });

  function stripePaymentMethodHandler(result) {
    if (result.error) {
      console.log("Error creating payment method");
    } else {
      // First submission attempt
      fetch("https://formspree.io/f/FORM_ID", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          paymentMethod: result.paymentMethod.id,
          email: "jenny@rosen.com",
        }),
      }).then(function (response) {
        // Handle server response (see Step 4)
        response.json().then(function (json) {
          handleServerResponse(json);
        });
      });
    }
  }

  function handleServerResponse(response) {
    if (response.stripe && response.stripe.requiresAction) {
      // Stripe require additional actions to charge this card
      // Use Stripe.js to handle required card action and open 3DS
      stripe
        .handleCardAction(response.stripe.paymentIntentClientSecret)
        .then(function (stripeResult) {
          // Get handleCardAction response and resubmit
          resubmitForm(stripeResult, response.resubmitKey);
        });
    } else if (response.error) {
      // Show error from server on payment form
      console.log(response.error);
    } else {
      console.log("Payment finished successfully");
    }
  }

  function resubmitForm(result, resubmitKey) {
    console.log("handle Stripe SCA result");
    if (result.error) {
      // Display error in the payment form
      console.log("Stripe SCA error");
    } else {
      // The card action has been handled
      // The PaymentIntent can be confirmed again on the server
      fetch("https://formspree.io/f/FORM_ID", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          paymentIntent: result.paymentIntent.id,
          resubmitKey: resubmitKey,
          email: "jenny@rosen.com",
        }),
      })
        .then(function (confirmResult) {
          return confirmResult.json();
        })
        .then(handleServerResponse);
    }
  }
});
```

Pour en savoir plus sur les tests avec Stripe et Stripe SCA, consultez [https://stripe.com/docs/testing](https://stripe.com/docs/testing) et notre [article de blog](https://formspree.io/blog/custom-payment-stripe/).
