#tallmanpapi
1 messages · Page 1 of 1 (latest)
Your API request is failing, and as such the response object is not what you think (and the .json() method fails)
Are there any errors thrown by your backend?
Hmm, interesting. Okay, sounds very logical. Thank you.
No, not that I am aware of. You want my backend to be shared here with you?
You should include a try/catch block in your async function to actually catch the errors
Yes, I think I had that in the beginning, I was hitting some problems with that, but I will start doing that again, thank you.
Sure, but equally just check your Dashboard logs for any failed requests
Oh, of course, let me check that as well, thank you.
Hmm, seems like nothing wrong regarding to the logs.
Honestly now looking at this, it could be that I am missing something, it looks so basic, lol.
Here the backend for Stripe checkout:
import type { NextApiRequest, NextApiResponse } from 'next';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-11-15',
});
console.log('outside the const handler!');
export async function POST(req: NextApiRequest, res: NextApiResponse) {
const { price, quantity } = req.body;
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price: 'price_1N2UwFHjh6rwfnNSgLo5XwJs',
quantity: 1,
},
],
mode: 'payment',
success_url:
'http://localhost:3000/result?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'http://localhost:3000/checkout',
});
res.status(200).json({ sessionId: session.id });
}
Oh maybe to mention, could this be the problem of it all?..
These are the only two errors tho, nothing else/more.
Ah, ok this is Next.js Route Handlers. The Response object is different. Should be:
NextResponse.json({ sessionId: session.id })
Oh great, thank you that was the fix, I will definitely start reading that afterwards to understand what you just helped me with.
Now there is a error regarding the headers, a TypeError: TypeError: Cannot read properties of undefined (reading 'headers').
Do you know where this is coming from? 'headers', they mean from the fetch? as in what happens here:
headers: {
'content-type': 'application/json',
},
It's saying it can't read it? Should it be with brackets in json? I don't understand what they mean. @floral meteor
Sorry, here is the error.
Lol people talking about deleting your nodemodules and others about where I should want to read my headers from, its looks broad.
I can't even see where you're reading the headers
Oh, I am sorry. Let me show you.
'use client';
import { NextApiRequest, NextApiResponse } from 'next';
import { buttonVariants } from './ui/Button';
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.STRIPE_SECRET_KEY!);
export default function ContinueToPayment(
req: NextApiRequest,
res: NextApiResponse
) {
const handleClick = async (event) => {
// Call your backend to create the Checkout session.
const response = await fetch('/api/stripe/checkout', {
method: 'POST',
///////////// HEADERS IS HEREE ///////////////
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({ quantity: 1 }),
});
const session = await response.json();
// When the customer clicks on the button, redirect them to Checkout.
const stripe = await stripePromise;
const result = await stripe?.redirectToCheckout({
sessionId: session.id,
});
if (result?.error) {
}
};
return (
<div>
<button
className={buttonVariants({ variant: 'default', size: 'lg' })}
onClick={handleClick}
role='link'
>
Checkout
</button>
</div>
);
}
Made it clear to see.
Right, but the error is thrown from your Route Handler
You're not accessing them there
Ah hence the error it cant read it, right?
Just guessing here
Not really a Stripe issue so I'm limited in what I can help with
I'm pretty familiar with Next.js though so can try help
Thank you so much, that means a lot to me. Let me try something, I deleted earlier. I'll update you! : )
So as maybe expected. success_url: `${req.headers.origin}/result?session_id={CHECKOUT_SESSION_ID}`, in const session = await stripe.checkout.sessions.create is undefined so req.headers.origin isn't showing anything, that could be why it can't read it in the first place. So I miss something for the headers, right? @floral meteor
message: 'Invalid URL: undefined/results?session_, etc...
I think you may need to do req.headers.get('origin')
Hmm.. Idk, seems hard to add, a lot of errors, maybe I am doing something wrong tho.
req.headers.origin + '/result?session_id={CHECKOUT_SESSION_ID}', Doesn't throw much errors, I will try it out.
.get('origin') looks good, it's just hard to put in there for some reason.
Hmm, no same error. Let me try yours again in some different ways, thank you so much for the help.
I really appreciate this, I have been struggling with these problems for days.
Hi @torn jetty !! Thank you for taking over, I appreciate that.
Yes, I will.
So basically, me and @floral meteor found out that headers is never being read/returned.
In the code snippet below. I am 'asking' for the first time for the headers. Its value is undefined unfortunately though.
success_url: `${req.headers.origin}/result?session_id={CHECKOUT_SESSION_ID}`,.
The whole code block shown below here. The server side:
import type { NextApiRequest, NextApiResponse } from 'next';
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-11-15',
});
console.log('outside the const handler!');
export async function POST(req: NextApiRequest, res: NextApiResponse) {
const { price, quantity } = req.body;
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price: 'price_1N2UwFHjh6rwfnNSgLo5XwJs',
quantity: 1,
},
],
mode: 'payment',
success_url: `${req.headers.origin}/result?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${req.headers.origin}/checkout`,
});
NextResponse.json({ sessionId: session.id });
}
The whole code block shown below here. The client side:
'use client';
import { NextApiRequest, NextApiResponse } from 'next';
import { buttonVariants } from './ui/Button';
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.STRIPE_SECRET_KEY!);
export default function ContinueToPayment(
req: NextApiRequest,
res: NextApiResponse
) {
const handleClick = async (event) => {
// Call your backend to create the Checkout session.
const response = await fetch('/api/stripe/checkout', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({ quantity: 1 }),
});
const session = await response.json();
// When the customer clicks on the button, redirect them to Checkout.
const stripe = await stripePromise;
const result = await stripe?.redirectToCheckout({
sessionId: session.id,
});
if (result?.error) {
}
};
return (
<div>
<button
className={buttonVariants({ variant: 'default', size: 'lg' })}
onClick={handleClick}
role='link'
>
Checkout
</button>
</div>
);
}
Now my question is why and how is headers being returned as undefined? I am assuming myself it's because I am not returning them from the client to the server so it doesn't know headers value from the start. But I am lacking knowledge regarding Stripe in this usecase to understand what I am missing and/or doing wrong.
FWIW, req.headers.get('origin') works for me
Not sure what specific issues you're having. As explained, in the Route Handlers req is a Request object: https://developer.mozilla.org/en-US/docs/Web/API/Request
Okay, thank you for letting me know. How would you put req.headers.get('origin') in the success_url though? Would that be req.headers.get('origin')+'/result?session_id={CHECKOUT_SESSION_ID}'?
${req.headers.get('origin')}/result?session_id={CHECKOUT_SESSION_ID}
returns Cannot invoke an object which is possibly 'undefined'.ts(2722)
but only when hovered over req.headers.get
Ah, it's because you're using the wrong type interfaces (NextApiRequest) for your req param
That's for API Routes
Oh...
So I should use: req: Request and res: Response? But what do I need to import then?
I haven't slept for 19 hours so I am starting to oversee a lot of things.. Sorry.
Well, you can use NextRequest which extends the native Request interface: https://nextjs.org/docs/app/building-your-application/routing/router-handlers#extended-nextrequest-and-nextresponse-apis
As per earlier, these aren't Stripe specific issues. I'd recommend reading through the Next.js docs to understand their APIs
Yes, I will.. Sorry, it's getting very out of scope. I am very thankful for this. I will go through this.
Thanks a lot!!
Although it seems to work now, Its still returning: undefined with ${req.headers.get('origin')}.. It's so weird and frustrating... @torn jetty Sorry for all this, I am so clueless at this point.
Oh, wait.
Where const res = fetch(''), etc..
I added const data = await res.json() is now everything in data? Because I need to return the headers.
Sorry @torn jetty didn't mean to let you wait.
I'm taking over here. What specifically are you stuck with?
Hahaha, I am so sorry, thank you @floral meteor !!
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-11-15',
});
console.log('outside the const handler!');
export async function POST(req: Request, res: Response) {
// const { price, quantity } = req.body;
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price: 'price_1N2UwFHjh6rwfnNSgLo5XwJs',
quantity: 1,
},
],
mode: 'payment',
success_url: `${req.headers.get(
'origin'
)}/result?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${req.headers.get('origin')}/checkout`,
});
NextResponse.json({ sessionId: session.id });
}
So we def. got a little further, and your colleague told me about the wrong type interfaces (NextApiRequest) i was using, so I changed that. Also I added some things from the docs your colleague send me from Mozilla Routing: Route Handlers. So the code looks now like this.
The only error its now returning in the console is that it still isn't reading or grabbing the Headers and the value is being returned as undefined.
This is how the client component looks like:
'use client';
import { NextResponse } from 'next/server';
import { buttonVariants } from './ui/Button';
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.STRIPE_SECRET_KEY!);
export default function ContinueToPayment(req: Request, res: Response) {
const handleClick = async (event) => {
// Call your backend to create the Checkout session.
const res = await fetch('/api/stripe/checkout', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({ quantity: 1 }),
});
const session = await res.json();
return NextResponse.json({ session });
// When the customer clicks on the button, redirect them to Checkout.
const stripe = await stripePromise;
const result = await stripe?.redirectToCheckout({
sessionId: session.id,
});
if (result?.error) {
}
};
return (
<div>
<button
className={buttonVariants({ variant: 'default', size: 'lg' })}
onClick={handleClick}
role='link'
>
Checkout
</button>
</div>
);
}
your colleague told me about the wrong type interfaces (NextApiRequest) i was using
That was me 🙂
The only error its now returning in the console is that it still isn't reading or grabbing the Headers and the value is being returned as undefined.
My guess is yourheaderskey in yourfetchrequest is overwriting the defaults. Try:
headers: new Headers({ 'Content-Type': 'application/json' })
I am so sorry, yes, you helped me with a lot
Okay, sorry, I am also trying to learn from it. Why would it overwrite the defaults? Or what is the reason or your thought it could possibly do this.
It's so weird and confusing why this only happens with headers.. Unfortunately is it returning the same error. But it looks good and the IDE isn't showing any errors.
Can you share the code from your Route Handler?
Of course, sorry, what do you mean with Route handler? The server side?
The other file?
Yes, this one
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-11-15',
});
console.log('outside the const handler!');
export async function POST(req: Request, res: Response) {
// const { price, quantity } = req.body;
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card'],
line_items: [
{
price: 'price_1N2UwFHjh6rwfnNSgLo5XwJs',
quantity: 1,
},
],
mode: 'payment',
success_url: `${req.headers.get(
'origin'
)}/result?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${req.headers.get('origin')}/checkout`,
});
NextResponse.json({ sessionId: session.id });
}
Are you able to even log req.headers.get('origin')?
Yes I am but will be returned as undefined
Let me try again, I did that a bit back.
Hmm, yeah I've no idea. That works for me in an identical setup
Ooooh, it does work.
Look
I just logged this
TypeError: Cannot read properties of undefined (reading 'headers')
Is the only thing it shows..
But the value is there tho..
@floral meteor
Thank you for cloning this setup, is yours also giving the same TypeError in the console/terminal?
Where is that thrown tough?
Yes, but which line
Seems like directly after the console.log(req.headers.get('origin') + 'This is it<<<<<<<<<');
So that means its directly being returned when const session = await stripe.checkout.sessions.create({ should start working/is being called.
So first the console.log and then immediately the TypeError.
Can you try adding return statement before NextResponse.json(...)
Of course!
Literally the only difference from my functioning code
Okay, yeah, the error is gone. One question do you have this return NextResponse.json({ session }); commented? Because I see If I comment this everything under there becomes light in opacity meaning its not being used.
Wait, what. Why are you using NextResponse.json in your component?
I meant in your backend code
I commented it now, that seems to work better.
In my backend code its only at the bottom:
return NextResponse.json({ sessionId: session.id });
It seems to work though, because that error is gone, its just complaingin now:
Uncaught (in promise) IntegrationError: Missing value for Stripe(): apiKey should be a string.
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-11-15',
});
But I am just going to try and put it hardcoded in, and see what it does.
Ok, glad that's resolved
Yeah, sorry for that confusion. But that hard coded part wasn't working.. What do you have there? I am also going to check the docs for that, I had them open, I think it showed how to do this part somewhere.
Wait, did we not resolve the TypeError: Cannot read properties of undefined (reading 'headers') error?
Yes, we did. You said it was the "return" thingy, right?
I mean that stopped showing the error hahaha
Ok, now what's the issue?
So, at the beginning:
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY ?? '', {
apiVersion: '2022-11-15',
});
It returns in this in the web console. So I was curious if you use the same one as me here.
Should be a string
Nope. Do you have a STRIPE_SECRET_KEY variable in your .env file?
Then it's not a string
should be STRIPE_SECRET_KEY="sk_test_xxx"
damn, really? So how are all those tutorials without?
Thanks though!
Hmm.. still returning this error.
Let me see online, if others had the same problem.
Did you restart your Next.js server after changing the variable
We're going to have to wrap this thread up soon
These are all non-Stripe issues
Yes I understand, thank you so much for everything you did! You helped me so much.