PHPackages                             nizaamomer/laravel-fastpay - 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. nizaamomer/laravel-fastpay

ActiveLibrary[Payment Processing](/categories/payments)

nizaamomer/laravel-fastpay
==========================

Modern Laravel SDK for FastPay Iraq: payment gateway initiation, validation, refunds, QR vending payments, IPN handling and mobile deep links.

v1.0.0(today)02↑2900%MITPHPPHP ^8.2CI passing

Since Jul 2Pushed todayCompare

[ Source](https://github.com/nizaamomer/laravel-fastpay)[ Packagist](https://packagist.org/packages/nizaamomer/laravel-fastpay)[ Docs](https://github.com/nizaamomer/laravel-fastpay)[ RSS](/packages/nizaamomer-laravel-fastpay/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (11)Versions (2)Used By (0)

Laravel FastPay SDK — Payment Gateway, QR Vending &amp; Mobile Deep Links
=========================================================================

[](#laravel-fastpay-sdk--payment-gateway-qr-vending--mobile-deep-links)

[![Latest Version on Packagist](https://camo.githubusercontent.com/048f2580868f22c73ec66b5dc664d19989623370cc416e0af453ad502f9f68dc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6e697a61616d6f6d65722f6c61726176656c2d666173747061792e7376673f7374796c653d666c61742d737175617265266c6162656c3d5061636b616769737426636f6c6f723d6f72616e6765)](https://packagist.org/packages/nizaamomer/laravel-fastpay)[![Tests](https://camo.githubusercontent.com/98969f7ec2062b5f4244267660ef86fa7e86b7aa677931f11576936c7e9ccdbc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6e697a61616d6f6d65722f6c61726176656c2d666173747061792f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d5465737473267374796c653d666c61742d737175617265)](https://github.com/nizaamomer/laravel-fastpay/actions)[![Total Downloads](https://camo.githubusercontent.com/297ae194d0f1de8e4b1d2e3700fd3c77ff0e325c34aed5826bd19fdc54190eb3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6e697a61616d6f6d65722f6c61726176656c2d666173747061792e7376673f7374796c653d666c61742d737175617265266c6162656c3d446f776e6c6f61647326636f6c6f723d626c7565)](https://packagist.org/packages/nizaamomer/laravel-fastpay)[![PHP Version](https://camo.githubusercontent.com/a23022e566b6265a45073f54d4a52366c2187706d31e2256b0eaffc2cf3376ab/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6e697a61616d6f6d65722f6c61726176656c2d666173747061792e7376673f7374796c653d666c61742d737175617265266c6162656c3d50485026636f6c6f723d373737626234)](https://packagist.org/packages/nizaamomer/laravel-fastpay)[![Laravel Version](https://camo.githubusercontent.com/11e569685816c7320414be3556c600e4ffed85d6d93837a325f017cb479df7eb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d3131253230253743253230313225323025374325323031332d6666326432303f7374796c653d666c61742d737175617265)](https://laravel.com)[![License](https://camo.githubusercontent.com/568b9a1edd123a5807a2ad4a39dcfd92651d8095c5e9bc865c76c93a4a9ebfc2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6e697a61616d6f6d65722f6c61726176656c2d666173747061792e7376673f7374796c653d666c61742d73717561726526636f6c6f723d73756363657373)](LICENSE.md)

A modern Laravel SDK for [FastPay Iraq](https://www.fast-pay.iq) — one package covering all three ways FastPay lets you accept money: **1) a redirect-based Payment Gateway for the web**, **2) QR Vending for kiosks/POS**, and **3) Mobile Deep Links for native Android/iOS/Flutter apps** — plus refunds, typed DTOs, multi-store support, and automatic status persistence.

Built by [Nizaam Omer](https://nizaamomer.com) — [nizaamomer.com](https://nizaamomer.com)

Table of Contents
-----------------

[](#table-of-contents)

- [Why one package?](#why-one-package)
- [Requirements](#requirements)
- [Installation](#installation)
- [Part 1 — Payment Gateway (Web)](#part-1--payment-gateway-web)
    - [Initiating a payment](#initiating-a-payment)
    - [The IPN webhook — never trust the payload](#the-ipn-webhook--never-trust-the-payload)
    - [Validating a payment](#validating-a-payment)
    - [Refunding a payment](#refunding-a-payment)
    - [Checking refund status](#checking-refund-status)
    - [Missed notifications: the sync command](#missed-notifications-the-sync-command)
- [Part 2 — QR Vending](#part-2--qr-vending)
    - [Generating a QR](#generating-a-qr)
    - [Validating &amp; refunding a QR payment](#validating--refunding-a-qr-payment)
- [Part 3 — Mobile Deep Links](#part-3--mobile-deep-links)
    - [Building the deep link](#building-the-deep-link)
    - [Handling the callback in your app](#handling-the-callback-in-your-app)
- [Automatic persistence](#automatic-persistence)
- [Full example](#full-example)
- [Security](#security)
- [Testing](#testing)
- [FastPay API Reference](#fastpay-api-reference)
- [Changelog](#changelog)
- [Author](#author)
- [License](#license)

Why one package?
----------------

[](#why-one-package)

All three parts share the same store credentials, the same response envelope quirks, and the same validation/refund shape — splitting them into separate packages would mean re-solving the same HTTP plumbing three times over. `FastpayPayment` covers **Part 1 (Payment Gateway)** and doubles as the validate/refund API for **Part 2 (QR Vending)** via `FastpayQr`; **Part 3 (Mobile Deep Links)** is a thin, dependency-free helper that turns a Part 2 QR into a URL your native app can open. All three sit on the same underlying HTTP client and store configuration.

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

[](#requirements)

- PHP 8.2+
- Laravel 11.x, 12.x or 13.x

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

[](#installation)

```
composer require nizaamomer/laravel-fastpay
```

Publish the config file:

```
php artisan vendor:publish --tag="fastpay-config"
```

Run the migrations — creates `fastpay_payments` and `fastpay_refunds`; every payment and refund is persisted automatically, no manual tracking code needed:

```
php artisan migrate
```

Add your FastPay credentials to `.env` (from the Merchant Panel at [merchant.fast-pay.iq](https://merchant.fast-pay.iq)):

```
FASTPAY_ENVIRONMENT=staging                    # "staging" or "production"
FASTPAY_STORE_ID=your-store-id                 # from Store Configuration in the Merchant Panel
FASTPAY_STORE_PASSWORD=your-store-password     # from Store Configuration — keep this out of version control
FASTPAY_REFUND_SECRET_KEY=your-refund-key      # optional, only needed for gateway refunds — found under Store Details
FASTPAY_CURRENCY=IQD                           # FastPay currently only supports IQD
FASTPAY_SUCCESS_URL=https://your-app.test/checkout/success   # Part 1 only: where FastPay redirects on success
FASTPAY_CANCEL_URL=https://your-app.test/checkout/cancel     # Part 1 only: where FastPay redirects on cancel
FASTPAY_CALLBACK_URL=https://your-app.test/fastpay/ipn       # Part 1 only: where FastPay POSTs the IPN
```

`success_url`/`cancel_url`/`callback_url` only apply to Part 1 (the web redirect flow). Parts 2 and 3 have no equivalent — the FastPay app talks to your own app's deep-link callback scheme directly instead (see [Part 3](#part-3--mobile-deep-links)).

Part 1 — Payment Gateway (Web)
------------------------------

[](#part-1--payment-gateway-web)

For a normal web checkout: you redirect the customer to a FastPay-hosted payment page, and they land back on your `success_url` or `cancel_url` afterward.

> **Note:** FastPay has no "cancel payment" API — `cancel_url` is purely where the browser is redirected if the customer backs out; there's nothing to call on your side for that outcome. The only merchant-initiated actions are initiate, validate, and refund.

### Initiating a payment

[](#initiating-a-payment)

```
use Nizaamomer\LaravelFastpay\Facades\FastpayPayment;

$initiation = FastpayPayment::initiate(
    orderId: (string) $order->id, // 8-32 alphanumeric characters, required by FastPay
    cart: [
        ['name' => 'Scarf', 'qty' => 1, 'unit_price' => 5000],
        ['name' => 'T-Shirt', 'qty' => 2, 'unit_price' => 10000],
    ],
    // amount, successUrl, cancelUrl and callbackUrl are all optional — amount
    // defaults to the sum of the cart, the URLs fall back to FASTPAY_SUCCESS_URL
    // / FASTPAY_CANCEL_URL / FASTPAY_CALLBACK_URL automatically when omitted.
);

return redirect($initiation->redirectUri);
```

### The IPN webhook — never trust the payload

[](#the-ipn-webhook--never-trust-the-payload)

FastPay POSTs an Instant Payment Notification to your `FASTPAY_CALLBACK_URL` **only on successful payments** — failed and cancelled payments send no notification at all. The IPN body is **not signed**, so always re-verify with `validate()` before trusting it, exactly as FastPay's own docs mandate:

```
Route::post('/fastpay/ipn', function (\Illuminate\Http\Request $request) {
    $validation = FastpayPayment::validate($request->input('merchant_order_id'));

    if ($validation->isSuccessful()) {
        // fulfil the order
    }

    return response()->noContent();
})->withoutMiddleware([\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class])
  ->middleware('throttle:60,1');
```

### Validating a payment

[](#validating-a-payment)

Also call this on the page the customer lands on after being redirected back (`success_url`/`cancel_url`) — the IPN might not have arrived yet, or might never arrive at all for a failed/cancelled payment:

```
$validation = FastpayPayment::validate($orderId);

$validation->status;           // PaymentStatus::Success | Failed | Cancel
$validation->isSuccessful();   // bool
$validation->receivedAmount;   // float
$validation->customerName;
$validation->customerMobileNumber;
```

### Refunding a payment

[](#refunding-a-payment)

Requires `FASTPAY_REFUND_SECRET_KEY` (found under Store Details in the Merchant Panel).

```
$refund = FastpayPayment::refund(
    orderId: $orderId,
    msisdn: '+9641000000004', // recipient's FastPay mobile number
    amount: 250.00,
);

$refund->invoiceId;
$refund->recipientName;
```

### Checking refund status

[](#checking-refund-status)

```
$status = FastpayPayment::refundStatus($orderId);

$status->refunded; // bool
```

### Missed notifications: the sync command

[](#missed-notifications-the-sync-command)

Since only successful payments trigger an IPN, any payment left `Pending` in your database needs to be re-checked manually. Run:

```
php artisan fastpay:sync-statuses
```

to re-validate every pending payment directly against FastPay. Schedule it in `bootstrap/app.php`:

```
->withSchedule(function (Illuminate\Console\Scheduling\Schedule $schedule) {
    $schedule->command('fastpay:sync-statuses')->everyFiveMinutes();
})
```

Part 2 — QR Vending
-------------------

[](#part-2--qr-vending)

For vending machines, kiosks, and POS screens: instead of redirecting to a web page, you generate a QR the customer scans with the FastPay app. Minimum amount is 1000 IQD.

### Generating a QR

[](#generating-a-qr)

```
use Nizaamomer\LaravelFastpay\Facades\FastpayQr;

$qr = FastpayQr::generate($orderId, 1500.00);

$qr->qrUrl;   // image URL — display this for the customer to scan
$qr->qrText;  // raw token — hand this to Part 3 if you also want an in-app deep link
```

### Validating &amp; refunding a QR payment

[](#validating--refunding-a-qr-payment)

Same shape as Part 1, just called on `FastpayQr` instead:

```
FastpayQr::validate($orderId);                              // same DTO as the gateway's validate()
FastpayQr::refund($orderId, '+9641000000004', 1500.00);      // no refund secret key needed here, unlike the gateway
```

Part 3 — Mobile Deep Links
--------------------------

[](#part-3--mobile-deep-links)

For a native Android/iOS/Flutter app: skip the "scan a QR with your camera" step and open the FastPay app directly from within your own app. This builds on a Part 2 QR — generate one first, then turn it into a deep link.

### Building the deep link

[](#building-the-deep-link)

```
$qr = FastpayQr::generate($orderId, 1500.00);

$deepLink = $qr->deepLink(clientUri: 'MyApp', orderId: $orderId);
// appFpp://fast-pay.cash/qrpay?qrdata=...&clientUri=appfpclientMyApp&transactionId=...
```

Opening that URL launches the FastPay app directly to the payment screen if installed, or falls back to the app store if not (that fallback logic lives in your native app, not this package).

### Handling the callback in your app

[](#handling-the-callback-in-your-app)

After payment, FastPay redirects back to **your** app via the `appfpclientMyApp://` scheme you register in your Android manifest / iOS `Info.plist` / Flutter `app_links` setup, with `transactionStatus`, `transactionId`, and `amount` as query parameters. This is a **native, client-side callback** — it never touches your Laravel backend, so nothing on the server side needs to handle it directly. Once your app receives it, call `FastpayQr::validate($orderId)` from your backend (same as Part 2) to confirm the outcome server-side before marking anything as paid.

The native-side registration and callback handling (Kotlin/Swift/Dart) is FastPay's own platform-specific integration, documented at [developer.fast-pay.iq](https://developer.fast-pay.iq) — this package only builds the correctly-formatted deep link URL from your backend.

Automatic persistence
---------------------

[](#automatic-persistence)

Every `initiate()`, `validate()`, and `refund()` call — from any of the three parts — fires an event (`PaymentInitiated`, `PaymentValidated`, `PaymentRefunded`) that this package listens to and upserts into `fastpay_payments`/`fastpay_refunds` automatically — no manual tracking code required. Link your own models via the `payable` polymorphic relation:

```
use Nizaamomer\LaravelFastpay\Models\FastpayPayment;

FastpayPayment::where('order_id', $orderId)->first()?->payable()->associate($order)->save();
```

Full example
------------

[](#full-example)

[`docs/examples/PaymentController.php`](docs/examples/PaymentController.php) is a complete, heavily-commented controller covering every public method from all three parts — initiating a web payment, the IPN webhook, the success/cancel return page, refunding, refund status, QR generation/validation, and the deep-link flow. It's illustrative (not autoloaded), so copy what you need into your own app.

Security
--------

[](#security)

- **TLS verification is never disabled.** This SDK does not expose a way to set Guzzle's `verify => false`.
- **IPN payloads are not trusted.** `FastpayPayment::validate()` always calls FastPay directly; use it inside your IPN handler instead of reading `status` off the request body.
- **FastPay's HTTP-200-with-error-code quirk is handled for you.** FastPay returns HTTP 200 for both successes and logical failures (the real outcome is in the JSON `code` field) — this SDK treats `code !== 200` as a failure and throws, so you don't need to remember to check it yourself.
- **Order IDs and MSISDNs are format-validated** (8-32 alphanumeric; `+964` phone format) before any request is sent.
- **Amounts must be greater than zero**, and QR payments enforce FastPay's 1000 IQD minimum, before any request is sent.
- **Credentials live in `.env`,** never in version control. Rotate `FASTPAY_STORE_PASSWORD` immediately if it's ever exposed.

If you discover a security issue, please email  instead of using the public issue tracker.

Testing
-------

[](#testing)

```
composer test        # Pest
composer analyse      # Larastan / PHPStan (level 8)
composer format        # Laravel Pint
```

FastPay API Reference
---------------------

[](#fastpay-api-reference)

See the [FastPay Developer Documentation](https://developer.fast-pay.iq) for the underlying REST API this SDK wraps.

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for what's changed in each release.

Author
------

[](#author)

**Nizaam Omer** — [nizaamomer.com](https://nizaamomer.com) ·

License
-------

[](#license)

MIT. See [LICENSE.md](LICENSE.md).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

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

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/98692798?v=4)[Nizam Omer](/maintainers/nizaamomer)[@nizaamomer](https://github.com/nizaamomer)

---

Top Contributors

[![nizaamomer](https://avatars.githubusercontent.com/u/98692798?v=4)](https://github.com/nizaamomer "nizaamomer (2 commits)")

---

Tags

deep-linkfast-payfastpayiraqlaravellaravel-fastpaylaravel-packagepaymentphpqrrefundsdkqrlaravelsdkpaymentgatewayrefundiraqfastpayFast Pay

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/nizaamomer-laravel-fastpay/health.svg)

```
[![Health](https://phpackages.com/badges/nizaamomer-laravel-fastpay/health.svg)](https://phpackages.com/packages/nizaamomer-laravel-fastpay)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M345](/packages/psalm-plugin-laravel)[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.5k55.4M8.1k](/packages/larastan-larastan)[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M184](/packages/laravel-ai)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k15.1M129](/packages/laravel-pulse)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M143](/packages/laravel-mcp)[spatie/laravel-health

Monitor the health of a Laravel application

87512.0M159](/packages/spatie-laravel-health)

PHPackages © 2026

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