2026-06-07 17:54:30 -04:00
|
|
|
import { prisma } from "@/lib/db";
|
|
|
|
|
|
|
|
|
|
/** True if we've already handled this provider event (idempotency). */
|
|
|
|
|
export async function alreadyProcessed(eventId: string): Promise<boolean> {
|
|
|
|
|
const existing = await prisma.webhookEvent.findUnique({ where: { eventId } });
|
2026-06-20 20:59:03 -04:00
|
|
|
// Only a successfully "processed" event is considered handled. Rows logged as
|
|
|
|
|
// "failed" (or "skipped") must be reprocessable when the provider retries.
|
|
|
|
|
return existing?.status === "processed";
|
2026-06-07 17:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Record a webhook delivery for the admin log (best-effort; unique on eventId). */
|
|
|
|
|
export async function logWebhook(
|
|
|
|
|
provider: "stripe" | "paypal",
|
|
|
|
|
eventId: string,
|
|
|
|
|
type: string,
|
|
|
|
|
status: "processed" | "failed" | "skipped",
|
|
|
|
|
error?: string
|
|
|
|
|
): Promise<void> {
|
|
|
|
|
await prisma.webhookEvent
|
|
|
|
|
.upsert({
|
|
|
|
|
where: { eventId },
|
|
|
|
|
create: { provider, eventId, type, status, error },
|
|
|
|
|
update: { status, error },
|
|
|
|
|
})
|
|
|
|
|
.catch((e) => console.error("[webhook-log] write failed", e));
|
|
|
|
|
}
|