--- title: Use Payment Element across multiple processors subtitle: Learn how to collect card details with Payment Element and use them with a third-party processor. route: /payments/forwarding-third-party-processors --- # Use Payment Element across multiple processors Learn how to collect card details with Payment Element and use them with a third-party processor. Use [Payment Element](https://docs.stripe.com/payments/payment-element.md) to build a custom payment flow that allows you to collect card details, create a [PaymentMethod](https://docs.stripe.com/api/payment_methods.md), and [forward](https://docs.stripe.com/api/forwarding/request.md) the payment method to a third-party processor. To gain access to use Stripe’s forwarding service, contact [Stripe support](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). ## Create a PaymentMethod Use a Payment Element to collect payment details. If you’re not integrated with the Payment Element, learn how to [get started](https://docs.stripe.com/payments/accept-a-payment.md). After the customer submits your payment form, call [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) to create a *PaymentMethod*. Pass the PaymentMethod ID to the ForwardingRequest endpoint on your server. ```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('<>'); 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); }); ``` ```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 (
{errorMessage &&
{errorMessage}
} ); } ``` ## Create a ForwardingRequest Contact Stripe support to [configure](https://docs.stripe.com/payments/vault-and-forward.md#configuring) your destination endpoint and begin forwarding transactions. Send the card details to this test endpoint before you connect your integration with your third-party processor. ```javascript const stripe = require("stripe")("<>"); 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'); }); ``` ## Handle the Response After you send the request, you must handle the response. ```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 } } ```