#CheerfulGolem
1 messages · Page 1 of 1 (latest)
hi! can you share the full code you've written?
Frontend and Backend right?
frontend to start with since it's a frontend error
Give me one secod
Ehh message too long
PaymentForm.tsx
const SubscriptionPaymentForm: React.FC<Props> = ({ email }) => {
const [clientSecret, setClientSecret] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const publicURL = process.env.NEXT_PUBLIC_VERCEL_URL?.includes('http')
? process.env.NEXT_PUBLIC_VERCEL_URL
: `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`;
const returnURL = `${publicURL}/explore`;
useEffect(() => {
setLoading(true);
// Create PaymentIntent as soon as the page loads
axios
.post(
'/api/company/create-business-subscription',
{
email,
},
{
headers: {
'Content-Type': 'application/json',
},
withCredentials: true,
}
)
.then((res) => {
setClientSecret(res.data.clientSecret);
setLoading(false);
})
.catch((err) => {
setError('Something went wrong. Please try again later');
});
}, [email]);
const options: StripeElementsOptions = {
clientSecret,
appearance: {
theme: 'stripe',
variables: {
colorPrimary: '#3b82f6',
},
},
};
return (
<>
{!clientSecret || loading || error ? (
<div>Loading...
</div>): (
<Elements options={options} stripe={stripePromise}>
<CheckoutForm
email={email}
isLoading={loading}
setIsLoading={setLoading}
returnURL={returnURL}
/>
</Elements>
)}
</>
);
};
(sending the checkoutform as well one second)
CheckoutForm.tsx
const CheckoutForm: React.FC<Props> = ({ returnURL, handleFormSubmit, setIsLoading }) => {
const stripe = useStripe();
const elements = useElements();
const [email, setEmail] = useState('');
useEffect(() => {
if (!stripe) {
return;
}
const clientSecret = new URLSearchParams(window.location.search).get(
'payment_intent_client_secret'
);
if (!clientSecret) {
return;
}
// stripe.retrievePaymentIntent(clientSecret).then(({ paymentIntent }) => {});
}, [stripe]);
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (!stripe || !elements) {
// Stripe.js has not yet loaded.
// Make sure to disable form submission until Stripe.js has loaded.
return;
}
setIsLoading(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
// Make sure to change this to your payment completion page
return_url: returnURL,
receipt_email: email,
},
redirect: 'if_required',
});
setIsLoading(false);
if (error) {
return;
}
handleFormSubmit && handleFormSubmit();
};
return (
<form className="space-y-4" id="payment-form" onSubmit={(event) => handleSubmit(event)}>
<LinkAuthenticationElement
id="link-authentication-element"
onChange={(event) => setEmail(event.value.email)}
/>
<PaymentElement
id="payment-element"
options={{
layout: 'tabs',
}}
/>
<button type="submit">Submit</button>
</form>
);
};
I get the error when I press Submit
Full error:
caught (in promise) IntegrationError: Invalid value for stripe.confirmPayment(): elements should have a mounted Payment Element or Express Checkout Element.
at h (v3:1:435844)
at g.betas (v3:1:437766)
at y (v3:1:438136)
at v3:1:383672
at async handleSubmit (webpack-internal:///(app-client)/./app/components/checkout/CheckoutForm.tsx:37:28)
h
hmm
just for clarity, is the PaymentElement credit card form actually appearing on the page and you're filling it in?
The credit card form appears, but I press submit without filling it in and it crashes
But regardless of if I fill it in or not, as soon as I press submit it hides the credit card form and shows error
Ah nevermind, I think I found the issue lol
<>
{!clientSecret || loading || error ? (
<div className="flex items-center justify-center">
<p className="text-md animate-pulse font-semibold">
{loading && 'Loading...'}
{error && <span className="text-red-500">{error}</span>}
</p>
</div>
) : (
<Elements options={options} stripe={stripePromise}>
<CheckoutForm
email={email}
isLoading={loading}
setIsLoading={setLoading}
returnURL={returnURL}
/>
</Elements>
)}
</>
This bit was causing the issue
As soon as there would be an error, it would unmount the payment element
ah, because it destroys the DOM that the Element is mounted into
Yea or if it starts to load