giorgigrdzelidze/laravel-fina-sdk
A Laravel SDK for integrating the Fina API into PHP applications. It provides configuration, service bindings, and convenient helpers for authenticating and making Fina requests, helping keep your Laravel integration clean, reusable, and maintainable.
config/fina.php or similar) — this is where the FINA Web API v8.0 base URL, credentials and token storage live.array (it must survive between requests, otherwise every request pays a token round-trip).rest() and you get { rest: [{ id, store, rest, reserve }] } — one entry per product per store, which is the shape you want for a per-store availability table or a cache warm-up job.getProductOutSingle($id) returns the product_out_single document with its products[] array — useful for pulling up one receipt/sale for support or reconciliation without a bulk export.Resolve the client from the container, don't new it. Bind/inject the API client (or use the facade) so tests can swap it. The package already centralises the HTTP layer; duplicating Http::withToken(...) calls around it defeats the guard and the refresh logic.
Treat the response guard as the contract. Every call — including the two new v0.1.3 endpoints — goes through the guard, so a FINA ex payload surfaces as FinaRemoteException rather than as data. Structure your calling code as:
try {
$levels = $fina->products()->rest();
} catch (FinaRemoteException $e) {
// business/validation error from FINA (`ex`) or transport failure
report($e);
return;
}
Catch FinaRemoteException at the job/controller boundary, not around every call, and let genuine programming errors bubble.
Sync jobs for rest(). The all-products/all-stores payload grows with catalogue size. Pull it in a queued job, then upsert into a product_store_stock table keyed on (product_id, store) so reruns are idempotent. Keep rest and reserve in separate columns — they answer different questions (on-hand vs. committed) and consumers will ask for both.
Fetch documents on demand. getProductOutSingle($id) is a per-document call — use it lazily (an admin "view sale" action, a webhook follow-up), not inside a loop over a date range. If you find yourself looping, you want a bulk endpoint instead.
Don't hand-roll retries around the 401 path. The package refreshes the token on 401 and retries. Adding your own retry wrapper on top risks double-refreshing under concurrency. If you need resilience for 5xx/400, wrap at the job level with backoff and let FinaRemoteException be the trigger.
Test against the guard, not the message. When writing your own feature tests, assert FinaRemoteException is thrown and inspect the exception's payload/context rather than matching FINA's Dutch error strings.
ex case now throws instead of returning the error body as $response->json(). Audit any ad-hoc Http:: calls to getProductsRest / getDocProductOutSingle and delete them.rest() is denormalised. It is not one row per product — it is one row per product-store. Grouping, summing or "is this product in stock anywhere?" logic must aggregate over store. Getting this wrong silently shows the last store's figure.php artisan config:cache in deploy — and remember cached config ignores .env changes, a classic "why is it still hitting sandbox?" moment.Http:: debug logs and exception contexts. Scrub Authorization before reporting; FinaRemoteException payloads may echo request context.Http::fake() and assert the outgoing URL — the 9 tests added in v0.1.3 (URL/method, bearer token, payload passthrough, ex, 400/500, 401 refresh) are a copyable template for exactly this.How can I help you explore Laravel packages today?