A webhook can contain perfectly sensible JSON and still fail signature verification. If the signature covers the original request body, parsing that body and turning it back into JSON can change the bytes you are checking. The objects might look identical while the signed material is different.
Stripe’s signature troubleshooting guide is explicit about preserving the raw request body. Middleware can get there first, so I would check the route’s request handling before assuming the signing secret is wrong. Use the provider’s supported verification method with the original body, signature header and correct endpoint secret.
Keep that boundary easy to follow. Verify the request before trusting its contents or performing an action, then pass the verified event into the application. Test a valid request and a modified one. There is no need to print secrets or complete event payloads into logs to prove which branch ran; a bounded diagnostic result is usually more useful anyway.
Signature checks are much easier to maintain when the code shows exactly what was verified. A failed check should send you towards the input and endpoint configuration, rather than towards a convenient switch that disables verification. Preserve the evidence until the check has finished with it.