Home > Software engineering >  Stripe React PaymentElement not showing for connected accounts
Stripe React PaymentElement not showing for connected accounts

Time:03-07

I am trying create a custom Stripe Checkout according to the docs here. (Web/React/Node) https://stripe.com/docs/payments/quickstart

Following the docs I am successful in creating a paymentIntent and charging.

The problem is when I add a connected account to the stripe instance, the <PaymentElement> refuses to show. I can confirm on the Stripe dashboard that indeed a payment intent is created successfully in the connected account for the correct customer existing in said connected account, I am successfully passing back the payment intent id, but the element just won't show. Just as a sanity check, when I remove the connected account, it works as expected.

I am following here https://stripe.com/docs/connect/enable-payment-acceptance-guide?elements-or-checkout=elements&html-or-react=react on how to add the connected account.

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('pk_test_NTv6FvtshDhM7cWcoiIvFk1w', {
  stripeAccount: '{{CONNECTED_STRIPE_ACCOUNT_ID}}'
});

function App() {
  return (
    <Elements stripe={stripePromise}>
      <CheckoutForm />
    </Elements>
  );
};

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

Here is my implementation

import React, { useState, useEffect } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Elements } from "@stripe/react-stripe-js";
import CheckoutForm from "./CheckoutForm";

export default function Checkout({
  stripeAccount,
  amount,
  firstName,
  lastName,
  email,
}) {

// Make sure to call loadStripe outside of a component’s render to avoid
// recreating the Stripe object on every render.
// This is your test publishable API key.
const stripePromise = loadStripe(
  "pk_test_1234",
  stripeAccount
);

  const [clientSecret, setClientSecret] = useState("");

  useEffect(async () => {
    // Create PaymentIntent as soon as the page loads
    fetch("http://localhost:3000/api/app/createPaymentIntent", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        stripeAccount,
        amount,
        firstName,
        lastName,
        email,
      }),
    })
      .then((res) => res.json())
      .then((data) => setClientSecret(data.clientSecret));
  }, []);

  const appearance = {
    theme: "stripe",
    labels: "floating",
    variables: {
      fontLineHeight: "50px",
      borderStyle: "solid",
      borderWidth: "2px",
      borderColor: "#efefef",
      backgroundColor: "#000",
      boxShadow: "0px 16px 32px 0px rgb(0 0 0 / 6%)",
      borderRadius: "30px",
      padding: "0 25px",
      marginBottom: "20px",
    },
  };

  const options = {
    clientSecret,
    appearance,
  };

  return (
    <div className="Checkout">
      {clientSecret && (
        <Elements options={options} stripe={stripePromise}>
          <CheckoutForm />
        </Elements>
      )}
    </div>
  );
}

//node

 // Create a PaymentIntent with the order amount and currency
          const paymentIntent = await stripe.paymentIntents.create(
            {
              customer: stripeCustomer.id,
              amount: amount * 100,
              currency: "usd",
              automatic_payment_methods: {
                enabled: true,
              },
            },
            {
               stripeAccount,
            }
          );

//node NOTE: if I comment out the connected account like below, then it works fine.

  // Create a PaymentIntent with the order amount and currency
          const paymentIntent = await stripe.paymentIntents.create(
            {
            //   customer: stripeCustomer.id,
              amount: amount * 100,
              currency: "usd",
              automatic_payment_methods: {
                enabled: true,
              },
            },
            // {
            //   stripeAccount,
            // }
          );

CodePudding user response:

Thanks for sharing the additional context. It appears that you're not initialising Stripe.js correctly, specifically when trying to pass the stripeAccount parameter:

const stripePromise = loadStripe("pk_test_1234", {
  stripeAccount
});

See here.

CodePudding user response:

Looks like you aren't passing the options prop the the <Elements /> provider component (which needs the client_secret from your Payment Intent).

function App() {
  return (
    <Elements stripe={stripePromise} options={{ clientSecret: 'pi_xxx_secret_yyy' }}>
      <CheckoutForm />
    </Elements>
  );
};
  • Related