PHPackages                             digitaldev-lx/laravel-eupago - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. digitaldev-lx/laravel-eupago

ActiveLibrary[Payment Processing](/categories/payments)

digitaldev-lx/laravel-eupago
============================

A Laravel package for making payments through the EuPago API.

v3.2.1(6d ago)11.1kMITPHPPHP ^8.4CI passing

Since Jun 19Pushed 5d ago2 watchersCompare

[ Source](https://github.com/digitaldev-lx/laravel-eupago)[ Packagist](https://packagist.org/packages/digitaldev-lx/laravel-eupago)[ RSS](/packages/digitaldev-lx-laravel-eupago/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (10)Dependencies (28)Versions (31)Used By (0)

[![laravel-eupago-repo-banner](https://camo.githubusercontent.com/7b3701aded3239bd687b980e7399ead9975630feaf93ee7b9822fd5cc77b4ef6/68747470733a2f2f7062732e7477696d672e636f6d2f70726f66696c655f62616e6e6572732f3539333738353535382f313637313139343635372f3135303078353030)](https://camo.githubusercontent.com/7b3701aded3239bd687b980e7399ead9975630feaf93ee7b9822fd5cc77b4ef6/68747470733a2f2f7062732e7477696d672e636f6d2f70726f66696c655f62616e6e6572732f3539333738353535382f313637313139343635372f3135303078353030)

Laravel EuPago
==============

[](#laravel-eupago)

A comprehensive Laravel package for integrating with the EuPago payment gateway API. Support for Multibanco, MB Way, Credit Card, Google Pay, Apple Pay, and Payouts management.

[![Latest version](https://camo.githubusercontent.com/1d43529802d8c400a4a7d0de52bbb3beb2f2ecde89c165da57c517e2075ec0ca/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f6469676974616c6465762d6c782f6c61726176656c2d65757061676f3f7374796c653d666c61742d737175617265)](https://github.com/digitaldev-lx/laravel-eupago/releases)[![GitHub license](https://camo.githubusercontent.com/c8b74bf9930e8f6256e1b5508b173f1a3397ea92d3eb28318f38ba332061a5fb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6469676974616c6465762d6c782f6c61726176656c2d65757061676f3f7374796c653d666c61742d737175617265)](https://github.com/digitaldev-lx/laravel-eupago/blob/master/LICENSE)

Requirements
------------

[](#requirements)

ReleasePHPLaravel3.0.0&gt;= 8.411 || 12 || 132.3.08.3, 8.411 || 122.2.0&gt;= 8.3112.1.0&gt;= 8.110Installation
------------

[](#installation)

```
composer require digitaldev-lx/laravel-eupago
```

Publish the migration

```
php artisan vendor:publish --provider=DigitaldevLx\\LaravelEupago\\Providers\\EuPagoServiceProvider --tag=migrations
```

Run the migration

```
php artisan migrate
```

Publish the configuration file (optional)

```
php artisan vendor:publish --provider=DigitaldevLx\\LaravelEupago\\Providers\\EuPagoServiceProvider --tag=config
```

Publish the translations files (optional)

```
php artisan vendor:publish --provider=DigitaldevLx\\LaravelEupago\\Providers\\EuPagoServiceProvider --tag=translations
```

Configuration
-------------

[](#configuration)

### Environment Variables

[](#environment-variables)

Add the following to your `.env` file:

```
EUPAGO_ENV=test          # or 'prod'
EUPAGO_API_KEY=your_api_key
EUPAGO_CHANNEL=your_channel

# Optional callback hardening
EUPAGO_ALLOWED_IPS=        # comma-separated EuPago source IPs; empty = accept all
EUPAGO_LOG_CALLBACKS=true  # log a redacted callback summary (never the API key)
```

There are two environments available: "test" and "prod". Use the "test" environment during development and switch to "prod" when your application is ready for production.

### Callback Security

[](#callback-security)

The callback endpoint (`GET /eupago/callback`) is the trust boundary that confirms payments, so it is hardened as follows:

- **API key authentication** — the `chave_api` parameter is compared against `EUPAGO_API_KEY` in constant time (`hash_equals`). Invalid callbacks are rejected with an HTTP `422` and never reveal which field failed.
- **No secret leakage** — the API key is never logged (only a redacted summary is, when `EUPAGO_LOG_CALLBACKS=true`) and is stripped from the `CallbackReceived` event payload.
- **Atomic confirmation** — payments are confirmed inside a locked transaction, so concurrent callbacks for the same reference cannot fire the "paid" event twice.
- **Rate limiting** — the route is throttled to 60 requests/minute per IP.
- **Optional IP allowlist** — set `EUPAGO_ALLOWED_IPS` to the EuPago callback source IPs to reject any other origin. Leave it empty to accept all (default).

Payment Methods
---------------

[](#payment-methods)

### Multibanco (MB) References

[](#multibanco-mb-references)

#### Usage

[](#usage)

```
use DigitaldevLx\LaravelEupago\MB\MB;

$order = Order::find(1);

$mb = new MB(
    $order->value,              // float: payment amount
    $order->id,                 // string: external identifier
    $order->date,               // string: start date (Y-m-d)
    $order->payment_limit_date, // string: end date (Y-m-d)
    $order->value,              // float: minimum value
    $order->value,              // float: maximum value
    0                           // bool: allow duplicated payments
);

try {
    $mbReferenceData = $mb->create();

    if ($mb->hasErrors()) {
        // handle errors
    }

    $order->mbReferences()->create($mbReferenceData);
} catch (\Exception $e) {
    // handle exception
}
```

Response format:

```
[
    'success' => true,
    'state' => 0,
    'response' => "OK",
    'reference' => "000001236",
    'value' => "3.00000",
    'entity' => "11249",
]
```

#### Using the Trait

[](#using-the-trait)

```
use DigitaldevLx\LaravelEupago\Traits\Mbable;

class Order extends Model
{
    use Mbable;
}

// Retrieve references
$order = Order::find(1);
$mbReferences = $order->mbReferences;
```

#### Callback

[](#callback)

The package handles callbacks automatically, updating the payment state and triggering events.

**Endpoint:** `GET /eupago/callback`**Payment Method Code:** `PC:PT`

### MB Way References

[](#mb-way-references)

#### Usage

[](#usage-1)

```
use DigitaldevLx\LaravelEupago\MBWay\MBWay;

$order = Order::find(1);

$mbway = new MBWay(
    $order->value,      // float: payment amount
    $order->id,         // int: external identifier
    $customer->phone,   // string: phone number (alias)
    'Order payment'     // string|null: optional description
);

try {
    $mbwayReferenceData = $mbway->create();

    if ($mbway->hasErrors()) {
        // handle errors
    }

    $order->mbwayReferences()->create($mbwayReferenceData);
} catch (\Exception $e) {
    // handle exception
}
```

#### Using the Trait

[](#using-the-trait-1)

```
use DigitaldevLx\LaravelEupago\Traits\Mbwayable;

class Order extends Model
{
    use Mbwayable;
}

// Retrieve references
$order = Order::find(1);
$mbwayReferences = $order->mbwayReferences;
```

#### Callback

[](#callback-1)

**Endpoint:** `GET /eupago/callback`**Payment Method Code:** `MW:PT`

### Credit Card

[](#credit-card)

#### Single Payment

[](#single-payment)

```
use DigitaldevLx\LaravelEupago\CreditCard\CreditCard;

$creditCard = new CreditCard(
    150.00,                                // float: amount
    'ORDER-456',                           // string: identifier
    'https://example.com/success',         // string: success URL
    'https://example.com/fail',            // string: fail URL
    'https://example.com/back',            // string: back URL
    'customer@example.com',                // string: customer email (required)
    'PT',                                  // string: language (PT, EN, FR, ES)
    'EUR',                                 // string: currency
    true,                                  // bool: notify customer
    60                                     // int|null: minutes form up
);

try {
    $result = $creditCard->create();

    if ($result['success']) {
        // Redirect user to $result['redirect_url']
        // Store $result['reference'] and $result['transaction_id']
    }
} catch (\Exception $e) {
    // handle exception
}
```

**Maximum:** €3,999 per transaction **Callback Code:** `CC:PT`

#### Recurring Payments (Subscriptions)

[](#recurring-payments-subscriptions)

**Step 1: Create Authorization**

```
use DigitaldevLx\LaravelEupago\CreditCard\CreditCardRecurrence;

$recurrence = new CreditCardRecurrence(
    'SUBSCRIPTION-123',                    // string: identifier
);

try {
    $result = $recurrence->create();

    if ($result['success']) {
        // Redirect user to $result['redirect_url'] to authorize subscription
        // Store $result['subscription_id']
    }
} catch (\Exception $e) {
    // handle exception
}
```

**Step 2: Execute Recurring Payment**

```
use DigitaldevLx\LaravelEupago\CreditCard\CreditCardRecurringPayment;

$payment = new CreditCardRecurringPayment(
    'subscription-id-from-authorization',  // string: subscription ID
    50.00,                                 // float: amount
    'PAYMENT-789',                         // string: identifier
    'EUR',                                 // string: currency
    'customer@example.com',                // string|null: customer email
    true                                   // bool: notify customer
);

try {
    $result = $payment->create();

    if ($result['success']) {
        // Payment processed
    }
} catch (\Exception $e) {
    // handle exception
}
```

#### Using the Trait

[](#using-the-trait-2)

```
use DigitaldevLx\LaravelEupago\Traits\Creditcardable;
use DigitaldevLx\LaravelEupago\Traits\Creditcardrecurrable;

class Order extends Model
{
    use Creditcardable;
}

class Subscription extends Model
{
    use Creditcardrecurrable;
}
```

### Google Pay

[](#google-pay)

```
use DigitaldevLx\LaravelEupago\GooglePay\GooglePay;

$googlePay = new GooglePay(
    150.00,                                // float: amount
    'ORDER-456',                           // string: identifier
    'https://example.com/success',         // string: success URL
    'https://example.com/fail',            // string: fail URL
    'https://example.com/back',            // string: back URL
    'EN',                                  // string: language
    'EUR',                                 // string: currency
    'customer@example.com',                // string|null: email
    'John',                                // string|null: first name
    'Doe',                                 // string|null: last name
    'PT',                                  // string|null: country code
    true,                                  // bool: notify customer
    60                                     // int|null: minutes form up
);

try {
    $result = $googlePay->create();

    if ($result['success']) {
        // Redirect to $result['redirect_url']
    }
} catch (\Exception $e) {
    // handle exception
}
```

**Maximum:** €99,999 per transaction **Callback Code:** `GP:PT`

#### Using the Trait

[](#using-the-trait-3)

```
use DigitaldevLx\LaravelEupago\Traits\Googlepayable;

class Order extends Model
{
    use Googlepayable;
}
```

### Apple Pay

[](#apple-pay)

```
use DigitaldevLx\LaravelEupago\ApplePay\ApplePay;

$applePay = new ApplePay(
    150.00,                                // float: amount
    'ORDER-456',                           // string: identifier
    'https://example.com/success',         // string: success URL
    'https://example.com/fail',            // string: fail URL
    'https://example.com/back',            // string: back URL
    'EN',                                  // string: language
    'EUR',                                 // string: currency
    'customer@example.com',                // string|null: email
    'John',                                // string|null: first name
    'Doe',                                 // string|null: last name
    'PT',                                  // string|null: country code
    true,                                  // bool: notify customer
    60                                     // int|null: minutes form up
);

try {
    $result = $applePay->create();

    if ($result['success']) {
        // Redirect to $result['redirect_url']
    }
} catch (\Exception $e) {
    // handle exception
}
```

**Callback Code:** `AP:PT`

#### Using the Trait

[](#using-the-trait-4)

```
use DigitaldevLx\LaravelEupago\Traits\Applepayable;

class Order extends Model
{
    use Applepayable;
}
```

Payouts Management
------------------

[](#payouts-management)

### List Payouts

[](#list-payouts)

Retrieve all payouts for a specific date range using OAuth Bearer Token authentication.

```
use DigitaldevLx\LaravelEupago\Payouts\Payout;

$payout = new Payout(
    '2024-01-01',              // string: start date (yyyy-mm-dd)
    '2024-01-31',              // string: end date (yyyy-mm-dd)
    'your-bearer-token'        // string: OAuth Bearer Token
);

try {
    $result = $payout->list();

    if ($result['success']) {
        foreach ($result['payouts'] as $payout) {
            // Process payout data
        }
    }
} catch (\Exception $e) {
    // handle exception
}
```

### List Payout Transactions

[](#list-payout-transactions)

Retrieve all transaction details within a date range.

```
use DigitaldevLx\LaravelEupago\Payouts\PayoutTransaction;

$transactions = new PayoutTransaction(
    '2024-01-01',              // string: start date (yyyy-mm-dd)
    '2024-01-31',              // string: end date (yyyy-mm-dd)
    'your-bearer-token'        // string: OAuth Bearer Token
);

try {
    $result = $transactions->list();

    if ($result['success']) {
        foreach ($result['transactions'] as $transaction) {
            // Process transaction data
            // Includes: trid, date, amount, payment_method, status
        }
    }
} catch (\Exception $e) {
    // handle exception
}
```

**Note:** For single-day queries, use the same date for both `start_date` and `end_date`.

Callback Parameters
-------------------

[](#callback-parameters)

All payment callbacks receive the following parameters:

NameTypeDescriptionvalorfloatPayment amountcanalstringChannel identifierreferenciastringPayment referencetransacaostringTransaction IDidentificadorintegerExternal identifiermpstringPayment method codechave\_apistringAPI keydatadate:Y-m-d H:i:sTransaction dateentidadestringEntity codecomissaofloatCommissionlocalstringTransaction locationEvents
------

[](#events)

The package dispatches events throughout the payment lifecycle.

### Reference Creation Events

[](#reference-creation-events)

- `MBReferenceCreated` / `MBReferenceCreationFailed`
- `MBWayReferenceCreated` / `MBWayReferenceCreationFailed`
- `CreditCardReferenceCreated` / `CreditCardReferenceCreationFailed`
- `CreditCardRecurrenceAuthorizationCreated` / `CreditCardRecurrenceAuthorizationCreationFailed`
- `CreditCardRecurringPaymentCreated` / `CreditCardRecurringPaymentCreationFailed`
- `GooglePayReferenceCreated` / `GooglePayReferenceCreationFailed`
- `ApplePayReferenceCreated` / `ApplePayReferenceCreationFailed`

### Payment Events

[](#payment-events)

- `MBReferencePaid`
- `MBWayReferencePaid`
- `CreditCardReferencePaid`
- `GooglePayReferencePaid`
- `ApplePayReferencePaid`

### Expiration Events

[](#expiration-events)

- `MBReferenceExpired`
- `MBWayReferenceExpired`

### Callback Events

[](#callback-events)

- `CallbackReceived` - Dispatched for every valid callback. The payload **excludes** the API key and channel.
- `InvalidCallbackReceived` - Dispatched when a callback fails validation (wrong API key/channel, unknown payment method, malformed data). Carries the validation `errors` and a redacted `callbackData` (the API key and channel are excluded).

Invalid callbacks are rejected with a generic HTTP `422` response (no field-level detail), while listeners can still inspect the failure through `InvalidCallbackReceived`.

### Listening to Events

[](#listening-to-events)

**Auto-discovery (recommended):**

Create a listener class in `app/Listeners/` — Laravel automatically discovers it via the type-hinted `handle()` method:

```
// app/Listeners/HandleMBPayment.php
namespace App\Listeners;

use DigitaldevLx\LaravelEupago\Events\MBReferencePaid;
use Illuminate\Support\Facades\Mail;

class HandleMBPayment
{
    public function handle(MBReferencePaid $event): void
    {
        $reference = $event->reference;

        $reference->mbable->update(['status' => 'paid']);

        Mail::to($reference->mbable->user)->send(
            new \App\Mail\PaymentConfirmed($reference)
        );
    }
}
```

No manual registration needed. Laravel scans `app/Listeners/` automatically.

**Manual registration:**

Register listeners in your `app/Providers/AppServiceProvider.php`:

```
use DigitaldevLx\LaravelEupago\Events\MBReferencePaid;
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::listen(
        MBReferencePaid::class,
        SendPaymentConfirmationEmail::class,
    );
}
```

**Closure listeners:**

```
use DigitaldevLx\LaravelEupago\Events\MBReferencePaid;
use Illuminate\Support\Facades\Event;

Event::listen(function (MBReferencePaid $event) {
    $reference = $event->reference;
    $reference->mbable->update(['status' => 'paid']);
});
```

Commands
--------

[](#commands)

### Check Expired References

[](#check-expired-references)

Check for expired payment references and dispatch expiration events:

```
php artisan eupago:check-expired
```

This command finds all MB references where `end_date` has passed and `state` is 0 (unpaid), then dispatches `MBReferenceExpired` event for each.

**Scheduling:**

**Laravel 11 &amp; 12:**

Add to your `routes/console.php`:

```
use Illuminate\Support\Facades\Schedule;

Schedule::command('eupago:check-expired')->daily();
```

**Laravel 10:**

Add to your `app/Console/Kernel.php`:

```
protected function schedule(Schedule $schedule)
{
    $schedule->command('eupago:check-expired')->daily();
}
```

Testing
-------

[](#testing)

The package includes comprehensive test coverage using Pest PHP.

### Running Tests

[](#running-tests)

```
# Run all tests
composer test

# Run with coverage (minimum 50% required)
composer test:coverage

# Run specific test file
vendor/bin/pest tests/Unit/MB/MBTest.php
```

### Code Style

[](#code-style)

```
# Fix code style with Pint
composer lint

# Check code style without fixing
composer lint:check
```

### Static Analysis

[](#static-analysis)

```
# Run Larastan Level 6 analysis
composer analyse
```

### Using Factories in Tests

[](#using-factories-in-tests)

```
use DigitaldevLx\LaravelEupago\Models\MbReference;
use DigitaldevLx\LaravelEupago\Models\MbwayReference;
use DigitaldevLx\LaravelEupago\Models\CreditCardReference;
use DigitaldevLx\LaravelEupago\Models\GooglePayReference;
use DigitaldevLx\LaravelEupago\Models\ApplePayReference;

// Create unpaid reference
$reference = MbReference::factory()->create();

// Create paid reference
$paidReference = MbReference::factory()->paid()->create();

// Create expired reference
$expiredReference = MbReference::factory()->expired()->create();

// Other payment methods
$mbwayReference = MbwayReference::factory()->create();
$ccReference = CreditCardReference::factory()->paid()->create();
$googlePayReference = GooglePayReference::factory()->create();
$applePayReference = ApplePayReference::factory()->paid()->create();
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.

Changelog
---------

[](#changelog)

Please see [CHANGELOG.md](CHANGELOG.md) for details on recent changes.

License
-------

[](#license)

**digitaldev-lx/laravel-eupago** is open-sourced software licensed under the [MIT license](https://github.com/digitaldev-lx/laravel-eupago/blob/master/LICENSE).

About DigitalDev
----------------

[](#about-digitaldev)

[DigitalDev](https://www.digitaldev.pt) is a digital transformation agency based in Lisbon, Portugal. We specialize in transforming ideas into digital solutions that drive business growth online.

With expertise in custom web development, system integration, DevOps, AI implementation, and advanced search systems, we help businesses scale beyond generic templates with practical, data-driven solutions. Our tech stack includes Laravel, Livewire, React, and modern cloud infrastructure.

**Contact:**  | +351 961 546 227

###  Health Score

57

—

FairBetter than 98% of packages

Maintenance99

Actively maintained with recent releases

Popularity21

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity80

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 64.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~70 days

Recently: every ~22 days

Total

27

Last Release

6d ago

Major Versions

v1.1.2 → v2.0.02022-04-05

v2.3.0 → v3.0.02026-04-01

PHP version history (6 changes)v1.0.0PHP ^8.0

v1.0.3PHP ^7.3|^8.0

v2.0.1PHP ^8.1

v2.2.0PHP ^8.3

v2.3.0PHP ^8.3 || ^8.4

v3.0.0PHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/c6498ae164eb066d13ae98668c2c9df065410dcb1da196561ef8f76c93c1a827?d=identicon)[digitaldevlx](/maintainers/digitaldevlx)

---

Top Contributors

[![digitaldev-lx](https://avatars.githubusercontent.com/u/81043832?v=4)](https://github.com/digitaldev-lx "digitaldev-lx (25 commits)")[![jfrosorio](https://avatars.githubusercontent.com/u/17640929?v=4)](https://github.com/jfrosorio "jfrosorio (14 commits)")

---

Tags

laravelEupagocodetechmb referenceslaravel-eupagoreferências multibancombway references

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/digitaldev-lx-laravel-eupago/health.svg)

```
[![Health](https://phpackages.com/badges/digitaldev-lx-laravel-eupago/health.svg)](https://phpackages.com/packages/digitaldev-lx-laravel-eupago)
```

###  Alternatives

[unopim/unopim

UnoPim Laravel PIM

10.5k2.4k](/packages/unopim-unopim)[juzaweb/cms

Juzaweb CMS is a Content Management System (CMS) developed based on Laravel Framework and web platform whose sole purpose is to make your development workflow simple again. Project develop by Juzaweb

188571.2k](/packages/juzaweb-cms)[duncanmcclean/statamic-cargo

Comprehensive e-commerce addon for Statamic. Build bespoke e-commerce sites without the complexity.

3417.0k](/packages/duncanmcclean-statamic-cargo)[api-platform/laravel

API Platform support for Laravel

58171.8k14](/packages/api-platform-laravel)[nasirkhan/module-manager

Module Manager &amp; Generator for Laravel Starter Kit (https://github.com/nasirkhan/laravel-starter)

1044.6k5](/packages/nasirkhan-module-manager)[ecotone/laravel

Ecotone for Laravel — CQRS, Event Sourcing, Sagas, Durable Workflows, and Outbox on top of Laravel Queue, via PHP attributes.

21318.6k3](/packages/ecotone-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
