PHPackages                             thejano/fib-payment-laravel - 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. thejano/fib-payment-laravel

ActiveLibrary[Payment Processing](/categories/payments)

thejano/fib-payment-laravel
===========================

A Laravel package for FIB online payments using OAuth2 authentication.

1.0.0(today)00MITPHPPHP &gt;=8.1CI passing

Since Jun 27Pushed todayCompare

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

READMEChangelog (1)Dependencies (4)Versions (2)Used By (0)

thejano/fib-payment-laravel
===========================

[](#thejanofib-payment-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/e47212b29758976a0587f0a99fa3d9e5e02f2f3cca679d359d8f7018a7a97bf8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7468656a616e6f2f6669622d7061796d656e742d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/thejano/fib-payment-laravel)[![Tests](https://camo.githubusercontent.com/9c74c2c3ab51cfe01a8ed9d899352d7993a617828aa56cbb4a09b6c206ca034d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7468656a616e6f2f6669622d7061796d656e742d6c61726176656c2f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/thejano/fib-payment-laravel/actions/workflows/tests.yml)[![Total Downloads](https://camo.githubusercontent.com/d9d09e709bb1170cbaa4903ef5db2239eac43eee19f2c6e2e3e22b7b37dd3e58/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7468656a616e6f2f6669622d7061796d656e742d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/thejano/fib-payment-laravel)[![PHP Version Support](https://camo.githubusercontent.com/8bd6b36c8aa4e4c5b200c7f4d07f2e84e82346fa2dfc381ef9bde711cd15e2f0/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7468656a616e6f2f6669622d7061796d656e742d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/thejano/fib-payment-laravel)[![License](https://camo.githubusercontent.com/baeb4e8078678bedd09f64e02d38ee11e91e23231e848d4a1a2b8a8323e29cd2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7468656a616e6f2f6669622d7061796d656e742d6c61726176656c2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/thejano/fib-payment-laravel)

A Laravel package for integrating with the First Iraqi Bank (FIB) online-shop payment API. Supports payment creation, status checks, cancellation, refunds, and typed error handling via OAuth2 client-credentials authentication.

Features
--------

[](#features)

- OAuth2 authentication (client-credentials grant, automatic per-request)
- Create a payment with configurable amount, description, and options
- Check payment status (PAID / UNPAID / DECLINED)
- Cancel a payment
- Refund a paid payment
- Receive status-change callbacks (webhooks) from FIB
- Retrieve a raw access token
- Typed exceptions (`FibPaymentException`) on any 4xx/5xx response
- First-class testability — facade or dependency-injected services, all driven by Laravel's `Http` client

### Feature ↔ API coverage

[](#feature--api-coverage)

FeatureMethodFIB endpointAuthenticate`FibPayment::getToken()``POST /auth/realms/fib-online-shop/protocol/openid-connect/token`Create payment`FibPayment::create()``POST /protected/v1/payments`Check status`FibPayment::status()``GET /protected/v1/payments/{id}/status`Cancel payment`FibPayment::cancel()``POST /protected/v1/payments/{id}/cancel`Refund payment`FibPayment::refund()``POST /protected/v1/payments/{id}/refund`Status callback*(your route)*FIB `POST`s to `FIB_PAYMENT_CALLBACK_URL`Requirements
------------

[](#requirements)

- PHP `>= 8.1` (with the `mbstring` extension)
- Laravel `>= 9.0` (`illuminate/support` and `illuminate/http`)
- FIB online-shop credentials (client ID + secret)

The CI suite runs against **Laravel 11, 12, and 13** on **PHP 8.3 and 8.4** (see [`.github/workflows/tests.yml`](.github/workflows/tests.yml)).

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

[](#installation)

Install the package via Composer:

```
composer require thejano/fib-payment-laravel
```

Publish the config file:

```
php artisan vendor:publish --tag="fib-payment"
```

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

[](#configuration)

Add the following variables to your `.env` file:

```
FIB_PAYMENT_ENV=stage
FIB_PAYMENT_DEV_URL=https://fib.dev.fib.iq
FIB_PAYMENT_STAGE_URL=https://fib.stage.fib.iq
FIB_PAYMENT_PROD_URL=https://fib.prod.fib.iq
FIB_PAYMENT_CLIENT_ID=your-client-id
FIB_PAYMENT_CLIENT_SECRET=your-client-secret
FIB_PAYMENT_CALLBACK_URL=https://your-app.com/fib/callback
FIB_PAYMENT_CURRENCY=IQD
```

VariableRequiredDefaultDescription`FIB_PAYMENT_ENV`Yes`stage`Active environment: `dev`, `stage`, or `production``FIB_PAYMENT_DEV_URL`No`https://fib.dev.fib.iq`Base URL for the `dev` environment`FIB_PAYMENT_STAGE_URL`No`https://fib.stage.fib.iq`Base URL for the `stage` environment`FIB_PAYMENT_PROD_URL`No`https://fib.prod.fib.iq`Base URL for the `production` environment`FIB_PAYMENT_CLIENT_ID`Yes—OAuth2 client ID issued by FIB`FIB_PAYMENT_CLIENT_SECRET`Yes—OAuth2 client secret issued by FIB`FIB_PAYMENT_CALLBACK_URL`Yes—URL FIB will POST to when a payment status changes`FIB_PAYMENT_CURRENCY`No`IQD`Default currency for paymentsUsage
-----

[](#usage)

All operations are accessed through the `FibPayment` facade.

```
use TheJano\FibPayment\Facades\FibPayment;
```

**Lifecycle:** you `create()` a payment and present its QR code / app links to the customer. The payment starts as `UNPAID`; once the customer pays it becomes `PAID`, and FIB calls your callback URL. A payment can be `cancel()`ed while unpaid, or `refund()`ed after it is paid (within the refundable window). At any point you can poll `status()` for the authoritative state.

### Create a Payment

[](#create-a-payment)

```
use TheJano\FibPayment\Facades\FibPayment;

$payment = FibPayment::create(1000, 'Order #5', [
    'expiresIn'    => 'PT12H',
    'refundableFor' => 'P7D',
    'category'     => 'ECOMMERCE',
    'redirectUri'  => 'https://your-app.com/order/5',
]);
```

Response structure:

```
{
    "paymentId": "string",
    "readableCode": "string",
    "qrCode": "base64 string",
    "validUntil": "2024-01-01T12:00:00Z",
    "personalAppLink": "https://...",
    "businessAppLink": "https://...",
    "corporateAppLink": "https://..."
}
```

FieldDescription`paymentId`Unique payment identifier — use this for status checks, cancellation, and refunds`readableCode`Human-readable code the customer can enter manually if they cannot scan the QR code`qrCode`Base64-encoded data URL of the QR code image for scanning with the FIB mobile app`validUntil`ISO-8601 datetime when the payment expires`personalAppLink`Deep link to the payment screen in the FIB Personal app`businessAppLink`Deep link to the payment screen in the FIB Business app`corporateAppLink`Deep link to the payment screen in the FIB Corporate app#### Supported `$options` keys

[](#supported-options-keys)

KeyTypeDescription`currency`stringCurrency code (overrides `FIB_PAYMENT_CURRENCY`), e.g. `IQD``callbackUrl`stringPer-payment callback URL (overrides `FIB_PAYMENT_CALLBACK_URL`)`expiresIn`stringISO-8601 duration for payment expiry, e.g. `PT12H` (12 hours)`refundableFor`stringISO-8601 duration during which the payment can be refunded, e.g. `P7D` (7 days)`category`stringPayment category, e.g. `ECOMMERCE``redirectUri`stringURI the FIB app redirects to after the customer completes paymentDescription is automatically trimmed to 50 characters (multibyte-safe).

### Check Payment Status

[](#check-payment-status)

```
use TheJano\FibPayment\Facades\FibPayment;

$status = FibPayment::status('payment-uuid');
```

Response structure:

```
{
    "paymentId": "string",
    "status": "PAID",
    "validUntil": "2024-01-01T12:00:00Z",
    "amount": {
        "amount": 1000,
        "currency": "IQD"
    },
    "decliningReason": null,
    "declinedAt": null,
    "paidBy": {
        "name": "string",
        "iban": "string"
    }
}
```

FieldDescription`paymentId`The payment's unique identifier`status`One of `PAID`, `UNPAID`, or `DECLINED``validUntil`ISO-8601 datetime when the payment expires`amount`Object with `amount` (number) and `currency` (string)`decliningReason``null`, or one of `SERVER_FAILURE`, `PAYMENT_EXPIRATION`, `PAYMENT_CANCELLATION``declinedAt`ISO-8601 datetime of decline, or `null``paidBy``null` while unpaid; object with `name` and `iban` of the payer once paid### Cancel a Payment

[](#cancel-a-payment)

```
use TheJano\FibPayment\Facades\FibPayment;

$result = FibPayment::cancel('payment-uuid');
// Returns [] on success
```

### Refund a Payment

[](#refund-a-payment)

Only `PAID` payments within the configured refundable window can be refunded.

```
use TheJano\FibPayment\Facades\FibPayment;

$result = FibPayment::refund('payment-uuid');
// Returns [] on success
```

### Retrieve an Access Token

[](#retrieve-an-access-token)

```
use TheJano\FibPayment\Facades\FibPayment;

$token = FibPayment::getToken();
// Returns the raw OAuth2 access token string
```

Handling Status-Change Callbacks (Webhooks)
-------------------------------------------

[](#handling-status-change-callbacks-webhooks)

When a payment's status changes, FIB sends a `POST` request to your `FIB_PAYMENT_CALLBACK_URL`(or the per-payment `callbackUrl` option). The request body contains two fields:

```
{
    "id": "payment-uuid",
    "status": "PAID"
}
```

This package does not register a route for you — you own the endpoint so you can apply your own middleware, validation, and queueing. The recommended pattern is to treat the callback as a trigger and re-fetch the authoritative status from FIB rather than trusting the payload:

```
// routes/web.php (exclude from CSRF protection — it is a server-to-server POST)
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\FibCallbackController;

Route::post('/fib/callback', FibCallbackController::class);
```

```
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use TheJano\FibPayment\Facades\FibPayment;
use TheJano\FibPayment\Exceptions\FibPaymentException;

class FibCallbackController extends Controller
{
    public function __invoke(Request $request)
    {
        $paymentId = $request->input('id');

        try {
            // Re-verify against FIB instead of trusting the callback body.
            $payment = FibPayment::status($paymentId);
        } catch (FibPaymentException $e) {
            report($e);

            return response()->noContent(500);
        }

        if (($payment['status'] ?? null) === 'PAID') {
            // Fulfil the order, mark it paid, etc.
        }

        return response()->noContent();
    }
}
```

Remember to add the callback path to the CSRF exception list (`VerifyCsrfToken::$except`in Laravel 9–10, or `$middleware->validateCsrfTokens(except: [...])` in Laravel 11+).

Using the Services Directly (Dependency Injection)
--------------------------------------------------

[](#using-the-services-directly-dependency-injection)

The facade is a thin wrapper over two container-resolvable services. If you prefer constructor injection — for example, to keep classes explicit and easy to test in isolation — resolve `PaymentService` and `AuthService` directly:

```
use TheJano\FibPayment\Services\PaymentService;

class CheckoutService
{
    public function __construct(private PaymentService $payments) {}

    public function startPayment(int $amount, string $description): array
    {
        return $this->payments->create($amount, $description);
    }
}
```

`PaymentService` exposes the same `create()`, `status()`, `cancel()`, and `refund()` methods as the facade; `AuthService::getAccessToken()` returns the raw token. Both are bound through the container, so Laravel autowires them anywhere dependency injection is available.

Error Handling
--------------

[](#error-handling)

All methods throw `TheJano\FibPayment\Exceptions\FibPaymentException` on any 4xx or 5xx response. Use `getStatusCode()` to retrieve the HTTP status and `getResponseBody()` to inspect the API error payload.

```
use TheJano\FibPayment\Facades\FibPayment;
use TheJano\FibPayment\Exceptions\FibPaymentException;

try {
    $payment = FibPayment::create(1000, 'Order #5');
} catch (FibPaymentException $e) {
    $httpStatus  = $e->getStatusCode();   // int, e.g. 400 or 422
    $body        = $e->getResponseBody(); // mixed — the decoded JSON response body
    $message     = $e->getMessage();      // string — 'FIB payment request failed.'

    // Log or handle accordingly
    \Log::error('FIB payment failed', [
        'status' => $httpStatus,
        'body'   => $body,
    ]);
}
```

### Error-handling caveats

[](#error-handling-caveats)

**Network failures:** `FibPaymentException` is thrown when the FIB API returns a response (4xx/5xx). A low-level network failure (DNS error, connection timeout, etc.) surfaces instead as Laravel's `Illuminate\Http\Client\ConnectionException`, which callers should also catch if needed.

**No token caching:** The OAuth2 access token is never cached or stored. Every `create`, `status`, `cancel`, `refund`, or `getToken` call performs a fresh client-credentials authentication against FIB.

**Instance caching:** The `FibPayment` facade resolves a singleton whose `AuthService` and `PaymentService` *objects* are constructed once per process (config is read at construction time). This caches the service instances only — not the token. It is not designed to pick up runtime config changes within a long-lived worker such as Laravel Octane. Re-deploy or restart the worker to apply config changes.

Testing
-------

[](#testing)

Run the package's own suite:

```
composer test
```

The test suite uses [Pest](https://pestphp.com/) and [Orchestra Testbench](https://packages.tools/testbench).

### Testing your integration

[](#testing-your-integration)

Because every request goes through Laravel's `Http` client, you can fake FIB entirely in your own application's tests — no network calls, no credentials:

```
use Illuminate\Support\Facades\Http;
use TheJano\FibPayment\Facades\FibPayment;

Http::fake([
    '*/auth/realms/fib-online-shop/protocol/openid-connect/token' => Http::response([
        'access_token' => 'fake-token',
    ]),
    '*/protected/v1/payments' => Http::response([
        'paymentId' => 'pay_123',
        'readableCode' => 'ABC123',
    ]),
]);

$payment = FibPayment::create(1000, 'Test order');

expect($payment['paymentId'])->toBe('pay_123');
```

License
-------

[](#license)

The `thejano/fib-payment-laravel` package is open-source software licensed under the [MIT License](https://choosealicense.com/licenses/mit/).

fib-payment-laravel
===================

[](#fib-payment-laravel)

###  Health Score

39

—

LowBetter than 85% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

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://www.gravatar.com/avatar/c3bae4eda28dfbd2e4a288a22c49c4a93c504c7b483e8d8353d7fea1eabcd921?d=identicon)[drpshtiwan](/maintainers/drpshtiwan)

---

Top Contributors

[![drpshtiwan](https://avatars.githubusercontent.com/u/6718949?v=4)](https://github.com/drpshtiwan "drpshtiwan (1 commits)")

---

Tags

laravelpaymentFIBiraq

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/thejano-fib-payment-laravel/health.svg)

```
[![Health](https://phpackages.com/badges/thejano-fib-payment-laravel/health.svg)](https://phpackages.com/packages/thejano-fib-payment-laravel)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)

PHPackages © 2026

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