Clerk 和 Svix Web hook 无法正常工作,并出现错误:“src 属性必须是有效的 json 对象”

Eth*_*han 5 webhooks ngrok next.js clerk

我正在尝试将我的 Clerk 数据同步到 Next js 13 项目中的数据库。我的 webhooks 通过 Ngrok 公开暴露。这是我的代码:

import { IncomingHttpHeaders } from "http";
import { headers } from "next/headers";
import { NextResponse } from "next/server";
import { Webhook, WebhookRequiredHeaders } from "svix";

const webhookSecret = process.env.WEBHOOK_SECRET || "";

async function handler(request: Request) {

  console.log(await request.json())

  const payload = await request.json();
  const headersList = headers();
  const heads = {
    "svix-id": headersList.get("svix-id"),
    "svix-timestamp": headersList.get("svix-timestamp"),
    "svix-signature": headersList.get("svix-signature"),
  };
  const wh = new Webhook(webhookSecret);
  let evt: Event | null = null;

  try {
    evt = wh.verify(
      JSON.stringify(payload),
      heads as IncomingHttpHeaders & WebhookRequiredHeaders
    ) as Event;
  } catch (err) {
    console.error((err as Error).message);
    return NextResponse.json({}, { status: 400 });
  }

  const eventType: EventType = evt.type;
  if (eventType === "user.created" || eventType === "user.updated") {
    const { id, ...attributes } = evt.data;
    console.log(attributes)
  }
}

type EventType = "user.created" | "user.updated" | "*";

type Event = {
  data: Record<string, string | number>;
  object: "event";
  type: EventType;
};

export const GET = handler;
export const POST = handler;
export const PUT = handler;
Run Code Online (Sandbox Code Playgroud)

这段代码应该执行以下操作:

  1. 在下面创建一个API路由/api/webhooks/user
  2. 获取有效负载和标头
  3. 使用 Svix 验证此信息
  4. 控制台信息

然而,据我所知,只有步骤 1 有效。在我的职员仪表板中,我收到一个错误:

{
  "message": "src property must be a valid json object"
}
Run Code Online (Sandbox Code Playgroud)

编辑:

使用以下代码我仍然遇到相同的错误:

import { Webhook, WebhookRequiredHeaders } from "svix";

const webhookSecret = process.env.WEBHOOK_SECRET || "";

async function handler(request: Request) {
    const svix_id = request.headers.get("svix-id") ?? "";
    const svix_timestamp = request.headers.get("svix-timestamp") ?? "";
    const svix_signature = request.headers.get("svix-signature") ?? "";

    const body = await request.text(); // This get's the raw body as a string

    const sivx = new Webhook("your_secret_key_here");

    const payload = sivx.verify(body, {
        "svix-id": svix_id,
        "svix-timestamp": svix_timestamp,
        "svix-signature": svix_signature,
    });

    console.log(payload)
}

export const GET = handler;
export const POST = handler;
export const PUT = handler;
Run Code Online (Sandbox Code Playgroud)

我哪里出错了?

Von*_*onC 1

我首先记录原始请求:

const rawBody = await request.text();
console.log(rawBody);
const payload = JSON.parse(rawBody);
Run Code Online (Sandbox Code Playgroud)

您正在使用request.json() 解析传入的请求正文。该函数返回一个Promise将正文解析为 JSON 的结果。
如果传入的正文文本不是有效的 JSON,这可能是错误的根源。

例如,“如何在 nextjs 13.2 路由处理程序中访问请求正文”使用const body = await req.text();

  import { Webhook, WebhookRequiredHeaders } from "svix";

const webhookSecret = process.env.WEBHOOK_SECRET || "";

async function handler(request: Request) {
    const svix_id = request.headers.get("svix-id") ?? "";
    const svix_timestamp = request.headers.get("svix-timestamp") ?? "";
    const svix_signature = request.headers.get("svix-signature") ?? "";

    const body = await request.text(); // This gets the raw body as a string

    const sivx = new Webhook(webhookSecret);

    try {
        const payload = sivx.verify(body, {
            "svix-id": svix_id,
            "svix-timestamp": svix_timestamp,
            "svix-signature": svix_signature,
        });

        console.log(payload);
    } catch (err) {
        console.error('Error verifying webhook:', err);
    }
}

export const GET = handler;
export const POST = handler;
export const PUT = handler;
Run Code Online (Sandbox Code Playgroud)