Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fatura Laravel Package

mlevent/fatura

A Laravel package for generating invoices in PHP applications. Create itemized invoices with taxes, discounts, and customizable templates, then export them as PDFs for billing, accounting, or record-keeping workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a patch release (v0.3.3) on a pre-1.0 package, so treat the API surface as still settling. There are no breaking changes announced — both entries are behavioural fixes — so an existing v0.3.1/v0.3.2 integration can be bumped with a composer update mlevent/fatura and a re-run of your invoice flow.

First steps:

  1. composer require mlevent/fatura, then publish the config (php artisan vendor:publish --tag=... — check src/ for the exact tag) and fill in the GİB credentials, environment (test/production), and company VKN/TCKN.
  2. Read the service provider and the main facade/manager class first — that tells you which methods are public and how the HTTP client and config are wired. Then read the README examples.
  3. Do not point your first call at production. Create a single taslak (draft) invoice for your own company's VKN against the GİB test environment.

The single most useful first use case is exactly what v0.3.3 touched: create a draft, then immediately fetch back the ETTN/UUID the GİB assigned. That round-trip proves credentials, endpoint, UBL-TR payload shape, and the response parsing all work before you build anything on top. Persist the ETTN in your own invoices table the moment you get it — everything downstream (status polling, cancellation, PDF/HTML retrieval, e-Arşiv vs e-Fatura routing) keys off it.

Implementation Patterns

Draft-then-confirm. Keep the package's draft creation and the later "sign/send" step as two separate jobs in your own code. v0.3.3 specifically improves retrieving the ETTN of the document produced after a draft is created — so the pattern is: create draft → capture ETTN from the returned document → store it → dispatch a queued job that signs/sends once business rules (stock, payment, approval) pass. Never treat the draft call as the invoice being issued.

Persist identifiers, not package objects. Store ettn, invoice_number, recipient_vkn_tckn, status, and raw response JSON on your model. You will need the raw response for support tickets with GİB, and the package's response objects are not a stable serialisation format across 0.x versions.

Reconciliation job. A scheduled command that pulls status for invoices stuck in a pending state is table stakes. With v0.3.3, the "last document" lookup now filters by recipient VKN/TCKN, which makes a recipient-scoped poll safe: lastDocumentFor($vkn)-style calls will no longer hand you another customer's invoice just because it was the most recent one in the account. Where the package exposes it, always pass the recipient explicitly rather than relying on an unscoped "last document" call — that is the whole point of the fix.

Wrap it in your own service. One InvoiceService with draft(), issue(), status(), pdf() methods that return your own DTOs. The package sits behind that boundary; your controllers, listeners, and jobs never import the vendor namespace. This keeps a future 0.4 bump to a single file.

Model events + queue. Fire an InvoiceIssued event after a successful ETTN capture and fan out to notifications, accounting exports, and customer email from listeners. All GİB calls go through queued jobs with $tries and a backoff — the portal is not reliably fast and a request that times out on the HTTP layer may still have created the document.

Multi-tenant. If you issue for several legal entities, put the credentials in a per-tenant config array or a database-backed settings model, and resolve them at call time rather than in the singleton constructor. Combined with the new recipient-scoped lookup, this prevents the worst failure mode: an invoice from tenant A returned for tenant B's query.

Gotchas and Tips

  • 0.x semver. A "patch" bump is not a guarantee of stability elsewhere in the API. Pin the version in composer.json ("mlevent/fatura": "0.3.*") and read the diff between v0.3.1 and v0.3.3 before deploying, not just the changelog bullets.
  • The v0.3.3 lookup change can alter behaviour. If your code called the "last document" endpoint without a recipient and then matched on amount or date, you may now get a different (or no) result. Re-test that flow — the new recipient filter is a correctness win, but it is a silent change in what a query returns.
  • ETTN vs invoice number. These are different things and are easy to conflate. ETTN is the UUID; the human-readable invoice number is a separate field. Store both, and key your own idempotency logic on ETTN.
  • Turkish locale strings. VKN/TCKN are strings, not integers — a leading zero lost to int casting will fail validation or route to the wrong taxpayer. Validate VKN (10 digits) and TCKN (11 digits) separately; a shared 10-vs-11 check is a common source of rejected drafts.
  • Debugging. Log request and response bodies at debug level with a correlation ID, but scrub credentials and customer tax IDs. When GİB returns a vague error, the raw XML response body is usually the only thing that tells you which field failed UBL-TR schema validation.
  • Timeouts and retries. Set an explicit HTTP timeout in config and make the send job idempotent by checking for an existing ETTN before creating a new draft. Duplicate drafts are cheap; duplicate issued invoices are not.
  • Extension points. The config-published HTTP client options and the response-parsing layer are where you'll want to hook in — check whether the package exposes a custom client or transport binding, and use it for proxy, retry, or mock-based testing rather than editing vendor files.
  • Testing. Fake at your InvoiceService boundary, and keep one optional integration test against the GİB test environment that runs nightly. Assert on ETTN being returned after draft creation — that is the exact path v0.3.3 hardened, so it is the one worth pinning with a test.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums