async function verifyWebhook(
  payload: string,
  headers: Record<string, string>,
  secret: string,
  tolerance = 300, // 5 minutes
) {
  // Get the signature and timestamp from headers
  const receivedSignature =
    headers["x-payload-signature"] || headers["x-pay-signature"];
  const receivedTimestamp =
    headers["x-timestamp"] || headers["x-pay-timestamp"];
 
  if (!receivedSignature || !receivedTimestamp) {
    throw new Error(
      "Missing required webhook headers: signature or timestamp",
    );
  }
 
  // Verify timestamp
  const now = Math.floor(Date.now() / 1000);
  const timestamp = parseInt(receivedTimestamp, 10);
  const diff = Math.abs(now - timestamp);
 
  if (diff > tolerance) {
    throw new Error(
      `Webhook timestamp is too old. Difference: ${diff}s, tolerance: ${tolerance}s`,
    );
  }
 
  // Generate signature using Web Crypto API
  const encoder = new TextEncoder();
  const key = await crypto.subtle.importKey(
    "raw",
    encoder.encode(secret),
    { hash: "SHA-256", name: "HMAC" },
    false,
    ["sign"],
  );
 
  const signature = await crypto.subtle.sign(
    "HMAC",
    key,
    encoder.encode(`${receivedTimestamp}.${payload}`),
  );
 
  // Convert the signature to hex string
  const computedSignature = Array.from(new Uint8Array(signature))
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
 
  // Compare signatures
  if (computedSignature !== receivedSignature) {
    throw new Error("Invalid webhook signature");
  }
 
  // Parse and return the payload
  return JSON.parse(payload);
}