Reputation: 1
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
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