我在我的 nextjs 应用程序中集成了职员身份验证。现在我需要通过 clerk webhook 将用户保存在 MongoDB 中。我已经将我的应用程序托管到 vercel,在 clerk 中添加了
${vercel_site}/api/webhook
端点,拿起 clerk webhook 密钥并将其添加到 .env.local
,但到目前为止没有任何效果。在职员中,我收到消息:
该端点尚未收到任何消息。
控制台中没有错误,应用程序似乎工作正常,但我没有得到店员的任何回应。可能是什么问题?
api/webhook/route.js
import { Webhook } from "svix";
import { headers } from "next/headers";
import { createOrUpdateUser } from "../../lib/controllers/user.controller.js";
export async function POST(req) {
// 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 occured -- 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;
// Verify the payload with the headers
try {
evt = wh.verify(body, {
"svix-id": svix_id,
"svix-timestamp": svix_timestamp,
"svix-signature": svix_signature,
});
} catch (err) {
console.error("Error verifying webhook:", err);
return new Response("Error occured", {
status: 400,
});
}
// Handle the event
const eventType = evt?.type;
if (eventType === "user.created" || eventType === "user.updated") {
const { id, first_name, last_name, profile_image_url, email_addresses } =
evt?.data;
try {
await createOrUpdateUser(
id,
first_name,
last_name,
profile_image_url,
email_addresses,
);
return new Response("User is created or updated", {
status: 200,
});
} catch (err) {
console.error("Error creating or updating user:", err);
return new Response("Error occured", {
status: 500,
});
}
}
}
用户.controller.js
import User from '../models/Users.model.js';
import { connectToDB } from '../mongo.js';
export const createOrUpdateUser = async(id, first_name, last_name, profile_image_url, email_addresses) => {
try{
await connectToDB();
const user = await User.findOneAndUpdate(
{ clerkId: id },
{
$set: {
firstName: first_name,
lastName: last_name,
profilePhoto: profile_image_url,
email: email_addresses[0].email_address,
},
},
{ upsert: true, new: true } // if user doesn't exist, create a new one
);
await user.save();
return user;
} catch (error) {
console.error(error);
}
}
连接数据库
import mongoose from "mongoose";
let isConnected = false;
export const connectToDB = async () => {
mongoose.set("strictQuery", true);
if (isConnected) {
console.log("Database is connected");
} else {
try {
await mongoose.connect(process.env.MONGO_STRING, {
dbName: "Users",
useNewUrlParser: true,
useUnifiedTopology: true,
});
isConnected = true;
} catch (error) {
console.log(error);
}
}
};
在route.js中,我尝试
console.log(svix_id, svix_timestamp, svix_signature)
但再次没有响应。这让我想知道,这个文件是否首先被调用。我还尝试捕获任何错误,以防 POST 请求失败,但到目前为止还没有错误。
catch (err) {
console.error("Error creating or updating user:", err);
return new Response("Error occured", {
status: 500,
});
}
您可以尝试在 vercel 应用程序设置 -> 在部署保护下关闭 vercel 身份验证中删除身份验证。我收到 401 并且 webhooks 无法正常工作,这改变了一切。现在正在按预期工作