#thekents_unexpected

1 messages ยท Page 1 of 1 (latest)

faint nightBOT
#

๐Ÿ‘‹ 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/1354084406134046772

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

solid pumice
#

Main culprit of this i suspect is this: "ReferenceError: location is not defined"

steel sable
#

It looks like you've set your return URL to /tilaus?session_id=cs_test_b1N2 using the session ID templating

#

Where is that ReferenceError: location is not defined error coming from?

#

This seems like a runtime error within your /tilaus page/route

#

This doesn't sound like an error or unexpected behaviour from the Stripe API/SDK but rather how your site/page is handling the redirect

solid pumice
#

Thats what i thought aswell.. I changed my code to copy the nextjs example from your page and still ended up in the same spot

steel sable
#

What code, exactly?

#

Where in your success/redirect page do you access location?

solid pumice
#

this is /tilaus page:

import { stripe } from '@/lib/stripe';
import { redirect } from 'next/navigation';
import Image from 'next/image';
import { formatPrice } from '@/lib/utils';
import ClearCart from '@/lib/ClearCart';

export default async function Return({
searchParams,
}: {
searchParams: { session_id?: string };
}) {
const { session_id } = searchParams;

if (!session_id)
throw new Error('Please provide a valid session_id (cs_test_...)');

const {
status,
customer_details,
line_items,
shipping_details,
total_details,
amount_subtotal,
amount_total,
} = await stripe.checkout.sessions.retrieve(session_id, {
expand: ['line_items.data.price.product', 'payment_intent'],
});

if (status === 'open') {
return redirect(${process.env.SITE_URL}/ostoskori);
}

if (status === 'complete') {
return(...)
}
}

solid pumice
#

Checkout page:

'use client';

import { loadStripe } from '@stripe/stripe-js';
import {
EmbeddedCheckoutProvider,
EmbeddedCheckout,
} from '@stripe/react-stripe-js';
import { useCallback } from 'react';
import { useCart } from '../context/CartContext';
import { useRouter } from 'next/navigation';
import { trackInititateCheckout } from '@/modules/analytics/product/trackInitiateCheckout';
import Cookies from 'js-cookie';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PK_KEY!);

export default function Checkout() {
const { cartTotal, cartItems } = useCart();
const router = useRouter();

if (cartItems.length === 0) {
router.replace('/ostoskori');
}

const fetchClientSecret = useCallback(async () => {
// Create a Checkout Session
const res = await fetch('/api/stripe/create-checkout', {
method: 'POST',
body: JSON.stringify({
cartItems: cartItems,
gclid: Cookies.get('gclid'),
gadSource: Cookies.get('gad_source'),
}),
headers: {
'Content-Type': 'application/json',
},
});
const data = await res.json();

trackInititateCheckout(cartTotal, cartItems);

return data.clientSecret;

}, [cartItems]);

const options = { fetchClientSecret };

return (
<div id="checkout">
<EmbeddedCheckoutProvider stripe={stripePromise} options={options}>
<EmbeddedCheckout />
</EmbeddedCheckoutProvider>
</div>
);
}

#

So there really isnt much of my code where it goes wrong, mind you that it only happens when i run "npm run dev", and i try to complete the checkout for the first time

#

The payment goes thru, i get the invoice in the dashboard. No error logs in developer tab either.

#

Second time there is no problems.

#

I can recreate the problem by just closing the server with ctrl+c and running npm run dev again

#

There are no problems when i launch the new server and navigate manually to /tilaus, and then try to complete the checkout

steel sable
#

I don't expect you'll find any errors in your stripe dashboard because as i said i dont think ther eare any stripe errors

#

you're going to need to narrow down where that error comes from to debug it

solid pumice
#

Are you sure the location error doesnt come from embedded checkout trying to replace the window location?

This part gives me those vibes:
ReferenceError: location is not defined
at eval (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/app-router.js:155:66)
at eval (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/app-router.js:278:21)
at t.startTransition (/Users/kenertlauri/Documents/sanalliset-nextjs/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:161416)
at Object.replace (webpack-internal:///(ssr)/./node_modules/next/dist/client/components/app-router.js:276:44)
at Checkout (webpack-internal:///(ssr)/./src/app/checkout/page.tsx:28:16)

I have window.location in other parts of my code but they are guarded by if (typeof window === 'undefined') return;
There are no functions that use window in either tilaus, checkout, layout nor navigation

steel sable
#

It's possible, but it seems unlikely given that it should be running client side and thats not shown in the stack trace

#

What is at:

at Checkout (webpack-internal:///(ssr)/./src/app/checkout/page.tsx:28:16)
#

And does the (ssr) there indicate server side rendering for that page? I'm not a Next.js expert, though I am familiar with it in a broad sense.

faint nightBOT
solid pumice
#

There shouldn't be, I am using 'use client'; in there. I am checking now if GA could interfiere with this.

shut garden
#

Hello, my colleague had to step out but I can help. Catching up in this thread...

#

Hmm trying to think of what could help debug here. So this error is happening before Checkout redirects off of your page?

solid pumice
#

So it is embedded.

  1. User is in cart -> presses a button -> navigates to /checkout

  2. Checkout creates session (in session params there is a field called return_url and it redirects to: ${process.env.SITE_URL}/tilaus?session_id={CHECKOUT_SESSION_ID}) and returns clientsecret with fetch. This clientsecret is added to embeddedCheckout

  3. /tilaus should open now. With the first payment it doesnt and gives the error, all future payments work correctly

shut garden
solid pumice
#

Haven't tried, i think i fixed it now..

#

// const getReturnUrlWithParams = (gclid: string, gadSource: string) => {
// // Base return URL (from environment variable or wherever it's set)
// const baseReturnUrl = ${process.env.SITE_URL}/tilaus?session_id={CHECKOUT_SESSION_ID};

// // If gclid or gad_source exist, append them to the URL
// const urlParams: URLSearchParams = new URLSearchParams();

// if (gclid) urlParams.set('gclid', gclid);
// if (gadSource) urlParams.set('gad_source', gadSource);

// // If we have any parameters, append them to the return URL
// if (urlParams.toString()) {
// return ${baseReturnUrl}&${urlParams.toString()};
// }

// // Return the base return URL if no additional params
// return baseReturnUrl;
// };

#

i had possible urlParams appended to the url, guess it didnt like those

#

I wonder why did it only crash one time and also I would now like to ask if you have any documentation how to add params to return url?

shut garden
#

You are adding it the way we recommend doing in our docs. As long as you have {CHECKOUT_SESSION_ID} as one of the URL params we will insert the checkout session ID somewhere in the URL, we will replace it with the session's ID

#

If you haven't already, I'd reccommend stepping through that code on the redirect page to see what goes on with the URL params the first time

solid pumice
#

It seems to work now for some reason...

#

Mystic code i must say

#

Now it didnt work again ๐Ÿ˜„

#

All i did was restart dev server

#

Also could you give me information about how to return user to the same checkout if it was not yet paid?. Should i just create new session?

if (status === 'open') {
return redirect('/')
}

shut garden
#

Yep, that is a great idea. As long as the session is still open, they can keep trying to pay it. If you create a new one there can be a risk of double payment if there is a bug in your logic for checking when to create a new one

solid pumice
#

But how do I link checkout together with a previous attempt? using a key here?

return (
<div id="checkout">
<EmbeddedCheckoutProvider stripe={stripePromise} options={options}>
<EmbeddedCheckout />
</EmbeddedCheckoutProvider>
</div>
);

#

i redirect to /checkout with session_id and user that to fetch client secret, right?

shut garden
#

Exactly, your server can retrieve the session by that Id (or look it up in your own system if you cache it) and return the secret from that retrieve

solid pumice
#

I also fixed the location problem

shut garden
#

Nice, what did that end up being?

solid pumice
#

Its basically this now:

const router = useRouter();

useEffect(() => {
if (cartItems.length === 0) {
router.replace('/ostoskori');
}
}, []);

before it was this:

const router = useRouter();

if (cartItems.length === 0) {
  router.replace('/ostoskori');
}

useRouter is client-side, the server has no knowledge of it. I got around this problem by wrapping automatic routing logic inside a useEffect, which will only run once the component is loaded on the frontend.

For example, if you have a line of code in the global scope that runs as soon as the file is loaded like: if (someCondition) router.push('/login') or something like that, the server will not recognise it and it will error.

Wrap it in a useEffect and it wil only run client-side, so should be no problems.

#

Even though /checkout has 'use client' on the top, for some reason it loads it in server aswell at some point

#

before redirecting probably, and that is why it crashed

shut garden
#

Huh, that is wild. Nice job debugging that one!

solid pumice
#

Thanks,took a long time.. Have a nice day!!