我正在使用 next js 和 clerk 来验证用户身份。我正在使用 clerk webhook,但消息失败。我将应用程序部署到 vercel 并使用已部署应用程序的 url 作为 clerk webhook 端点中的端点。请帮忙。
route.js
import { Webhook } from 'svix';
import { headers } from 'next/headers';
import { WebhookEvent } from '@clerk/nextjs/server';
import { createUser, deleteUser, updateUser } from '@/lib/actions/user.actions';
import { clerkClient } from '@clerk/nextjs';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
// You can find this in the Clerk Dashboard -> Webhooks -> choose the webhook
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
if (!WEBHOOK_SECRET) {
throw new Error('Please add WEBHOOK_SECRET from Clerk Dashboard to .env or .env.local');
}
// Get the headers
const headerPayload = headers();
const svix_id = headerPayload.get("svix-id");
const svix_timestamp = headerPayload.get("svix-timestamp");
const svix_signature = headerPayload.get("svix-signature");
// If there are no headers, error out
if (!svix_id || !svix_timestamp || !svix_signature) {
return new Response('Error occurred -- no svix headers', {
status: 400
});
}
// Get the body
const payload = await req.json();
const body = JSON.stringify(payload);
// Create a new Svix instance with your secret.
const wh = new Webhook(WEBHOOK_SECRET);
let evt: WebhookEvent;
// Verify the payload with the headers
try {
evt = wh.verify(body, {
"svix-id": svix_id,
"svix-timestamp": svix_timestamp,
"svix-signature": svix_signature,
}) as WebhookEvent;
} catch (err) {
console.error('Error verifying webhook:', err);
return new Response('Error occurred', {
status: 400
});
}
// Get the ID and type
const { id } = evt.data;
const eventType = evt.type;
if (eventType === 'user.created') {
const { id, email_addresses, image_url, first_name, last_name, username } = evt.data;
const user = {
clerkId: id,
email: email_addresses[0].email_address,
username: username!,
firstName: first_name,
lastName: last_name,
photo: image_url,
};
const newUser = await createUser(user);
if (newUser) {
await clerkClient.users.updateUserMetadata(id, {
publicMetadata: {
userId: newUser._id
}
});
}
return NextResponse.json({ message: 'OK', user: newUser });
}
if (eventType === 'user.updated') {
const { id, image_url, first_name, last_name, username } = evt.data;
const user = {
firstName: first_name,
lastName: last_name,
username: username!,
photo: image_url,
};
const updatedUser = await updateUser(id, user);
return NextResponse.json({ message: 'OK', user: updatedUser });
}
if (eventType === 'user.deleted') {
const { id } = evt.data;
const deletedUser = await deleteUser(id!);
return NextResponse.json({ message: 'OK', user: deletedUser });
}
return new Response('', { status: 200 });
}
中间件.js
import { authMiddleware } from "@clerk/nextjs";
export default authMiddleware({
publicRoutes: [
'/',
'/events/:id',
'/api/webhook',
'/api/webhook/stripe',
'/api/uploadthing'
],
ignoredRoutes: [
'/api/webhook/clerk',
'/api/webhook/stripe',
'/api/uploadthing'
]
});
export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
};
我想将经过身份验证的用户的数据保存在我的 mongodb 数据库中。
在职员文档中,route.ts 文件应位于 api/webhooks 文件夹中,并根据该文件更新职员仪表板上的端点,然后转到职员仪表板、用户和身份验证、电子邮件、电话、用户名,然后单击用户名旁边的设置图标并允许需要用户名,然后我对个人信息做了同样的操作,允许需要名字和姓氏,我想通过这样做,职员仪表板中的设置与创建的用户模型保持一致,其中用户对象需要这些信息在数据库集合中创建,最后一件事确保 middleware.ts 文件中的“publicRoutes”包含此行“/api/webhooks(.*)”,这将修复它