# Utiliser Payment Element avec différents prestataires

Découvrez comment collecter des informations de carte bancaire avec le composant Payment Element, et les utiliser avec un prestataire de services de paiement tiers.

Utilisez le composant [Payment Element](https://docs.stripe.com/payments/payment-element.md) pour créer un tunnel de paiement personnalisé qui vous permet de collecter les informations de la carte bancaire, de créer un [PaymentMethod](https://docs.stripe.com/api/payment_methods.md) et de [transmettre](https://docs.stripe.com/api/forwarding/request.md) le moyen de paiement à un prestataire tiers.

> #### Demander un accès
> 
> Pour obtenir un accès au service de transfert de Stripe, contactez le [service Support de Stripe](https://dashboard.stripe.com/login?redirect=https%3A%2F%2Fsupport.stripe.com%2Fcontact%2Femail%3Fquestion%3Dother%26topic%3Dpayment_apis%26subject%3DHow%2520can%2520I%2520access%2520the%2520Vault%2520and%2520Forward%2520API%3F%26body%3DWhat%2520endpoint%28s%29%2520would%2520you%2520like%2520to%2520forward%2520card%2520details%2520to%3F).

Transmettez des coordonnées de carte bancaire à un prestataire tiers (See full diagram at https://docs.stripe.com/payments/forwarding-third-party-processors)

```text
[Client] -- Créer un PaymentMethod --> [Stripe]
[Client] -- Traitez le paiement sur votre serveur --> [Serveur]
[Serveur] -- Appelez l’API Vault and Forward avec le moyen de paiement fourni --> [Stripe]
[Stripe] -- Stripe transmet la requête avec les données de carte bancaire --> [Prestataire tiers]
[Prestataire tiers] -- Le prestataire tiers renvoie une réponse --> [Stripe]
[Stripe] -- Stripe édite les données sensibles PCI identifiées et transmet la réponse --> [Serveur]
[Serveur] -- Traitez la réponse du serveur --> [Client]
```

## Créer un PaymentMethod [Côté client]

Utilisez le composant Payment Element pour collecter les informations de paiement. Si vous n’avez pas intégré Payment Element, découvrez comment [démarrer](https://docs.stripe.com/payments/accept-a-payment.md). Quand le client envoie votre formulaire de paiement, appelez [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) pour créer un objet *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs). Transmettez l’ID de PaymentMethod à l’endpoint ForwardingRequest sur votre serveur.

#### HTML + JS

```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>>');

const options = {
    mode: 'payment',
    amount: 1099,
    currency: 'usd',
    paymentMethodCreation: 'manual',
    // Fully customizable with appearance API.
    appearance: {
        theme: 'stripe'
    }
};

// Set up Stripe.js and Elements to use in checkout form
const elements = stripe.elements(options);

const paymentElementOptions = {
layout: "tabs",
};

// Create and mount the Payment Element
const paymentElement = elements.create('payment', paymentElementOptions);
paymentElement.mount('#payment-element');

const form = document.getElementById('payment-form');
const submitBtn = document.getElementById('submit');

const handleError = (error) => {
    const messageContainer = document.querySelector('#error-message');
    messageContainer.textContent = error.message;
    submitBtn.disabled = false;
}

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

    // Prevent multiple form submissions
    if (submitBtn.disabled) {
        return;
    }

    // Disable form submission while loading
    submitBtn.disabled = true;

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

    // Create the PaymentMethod using the details collected by the Payment Element
    const { error, paymentMethod } = await stripe.createPaymentMethod({
        elements,
        params: {
            billing_details: {
                name: 'John Doe',
            }
        }
    });

    if (error) {
        // This point is only reached if there's an immediate error when
        // creating the PaymentMethod. Show the error to your customer (for example, payment details incomplete)
        handleError(error);
        return;
    }

    // Call the ForwardingRequest endpoint on your server
    const res = await fetch("/create-forwarding-request", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
            paymentMethodId: paymentMethod.id,
        }),
    });
    const data = await res.json();

    // Handle the response or errors
    handleServerResponse(data);
});
```

#### React

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

export default function CheckoutForm() {
  const stripe = useStripe();
  const elements = useElements();
  const [errorMessage, setErrorMessage] = useState();
  const [loading, setLoading] = useState(false);
  const handleError = (error) => {
    setLoading(false);
    setErrorMessage(error.message);
  }

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

    if (!stripe) {
      // Stripe.js hasn't yet loaded.
      // Make sure to disable form submission until Stripe.js has loaded.
      return;
    }
    setLoading(true);
    // Trigger form validation and wallet collection
    const {error: submitError} = await elements.submit();
    if (submitError) {
      handleError(submitError);
      return;
    }

    // Create the PaymentMethod using the details collected by the Payment Element
    const {error, paymentMethod} = await stripe.createPaymentMethod({
      elements,
      params: {
        billing_details: {
          name: 'Jenny Rosen',
        }
      }
    });

    if (error) {
      // This point is only reached if there's an immediate error when
      // creating the PaymentMethod. Show the error to your customer (for example, payment details incomplete)
      handleError(error);
      return;
    }

    // Call the ForwardingRequest endpoint on your server
    const res = await fetch("/create-forwarding-request", {
      method: "POST",
      headers: {"Content-Type": "application/json"},
      body: JSON.stringify({
        paymentMethodId: paymentMethod.id,
      }),
    });
    const data = await res.json();
    // Handle any next actions or errors. See the Handle any next actions step for implementation.
    handleServerResponse(data);
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      <button type="submit" disabled={!stripe || loading}>
        Submit
      </button>
      {errorMessage && <div>{errorMessage}</div>}
    </form>
  );
}
```

## Créer une ForwardingRequest

Contactez le service Support de Stripe pour [configurer](https://docs.stripe.com/payments/vault-and-forward.md#configuring) votre endpoint de destination et commencer à acheminer des transactions. Envoyez les informations de carte à cet endpoint de test avant de connecter votre intégration à votre prestataire de services de paiement tiers.

```javascript
// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
const stripe = require("stripe")("<<YOUR_SECRET_KEY>>");
const express = require('express');
const app = express();

app.set('trust proxy', true);
app.use(express.json());
app.use(express.static("."));

app.post('/create-forwarding-request', async (req, res) => {
    try {
        const forwardedReq = await stripe.forwarding.requests.create(
            {
                payment_method: req.body.paymentMethodId,
                url: '{{DESTINATION_ENDPOINT}}',
                request: {
                    headers: [{
                        name: 'Destination-API-Key',
                        value: '{{DESTINATION_API_KEY}}'
                    },{
                        name: 'Destination-Idempotency-Key',
                        value: '{{DESTINATION_IDEMPOTENCY_KEY}}'
                    }],
                    body: JSON.stringify({
                        "amount": {
                            "currency": "USD",
                            "value": 1099
                        },
                        "reference": "Your order number",
                        "card": {
                            "number": "",
                            "exp_month": "",
                            "exp_year": "",
                            "cvc": "",
                            "name": ""
                        }
                    })
                },
                replacements: ['card_number', 'card_expiry', 'card_cvc', 'cardholder_name'],
            }
        );

        if (forwardedReq.response_details.status != 200) {
            // Return error based on third-party API response code
        } else {
            // Parse and handle the third-party API response
            const forwardedResult = JSON.parse(forwardedReq.response_details.body);
            res.json({
                status: forwardedReq.response_details.status
            });
        }
    } catch (err) {
        res.json({
            error: err
        });
    }
});

app.listen(3000, () => {
    console.log('Running on port 3000');
});
```

## Traiter la réponse [Côté client]

Une fois la requête envoyée, vous devez traiter la réponse.

```javascript
const handleServerResponse = async (response) => {
  if (response.error) {
    // Show error on payment form
  } else if (response.status != 200) {
    // Show error based on response code
  } else {
     // Parse the response body to render your payment form
  }
}
```
