The payload has to stay byte-for-byte stable

Stripe-style signatures are sensitive to the exact signed string. If a framework parses JSON, changes whitespace, or reserializes the body before verification, the HMAC can fail even when the secret and header are correct.

  • Read the raw request body before JSON parsing.
  • Build the signed string with the provider timestamp exactly as documented.
  • Compare against every signature value present in the header.
  • Keep the endpoint signing secret separate from account API keys.

Timestamp checks are part of the security model

A signature that matches an old payload should still fail when the timestamp is outside the allowed tolerance. The verifier should return a distinct replay-protection reason so teams do not mistake an expired event for a bad secret.

  • Pass a trusted current timestamp into repeatable tests.
  • Use a narrow tolerance window for production receivers.
  • Return reason values such as valid, signature_mismatch, missing_header, and timestamp_out_of_tolerance.
  • Avoid logging full payloads or signing secrets while debugging.

Use a diagnostic before touching production

A small verification API can turn one opaque failure into named checks: header found, timestamp parsed, expected signature calculated, signature matched, and replay window accepted.