hyprpay / payments
Self-contained multi-gateway payment SDK. Drivers: CyberSource Unified Checkout, Fawry, Paymob, PayLink, PayTabs, PayPal, Mastercard MPGS.
Requires
- php: ^8.2
- ext-json: *
- firebase/php-jwt: ^6.10 || ^7.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/support: ^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
This package is auto-updated.
Last update: 2026-08-12 15:56:09 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 eight gateways built in: CyberSource Unified Checkout, Fawry, Paymob, PayLink, PayTabs, PayPal, Mastercard Payment Gateway Services, and Authorize.Net.
- 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), 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; 290+ 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.
Gateways
Eight drivers behind one PaymentGatewayInterface: CyberSource Unified Checkout,
Fawry, Paymob, PayLink, PayTabs, PayPal, Mastercard Payment
Gateway Services, and Authorize.Net. 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, plus a guide to exposing the SDK 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.