gordalina/easypay-bundle
Easypay payment gateway integration for Symfony via the Gordalina EasyPay bundle. Provides services and configuration to process payments in Symfony applications.
First, a reality check. gordalina/easypay-bundle is a Symfony bundle, not a Laravel package. There is no bundle registration, no config/packages/easypay.yaml, and no autowiring in Laravel. If you composer require this into a Laravel app you'll drag in Symfony components, potentially pin conflicting versions of symfony/* packages, and still not have an installable bundle. Don't do it.
What you actually want is the library it wraps: gordalina/easypay-php. That package contains the real Easypay client (payment references, MB references, credit card, direct debit), and the bundle is little more than a DI shim around it. Read the bundle's DependencyInjection/ and Resources/config/services.* first — that tells you exactly which classes need which config keys, and is the blueprint you'll copy into a Laravel service provider. Look at the underlying library's README second.
Minimal steps to get productive:
composer require gordalina/easypay-php (skip the bundle).config/easypay.php with keys pulled from .env: EASYPAY_USER, EASYPAY_PASSWORD, EASYPAY_CIN, EASYPAY_ENTITY, EASYPAY_CLEARKEY, EASYPAY_SANDBOX.AppServiceProvider:$this->app->singleton(\Easypay\Easypay::class, function ($app) {
$cfg = $app['config']['easypay'];
return new \Easypay\Easypay(
$cfg['user'], $cfg['password'], $cfg['cin'],
$cfg['entity'], $cfg['clearkey'], $cfg['sandbox']
);
});
Mirror the bundle's service wiring. The bundle's only real value is binding the Easypay client with credentials from a config tree. Reproduce that in AppServiceProvider (or a dedicated EasypayServiceProvider) as a singleton — the client is stateless and safe to share across a request, but each API call mutates internal state, so don't cross-contaminate between concurrent order flows in the same process (queue workers).
Wrap it in a domain service, not a facade. Rather than Easypay::createReference(...) scattered through controllers, add App\Payments\EasypayGateway with methods like createMbReference(Order $order): PaymentReference and handleNotification(Request $request): PaymentResult. This makes the SDK swappable and keeps the Portuguese gateway's quirks out of your controllers.
Webhook handling. Easypay calls back to a URL you configure per payment. Create a single POST route (e.g. POST /easypay/notification), verify the payload against your stored reference, and update the order inside a transaction. Keep the handler idempotent — Easypay can retry, and your order service should tolerate duplicate notifications.
Config as environment, not hard-coded. The bundle uses Symfony's config/parameters; in Laravel this is config/easypay.php returning env(...) values, with a sandbox boolean switching base URLs. Cache the config (php artisan config:cache) so credential reads aren't hitting env() at runtime.
Testing. Point the client at Easypay's sandbox in your phpunit.xml and use Http::fake() against the underlying Guzzle handler (bind a mock Easypay singleton in the test container) so unit tests don't hit the network.
The bundle is effectively abandoned. 3 stars, 0 dependents, no recent activity. Treat the bundle itself as documentation, not code you'll run. The underlying easypay-php library is where you'll actually debug issues, and even that may have stale PHP version constraints — check composer.json for its PHP upper bound before committing to it.
Symfony components will leak. Even if you only pull in gordalina/easypay-php, verify it doesn't require Symfony's HTTP client or YAML component; if it does, run composer why symfony/... and be prepared to lock compatible versions against your Laravel install.
Amounts are in cents — always. EasyPay's API expects integer cents. Passing 19.99 creates a €0.19 charge or fails validation depending on the endpoint. Centralise the conversion in one place (a Money value object or a cents() helper) rather than remembering at each call site.
The CIN / entity / clearkey are not credentials. They're the merchant identifiers that identify your payment channel to the bank, and they're different in sandbox vs. production. EasyPay will return cryptic errors if you mix sandbox CIN with a production API key — double-check the sandbox flag is actually flipping base URLs, not just a dead config value.
Callback URL must be publicly reachable and HTTPS. EasyPay won't call back to localhost or to a URL behind basic auth. During development, expose via ngrok / expose and register that URL per reference — the callback is stored on the reference at creation time, so a URL change mid-test invalidates in-flight references.
Idempotency and reference reuse. Each created reference is a single-use object on EasyPay's side. Store the reference_id on your order and, on callback, look up by that ID before mutating anything. Re-calling the create endpoint for the same order produces a new reference and a real risk of double-charging the user if they pay both.
Where you'd extend it: if EasyPay later adds new payment methods (MB Way, etc.), the pattern is to add methods to your gateway wrapper and a corresponding notification handler — don't fork the SDK. The bundle's extension point is a Symfony compiler pass; in Laravel the equivalent is a service provider boot() method registering a new binding, so future payment methods should be new services the provider can resolve by name.
How can I help you explore Laravel packages today?