AxiamWebhooks
in package
Verifies the `X-Axiam-Signature` HMAC-SHA256 header AXIAM attaches to every webhook delivery (CONTRACT.md §13, T-145). Mirrors the server's signer (`crates/axiam-api-rest/src/webhook.rs`'s `compute_signature_v2`): the MAC covers the ASCII string `<t>.<raw_body>`, keyed with the webhook secret's raw UTF-8 bytes.
Table of Contents
Constants
- DEFAULT_TOLERANCE_SECONDS : mixed = 300
- The default freshness window (CONTRACT.md §13.2): a signature whose `t=` is more than this far in the past OR the future (relative to the `$now` clock — see {@see self::verify()}) is rejected.
Methods
- verify() : WebhookEvent
- Verifies a webhook delivery's `X-Axiam-Signature` header against `$body` and returns the parsed {@see WebhookEvent} on success.
Constants
DEFAULT_TOLERANCE_SECONDS
The default freshness window (CONTRACT.md §13.2): a signature whose `t=` is more than this far in the past OR the future (relative to the `$now` clock — see {@see self::verify()}) is rejected.
public
mixed
DEFAULT_TOLERANCE_SECONDS
= 300
Methods
verify()
Verifies a webhook delivery's `X-Axiam-Signature` header against `$body` and returns the parsed {@see WebhookEvent} on success.
public
static verify(Sensitive $secret, string $signatureHeader, string $body[, int $toleranceSeconds = self::DEFAULT_TOLERANCE_SECONDS ][, callable(): int|null $now = null ]) : WebhookEvent
Parameters
- $secret : Sensitive
-
The webhook's plaintext signing secret (CONTRACT.md §7). Its raw UTF-8 bytes are the HMAC key.
- $signatureHeader : string
-
The raw, unparsed
X-Axiam-Signatureheader value —t=<unix_seconds>,v1=<hex>, optionally with multiplev1entries during secret rotation. - $body : string
-
The exact raw bytes received off the wire, before any JSON decoding. Re-serializing a parsed body (different key order/whitespace) changes these bytes and breaks the MAC — callers MUST pass the untouched request body, e.g.
file_get_contents('php://input')read BEFORE any framework has parsed it as JSON. - $toleranceSeconds : int = self::DEFAULT_TOLERANCE_SECONDS
-
The freshness window in seconds; a non-positive value falls back to self::DEFAULT_TOLERANCE_SECONDS (300). Rejects a
t=more than this far in the past OR the future — a two-sided check, so a future-dated timestamp is rejected just like a stale one (clock-skew abuse). - $now : callable(): int|null = null
-
Test/injection seam for "now" (unix seconds); defaults to
time(). Pass a fake clock to deterministically exercise the freshness check.