hyprpay / payments
Self-contained multi-gateway payment SDK. Drivers: CyberSource Unified Checkout, Fawry, Paymob, PayLink, PayTabs, PayPal, Mastercard MPGS, Authorize.Net, Airwallex, Tamara.
Requires
- php: ^8.2
- ext-json: *
- firebase/php-jwt: ^6.10 || ^7.0
- illuminate/auth: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/cache: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/console: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/http: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/log: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/pipeline: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/routing: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/support: ^10.0 || ^11.0 || ^12.0 || ^13.0
- illuminate/view: ^10.0 || ^11.0 || ^12.0 || ^13.0
- psr/log: ^3.0
Requires (Dev)
- laravel/pint: ^1.24
- pestphp/pest: ^3.0
- phpstan/phpstan: ^2.1
- rector/rector: ^2.3
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-05 10:51:42 UTC
README
📦 Package: hyprpay/payments on Packagist
📖 Documentation: HyprPay docs
Requirements
- PHP
^8.2 illuminate/supportandilluminate/http^10 | ^11 | ^12 | ^13firebase/php-jwt^6.10 | ^7.0(CyberSource orchestrated-flow result-JWT verification)
Installation
Install from the package repository (or add it as a Composer path repository when
developing locally):
composer require hyprpay/payments
The GatewayServiceProvider is auto-discovered. Publish the config if you want to
tweak the defaults:
php artisan vendor:publish --tag=gateway-config
A self-contained, multi-gateway payment SDK for PHP. One clean interface, a factory that resolves the right driver, and a swappable HTTP transport — with ten gateways built in: CyberSource Unified Checkout, Fawry, Paymob, PayLink, PayTabs, PayPal, Mastercard Payment Gateway Services, Authorize.Net, Airwallex, and Tamara.
- Domain-driven layering — a pure
Domain(contracts, commands, results, value objects, enums), a thinApplicationlayer (PaymentGatewayFactory), and anInfrastructurelayer (the gateway drivers and Laravel adapters). Business rules never depend on the framework. - Factory + single interface — resolve any gateway through
PaymentGatewayFactoryand program against onePaymentGatewayInterface. - Ports & adapters — the
HttpClientandCredentialResolverports live in theDomain; their adapters live inInfrastructure. The HTTP port ships a Laravel adapter (wrapped with retrying, plus optional rate-limiting and logging decorators) for production and an in-memory fake for tests, keeping the core transport- and framework-agnostic. - Raw REST, no vendor SDKs — every driver speaks the gateway's REST API directly and signs requests itself (CyberSource HMAC HTTP-Signature, Fawry SHA-256, Paymob HMAC-SHA512, PayLink HMAC-SHA256, PayTabs server-key auth + HMAC-SHA256 callbacks, PayPal OAuth 2.0 client credentials + API webhook-signature verification, Mastercard MPGS HTTP Basic auth, Authorize.Net name/transaction-key auth + HMAC-SHA512 webhooks, Airwallex API-access login token + HMAC-SHA256 webhooks, Tamara Bearer API token + shared webhook-authorization header), so there are no heavy third-party gateway dependencies.
- Deterministic & idempotent — request bodies are built deterministically (no
hidden
uniqid()/time()), and write operations carry an idempotency key. - Exact money — amounts are carried as minor units and never rounded.
- Statically strict — PHPStan level max, zero baseline; formatted with Pint; refactor-checked with Rector; 370+ Pest tests.
Quick start
The GatewayServiceProvider registers PaymentGatewayFactory (and the HttpClient
and CredentialResolver ports) in the container, so inject the factory via the
constructor — no service location, no new:
use Hyprpay\Payments\Domain\Command\ChargeRequest; use Hyprpay\Payments\Domain\ValueObject\Money; use Hyprpay\Payments\Domain\Enum\GatewayName; use Hyprpay\Payments\Application\PaymentGatewayFactory; final readonly class ChargeInvoice { // Type-hint the factory; Laravel resolves and injects it automatically. public function __construct(private PaymentGatewayFactory $gateways) {} public function handle(string $tokenFromWidget): void { // Credentials resolve from config by default; pass them explicitly to override. $gateway = $this->gateways->make(GatewayName::CybersourceUnifiedCheckout); $result = $gateway->charge(new ChargeRequest( transientToken: $tokenFromWidget, money: Money::minor(10000, 'EGP'), // 100.00 EGP, exact minor units orderReference: 'ORDER-123', // also the idempotency key )); if ($result->success) { // $result->status, $result->transactionId, $result->raw } } }
Prefer to swap the transport or credential source? Bind the ports in a service
provider — the factory depends only on the HttpClient and CredentialResolver
interfaces:
use Hyprpay\Payments\Domain\Contract\CredentialResolver; use Hyprpay\Payments\Domain\Contract\HttpClient; $this->app->bind(HttpClient::class, MyHttpClient::class); $this->app->bind(CredentialResolver::class, MyCredentialResolver::class);
MyHttpClient and MyCredentialResolver are your own classes — each implements the
port interface it is bound to (HttpClient sends the outbound gateway requests;
CredentialResolver supplies the per-gateway credentials). Both bindings are optional:
out of the box the SDK binds a retrying Laravel HTTP adapter (LaravelHttpClient, with
optional rate-limiting/logging decorators) and a config-driven ConfigCredentialResolver,
so bind only the port you want to replace.
Monitoring dashboard
An opt-in operator dashboard — off by default — mounts at /hyprpay to watch gateway
activity: each gateway's health (configured vs not, test vs live, the default), headline
stats and a live recent-activity feed, plus a look-up-by-reference panel that queries the
gateway directly. Enable it (and, separately, the activity store that feeds the feed) via
env:
GATEWAY_DASHBOARD=true # mount the dashboard routes/views GATEWAY_DASHBOARD_STORE=true # record activity into the (cache-backed) feed # GATEWAY_DASHBOARD_PATH=hyprpay # GATEWAY_DASHBOARD_LIMIT=500
Access is gated exactly like Telescope/Horizon: every request must pass the configured
gateway.dashboard.middleware stack (default ['web']) and satisfy the viewHyprpay
gate. The default gate allows only the local environment — open it to real operators from
any service provider:
use Illuminate\Support\Facades\Gate; Gate::define('viewHyprpay', fn ($user = null) => $user?->isAdmin() === true);
The activity store is a bounded cache ring buffer by default (no database, no migration);
bind a custom PaymentActivityRepository to persist durable history instead. The view is
self-contained (inline CSS/JS, no build step) and publishable with
php artisan vendor:publish --tag=gateway-dashboard-views.
Gateways
Ten drivers behind one PaymentGatewayInterface: CyberSource Unified Checkout,
Fawry, Paymob, PayLink, PayTabs, PayPal, Mastercard Payment
Gateway Services, Authorize.Net, Airwallex, and Tamara (buy now, pay
later). Operations a gateway does not support throw
UnsupportedOperationException, so the same surface holds everywhere. A runnable sample
per gateway and the full operation-support matrix live in the docs below.
Documentation
The hosted docs are browsable by gateway. The reference is split into focused guides:
- Gateways & operations — a runnable sample per gateway and the operation-support matrix.
- Payment operations — Dynamic Currency Conversion, idempotency, webhooks, and reconciliation.
- Events & operation logging — the domain events every driver emits and per-operation logging.
- Architecture — the DDD layering and how to add a gateway.
- AI & MCP reference — a machine-consumable, 100%-coverage reference for AI assistants, the developer MCP server that ships in
mcp/(read-only tools that reflect the SDK so coding agents can explore it and generate correct integrations), and a guide to exposing the SDK's operations as MCP tools.
Testing & quality
The package ships a full quality gate. From the package directory:
composer test # Pest composer format # Pint (write) composer analyse # PHPStan, level max composer rector # Rector composer check # format:test + rector:dry + analyse + test
Tests are database-free and never hit the network — they exercise the drivers through
the in-memory FakeHttpClient.
Contributing
See CONTRIBUTING.md. By participating you agree to the Code of Conduct. To report a vulnerability, follow SECURITY.md.
License
Released under the MIT License.