Webhook security

Verify every payment webhook before changing an order

Implement VyaparGateway signed payment webhooks using the exact raw body, timestamp replay checks, HMAC-SHA256, and idempotent event processing.

A webhook URL is public by design, so possession of the URL is not authentication. VyaparGateway sends X-VyaparGateway-Timestamp and X-VyaparGateway-Signature headers. Your server reconstructs the signed message from the timestamp, a period, and the exact raw request body, then compares the HMAC-SHA256 digest using a timing-safe operation.

Signature verification happens before JSON fields are trusted. After authentication, enforce a replay window, parse the payload, insert event_id into a unique database column, validate the mapped order, and acknowledge quickly. Expensive fulfilment belongs in a queue after the event transaction commits.

Design principles

The boundaries that keep this flow reliable

01

Preserve exact bytes

Read the raw body before a JSON middleware transforms it. Re-serialised JSON can change whitespace or key order and therefore change the digest.

02

Reject stale timestamps

Compare the signed timestamp with server time using a documented tolerance. This limits reuse of a captured valid request.

03

Deduplicate after authentication

Store event_id under a unique constraint before applying business effects. A retry should return 2xx without fulfilling twice.

Implementation workflow

From request to a durable result

  1. 1

    Capture headers and raw body

    Read signature, timestamp, and exact bytes. Reject missing or malformed headers with a non-2xx response.

  2. 2

    Check timestamp freshness

    Validate integer format and ensure the event falls inside your replay tolerance using a synchronized server clock.

  3. 3

    Compute and compare HMAC

    Create HMAC-SHA256 over timestamp + '.' + raw body and compare the received digest in constant time.

  4. 4

    Apply one event

    Insert event_id, validate the local order and amount, update state, commit, and then return 2xx or enqueue fulfilment.

Node.js raw-body signature verification

ts
const timestamp = request.headers.get("X-VyaparGateway-Timestamp") ?? "";
const received = request.headers.get("X-VyaparGateway-Signature") ?? "";
const rawBody = Buffer.from(await request.arrayBuffer());

if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
  return new Response("stale webhook", { status: 401 });
}

const expected = crypto
  .createHmac("sha256", process.env.VG_WEBHOOK_SECRET!)
  .update(timestamp + ".")
  .update(rawBody)
  .digest("hex");

const valid = expected.length === received.length &&
  crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));

Production checklist

Verify before going live

  • Webhook secret is stored separately from the API key
  • Framework route exposes exact raw bytes
  • Timestamp tolerance and server clock monitoring are configured
  • HMAC is compared with a constant-time function
  • event_id has a unique database constraint
  • Endpoint returns promptly after durable acceptance

Failure recovery

Why valid signatures fail

Body parsed before verification

Your framework changed the bytes. Configure raw-body handling for only the webhook route and parse JSON after HMAC succeeds.

Wrong secret or environment

The endpoint is using a rotated, staging, or copied secret. Confirm the active dashboard secret without logging it.

Timestamp concatenation differs

Sign exactly the documented timestamp, period, and raw bytes. Do not add spaces, a newline, or a parsed object.

FAQ

Questions developers ask

Can I whitelist webhook IP addresses instead of verifying HMAC?

Network controls may be an additional layer, but HMAC authenticates the message itself and should remain mandatory.

What should the endpoint return for a duplicate event?

If the original event was already durably processed, return 2xx without applying the business effect again.

Should failed signatures be logged?

Log a request ID, timestamp, reason, and safe metadata. Do not log secrets or unnecessary customer payment data.

Build the real flow

Move from guide to a verified ₹1 payment

The dashboard checklist takes you through merchant connection, payment verification, webhook testing, and go-live readiness.

Start setup