mirror of
https://github.com/theodore-song/polymarket-analyst.git
synced 2026-07-28 00:17:46 +00:00
Add provider webhook event store
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { recordProviderEvent } from "../_db.js";
|
||||
import { firstHeader, parseJson, rawBody, safeHeaders, sendMethodNotAllowed, verifyHmacSignature } from "../_webhook.js";
|
||||
|
||||
const SIGNATURE_HEADERS = [
|
||||
"circle-signature",
|
||||
"x-circle-signature",
|
||||
"x-signature",
|
||||
"webhook-signature",
|
||||
];
|
||||
|
||||
function eventType(payload) {
|
||||
return payload.type || payload.eventType || payload.notificationType || "circle.webhook";
|
||||
}
|
||||
|
||||
function externalId(payload) {
|
||||
return payload.id || payload.notificationId || payload.data?.id || payload.resource?.id || null;
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
if (req.method !== "POST") return sendMethodNotAllowed(res);
|
||||
|
||||
try {
|
||||
const body = await rawBody(req);
|
||||
const payload = parseJson(body);
|
||||
const headers = safeHeaders(req, SIGNATURE_HEADERS.concat(["user-agent"]));
|
||||
const secret = process.env.CIRCLE_WEBHOOK_SECRET;
|
||||
const signature = firstHeader(req, SIGNATURE_HEADERS);
|
||||
const signatureValid = verifyHmacSignature(body, secret, signature);
|
||||
|
||||
const recorded = await recordProviderEvent({
|
||||
provider: "circle",
|
||||
eventType: eventType(payload),
|
||||
externalId: externalId(payload),
|
||||
signatureValid,
|
||||
payload,
|
||||
headers,
|
||||
});
|
||||
|
||||
return res.status(202).json({
|
||||
ok: true,
|
||||
recorded: Boolean(recorded),
|
||||
provider: "circle",
|
||||
event_type: eventType(payload),
|
||||
signature_valid: signatureValid,
|
||||
warning: signatureValid ? undefined : "Event recorded, but no recognized Circle signature was verified.",
|
||||
});
|
||||
} catch (err) {
|
||||
return res.status(500).json({ ok: false, error: err?.message || "Circle webhook failed" });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Webhook } from "svix";
|
||||
import { recordProviderEvent } from "../_db.js";
|
||||
import { rawBody, parseJson, safeHeaders, sendMethodNotAllowed } from "../_webhook.js";
|
||||
|
||||
function eventType(payload) {
|
||||
return payload.type || "clerk.webhook";
|
||||
}
|
||||
|
||||
function externalId(payload) {
|
||||
return payload.id || payload.data?.id || payload.data?.user_id || null;
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
if (req.method !== "POST") return sendMethodNotAllowed(res);
|
||||
|
||||
try {
|
||||
const secret = process.env.CLERK_WEBHOOK_SIGNING_SECRET;
|
||||
if (!secret) return res.status(503).json({ ok: false, error: "Clerk webhook secret is not configured" });
|
||||
|
||||
const body = await rawBody(req);
|
||||
const headers = safeHeaders(req, ["svix-id", "svix-timestamp", "svix-signature"]);
|
||||
let payload;
|
||||
|
||||
try {
|
||||
payload = new Webhook(secret).verify(body, headers);
|
||||
} catch {
|
||||
return res.status(401).json({ ok: false, error: "Invalid Clerk webhook signature" });
|
||||
}
|
||||
|
||||
const recorded = await recordProviderEvent({
|
||||
provider: "clerk",
|
||||
eventType: eventType(payload),
|
||||
externalId: externalId(payload),
|
||||
signatureValid: true,
|
||||
payload,
|
||||
headers,
|
||||
});
|
||||
|
||||
return res.status(200).json({
|
||||
ok: true,
|
||||
recorded: Boolean(recorded),
|
||||
provider: "clerk",
|
||||
event_type: eventType(payload),
|
||||
signature_valid: true,
|
||||
});
|
||||
} catch (err) {
|
||||
const payload = parseJson(req.body);
|
||||
return res.status(500).json({
|
||||
ok: false,
|
||||
error: err?.message || "Clerk webhook failed",
|
||||
provider: "clerk",
|
||||
event_type: eventType(payload),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { recordProviderEvent } from "../_db.js";
|
||||
import { firstHeader, parseJson, rawBody, safeHeaders, sendMethodNotAllowed, verifyHmacSignature } from "../_webhook.js";
|
||||
|
||||
const SIGNATURE_HEADERS = [
|
||||
"x-hmac-signature",
|
||||
"x-veriff-signature",
|
||||
"veriff-signature",
|
||||
"x-signature",
|
||||
];
|
||||
|
||||
function eventType(payload) {
|
||||
return payload.action || payload.eventType || payload.type || payload.status || "veriff.webhook";
|
||||
}
|
||||
|
||||
function externalId(payload) {
|
||||
return payload.id || payload.sessionId || payload.verification?.id || payload.verification?.vendorData || payload.vendorData || null;
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
if (req.method !== "POST") return sendMethodNotAllowed(res);
|
||||
|
||||
try {
|
||||
const body = await rawBody(req);
|
||||
const payload = parseJson(body);
|
||||
const headers = safeHeaders(req, SIGNATURE_HEADERS.concat(["user-agent"]));
|
||||
const secret = process.env.VERIFF_WEBHOOK_SECRET || process.env.VERIFF_SECRET_KEY;
|
||||
const signature = firstHeader(req, SIGNATURE_HEADERS);
|
||||
const signatureValid = verifyHmacSignature(body, secret, signature);
|
||||
|
||||
const recorded = await recordProviderEvent({
|
||||
provider: "veriff",
|
||||
eventType: eventType(payload),
|
||||
externalId: externalId(payload),
|
||||
signatureValid,
|
||||
payload,
|
||||
headers,
|
||||
});
|
||||
|
||||
return res.status(202).json({
|
||||
ok: true,
|
||||
recorded: Boolean(recorded),
|
||||
provider: "veriff",
|
||||
event_type: eventType(payload),
|
||||
signature_valid: signatureValid,
|
||||
warning: signatureValid ? undefined : "Event recorded, but no recognized Veriff signature was verified.",
|
||||
});
|
||||
} catch (err) {
|
||||
return res.status(500).json({ ok: false, error: err?.message || "Veriff webhook failed" });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user