# Paiements pour les clients existants

Découvrez comment débiter un moyen de paiement existant pendant une session.

# Flux personnalisé


Le composant Payment Element permet aux clients de saisir leurs informations de paiement. Pour un client existant, vous pouvez configurer un composant Customer Session dans le composant Payment Element afin d’afficher ses [moyens de paiement existants](https://docs.stripe.com/payments/save-and-reuse.md?platform=web&ui=elements).
![Payment Element avec une carte bancaire enregistrée](https://b.stripecdn.com/docs-statics-srv/assets/saved_card.9ae121fe039c6d963f3c9831eb92172f.png)

Le composant Payment Element peut uniquement afficher les types de moyens de paiement enregistrés suivants&nbsp;:

- `card`
- `link`
- `us_bank_account`
- `acss_debit`
- `sepa_debit`
- `bacs_debit`
- `au_becs_debit`
- `nz_bank_account`
- `ideal`
- `sofort`
- `bancontact`

## Créer un PaymentIntent et une CustomerSession [Côté serveur]

Créez un [PaymentIntent](https://docs.stripe.com/api/payment_intents/create.md) et une [CustomerSession](https://docs.stripe.com/api/customer_sessions/create.md). Veillez à transmettre l’identifiant `Customer` ou `Account` existant et à activer la fonctionnalité `payment_method_redisplay`.

> #### Utiliser l’API Accounts v2 pour représenter les clients
> 
> L’API Accounts&nbsp;v2 est généralement disponible pour les utilisateurs de Connect et en aperçu public pour les autres utilisateurs de Stripe. Si vous avez accès à l’aperçu Accounts&nbsp;v2, vous devez spécifier une [version d’aperçu](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) dans votre code.
> 
> Pour accéder à l’aperçu Accounts&nbsp;v2, rendez-vous sur [aperçus et fonctionnalités de Account](https://dashboard.stripe.com/settings/previews) dans votre Dashboard et activez **Moyens de paiement réutilisables pour les virements internationaux**.
> 
> Dans la plupart des cas d’usage, nous vous recommandons de [modéliser vos clients en tant qu’objets Account configurés par le client](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md), plutôt que d’utiliser des objets [Customer](https://docs.stripe.com/api/customers.md).

#### Accounts&nbsp;v2

#### Ruby

```ruby

# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
# Find your keys at https://dashboard.stripe.com/apikeys.
client = Stripe::StripeClient.new('<<YOUR_SECRET_KEY>>')

post '/create-intent-and-customer-session' do
  intent = client.v1.payment_intents.create({
    amount: 1099,
    currency: 'usd',
    automatic_payment_methods: {enabled: true},
    customer_account: {{CUSTOMER_ACCOUNT_ID}},
  })
  customer_session = client.v1.customer_sessions.create({
    customer_account: {{CUSTOMER_ACCOUNT_ID}},
    components: {
      payment_element: {
          enabled: true,
          features: {
            payment_method_redisplay: 'enabled',
          },
        },
    },
  })
  {
    client_secret: intent.client_secret,
    customer_session_client_secret: customer_session.client_secret
  }.to_json
end
```

#### Customers&nbsp;v1

#### Ruby

```ruby

# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
# Find your keys at https://dashboard.stripe.com/apikeys.
client = Stripe::StripeClient.new('<<YOUR_SECRET_KEY>>')

post '/create-intent-and-customer-session' do
  intent = client.v1.payment_intents.create({
    amount: 1099,
    currency: 'usd',
    # In the latest version of the API, specifying the `automatic_payment_methods` parameter
    # is optional because Stripe enables its functionality by default.
    automatic_payment_methods: {enabled: true},
    customer: {{CUSTOMER_ID}},
  })
  customer_session = client.v1.customer_sessions.create({
    customer: {{CUSTOMER_ID}},
    components: {
      payment_element: {
          enabled: true,
          features: {
            payment_method_redisplay: 'enabled',
          },
        },
    },
  })
  {
    client_secret: intent.client_secret,
    customer_session_client_secret: customer_session.client_secret
  }.to_json
end
```

## Optional: Afficher les moyens de paiement enregistrés supplémentaires [Côté serveur]

> #### Conformité
> 
> Lorsque vous enregistrez les informations de paiement d’un client, vous êtes responsable du respect de l’ensemble des lois, réglementations et règles du réseau en vigueur. Lorsque vous offrez à un client la possibilité d’utiliser d’anciens moyens de paiement en vue d’achats futurs, assurez-vous d’avoir obtenu le consentement de vos clients à l’enregistrement des informations de paiement aux fins d’un futur achat.

Par défaut, nous affichons uniquement les moyens de paiement configurés pour [permettre toujours le réaffichage](https://docs.stripe.com/api/payment_methods/object.md#payment_method_object-allow_redisplay).

Vous ne pouvez pas réutiliser Apple Pay et Google Pay au cours d’une même session de paiement. Par conséquent, ces moyens de paiement n’apparaissent pas dans la liste des options enregistrées. Vous devez afficher l’interface utilisateur de Google Pay et d’Apple Pay, ainsi que le bouton de demande de paiement, chaque fois que la session de paiement est active.

Vous pouvez afficher d’autres moyens de paiement précédemment enregistrés en incluant d’autres valeurs de réaffichage dans la session de paiement ou en mettant à jour le paramètre `allow_redisplay` d’un moyen de paiement sur `always`.

- Utilisez le [paramètre](https://docs.stripe.com/api/customer_sessions/create.md#create_customer_session-components-payment_element-features-payment_method_allow_redisplay_filters) `payment_method_allow_redisplay_filters` pour spécifier les moyens de paiement enregistrés à afficher dans le Payment Element. Vous pouvez définir n’importe laquelle des valeurs valides&nbsp;: `limited`, `unspecified` et `always`.

  #### Accounts&nbsp;v2

  ```curl
  curl https://api.stripe.com/v1/customer_sessions \
    -u "<<YOUR_SECRET_KEY>>:" \
    -d "customer_account={{CUSTOMERACCOUNT_ID}}" \
    -d "components[payment_element][enabled]=true" \
    -d "components[payment_element][features][payment_method_redisplay]=enabled" \
    -d "components[payment_element][features][payment_method_allow_redisplay_filters][]=always" \
    -d "components[payment_element][features][payment_method_allow_redisplay_filters][]=limited" \
    -d "components[payment_element][features][payment_method_allow_redisplay_filters][]=unspecified"
  ```

  #### Customers&nbsp;v1

  ```curl
  curl https://api.stripe.com/v1/customer_sessions \
    -u "<<YOUR_SECRET_KEY>>:" \
    -d "customer={{CUSTOMER_ID}}" \
    -d "components[payment_element][enabled]=true" \
    -d "components[payment_element][features][payment_method_redisplay]=enabled" \
    -d "components[payment_element][features][payment_method_allow_redisplay_filters][]=always" \
    -d "components[payment_element][features][payment_method_allow_redisplay_filters][]=limited" \
    -d "components[payment_element][features][payment_method_allow_redisplay_filters][]=unspecified"
  ```

- [Mettez à jour le moyen de paiement](https://docs.stripe.com/api/payment_methods/update.md) pour définir la valeur `allow_redisplay` des moyens de paiement individuels.
  ```curl
  curl https://api.stripe.com/v1/payment_methods/{{PAYMENTMETHOD_ID}} \
    -u "<<YOUR_SECRET_KEY>>:" \
    -d allow_redisplay=always
  ```

## Afficher le Payment Element [Côté client]

#### HTML + JS

### Configurer Stripe.js

Incluez le script Stripe .js sur votre page de paiement en l’ajoutant dans le champ `head` de votre fichier HTML. Chargez toujours Stripe.js directement à partir de js.stripe.com pour rester en conformité avec la norme PCI. N’incluez pas le script dans un lot et n’en hébergez pas de copie vous-même.

```html
<head>
  <title>Checkout</title>
  <script src="https://js.stripe.com/endive/stripe.js"></script>
</head>
```

Créez une instance de Stripe avec le code JavaScript suivant sur votre page de paiement&nbsp;:

```javascript
// Set your publishable key: remember to change this to your live publishable key in production
// See your keys here: https://dashboard.stripe.com/apikeys
const stripe = Stripe('<<YOUR_PUBLISHABLE_KEY>>');
```

### Ajouter l’Element Payment à votre page de paiement

Le composant Element Payment doit avoir un emplacement dédié dans votre page de paiement. Créez un nœud DOM (conteneur) vide doté d’un ID unique dans votre formulaire de paiement&nbsp;:

```html
<form id="payment-form">
  <div id="payment-element">
    <!-- Elements will create form elements here -->
  </div>
  <button id="submit">Submit</button>
  <div id="error-message">
    <!-- Display error message to your customers here -->
  </div>
</form>
```

Récupérez les deux `clients_secret` de l’étape précédente pour initialiser l’Element. Ensuite, créez et montez le Payment Element.

```javascript
// Fetch the two `client_secret`
const response = await fetch('/create-intent-and-customer-session', { method: "POST" });
const { client_secret, customer_session_client_secret } = await response.json();

// Initialize Elements
const elements = stripe.elements({
  clientSecret: client_secret,
  customerSessionClientSecret: customer_session_client_secret,
});

// Create and mount the Payment Element
const paymentElementOptions = { layout: 'accordion'};
const paymentElement = elements.create('payment', paymentElementOptions);
paymentElement.mount('#payment-element');
```

#### React

### Configurer Stripe.js

Installez [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) et le [chargeur Stripe.js](https://www.npmjs.com/package/@stripe/stripe-js) à partir du registre public&nbsp;npm&nbsp;:

```bash
npm install --save @stripe/react-stripe-js @stripe/stripe-js
```

### Ajouter et configurer le fournisseur Elements sur votre page de paiement

Récupérez les deux `clients_secret` de l’étape précédente pour initialiser le [fournisseur d’Elements](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Affichez ensuite le composant CheckoutForm qui contient le formulaire de paiement.

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {Elements} from '@stripe/react-stripe-js';
import {loadStripe} from '@stripe/stripe-js';
import CheckoutForm from './CheckoutForm';

// Make sure to call `loadStripe` outside of a component's render to avoid
// recreating the `Stripe` object on every render.
const stripePromise = loadStripe('<<YOUR_PUBLISHABLE_KEY>>');

function App() {
  const [clientSecret, setClientSecret] = useState("");
  const [customerSessionClientSecret, setCustomerSessionClientSecret] = useState("");

  // Fetch the two `client_secret`
  useEffect(() => {
    fetch("/create-intent-and-customer-session", { method: "POST" })
      .then((res) => res.json())
      .then((data) => {
        setClientSecret(data.client_secret);
        setCustomerSessionClientSecret(data.customer_session_client_secret);
      });
  }, []);

  // Initialize the Element provider once we we received the two `client_secret`
  // And render the CheckoutForm
  return (
    <div>
      {clientSecret && customerSessionClientSecret && (
        <Elements stripe={stripePromise} options={{clientSecret, customerSessionClientSecret}}>
          <CheckoutForm />
        </Elements>
      )}
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
```

### Ajouter le composant Payment Element

Utilisez le composant `PaymentElement` pour afficher le formulaire de paiement.

```jsx
import React from 'react';
import {PaymentElement} from '@stripe/react-stripe-js';

const CheckoutForm = () => {
  return (
    <form>
      <PaymentElement />
      <button>Submit</button>
    </form>
  );
};

export default CheckoutForm;
```

## Envoyer le paiement à Stripe [Côté client]

Utilisez [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) pour effectuer le paiement à l’aide des informations du composant Payment&nbsp;Element. Ajoutez un paramètre [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) à cette fonction pour indiquer la page vers laquelle Stripe doit rediriger l’utilisateur à l’issue du paiement. Votre utilisateur peut être redirigé en premier lieu vers un site intermédiaire, comme une page d’autorisation bancaire, avant d’être redirigé vers la page spécifiée par le paramètre `return_url`. L’utilisateur sera immédiatement redirigé vers la page `return_url` après un paiement réussi par carte.

Si vous ne souhaitez pas effectuer de redirection à la fin des paiements par carte, vous pouvez assigner au paramètre [redirect](https://docs.stripe.com/js/payment_intents/confirm_payment#confirm_payment_intent-options-redirect) la valeur `if_required`. De cette manière, seuls les clients qui choisissent un moyen de paiement avec redirection seront redirigés.

#### HTML + JS

```javascript
const form = document.getElementById('payment-form');

form.addEventListener('submit', async (event) => {
  event.preventDefault();

  const {error} = await stripe.confirmPayment({
    //`Elements` instance that was used to create the Payment Element
    elements,
    confirmParams: {
      return_url: 'https://example.com/order/123/complete',
    },
  });

  if (error) {
    // This point will only be reached if there is an immediate error when
    // confirming the payment. Show error to your customer (for example, payment
    // details incomplete)
    const messageContainer = document.querySelector('#error-message');
    messageContainer.textContent = error.message;
  } else {
    // Your customer will be redirected to your `return_url`. For some payment
    // methods like iDEAL, your customer will be redirected to an intermediate
    // site first to authorize the payment, then redirected to the `return_url`.
  }
});
```

#### React

Pour appeler [stripe.confirmPayment](https://docs.stripe.com/js/payment_intents/confirm_payment) depuis votre composant de formulaire de paiement, utilisez les hooks [useStripe](https://docs.stripe.com/sdks/stripejs-react.md?ui=elements#usestripe-hook) et [useElements](https://docs.stripe.com/sdks/stripejs-react.md?ui=elements#useelements-hook).

Si vous préférez les composants de classe traditionnels aux hooks, vous pouvez utiliser un [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md?ui=elements#elements-consumer).

```jsx
import React, {useState} from 'react';
import {useStripe, useElements, PaymentElement} from '@stripe/react-stripe-js';

const CheckoutForm = () => {
  const stripe = useStripe();
  const elements = useElements();

  const [errorMessage, setErrorMessage] = useState(null);

  const handleSubmit = async (event) => {
    // We don't want to let default form submission happen here,
    // which would refresh the page.
    event.preventDefault();

    if (!stripe || !elements) {
      // Stripe.js hasn't yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return;
    }

    const {error} = await stripe.confirmPayment({
      //`Elements` instance that was used to create the Payment Element
      elements,
      confirmParams: {
        return_url: 'https://example.com/order/123/complete',
      },
    });


    if (error) {
      // This point will only be reached if there is an immediate error when
      // confirming the payment. Show error to your customer (for example, payment
      // details incomplete)
      setErrorMessage(error.message);
    } else {
      // Your customer will be redirected to your `return_url`. For some payment
      // methods like iDEAL, your customer will be redirected to an intermediate
      // site first to authorize the payment, then redirected to the `return_url`.
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      <button disabled={!stripe}>Submit</button>
      {/* Show error message to your customers */}
      {errorMessage && <div>{errorMessage}</div>}
    </form>
  );
};

export default CheckoutForm;
```

Veillez à ce que le paramètre `return_url` corresponde à une page de votre site web qui indique l’état du paiement. Lorsque Stripe redirige le client vers la page `return_url`, nous fournissons les paramètres de requête d’URL suivants&nbsp;:

| Paramètre                      | Description                                                                                                                                       |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `payment_intent`               | L’identifiant unique du `PaymentIntent`.                                                                                                          |
| `payment_intent_client_secret` | La [clé secrète du client](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) de l’objet `PaymentIntent`. |

> Si vous disposez d’outils qui assurent le suivi de la session navigateur du client, vous devrez peut-être ajouter le domaine `stripe.com` à la liste d’exclusion des sites référents. Les redirections font que certains outils créent de nouvelles sessions, ce qui empêche le suivi de la session dans son ensemble.

Utilisez l’un des paramètres de requête pour récupérer le PaymentIntent. Consultez l’[état du PaymentIntent](https://docs.stripe.com/payments/paymentintents/lifecycle.md) pour déterminer les informations à présenter à vos clients. Vous pouvez également ajouter vos propres paramètres de requête lorsque vous ajoutez l’URL `return_url`&nbsp;; ils seront conservés tout au long du processus de redirection.

#### HTML + JS

```javascript

// Initialize Stripe.js using your publishable key
const stripe = Stripe('<<YOUR_PUBLISHABLE_KEY>>');

// Retrieve the "payment_intent_client_secret" query parameter appended to
// your return_url by Stripe.js
const clientSecret = new URLSearchParams(window.location.search).get(
  'payment_intent_client_secret'
);

// Retrieve the PaymentIntent
stripe.retrievePaymentIntent(clientSecret).then(({paymentIntent}) => {
  const message = document.querySelector('#message')

  // Inspect the PaymentIntent `status` to indicate the status of the payment
  // to your customer.
  //
  // Some payment methods will [immediately succeed or fail][0] upon
  // confirmation, while others will first enter a `processing` state.
  //
  // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification
  switch (paymentIntent.status) {
    case 'succeeded':
      message.innerText = 'Success! Payment received.';
      break;

    case 'processing':
      message.innerText = "Payment processing. We'll update you when payment is received.";
      break;

    case 'requires_payment_method':
      message.innerText = 'Payment failed. Please try another payment method.';
      // Redirect your user back to your payment page to attempt collecting
      // payment again
      break;

    default:
      message.innerText = 'Something went wrong.';
      break;
  }
});
```

#### React

```jsx
import React, {useState, useEffect} from 'react';
import {useStripe} from '@stripe/react-stripe-js';

const PaymentStatus = () => {
  const stripe = useStripe();
  const [message, setMessage] = useState(null);

  useEffect(() => {
    if (!stripe) {
      return;
    }

    // Retrieve the "payment_intent_client_secret" query parameter appended to
    // your return_url by Stripe.js
    const clientSecret = new URLSearchParams(window.location.search).get(
      'payment_intent_client_secret'
    );

    // Retrieve the PaymentIntent
    stripe
      .retrievePaymentIntent(clientSecret)
      .then(({paymentIntent}) => {
        // Inspect the PaymentIntent `status` to indicate the status of the payment
        // to your customer.
        //
        // Some payment methods will [immediately succeed or fail][0] upon
        // confirmation, while others will first enter a `processing` state.
        //
        // [0]: https://stripe.com/docs/payments/payment-methods#payment-notification
        switch (paymentIntent.status) {
          case 'succeeded':
            setMessage('Success! Payment received.');
            break;

          case 'processing':
            setMessage("Payment processing. We'll update you when payment is received.");
            break;

          case 'requires_payment_method':
            // Redirect your user back to your payment page to attempt collecting
            // payment again
            setMessage('Payment failed. Please try another payment method.');
            break;

          default:
            setMessage('Something went wrong.');
            break;
        }
      });
  }, [stripe]);


  return message;
};

export default PaymentStatus;
```

### Collecter les informations du wallet

Si vous acceptez Apple Pay ou Google Pay, appelez [elements.submit()](https://docs.stripe.com/js/elements/submit) au début de votre gestionnaire de soumission. Cela déclenche la validation du formulaire et affiche la page de paiement native pour que votre client puisse autoriser le paiement.

#### HTML + JS

```javascript
form.addEventListener('submit', async (event) => {
  event.preventDefault();

  // Trigger form validation and wallet collection
  const {error: submitError} = await elements.submit();
  if (submitError) {
    handleError(submitError);
    return;
  }

  // Confirm the payment
});
```

#### React

```jsx
const handleSubmit = async (event) => {
  event.preventDefault();

  if (!stripe || !elements) {
    // Stripe.js hasn't yet loaded.
    // Make sure to disable form submission until Stripe.js has loaded.
    return;
  }

  // Trigger form validation and wallet collection
  const {error: submitError} = await elements.submit();
  if (submitError) {
    handleError(submitError);
    return;
  }

  // Confirm the payment
};
```

## Gérer les événements post-paiement [Côté serveur]

Stripe envoie un événement [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) à l’issue du paiement. Utilisez l’[outil de webhook du Dashboard](https://dashboard.stripe.com/webhooks) ou suivez le [guide consacré aux webhooks](https://docs.stripe.com/webhooks/quickstart.md) pour recevoir ces événements et exécuter des actions, comme envoyer une confirmation de commande par e-mail à votre client, enregistrer la vente dans une base de données ou lancer un flux de livraison.

Plutôt que d’attendre un rappel de votre client, écoutez ces événements. Côté client, il arrive en effet que l’utilisateur ferme la fenêtre de son navigateur ou quitte l’application avant l’exécution du rappel. Certains clients malintentionnés peuvent d’autre part tenter de manipuler la réponse. En configurant votre intégration de manière à ce qu’elle écoute les événements asynchrones, vous pourrez accepter [plusieurs types de moyens de paiement](https://stripe.com/payments/payment-methods-guide) avec une seule et même intégration.

En plus de l’événement `payment_intent.succeeded`, nous vous recommandons de gérer ces autres événements lorsque vous encaissez des paiements à l’aide de l’Element Payment&nbsp;:

| Événement                                                                                                                       | Description                                                                                                                                                                                                                                                                         | Action                                                                                                                                                                                                           |
| ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.succeeded)           | Envoyé lorsqu’un client effectue un paiement avec succès.                                                                                                                                                                                                                           | Envoyez au client une confirmation de commande et *traitez* (Fulfillment is the process of providing the goods or services purchased by a customer, typically after payment is collected) sa commande.           |
| [payment_intent.processing](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.processing)         | Envoyé lorsqu’un client initie un paiement, mais qu’il ne l’a pas encore finalisé. Dans la plupart des cas, cet événement est envoyé lorsque le client initie un prélèvement bancaire. Il est suivi par un événement `payment_intent.succeeded` ou `payment_intent.payment_failed`. | Envoyez au client une confirmation de commande qui indique que son paiement est en attente. Pour des marchandises dématérialisées, vous pourrez traiter la commande sans attendre que le paiement soit effectué. |
| [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md?lang=php#event_types-payment_intent.payment_failed) | Envoyé lorsqu’un client effectue une tentative de paiement qui se solde par un échec.                                                                                                                                                                                               | Si un paiement passe de l’état `processing` à `payment_failed`, proposez au client de retenter le paiement.                                                                                                      |

