json_validate on a webhook body before anything else

A webhook endpoint accepting bodies up to eight megabytes, and the signature check running after the decode.

// the order that matters
if (! json_validate($raw)) {
    return response()->json(['error' => 'invalid json'], 400);
}

if (! $this->signatureMatches($raw, $request->header('X-Signature'))) {
    return response()->json(['error' => 'bad signature'], 401);
}

$payload = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);

Validating before decoding costs one pass over the string and allocates nothing, which on an eight-megabyte body is the difference between a rejected request costing a kilobyte and costing sixty megabytes. Checking the signature against the raw string rather than the re-encoded payload is the other half — a decode-and-re-encode round trip changes key order and whitespace, and the signature no longer matches.