PHPackages                             tamfuldev/payment-gateway - 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. tamfuldev/payment-gateway

ActiveLibrary[Payment Processing](/categories/payments)

tamfuldev/payment-gateway
=========================

A unified abstraction for integrating multiple domestic and international payment gateways in Laravel (VNPay, MoMo, Stripe, PayPal, ...).

v0.1.0(yesterday)00Apache-2.0PHP ^8.2

Since Jul 22Compare

[ Source](https://github.com/tamfuldev/payment-gateway)[ Packagist](https://packagist.org/packages/tamfuldev/payment-gateway)[ Docs](https://github.com/tamfuldev/payment-gateway)[ RSS](/packages/tamfuldev-payment-gateway/feed)WikiDiscussions Synced today

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

Payment Gateway
===============

[](#payment-gateway)

A unified abstraction for integrating **multiple domestic and international payment gateways** in Laravel through a single, consistent API:

```
Payment::gateway('vnpay')->charge($request);
```

Instead of learning each provider's signing scheme, endpoints and payload formats, you code against one contract. Adding a new provider means writing one driver — the calling code never changes.

[![CI](https://camo.githubusercontent.com/6d3d0fa03c5d08b5c761821c2523206cd0c903b57998c61d2f5d382245cd599c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f43492d5048505374616e2532306d61782532302537432532305065737425323025374325323050696e742d627269676874677265656e)](.github/workflows/ci.yml)[![License](https://camo.githubusercontent.com/35b94db23d3ed026343335f74d52ce31e74b77ad7dab4e4b89f49f2026e0937f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4170616368652d2d322e302d626c7565)](LICENSE)

---

Features
--------

[](#features)

- **One API for every gateway** — `charge`, webhook verification, and normalized events.
- **Security-first** — constant-time signature verification (`hash_equals`), no floats for money, secrets read only from config, thin webhook controller that never trusts client input blindly.
- **Correct money handling** — integer minor units via a `Money` value object, with proper zero-decimal support (VND, JPY) vs. 2-decimal currencies (USD, EUR).
- **Framework-friendly** — auto-discovered service provider, publishable config, a `Payment` facade, and an auto-registered webhook route.
- **Built to extend** — SOLID design (Manager/Factory + Strategy + DTOs), interface segregation so a gateway only implements the capabilities it actually supports.

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

[](#requirements)

- PHP `^8.2`
- Laravel `^11.0 || ^12.0`

Installation
------------

[](#installation)

```
composer require tamfuldev/payment-gateway
```

Publish the config file:

```
php artisan vendor:publish --tag=payment-config
```

Then set your credentials in `.env` (see [`.env.example`](.env.example)):

```
PAYMENT_GATEWAY=vnpay

VNPAY_TMN_CODE=your-tmn-code
VNPAY_HASH_SECRET=your-hash-secret
VNPAY_PAY_URL=https://sandbox.vnpayment.vn/paymentv2/vpc/pay.html
```

Usage
-----

[](#usage)

### 1. Create a payment

[](#1-create-a-payment)

```
use Tamfuldev\Payment\Facades\Payment;
use Tamfuldev\Payment\Data\ChargeRequest;
use Tamfuldev\Payment\Enums\Currency;
use Tamfuldev\Payment\ValueObjects\Money;

$response = Payment::gateway('vnpay')->charge(new ChargeRequest(
    orderId:     'ORDER-123',
    amount:      Money::ofMajor('100000', Currency::VND), // 100,000 VND
    description: 'Order #123',
    returnUrl:   route('checkout.return'),
    ipAddress:   request()->ip(),
));

// For redirect-based gateways (VNPay, OnePay, ...):
return redirect()->away($response->redirectUrl);
```

`ChargeResponse` also carries `status`, `method` (redirect / QR / card / wallet), an optional `qrContent`, and a `gatewayReference`.

> **Money:** always build amounts with `Money::ofMajor()` (accepts a string/int, never a float) or `Money::ofMinor()`. The library manages each currency's decimal places for you.

### 2. Handle webhooks / IPN

[](#2-handle-webhooks--ipn)

The package auto-registers a route: `POST /payment/webhook/{gateway}`. It verifies the signature, normalizes the payload, and dispatches an event. You listen for the event to record the order:

```
use Illuminate\Support\Facades\Event;
use Tamfuldev\Payment\Events\PaymentCompleted;

Event::listen(PaymentCompleted::class, function (PaymentCompleted $event): void {
    $payload = $event->payload; // Tamfuldev\Payment\Data\WebhookPayload

    // IMPORTANT — do this in your listener:
    //  1. Be idempotent: the same webhook may arrive more than once
    //     (key off $payload->gatewayReference / $payload->orderId).
    //  2. Reconcile server-side: verify $payload->amount matches your stored order
    //     BEFORE marking it paid. Never trust the amount/status blindly.
});
```

Available events:

EventWhen`PaymentCompleted`A verified webhook reports a successful payment`PaymentFailed`A verified webhook reports a failed/declined paymentAn invalid signature returns `400` and dispatches nothing.

### 3. Change the webhook prefix or middleware

[](#3-change-the-webhook-prefix-or-middleware)

```
// config/payment.php
'webhook' => [
    'prefix'     => 'payment/webhook',
    'middleware' => ['api'],
],
```

Supported gateways
------------------

[](#supported-gateways)

GroupGatewayStatusVietnam**VNPay**✅ charge + webhook verification (reference driver)VietnamMoMo, ZaloPay, OnePay, PayOS, VietQR🔜 plannedInternationalStripe, PayPal, Paddle, 2Checkout🔜 plannedWallet / CryptoBinance Pay, Coinbase Commerce🔜 planned> The VNPay reference driver focuses on getting **charge + webhook verification** right (the security-critical core). Refund/query are follow-up work (they require extra fields such as `transactionDate` / `transactionType`).

Adding a new gateway
--------------------

[](#adding-a-new-gateway)

1. Create `src/Gateways//Gateway.php` extending `AbstractGateway` and implementing `PaymentGateway` (plus capability interfaces like `SupportsRefund` only if the gateway supports them).
2. Register a `createDriver()` method in `PaymentManager`.
3. Add a config block under `config/payment.php` (read secrets from `env()` **only** there).
4. Verify webhooks with a constant-time comparison (`hash_equals`).
5. Write tests first (signing + charge + webhook), mocking HTTP.

See [`CLAUDE.md`](CLAUDE.md) for the full architecture and security checklist.

Architecture
------------

[](#architecture)

```
Payment::gateway('x')
   → PaymentManager (Factory: pick the driver from config)
      → XGateway (Strategy: one class per provider)
         → DTOs in/out (ChargeRequest → ChargeResponse)
Webhook/IPN → WebhookController (verify signature → parse → dispatch event)

```

Development
-----------

[](#development)

This repo ships a Docker toolchain, so you don't need PHP/Composer installed locally.

```
make build      # build the PHP 8.3 image
make install    # composer install
make test       # run the Pest suite
make coverage   # tests with a 90% coverage gate
make analyse    # PHPStan (level max)
make format     # Laravel Pint
make ci         # pint --test + phpstan + pest (the full gate)
make shell      # shell inside the container
```

If you do have PHP/Composer locally, the equivalent `composer` scripts work too (`composer install`, `composer ci`, ...).

Security
--------

[](#security)

If you discover a security issue, please email the maintainer rather than opening a public issue. Key guarantees the library enforces: constant-time signature checks, integer-only money, and secrets sourced exclusively from configuration.

License
-------

[](#license)

Apache-2.0 — see [`LICENSE`](LICENSE).

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

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

Unknown

Total

1

Last Release

1d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/869f2145ad142ba435a92aa56345d32460202314890ed1f49ce95ebae3ad5080?d=identicon)[tamfuldev](/maintainers/tamfuldev)

---

Tags

laravelstripepaymentpayment gatewaymomovietnamvnpay

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/tamfuldev-payment-gateway/health.svg)

```
[![Health](https://phpackages.com/badges/tamfuldev-payment-gateway/health.svg)](https://phpackages.com/packages/tamfuldev-payment-gateway)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k30.2M151](/packages/laravel-cashier)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M184](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

813336.8k3](/packages/defstudio-telegraph)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.6k](/packages/simplestats-io-laravel-client)

PHPackages © 2026

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