PHPackages                             giorgigrdzelidze/laravel-fina-sdk - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. giorgigrdzelidze/laravel-fina-sdk

ActiveLibrary[Testing &amp; Quality](/categories/testing)

giorgigrdzelidze/laravel-fina-sdk
=================================

Laravel SDK for integrating with FINA Web API (v8.0). Provides authentication, HTTP client, and typed endpoints.

v0.1.2(1mo ago)00MITPHPPHP ^8.2CI passing

Since Feb 20Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/GiorgiGrdzelidze/laravel-fina-sdk)[ Packagist](https://packagist.org/packages/giorgigrdzelidze/laravel-fina-sdk)[ Docs](https://github.com/GiorgiGrdzelidze/fina-sdk-laravel)[ RSS](/packages/giorgigrdzelidze-laravel-fina-sdk/feed)WikiDiscussions main Synced 1w ago

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

FINA SDK for Laravel
====================

[](#fina-sdk-for-laravel)

[![CI](https://github.com/GiorgiGrdzelidze/fina-sdk-laravel/actions/workflows/ci.yml/badge.svg)](https://github.com/GiorgiGrdzelidze/fina-sdk-laravel/actions/workflows/ci.yml)[![Latest Version](https://camo.githubusercontent.com/51b736620e858ccee6064323837cc4c4b87351be731e50dc9a4c8718e651b3e4/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f47696f7267694772647a656c69647a652f66696e612d73646b2d6c61726176656c3f6c6162656c3d72656c65617365)](https://github.com/GiorgiGrdzelidze/fina-sdk-laravel/releases)[![PHP Version](https://camo.githubusercontent.com/8f0af9c5395ae4ef8ba7a7ad65fa61c44927ea9c3eb3be91a13c678254f29bd4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e322d383839324246)](https://php.net)[![Laravel Version](https://camo.githubusercontent.com/3dff4a557be8838f9d717a0e951c57625946424290bce8fc7e9fc39dd1130838/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d25334525334431322e302d464632443230)](https://laravel.com)[![License: MIT](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)

A production-ready Laravel SDK for the **FINA Web API v8.0**. Handles authentication, token caching, typed DTOs, request validation, chunked reporting with deduplication, and structured error handling out of the box.

---

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

[](#table-of-contents)

- [What's New in v8.0](#whats-new-in-v80)
- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Quick Start](#quick-start)
- [API Reference](#api-reference)
    - [Customers](#customers)
    - [Vendors](#vendors)
    - [Products](#products)
    - [Reference Data](#reference-data)
    - [Loyalty](#loyalty)
    - [Documents](#documents)
    - [Reporting](#reporting)
- [DTOs &amp; Validation](#dtos--validation)
- [Error Handling](#error-handling)
- [Performance](#performance)
- [Testing &amp; Quality](#testing--quality)
- [Troubleshooting](#troubleshooting)
- [License](#license)

---

What's New in v8.0
------------------

[](#whats-new-in-v80)

This release adds **18 new endpoints** and expands several existing ones:

AreaNew Capabilities**Customers**Agreements, sub-account fields, sub-accounts**Vendors**Sub-accounts**Products**Rest-after-date, rest summary, rest by store, provided service prices**Loyalty**Gift card info by code, bonus card rest by code**Reference**Transportation means, account value details**Documents**Save received service, bonus card, gift payment; get/save auto-service docs**Reporting**Auto services out journal (raw + typed + chunked), cafe order detailed report**DTOs**17 new typed DTOs and payloads with full validationExisting endpoints are unchanged -- the upgrade is fully backwards-compatible.

---

Features
--------

[](#features)

FeatureDescription**Auto-authentication**Fetches, caches (~35h TTL), and transparently refreshes tokens on 401**Configurable HTTP**Timeout, retry count, and retry delay via `.env`**8 API clients**Customers, Vendors, Products, Documents, Loyalty, Reference, Journals, Reporting**Chunked reporting**Splits large date ranges into windows, merges, deduplicates by `id+version`**Typed DTOs**`readonly` classes with `fromArray()` factories for all responses**Validated payloads**Request DTOs with Laravel validation rules, auto-validated before sending**Structured exceptions**Config, HTTP, Remote, and Validation exceptions with useful properties**PHPStan level 6**Full static analysis coverage---

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

[](#requirements)

- **PHP** &gt;= 8.2
- **Laravel** &gt;= 12.0
- A running **FINA Web API v8.0** instance

---

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

[](#installation)

### Via Composer

[](#via-composer)

```
composer require giorgigrdzelidze/laravel-fina-sdk
```

Laravel auto-discovers the service provider. No manual registration needed.

### Local (path repository)

[](#local-path-repository)

If using as a local path repository:

```
{
    "repositories": [
        { "type": "path", "url": "packages/fina/fina-sdk-laravel" }
    ]
}
```

```
composer require giorgigrdzelidze/laravel-fina-sdk:@dev
```

---

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

[](#configuration)

### 1. Add environment variables

[](#1-add-environment-variables)

```
FINA_BASE_URL=https://your-fina-host:5007
FINA_LOGIN=your_login
FINA_PASSWORD=your_password
```

### 2. Publish config (optional)

[](#2-publish-config-optional)

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

### Environment variable reference

[](#environment-variable-reference)

VariableDefaultDescription`FINA_BASE_URL`*(required)*FINA instance URL (scheme + host + port)`FINA_LOGIN`*(required)*API login`FINA_PASSWORD`*(required)*API password`FINA_TIMEOUT``120`HTTP timeout (seconds)`FINA_RETRY_TIMES``2`Retries on transient failure`FINA_RETRY_SLEEP_MS``300`Delay between retries (ms)`FINA_TOKEN_TTL``126000`Token cache lifetime (seconds, ~35h)`FINA_DOC_TYPES_TTL``3600`Doc-types cache lifetime (seconds)---

Quick Start
-----------

[](#quick-start)

### Get the client

[](#get-the-client)

```
use Fina\Sdk\Laravel\Client\FinaClient;

// Via container
$fina = app('fina');

// Via injection
public function __construct(private FinaClient $fina) {}
```

### Fetch reference data

[](#fetch-reference-data)

```
$stores   = $fina->reference()->stores();
$users    = $fina->reference()->users();            // UserDto[]
$docTypes = $fina->reference()->docTypesCached();    // cached 1h
$vehicles = $fina->reference()->transportationMeans(); // v8.0
```

### Save a document

[](#save-a-document)

```
use Fina\Sdk\Laravel\Operation\Dto\ProductOutPayload;
use Fina\Sdk\Laravel\Operation\Dto\ProductLine;

$response = $fina->documents()->saveProductOut(new ProductOutPayload(
    id: 0, date: now(), numPrefix: '', num: 0,
    purpose: 'Sale via API', amount: 100.0,
    currency: 'GEL', rate: 1.0,
    store: 1, user: 1, staff: 1, project: 0, customer: 8,
    isVat: true, makeEntry: true,
    payType: 1, wType: 0, tType: 1, tPayer: 2, wCost: 0, foreign: false,
    products: [new ProductLine(id: 2, subId: 0, quantity: 3, price: 33.33)],
));

$response->id; // saved document ID
$response->ex; // null on success
```

### Query a report

[](#query-a-report)

```
// Raw
$raw = $fina->reporting()->entriesJournal($from, $to);

// Typed
$dto = $fina->reporting()->entriesJournalTyped($from, $to);
$dto->journals; // EntriesJournalRowDto[]

// Chunked (splits large ranges, deduplicates automatically)
$dto = $fina->reporting()->entriesJournalChunkedTyped($from, $to, chunkDays: 7);
```

---

API Reference
-------------

[](#api-reference)

All methods are accessed through the `FinaClient` instance (`$fina`).

### Customers

[](#customers)

Access via `$fina->customers()`.

MethodFINA EndpointReturns`all()``getCustomers``array``getByCode($code)``getCustomersByCode/{code}``array``groups()``getCustomerGroups``array``addresses()``getCustomerAddresses``array``additionalFields()``getCustomerAdditionalFields``array``agreements()``getCustomerAgreements``CustomerAgreementDto[]``subAccountFields()``getContragentSubAccountFields``ContragentSubAccountFieldDto[]``subAccounts()``getCustomerSubAccounts``ContragentSubAccountDto[]`> Last 3 methods are new in v8.0.

### Vendors

[](#vendors)

Access via `$fina->vendors()`.

MethodFINA EndpointReturns`all()``getVendors``array``getByCode($code)``getVendorsByCode/{code}``array``groups()``getVendorGroups``array``addresses()``getVendorAddresses``array``additionalFields()``getVendorAdditionalFields``array``subAccounts()``getVendorSubAccounts``ContragentSubAccountDto[]`> `subAccounts()` is new in v8.0.

### Products

[](#products)

Access via `$fina->products()`.

MethodFINA EndpointReturns`all()``getProducts``array``groups()``getProductGroups``array``webGroups()``getWebProductGroups``array``byIds($ids)``getProductsArray` (POST)`array``after($date)``getProductsAfter/{date}``array``prices()``getProductPrices``array``pricesAfter($date)``getProductPricesAfter/{date}``array``units()``getProductUnits``array``characteristics()``getCharacteristics``array``imagesByProductIds($ids)``getProductsImageArray` (POST)`array``barcodesByProductIds($ids)``getProductsBarcodeArray` (POST)`array``restByProductIds($ids)``getProductsRestArray` (POST)`array``restAfter($date)``getProductsRestAfter/{date}``array``restSummary($prods, $stores, $date)``getProductsRestSummary` (POST)`array``restByStoreAfter($store, $date)``getProductsRestByStoreAfter/{store}/{date}``array``providedServicePrices()``getProvidedServicePrices``array`> Last 4 methods are new in v8.0.

### Reference Data

[](#reference-data)

Access via `$fina->reference()`.

**Raw endpoints:**

MethodFINA Endpoint`stores()``getStores``projects()``getProjects``terminals()``getTerminals``cashes()``getCashes``creditBanks()``getCreditBanks``priceTypes()``getPriceTypes``customers()``getCustomers` (returns `contragents[]`)`vendors()``getVendors` (returns `contragents[]`)`customerGroups()``getCustomerGroups``vendorGroups()``getVendorGroups``productGroups()``getProductGroups``webProductGroups()``getWebProductGroups``providedServiceGroups()``getProvidedServiceGroups``receivedServiceGroups()``getReceivedServiceGroups``inventoryGroups()``getInventoryGroups`**Typed endpoints:**

MethodReturns`users()``UserDto[]``userPermissions($id)``UserPermissionsDto``bankAccounts()``BankAccountDto[]``staffGroups()``StaffGroupDto[]``staffs()``StaffDto[]``giftCards()``GiftCardDto[]``discountTypes()``DiscountTypeDto[]``units()``UnitDto[]``docTypes()``DocTypeDto[]``docTypesCached()``DocTypeDto[]` (cached)`supportedDocTypes()``DocTypeDto[]` (filtered)`findDocType($id)``?DocTypeDto``transportationMeans()``TransportationMeanDto[]``accountValueDetails($account, $date, $currency?)``AccountValueDetailDto[]` (POST)> Last 2 methods are new in v8.0.

### Loyalty

[](#loyalty)

Access via `$fina->loyalty()`.

MethodFINA EndpointReturns`bonusCoeff()``getBonusCoeff``BonusCoeffResponse``cardsByHolder($code)``getLoyaltyCardsByHolder/{code}``array``saveBonusOperation($payload)``saveDocBonusOperation``BonusOperationResponse``giftCardInfoByCode($code)``getGiftCardInfoByCode/{code}``GiftCardInfoDto``bonusCardRestByCode($code)``getBonusCardRestByCode/{code}``array`> Last 2 methods are new in v8.0.

### Documents

[](#documents)

Access via `$fina->documents()`.

**Save methods** -- all return `SaveDocResponse` with `->id` and `->ex`:

MethodFINA EndpointPayload DTO`saveCustomerOrder($p)``saveDocCustomerOrder``CustomerOrderPayload``saveProductOut($p)``saveDocProductOut``ProductOutPayload``saveProductIn($p)``saveDocProductIn``ProductInPayload``saveProductMove($p)``saveDocProductMove``ProductMovePayload``saveProductCancel($p)``saveDocProductCancel``ProductCancelPayload``saveProvidedService($p)``saveDocProvidedService``ProvidedServicePayload``saveCustomerReturn($p)``saveDocCustomerReturn``CustomerReturnPayload``saveCafeOrder($p)``saveDocCafeOrder``CafeOrderPayload``saveCustomerMoneyIn($p)``saveDocCustomerMoneyIn``CustomerMoneyInPayload``saveCustomerAdvanceIn($p)``saveDocCustomerAdvanceIn`*(raw array)*`saveCustomerMoneyReturn($p)``saveDocCustomerMoneyReturn``CustomerMoneyReturnPayload``saveBonusPayment($p)``saveDocBonusPayment``BonusPaymentPayload``saveCustomerMoneyOut($p)``saveDocCustomerMoneyOut``CustomerMoneyOutPayload``saveVendorMoneyIn($p)``saveDocVendorMoneyIn``VendorMoneyInPayload``saveVendorMoneyOut($p)``saveDocVendorMoneyOut``VendorMoneyOutPayload``saveVendorMoneyReturn($p)``saveDocVendorMoneyReturn``VendorMoneyReturnPayload``saveProduction($p)``saveDocProduction``SaveProductionPayload` / `ProductionPayload``saveReceivedService($p)``saveDocReceivedService``ReceivedServicePayload``saveBonusCard($p)``saveDocBonusCard``BonusCardPayload``saveGiftPayment($p)``saveDocGiftPayment``GiftPaymentPayload`> Last 3 save methods are new in v8.0.

**Get methods** -- return raw arrays or typed DTOs:

MethodFINA EndpointReturns`getCustomerOrder($id)``getDocCustomerOrder/{id}``array``getProductOut($id)``getDocProductOut/{id}``array``getProductMove($id)``getDocProductMove/{id}``array``getReceivedService($id)``getDocReceivedService/{id}``array``getCustomerReturn($id)``getDocCustomerReturn/{id}``array``getProduction($id)``getDocProduction/{id}``array``getProductionTyped($id)``getDocProduction/{id}``ProductionDocDto``getAutoService($id)``getDocAutoService/{id}``array``getAutoServiceTyped($id)``getDocAutoService/{id}``AutoServiceDocDto`> Last 2 methods are new in v8.0.

**Generic methods** for any endpoint:

```
// Any save endpoint
$fina->documents()->save('saveDocCustomerOrder', $payload);

// Any get endpoint
$fina->documents()->getDoc('getDocProductOut', $id);
```

### Reporting

[](#reporting)

The Reporting API provides three access patterns for every endpoint:

PatternSuffixDescription**Raw***(none)*Returns the decoded JSON array as-is**Typed**`Typed`Maps response into typed DTO objects**Chunked + Typed**`ChunkedTyped`Splits large ranges, merges, deduplicates, returns typed DTOsAccess via `$fina->reporting()`.

**Journals:**

JournalRawTypedChunked TypedResponse DTOEntries`entriesJournal()``entriesJournalTyped()``entriesJournalChunkedTyped()``EntriesJournalResponseDto`Customers Orders`customersOrderJournal()``customersOrderJournalTyped()``customersOrderJournalChunkedTyped()``CustomersOrderJournalResponseDto`Customers Returns`customersReturnJournal()``customersReturnJournalTyped()``customersReturnJournalChunkedTyped()``CustomersReturnJournalResponseDto`Customers Money`customersMoneyJournal()``customersMoneyJournalTyped()``customersMoneyJournalChunkedTyped()``MoneyJournalResponseDto`Vendors Money`vendorsMoneyJournal()``vendorsMoneyJournalTyped()``vendorsMoneyJournalChunkedTyped()``MoneyJournalResponseDto`Productions`productionsJournal()``productionsJournalTyped()``productionsJournalChunkedTyped()``ProductionsJournalResponseDto`Discount Cards`discountCardsJournal()``discountCardsJournalTyped()``discountCardsJournalChunkedTyped()``DiscountCardsJournalResponseDto`Provided Services`providedServicesJournal()``providedServicesJournalTyped()``providedServicesJournalChunkedTyped()``ProvidedServicesJournalResponseDto`Received Services`receivedServicesJournal()``receivedServicesJournalTyped()``receivedServicesJournalChunkedTyped()``ReceivedServicesJournalResponseDto`Realizes`realizesJournal()`------Auto Services Out`autoServicesOutJournal()``autoServicesOutJournalTyped()``autoServicesOutJournalChunkedTyped()``AutoServicesOutJournalResponseDto`> Auto Services Out is new in v8.0.

**Reports:**

ReportRawTypedResponse DTOCustomers Cycle`customersCycleReport()``customersCycleReportTyped()``CycleReportResponseDto`Vendors Cycle`vendorsCycleReport()``vendorsCycleReportTyped()``CycleReportResponseDto`Products Last-In`productsLastInReport()``productsLastInReportTyped()``ProductsLastInReportResponseDto`Products In/Return`productsInReturnReport()``productsInReturnReportTyped()``ProductsInReturnReportResponseDto`Cafe Order Detailed`cafeOrderDetailedReport()``cafeOrderDetailedReportTyped()``CafeOrderDetailedReportResponseDto`> Cafe Order Detailed is new in v8.0.

**Low-level Journals API** -- access via `$fina->journals()` for simple date-range queries:

```
$fina->journals()->entries($from, $to);
$fina->journals()->customersOrders($from, $to);
$fina->journals()->autoServicesOut($from, $to); // v8.0
```

**Generic range call:**

```
$fina->reporting()->getRange('getEntriesJournal', $from, $to);

$fina->reporting()->getRangeChunked(
    method: 'getEntriesJournal',
    collectionKey: 'journals',
    from: $from,
    to: $to,
    chunkDays: 7,
    dedupeKeyFn: fn (array $item) => $item['id'] . ':' . $item['version'],
);
```

---

DTOs &amp; Validation
---------------------

[](#dtos--validation)

### Contracts

[](#contracts)

Request DTOs implement two interfaces:

```
ArrayPayload          -- toArray() for serialisation
    |
ValidatesPayload      -- adds rules(), messages(), attributes()

```

When you pass a `ValidatesPayload` to any `save*` method, it is validated automatically before the HTTP request. On failure, a `FinaValidationException` is thrown -- no request is made.

### Example: save with validation

[](#example-save-with-validation)

```
use Fina\Sdk\Laravel\Operation\Dto\BonusCardPayload;
use Carbon\CarbonImmutable;

$payload = new BonusCardPayload(
    id: 0,
    date: CarbonImmutable::now(),
    numPrefix: '',
    num: 0,
    purpose: 'New bonus card',
    customer: 31,
    store: 1,
    user: 1,
    cardCode: '231',
    personCode: '0100010101',
    personName: 'John Doe',
    personAddress: '123 Main St',
    personTel: '+995597222222',
    status: true,
);

$response = $fina->documents()->saveBonusCard($payload);
```

### Example: manual validation

[](#example-manual-validation)

```
use Fina\Sdk\Laravel\Support\PayloadValidator;
use Fina\Sdk\Laravel\Exceptions\FinaValidationException;

try {
    PayloadValidator::validate($payload);
} catch (FinaValidationException $e) {
    // $e->errors -- ['field_name' => ['Error message', ...]]
}
```

### Response DTOs

[](#response-dtos)

All typed response DTOs use `readonly` classes with `fromArray()` factories. Reporting row DTOs also preserve the full raw array for forward-compatibility:

```
$dto = $fina->reporting()->autoServicesOutJournalTyped($from, $to);

foreach ($dto->journals as $row) {
    $row->id;         // typed property
    $row->amount;     // typed property
    $row->raw;        // full original array (access future fields)
    $row->dedupeKey(); // stable key for chunk merging
}
```

### Complete DTO list

[](#complete-dto-list)

**Response DTOs (Operation):**

DTOPurpose`SaveDocResponse`Generic save response (`id`, `ex`)`BonusOperationResponse`Bonus operation result (`res`, `ex`)`BonusCoeffResponse`Bonus coefficient (`coeff`, `ex`)`UserDto`User reference data`UserPermissionsDto`User permissions and defaults`DocTypeDto`Document type reference`BankAccountDto`Bank account reference`StaffDto`Staff member with additional fields`StaffGroupDto`Staff group hierarchy`StaffAdditionalFieldDto`Staff field key-value`DiscountTypeDto`Discount type with percent`UnitDto`Measurement unit`GiftCardDto`Gift card (includes `restAmount` in v8.0)`GiftCardInfoDto`Detailed gift card info by code (v8.0)`CustomerAgreementDto`Customer price agreement (v8.0)`ContragentSubAccountFieldDto`Sub-account field definition (v8.0)`ContragentSubAccountDto`Contragent sub-account data (v8.0)`TransportationMeanDto`Vehicle/transportation mean (v8.0)`AccountValueDetailDto`Account debit/credit detail (v8.0)`AutoServiceDocDto`Full auto-service document (v8.0)`ProductionDocDto`Production document with materials**Payload DTOs (Operation):**

DTOValidatesPurpose`CustomerOrderPayload`--Customer order`ProductOutPayload`YesProduct out (sale/shipment)`ProductInPayload`YesProduct in (purchase)`ProductMovePayload`YesInter-store transfer`ProductCancelPayload`YesProduct cancellation`ProvidedServicePayload`YesProvided service`CustomerReturnPayload`YesCustomer return`CafeOrderPayload`YesCafe order`CustomerMoneyInPayload`--Customer money in`CustomerMoneyReturnPayload`YesCustomer money return`BonusPaymentPayload`YesBonus payment`BonusOperationPayload`YesBonus accumulate/spend`CustomerMoneyOutPayload`YesCustomer money out`VendorMoneyInPayload`YesVendor money in`VendorMoneyOutPayload`YesVendor money out`VendorMoneyReturnPayload`YesVendor money return`ProductionPayload`YesProduction (legacy format)`ReceivedServicePayload`YesReceived service (v8.0)`BonusCardPayload`YesBonus card issuance (v8.0)`GiftPaymentPayload`YesGift card payment (v8.0)`SaveProductionPayload`YesProduction with product tree (v8.0)**Line item DTOs:**

DTOUsed in`ProductLine`Product out, in, move, cancel, return`ServiceLine`Provided/received service`CafeOrderProductLine`Cafe order`CustomerOrderProduct`Customer order`AddField`Additional custom fields`ProductionChildLine`Production child product (v8.0)`ProductionProductLine`Production product with children (v8.0)`ProductionMaterialLineDto`Production material`ProductionConsumedLineDto`Consumed material`ProductionExpenseLineDto`Production expense---

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

[](#error-handling)

All exceptions extend `FinaException` (a `RuntimeException`):

```
FinaException
  ├── FinaConfigException      -- missing base_url, login, or password
  ├── FinaHttpException        -- HTTP 4xx/5xx ($status, $body)
  ├── FinaRemoteException      -- FINA returned non-null 'ex' ($ex)
  └── FinaValidationException  -- payload failed validation ($errors)

```

### Usage

[](#usage)

```
use Fina\Sdk\Laravel\Exceptions\FinaException;
use Fina\Sdk\Laravel\Exceptions\FinaHttpException;
use Fina\Sdk\Laravel\Exceptions\FinaRemoteException;
use Fina\Sdk\Laravel\Exceptions\FinaValidationException;

try {
    $fina->documents()->saveProductOut($payload);
} catch (FinaValidationException $e) {
    // No HTTP request was made
    return response()->json(['errors' => $e->errors], 422);
} catch (FinaHttpException $e) {
    Log::error("FINA HTTP {$e->status}", ['body' => $e->body]);
} catch (FinaRemoteException $e) {
    Log::error('FINA remote error', ['ex' => $e->ex]);
} catch (FinaException $e) {
    Log::error("FINA: {$e->getMessage()}");
}
```

### 401 auto-refresh

[](#401-auto-refresh)

When a request gets a `401`, the SDK automatically:

1. Clears the cached token
2. Fetches a fresh token
3. Retries the request **once**

If the retry also fails, a `FinaHttpException` is thrown.

---

Performance
-----------

[](#performance)

- **Use chunked reporting for ranges &gt; 30 days.** FINA may time out on large ranges. Chunked methods handle this transparently.
- **Recommended chunk sizes:** 7 days for entries (high volume), 14 days for money/order journals.
- **Deduplication** uses `id+version` when available, falls back to `id`, then SHA-1 hash.
- **Cache doc types** with `docTypesCached()` to avoid repeated calls for rarely-changing data.
- **Token caching** is ~35h by default. Adjust `FINA_TOKEN_TTL` for your instance.

---

Testing &amp; Quality
---------------------

[](#testing--quality)

All tests use `Http::fake()` -- no real HTTP, no database, no external services.

```
# Run tests
composer test

# Static analysis (PHPStan level 6)
composer phpstan -- --memory-limit=512M

# Code style (Laravel Pint)
composer pint -- --test

# All three
composer ci
```

### Test coverage

[](#test-coverage)

SuiteTestsAssertionsCoverage`ServiceProviderTest`4Singleton, alias, config, accessors`FinaClientHttpTest`5Token cache, reuse, 401 refresh, HTTP errors`ReportingUrlTest`3Date format, URL structure`ReportingChunkingTest`4Chunk merge, deduplication, typed output`DtoValidationTest`5Valid/invalid payloads, nested validation`DtoMappingTest`14DTO mapping, empty data, roundtrip`NewEndpointsTest`16All v8.0 endpoints (HTTP mocked)`NewDtoMappingTest`12All v8.0 DTO mapping + edge cases`NewDtoValidationTest`8v8.0 payload validation (valid + invalid)**Total****75****207**### CI

[](#ci)

GitHub Actions on every push/PR:

- **Matrix:** PHP 8.2, 8.3, 8.4
- **Steps:** tests -&gt; PHPStan -&gt; Pint
- **No external services required**

---

Troubleshooting
---------------

[](#troubleshooting)

### 401 loops

[](#401-loops)

```
// Verify credentials, then clear token cache:
app('fina')->auth()->forgetToken();
```

### Base URL format

[](#base-url-format)

```
# Correct
FINA_BASE_URL=https://your-fina-host:5007

# Wrong (no scheme)
FINA_BASE_URL=your-fina-host:5007

# Wrong (includes path)
FINA_BASE_URL=https://your-fina-host:5007/api
```

### Reporting timeouts

[](#reporting-timeouts)

```
// Switch to chunked:
$fina->reporting()->entriesJournalChunkedTyped($from, $to, chunkDays: 7);

// Or increase timeout:
// FINA_TIMEOUT=300
```

### Config exception on boot

[](#config-exception-on-boot)

Ensure `.env` contains `FINA_BASE_URL`, `FINA_LOGIN`, and `FINA_PASSWORD`. The SDK validates these when the client is first resolved.

---

License
-------

[](#license)

[MIT License](LICENSE)

---

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

[](#contributing)

Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

For security vulnerabilities, see [SECURITY.md](SECURITY.md).

###  Health Score

35

—

LowBetter than 77% of packages

Maintenance89

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 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 ~28 days

Total

3

Last Release

53d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/8641522?v=4)[Giorgi Grdzelidze](/maintainers/GiorgiGrdzelidze)[@GiorgiGrdzelidze](https://github.com/GiorgiGrdzelidze)

---

Top Contributors

[![GiorgiGrdzelidze](https://avatars.githubusercontent.com/u/8641522?v=4)](https://github.com/GiorgiGrdzelidze "GiorgiGrdzelidze (7 commits)")

---

Tags

api-clientcomposer-packagedtoerperp-integrationfinafina-apilaravellaravel-packagelaravel-sdkphpphpstanphpunitreportingsdkapiclientlaravelsdkintegrationfina

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/giorgigrdzelidze-laravel-fina-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/giorgigrdzelidze-laravel-fina-sdk/health.svg)](https://phpackages.com/packages/giorgigrdzelidze-laravel-fina-sdk)
```

###  Alternatives

[spatie/laravel-responsecache

Speed up a Laravel application by caching the entire response

2.8k8.7M64](/packages/spatie-laravel-responsecache)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

76318.2M110](/packages/laravel-mcp)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9732.3M121](/packages/roots-acorn)[propaganistas/laravel-disposable-email

Disposable email validator

6012.9M7](/packages/propaganistas-laravel-disposable-email)[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[resend/resend-laravel

Resend for Laravel

1212.2M8](/packages/resend-resend-laravel)

PHPackages © 2026

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