Natig Agharzayev
Natig Agharzayev

Reputation: 1

Stripe webhook 404 problem(Deliveries to webhook endpoints)

I can't send publicMetadata to Clerk(auth provider) because Stripe can't find /api/webhook route and call it in order to call certain function that will send publicMetadata.

/api/stripe/route.ts

import Stripe from 'stripe';
import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@clerk/nextjs/server';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string);
export async function POST(request: NextRequest) {
  try {
    const { userId } = auth()
    console.log("userId = ", userId)
    const checkoutSession: Stripe.Checkout.Session =
      await stripe.checkout.sessions.create({
        payment_method_types: ['card'],
        line_items: [
          {
            price: "price_1Q6CYqHP9wN4meCvzklGUQbx",
            quantity: 1,
          }
        ],
        mode: 'payment',
        success_url: 'https://chatti-jade.vercel.app/dashboard/habits',
        // success_url: 'http://localhost:3000/dashboard/habits',
        cancel_url: 'https://chatti-jade.vercel.app/dashboard/habits',
        // cancel_url: 'http://localhost:3000/dashboard/habits',
        metadata: {
          userId: userId,
          priceId: "price_1Q6CYqHP9wN4meCvzklGUQbx",
        }
      });
    return NextResponse.json({ result: checkoutSession, ok: true });
  } catch (error) {
    console.log(error);
    return NextResponse.json({ error: error}, { status: 500 });
  }
}

api/webhooks/route.ts

import { NextRequest, NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY as string)
import { clerkClient } from '@clerk/nextjs/server'

export async function POST(request: NextRequest) {
  try {
    const buf = await request.text(); // Get the raw body
    const sig = request.headers.get('stripe-signature') as string;

    // Construct the event with Stripe's signature
    const event = stripe.webhooks.constructEvent(buf, sig, process.env.STRIPE_WEBHOOK_SECRET!);

    // Handle the event (for example, checkout.session.completed)
    if (event.type === 'checkout.session.completed') {
      const session = event.data.object as Stripe.Checkout.Session;
      console.log(`Payment was successful for session ID: ${session.id}`);
      // Process the session or update your database here.
      const userId = session.metadata?.userId || 'user_2kbeVlEvHUAj35OGinSns4FktxF';

      console.log(`User ID: ${userId}`);

      if (userId) {
        await clerkClient.users.updateUserMetadata(userId, {
          publicMetadata: {
            paid: true, 
            paymentId: session.id,
          },
        })
      } else {
        console.error('User ID not found in session metadata');
      }
    }

    return NextResponse.json({ received: true });
  } catch (err: any) {
    console.error('Error:', err.message);
    return NextResponse.json({ error: err.message }, { status: 400 });
  }
}

My project construction: My project construction Stripe issue: Stripe issue Also, github link to have better understand: https://github.com/NatigAgarzayev/chatti

I tried to put api/webhook to ignoredRoutes, but it did't work for me. Payments are succesfull, but it doesn't send info to clerk. I reviewed all keys, they are all correct.

Upvotes: 0

Views: 54

Answers (1)

orakaro
orakaro

Reputation: 1981

It looks like the webhook events Stripe sent to your server failed with 404, which means your server doesn't serve https://chatti-jade.vercel.app/api/webhooks correctly.

You would want to debug your webhook endpoint first, ie. curl yourself to https://chatti-jade.vercel.app/api/webhooks to make sure it returns 200 or 400, so you know the code inside api/webhooks/route.ts actually being run.

Upvotes: -1

Related Questions