Browse documentationOpen

byrcsc/laravel-payrex · 1.x

Receiving webhooks.

Receive PayRex webhooks through the package route, verify signatures and timestamps, or build a verified custom route.

Laravel PayRex registers:

POST /payrex/webhook

Point a PayRex webhook endpoint at that URL and put its signing secret in the application environment:

PAYREX_WEBHOOK_SECRET=whsk_test_...

The package verifies the signature against the untouched request body, parses the event, dispatches Laravel events, and returns:

{ "received": true, "id": "evt_..." }

Configure the route

The webhook options live under webhooks in config/payrex.php:

'webhooks' => [
    'enabled' => true,
    'path' => 'payrex/webhook',
    'tolerance' => 300,
    'header' => 'Payrex-Signature',
    'middleware' => [],
    'events' => [
        // event type => Laravel event class
    ],
],

The matching environment variables are:

PAYREX_WEBHOOKS_ENABLED=true
PAYREX_WEBHOOK_PATH=payrex/webhook
PAYREX_WEBHOOK_TOLERANCE=300
PAYREX_WEBHOOK_HEADER=Payrex-Signature

The route is deliberately outside Laravel's web and CSRF middleware. A machine callback has no browser session; its signature authenticates it instead.

Add middleware

Add rate limiting or application-specific middleware without removing signature verification:

'webhooks' => [
    // ...
    'middleware' => [
        'throttle:60,1',
    ],
],

The package always prepends VerifyPayrexSignature.

Signature freshness

The default tolerance is 300 seconds. A signed delivery whose timestamp is older than the tolerance is rejected. Keep the server clock synchronized.

Set the value to 0 only when you intentionally want to disable timestamp freshness checking:

PAYREX_WEBHOOK_TOLERANCE=0

Freshness is not replay protection. An attacker cannot change a signed body, but a valid delivery can still be replayed within the window. PayRex also retries real deliveries. Deduplicate completed work using the event ID.

Delivery failures

An absent, malformed, invalid, or stale signature raises SignatureVerificationException and returns HTTP 400. A signed body that is not a valid PayRex event raises InvalidPayloadException and also returns 400.

Monitor bursts of signature failures. They can indicate a wrong secret, clock drift, a proxy changing the raw body, or unsolicited traffic.

Use a custom route

Disable the package route:

PAYREX_WEBHOOKS_ENABLED=false

Then verify and decode with parseEvent():

use ByRcsc\LaravelPayrex\Facades\Payrex;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::post('/webhooks/payrex', function (Request $request) {
    $event = Payrex::parseEvent(
        payload: $request->getContent(),
        header: $request->header('Payrex-Signature'),
    );

    // Dispatch or process the verified event.

    return response()->json([
        'received' => true,
        'id' => $event->id,
    ]);
});

Call getContent() before anything rewrites the body. parseEvent() uses the configured signing secret and tolerance and returns a typed WebhookEvent. When you own the route, you also own event dispatching, response timing, middleware, and exception behavior.

Respond quickly

Keep the HTTP path short. The package dispatches events synchronously, so make your listeners implement ShouldQueue. A slow or failed delivery can be retried by PayRex for up to three days with exponential backoff.

Laravel PayRex is an unofficial community SDK and is not affiliated with PayRex.

View source