#j-b_code
1 messages · Page 1 of 1 (latest)
👋 Welcome to your new thread!
⏲️ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
⏱️ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
🔗 This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1245553390499663934
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
``import { createStripeCustomer } from "@/app/library/middlewares/middlewareUser";
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe, Stripe } from "@stripe/stripe-js";
import { useEffect, useState } from "react";
import CheckoutForm from "./CheckoutForm";
import { config, createSubscription } from "./stripe";
import Spinner from "@/app/library/components/spinner/Spinner";
export default function Payment({ dataPlan, dataUser }: { dataPlan: any; dataUser: any }) {
const [stripePromise, setStripePromise] = useState<Promise<Stripe | null> | null>(null);
const [clientSecret, setClientSecret] = useState<string>("");
const [loading, setLoading] = useState<boolean>(true);
useEffect(() => {
const getKey = async () => {
const publishableKey = await config();
setStripePromise(loadStripe(publishableKey));
};
getKey();
}, []);
useEffect(() => {
const createPayment = async () => {
const user = await createStripeCustomer(dataUser.email, `${dataUser.name} ${dataUser.surname}`);
console.log(user);
const res = await createSubscription(user.id, "price_1PLvsTG2vVjK01VJW5lQd2Qw", dataPlan.cycle);
const subscription = JSON.parse(res);
console.log(subscription);
// Récupérer le client_secret du payment_intent
const paymentIntent = subscription.latest_invoice.payment_intent;
if (!paymentIntent || !paymentIntent.client_secret) return;
setClientSecret(paymentIntent.client_secret);
setLoading(false);
};
createPayment();
}, []);
return (
<div className="payment">
{loading && <Spinner text="Loading Stripe Form" />}
{clientSecret && stripePromise && (
<>
<h2>Paiement</h2>
<Elements stripe={stripePromise} options={{ clientSecret, locale: "fr" }}>
<CheckoutForm />
</Elements>
</>
)}
</div>
);
}
``
And this is my CheckoutForm :
``import Spinner from "@/app/library/components/spinner/Spinner";
import { PaymentElement, useElements, useStripe } from "@stripe/react-stripe-js";
import { useRouter } from "next/navigation";
import { useState } from "react";
export default function CheckoutForm() {
const stripe = useStripe();
const elements = useElements();
const router = useRouter();
const [message, setMessage] = useState<string | null | undefined>(null);
const [isProcessing, setIsProcessing] = useState(false);
const handleSubmit = async (e: { preventDefault: () => void }) => {
e.preventDefault();
if (!stripe || !elements) {
return;
}
setIsProcessing(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
return_url: `${window.location.origin}/checkout/completion`,
},
redirect: "if_required",
});
if (error) {
// Show error to your customer (for example, payment details incomplete)
setMessage(error.message);
} else {
// Payment successful, you can handle success on the same page here
setMessage("Paiement effectué avec succès ! Vous allez être redirigé vers la page de connexion.");
// Optionally, you can refresh the page or fetch the updated payment status
}
setTimeout(() => {
router.push("/boarding");
}, 5000);
setIsProcessing(false);
};
if (message !== "Paiement effectué avec succès ! Vous allez être redirigé vers la page de connexion.")
return (
<form id="payment-form" onSubmit={handleSubmit}>
<PaymentElement id="payment-element" />
{!isProcessing && (
<button disabled={isProcessing || !stripe || !elements} id="submit">
<span id="button-text">Payer</span>
</button>
)}
{isProcessing && <Spinner text="Loading payement..." />}
{/* Show any error or success messages */}
{message && <div id="payment-message">{message}</div>}
</form>
);
else return <div id="payment-message">{message}</div>;
}
``
I manage to make test payments in localhost, but not when I put in production, I have the problem with the following error message:
look like you website has deployed a CSP. You should include the following CSP directives that Stripe.js requires https://docs.stripe.com/security/guide?csp=csp-js#content-security-policy
Thanks, but I always have 972-adc5b8e7809daa24.js:1 Refused to load the script 'https://js.stripe.com/v3' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
here my next.config.mjs :
``/** @type {import('next').NextConfig} /
const nextConfig = {
images: {
remotePatterns: [{ hostname: "lh3.googleusercontent.com" }],
},
async headers() {
return [
{
source: "/(.)",
headers: [
{
key: "Content-Security-Policy",
value: default-src 'self'; script-src 'self' 'unsafe-inline' https://js.stripe.com; frame-src 'self' https://js.stripe.com https://hooks.stripe.com; connect-src 'self' https://api.stripe.com https://maps.googleapis.com; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self';
.replace(/\s{2,}/g, " ")
.trim(),
},
],
},
];
},
};
export default nextConfig;
``
now in localhoast I have caught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' https://js.stripe.com".
That's because your CSP only allows loading scripts from 'self' and 'unsafe-inline'. You might want to check Next.js documentation and see how to add in Stripe.js CSP directives
https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy I think this is the doc
If I understand correctly, I have to add the with-strict-csp-app package? I'm really sorry, I don't find the documentation very clear, and there's nothing about stripe at next js :/
https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy#without-nonces I believe you just need to add the Stripe.js CSP directives in the csp header
I'm not an expert in Next.js, you might want to work with someone who has more experience in Next.js
I found their discord, do you mind if I keep this ticket just in case? I'll let you know when I've found the solution. I'm going to get some sleep first, it's 4 o'clock in France and this code has made me very tired.
The thread will be closed after some time. Feel free to use the button in #help to reach out to us again.
Ok thank you !