Download the PHP package sandermuller/php-x402 without Composer
On this page you can find all versions of the php package sandermuller/php-x402. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download sandermuller/php-x402
More information about sandermuller/php-x402
Files in sandermuller/php-x402
Package php-x402
Short Description Framework-agnostic PHP implementation of the x402 payment protocol (HTTP 402 stablecoin settlement).
License MIT
Homepage https://github.com/sandermuller/php-x402
Informations about the package php-x402
php-x402
Framework-agnostic PHP implementation of the x402 payment protocol.
HTTP 402 stablecoin settlement. Pay-per-request APIs without subscriptions, API keys, or fiat rails. EIP-3009 transferWithAuthorization on EVM chains via the Coinbase facilitator (or any compatible facilitator).
[!NOTE] Pre-1.0 (
0.x). Public surface is feature-complete for v1 of the spec: HTTP / MCP / A2A transports,exact+uptoschemes on EVM, ERC-7710 shape, SVM pass-through, replay protection, response-cache idempotency, and Bazaar discovery. SeeROADMAP.mdfor what's shipped vs. deferred.
What it does
The server middleware drops a 402 challenge on protected resources, verifies and settles signed payments via a facilitator, then hands the request to the inner handler. The client decorator auto-pays 402 responses by signing an EIP-3009 authorization with your operator wallet and retrying. Both pieces are pure PSR-7/15/17/18 + PSR-16/3, so they wire into Slim, Mezzio, raw Symfony, or the Laravel adapter.
Install
Requires PHP ^8.2. Pulls in PSR-7/15/17/18, PSR-16 cache, PSR-3 logger.
Optional extensions for performance:
ext-secp256k1: ~50× faster signature verification.ext-gmp: required for BigInteger math in signature recovery.
Quick start
Server: gate a resource behind 402
Pipe $middleware through any PSR-15 dispatcher.
Client: pay automatically on 402
PrivateKeyWallet is fine for tests and CLI tools. For production, use X402\Client\AwsKmsWallet (or subclass X402\Client\KmsWallet for GCP / Azure / Vault / HSM) so private keys never sit in process memory. The abstract owns DER decoding, EIP-2 low-s normalisation, on-curve validation, and recovery-id derivation; subclasses provide two thin methods. See docs/kms.md for wiring + the GCP / Vault sketches.
Surface
| Layer | Class |
|---|---|
| Server middleware | X402\Server\PaymentEnforcer (PSR-15) |
| Response cache | X402\Server\PaymentResponseCache (PSR-15) |
| Price table | X402\Server\StaticPriceTable, RegexPriceTable |
| Bot detection | X402\Server\BotDetector |
| Idempotency key | X402\Server\IdempotencyKeyBuilder (transport-agnostic) |
| Client decorator | X402\Client\PayingClient (PSR-18) |
| Facilitator | X402\Facilitator\CoinbaseFacilitator |
| Event hooks | X402\Facilitator\DispatchingFacilitator (wraps any FacilitatorClient, fires closures on every outcome) |
| Outcome DTO | X402\Facilitator\PaymentOutcome, PaymentOutcomeKind (enum) |
| Payment history | X402\PaymentHistory\PaymentRowBuilder (flat-row helper) |
| Webhook primitives | X402\Webhook\SignatureVerifier, WebhookEvent, WebhookDedupStore |
| Schemes (opt-in) | X402\Schemes\ReplayKeyExtractor (per-scheme replay extraction) |
| Signing | X402\Schemes\Evm\AuthorizationSigner, Eip712Hasher |
| Wallets | X402\Client\PrivateKeyWallet, HdWallet (BIP-32), KmsWallet (abstract) + AwsKmsWallet |
| Verification | X402\Schemes\Evm\SignatureVerifier |
| Replay store | X402\Replay\NonceStoreContract, CallbackNonceStore |
| Decimal helper | X402\Support\PriceParser |
| Testing helpers | X402\Testing\PaymentRequiredBuilder, FakeFacilitator |
| CLI | bin/x402 decode <header> |
Composing policy
PaymentEnforcer accepts an optional shouldEnforce predicate that gates the entire pipeline per request. Useful for bot-only payment, IP allowlists, geo policy, or plan-tier exemption:
Predicate returns false → inner handler runs, no challenge / no nonce claim / no facilitator hit. Default (null) = always enforce. Compose multiple policies downstream: fn ($r) => $bot($r) && $geo($r) && $plan($r).
X402\Server\BotDetector ships a curated list of AI agents / assistants / scrapers / search crawlers (~70 patterns from https://knownagents.com) for the bot-only-payment shape:
Override the default list with patterns:, extend it with extra:, or pass patterns: [] to disable detection. Match is case-insensitive substring on the User-Agent.
Response-cache idempotency
PaymentResponseCache is a separate PSR-15 middleware that sits before PaymentEnforcer in the chain. It caches paid 2xx responses keyed by (network, from, nonce, signature bytes) and replays the cached body on duplicates, so a client whose connection drops between facilitator settle and response delivery sees the paid response on retry instead of a 402.
Same Redis-backed PSR-16 store as the nonce store. TTL should comfortably exceed the nonce TTL so retries past nonce expiry still hit the cache.
Replay protection
[!IMPORTANT] Replay protection requires an atomic "set-if-absent with TTL" store: Redis
SET key value NX EX ttlor equivalent. Two concurrent requests carrying the same(network, from, nonce)MUST resolve to a single winner; anything else lets a settled signature replay.
InMemoryNonceStore: in-process only, single worker.Psr16NonceStore:has() + set()on PSR-16. NOT atomic (PSR-16 has no add-if-absent primitive). Acceptable for tests and single-worker dev only. A small race window allows two workers to both claim the same nonce and both settle.- Production: use
LaravelNonceStore(insandermuller/laravel-x402, backed byCache::add()), or implementNonceStoreContractagainst RedisSETNX EXdirectly. Anything else breaks the security contract.
Event hooks and payment history
DispatchingFacilitator wraps any FacilitatorClient and fires a closure with a PaymentOutcome on every verify / settle outcome — VerifyRejected, VerifyError, SettleSucceeded, SettlePending, SettleFailed, SettleError. Adopters wire host-specific event dispatch (Symfony EventDispatcher, log channels, metrics) inside the closure:
PaymentRowBuilder::fromOutcome() returns a flat array matching the laravel-x402 x402_payments migration shape — adopters using Eloquent feed it directly into Payment::query()->updateOrCreate(...). Listener and context-capture exceptions on *-error paths are silently swallowed so the original facilitator throwable always propagates to the caller.
Framework adapters
- Laravel:
sandermuller/laravel-x402 - Laravel MCP:
sandermuller/laravel-x402-mcp
Testing
For adopter integration tests, the X402\Testing namespace ships:
PaymentRequiredBuilder: fluent USDC-on-Base / Base-Sepolia helpers, atomic-unit conversion viaX402\Support\PriceParser(since 0.4.1).FakeFacilitator: canonical test double. Settles locally, configures outcomes viarejectVerify('reason')/failSettle('reason')mid-test, records every call (signature + challenge + returnedverifyResults()/settleResults()), and ships PHPUnit assertion helpers (assertVerified,assertSettled,assertNothingSettled).
Conformance vectors in tests/Fixtures/eip712-vectors.json mirror the upstream Coinbase Go test suite. A hash deviation here is a deviation from the spec.
Roadmap
See ROADMAP.md for shipped scope and explicit non-goals (Solana client-side signing, Stellar, ERC-7710 redelegation chain hashing, RFC 9421, SIWX).
Changelog
See CHANGELOG.md. Updated automatically from GitHub release notes.
Upgrading
See UPGRADING.md for migration notes between minor / major bumps (0.2.x → 0.3.0, 0.3.x → 0.4.0, 0.6.x → 0.7.0, 0.7.x → 0.8.0).
Contributing
See CONTRIBUTING.md for boundary rules, the QA bar, the crypto-stub gotcha, and spec-drift policy.
Security
See SECURITY.md for vulnerability reporting.
License
MIT.
All versions of php-x402 with dependencies
psr/http-message Version ^1.1 || ^2.0
psr/http-server-middleware Version ^1.0
psr/http-server-handler Version ^1.0
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/simple-cache Version ^2.0 || ^3.0
psr/log Version ^2.0 || ^3.0
kornrunner/keccak Version ^1.1
simplito/elliptic-php Version ^1.0