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