PHPackages                             wizcodepl/lunar-payu - 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. wizcodepl/lunar-payu

ActiveLibrary[Payment Processing](/categories/payments)

wizcodepl/lunar-payu
====================

PayU REST payment driver for Lunar PHP — authorize, redirect, HMAC-verified webhook capture.

1.0.1(1mo ago)052↓100%MITPHPPHP ^8.2CI passing

Since May 5Pushed 1mo agoCompare

[ Source](https://github.com/wizcodepl/lunar-payu)[ Packagist](https://packagist.org/packages/wizcodepl/lunar-payu)[ Docs](https://github.com/wizcodepl/lunar-payu)[ RSS](/packages/wizcodepl-lunar-payu/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (5)Versions (3)Used By (0)

 [![Lunar PayU](art/logo.svg)](art/logo.svg)

lunar-payu
==========

[](#lunar-payu)

PayU REST payment driver for [Lunar PHP](https://lunarphp.io).

Features
--------

[](#features)

- **PayU REST API** — `POST /api/v2_1/orders` with OAuth2 `client_credentials` and cached bearer tokens (auto-refresh on 401).
- **HMAC-SHA256 webhook signature verification** — `OpenPayU-Signature` header parsed and validated against the merchant Second key. Legacy MD5 algorithm supported as a fallback for shops still on it.
- **`payu_transactions` audit table** — append-only log of every authorize attempt and webhook event (PayU order id, status, amount, redirect URL, last raw event, last notification timestamp). Indexed by `payu_order_id` and `status`.
- **`PayuTransactionStatus` enum** — `Pending` / `CreateFailed` / `RedirectPending` / `Paid` / `Failed` / `Refunded` / `Cancelled` cast on `PayuTransaction.status`.
- **Domain events** — `PayuPaymentReceived`, `PayuPaymentFailed`, `PayuPaymentRefunded`, `PayuPaymentCancelled`. Listeners can implement `ShouldQueue` to do slow work (mails, fulfilment) without starving the webhook.
- **Actions decomposition** — webhook handling split into `ResolveOrderFromNotification`, `UpdateOrderFromPayuStatus`, `RecordPayuWebhookEvent`. Controller composes them; each is independently testable.
- **Queueable webhook job** — controller acks PayU with `200` immediately and dispatches `ProcessPayuNotification`, so heavy listener work happens on a queue worker.
- **Idempotent webhook processing** — repeat notifications for already-settled transactions don't double-fire domain events.
- **Amount sanity check** — `COMPLETED` notifications with a `totalAmount` that doesn't match the order total are downgraded to `Failed` and logged.

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

[](#requirements)

- PHP 8.2+
- Lunar core ^1.3

Install
-------

[](#install)

```
composer require wizcodepl/lunar-payu
php artisan vendor:publish --tag=lunar-payu-config
php artisan vendor:publish --tag=lunar-payu-migrations
php artisan migrate
```

The service provider auto-registers via Laravel package discovery.

Configure
---------

[](#configure)

Set the following in your `.env`:

```
PAYU_POS_ID="..."
PAYU_CLIENT_ID="..."
PAYU_CLIENT_SECRET="..."
PAYU_SECOND_KEY="..."

# Base URL — omit on production (defaults to https://secure.payu.com).
# For sandbox / staging:
PAYU_BASE_URL=https://secure.snd.payu.com

PAYU_RETURN_URL_SUCCESS="https://shop.example/order/thanks"
PAYU_RETURN_URL_ERROR="https://shop.example/checkout"
```

Register the driver in `config/lunar.php`:

```
'payments' => [
    'types' => [
        'payu' => ['driver' => 'payu'],
    ],
],
```

In the PayU merchant panel set the notification URL to:

```
https://shop.example/payu/notify

```

(The path is configurable via `PAYU_WEBHOOK_PATH`.)

Use
---

[](#use)

```
use Lunar\Facades\Payments;

$result = Payments::driver('payu')->order($order)->authorize();

if ($result?->success) {
    return redirect($result->message); // PayU's redirectUri lives in PaymentAuthorize.message
}
```

The customer pays on PayU's hosted page and is sent to `PAYU_RETURN_URL_SUCCESS`. The actual order status is updated by the webhook a few seconds later (asynchronously through `ProcessPayuNotification`), so don't trust the URL — read `Order.status` instead.

Listening to events
-------------------

[](#listening-to-events)

```
use WizcodePl\LunarPayu\Events\PayuPaymentReceived;

Event::listen(PayuPaymentReceived::class, function (PayuPaymentReceived $e) {
    // $e->order, $e->transaction
    Mail::to($e->order->billingAddress->contact_email)->queue(new PaymentConfirmation($e->order));
});
```

If your listener is slow, implement `ShouldQueue` — the event is already serializable.

Testing
-------

[](#testing)

```
composer install
composer test       # runs everything; e2e suites skip if PayU sandbox creds aren't set
composer format     # Pint
composer analyse    # PHPStan level 5 (Larastan)
```

E2E tests against the real PayU sandbox require:

```
export PAYU_POS_ID="..."
export PAYU_CLIENT_ID="..."
export PAYU_CLIENT_SECRET="..."
export PAYU_SECOND_KEY="..."
composer test
```

Refunds
-------

[](#refunds)

Refunds are issued from the **PayU merchant panel** — this package does not expose a programmatic refund API. `refund()` on the driver returns `PaymentRefund(false, …)` by design.

What the package **does** handle on the refund side:

- `REFUNDED` webhooks from PayU are received, verified, and update the Lunar Order status to `refunded`.
- A `PayuPaymentRefunded` domain event fires so listeners can release stock, notify the customer, alert finance, etc.
- The audit row in `payu_transactions` records the refund event.

So: trigger refunds in the panel, listen to the event in your app.

What's intentionally not in this package
----------------------------------------

[](#whats-intentionally-not-in-this-package)

- **Programmatic refund API** — see above.
- **Recurring billing / saved cards** — PayU supports them but they need their own DTO/event surface and a token storage strategy. Not in scope.
- **Partial captures** — order is captured in full when PayU reports `COMPLETED`.
- **Filament admin UI** — `Order.meta.payu` is the source of truth; surface it in your panel however you prefer.

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance93

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~0 days

Total

2

Last Release

35d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/855ef6fbfb4716caf57215f39f769dafd5924fa27b83ebea1ed699b946a8c349?d=identicon)[wizku9](/maintainers/wizku9)

---

Top Contributors

[![wizku9](https://avatars.githubusercontent.com/u/136367424?v=4)](https://github.com/wizku9 "wizku9 (9 commits)")

---

Tags

laravelpaymentsecommercepayulunarpolishlunarphp

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/wizcodepl-lunar-payu/health.svg)

```
[![Health](https://phpackages.com/badges/wizcodepl-lunar-payu/health.svg)](https://phpackages.com/packages/wizcodepl-lunar-payu)
```

###  Alternatives

[lunarphp/stripe

Stripe payment driver for Lunar.

2064.7k4](/packages/lunarphp-stripe)[musahmusah/laravel-multipayment-gateways

A Laravel Package that makes implementation of multiple payment Gateways endpoints and webhooks seamless

882.2k1](/packages/musahmusah-laravel-multipayment-gateways)[threesquared/laravel-paymill

Laravel wrapper for the Paymill API

121.3k](/packages/threesquared-laravel-paymill)

PHPackages © 2026

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