#tallmanpapi

1 messages · Page 1 of 1 (latest)

coral lagoonBOT
floral meteor
#

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?

civic quiver
civic quiver
floral meteor
#

You should include a try/catch block in your async function to actually catch the errors

civic quiver
floral meteor
civic quiver
#

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.

floral meteor
#

Ah, ok this is Next.js Route Handlers. The Response object is different. Should be:
NextResponse.json({ sessionId: session.id })

civic quiver
#

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.

floral meteor
#

I can't even see where you're reading the headers

civic quiver
#

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.

floral meteor
#

Right, but the error is thrown from your Route Handler

#

You're not accessing them there

civic quiver
#

Ah hence the error it cant read it, right?

floral meteor
#

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

civic quiver
#

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

floral meteor
#

I think you may need to do req.headers.get('origin')

coral lagoonBOT
civic quiver
#

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.

torn jetty
#

Hi! I'm taking over this thread.

#

Can you try to summarize your question?

civic quiver
#

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.

floral meteor
#

FWIW, req.headers.get('origin') works for me

civic quiver
#

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}'?

floral meteor
#

${req.headers.get('origin')}/result?session_id={CHECKOUT_SESSION_ID}

civic quiver
#

returns Cannot invoke an object which is possibly 'undefined'.ts(2722)

#

but only when hovered over req.headers.get

floral meteor
#

Ah, it's because you're using the wrong type interfaces (NextApiRequest) for your req param

#

That's for API Routes

civic quiver
#

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.

floral meteor
#

As per earlier, these aren't Stripe specific issues. I'd recommend reading through the Next.js docs to understand their APIs

civic quiver
#

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.

coral lagoonBOT
civic quiver
#

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.

floral meteor
#

I'm taking over here. What specifically are you stuck with?

civic quiver
#

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>
  );
}
floral meteor
#

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 your headers key in your fetch request is overwriting the defaults. Try:
headers: new Headers({ 'Content-Type': 'application/json' })

civic quiver
civic quiver
#

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.

floral meteor
#

Can you share the code from your Route Handler?

civic quiver
#

Of course, sorry, what do you mean with Route handler? The server side?

#

The other file?

civic quiver
#
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 });
}
floral meteor
#

Are you able to even log req.headers.get('origin')?

civic quiver
#

Yes I am but will be returned as undefined

#

Let me try again, I did that a bit back.

floral meteor
#

Hmm, yeah I've no idea. That works for me in an identical setup

civic quiver
#

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?

floral meteor
civic quiver
#

In my Terminal

#

Where I run npm run dev etc..

floral meteor
#

Yes, but which line

civic quiver
#

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.

floral meteor
#

Can you try adding return statement before NextResponse.json(...)

civic quiver
#

Of course!

floral meteor
#

Literally the only difference from my functioning code

civic quiver
#

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.

floral meteor
#

Wait, what. Why are you using NextResponse.json in your component?

floral meteor
civic quiver
#

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.

floral meteor
#

Ok, glad that's resolved

civic quiver
# floral meteor 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.

floral meteor
#

Wait, did we not resolve the TypeError: Cannot read properties of undefined (reading 'headers') error?

civic quiver
#

Yes, we did. You said it was the "return" thingy, right?

#

I mean that stopped showing the error hahaha

floral meteor
#

Ok, now what's the issue?

civic quiver
#

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

floral meteor
#

Nope. Do you have a STRIPE_SECRET_KEY variable in your .env file?

civic quiver
#

Yes i do!

#

But it got no " ", just plain.

floral meteor
#

Then it's not a string

civic quiver
floral meteor
#

should be STRIPE_SECRET_KEY="sk_test_xxx"

civic quiver
#

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.

floral meteor
#

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

civic quiver
#

Yes I understand, thank you so much for everything you did! You helped me so much.