#j-b_code

1 messages · Page 1 of 1 (latest)

final ravenBOT
#

👋 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.

late quartz
#

``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:

stone radish
late quartz
#

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".

stone radish
#

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

late quartz
#

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 :/

stone radish
#

I'm not an expert in Next.js, you might want to work with someone who has more experience in Next.js

late quartz
#

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.

stone radish
#

The thread will be closed after some time. Feel free to use the button in #help to reach out to us again.

late quartz
#

Ok thank you !

wintry pine
#

helllo

#

are you guys able to help in this chat?

stone radish
#

Hi @wintry pine please click on the button in #help to create your own thread.