/** * 本地 Webhook 接收器(联调用): * bun tests/fixtures/webhook-receiver.ts [port] * 验证 X-WmailHub-Signature = HMAC-SHA256(secret, `${timestamp}.${body}`),打印收到的 payload。 */ const port = Number(process.argv[2] ?? 18790); /** # 成员变量: 与创建 webhook 时一致的 secret(由环境变量传入) **/ const SECRET = process.env.WEBHOOK_SECRET ?? ""; Bun.serve({ port, async fetch(req) { if (req.method !== "POST") return new Response("ok"); const body = await req.text(); const ts = req.headers.get("X-WmailHub-Timestamp") ?? ""; const sig = req.headers.get("X-WmailHub-Signature") ?? ""; const delivery = req.headers.get("X-WmailHub-Delivery") ?? ""; const key = await crypto.subtle.importKey( "raw", new TextEncoder().encode(SECRET), { name: "HMAC", hash: "SHA-256" }, false, ["sign"], ); const expected = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${ts}.${body}`)); const expectedHex = [...new Uint8Array(expected)].map((b) => b.toString(16).padStart(2, "0")).join(""); const valid = expectedHex === sig; console.log( JSON.stringify({ t: new Date().toISOString(), msg: "webhook received", delivery, signature_valid: valid, payload: JSON.parse(body), }), ); return Response.json({ received: true }); }, }); console.log(`webhook receiver on :${port}`);