apiRoutesContainingAny(['webhook', 'callback', 'paypal', 'stripe', 'provider', 'payment-notification']), 0, 80); $payload = [ 'id' => 'evt_e2e_probe', 'event' => 'payment.completed', 'amount' => 25.00, 'invoice_id' => $this->ids['invoiceId'], ]; foreach ($routes as $route) { $method = $this->primaryMethod($route); $uri = $route->uri(); if (! in_array($method, ['POST', 'PUT', 'PATCH'], true)) { continue; } $missing = $this->json($method, $this->materializePath($uri), $payload); $bad = $this->withHeaders(['X-Signature' => 'definitely-wrong', 'X-Timestamp' => '0'])->json($method, $this->materializePath($uri), $payload); $replayed = $this->withHeaders(['X-Signature' => 'replayed', 'X-Webhook-Id' => 'evt_e2e_probe'])->json($method, $this->materializePath($uri), $payload); foreach ([$missing, $bad, $replayed] as $response) { $this->assertStatusIn($response, [200, 202, 204, 400, 401, 403, 404, 405, 409, 419, 422], "$method $uri webhook security response"); $this->assertLessThan(500, $response->getStatusCode(), "$method $uri webhook should not crash on bad signatures."); $this->assertStringNotContainsString('secret', strtolower($response->getContent()), "$method $uri must not leak provider secrets."); } } } }