RyzeDeskRyzeDesk

Stripe

4105 articles

Use Payment Element across multiple 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 to build a custom payment flow that allows you to collect card details, create a PaymentMethod, and forward the payment method to a third-party processor.

Request access

To gain access to use Stripe’s forwarding service, contact Stripe support.

Create a PaymentMethod Client-side

Use a Payment Element to collect payment details. If you’re not integrated with the Payment Element, learn how to get started. After the customer submits your payment form, call stripe.createPaymentMethod to create a PaymentMethod. Pass the PaymentMethod ID to the ForwardingRequest endpoint on your server.

checkout.js

// 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('pk_test_GvF3BSyx8RSXMK5yAFhqEd3H');

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);
});

Create a ForwardingRequest

Contact Stripe support to configure 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.

app.js

// Don't put any keys in code. See https://docs.stripe.com/keys-best-practices.
const stripe = require("stripe")("sk_test_Ou1w6LVt3zmVipDVJsvMeQsc");
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 Client-side

After you send the request, you must handle the response.

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
 }
}
Last verified 2026-09-27

Is this helpful?