PHPackages                             ebethus/laravel-ticketbai - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. ebethus/laravel-ticketbai

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

ebethus/laravel-ticketbai
=========================

TicketBai Library for Laravel

13.2k2PHP

Since Mar 30Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/bethuxs/LaravelTicketBai)[ Packagist](https://packagist.org/packages/ebethus/laravel-ticketbai)[ RSS](/packages/ebethus-laravel-ticketbai/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

Laravel TicketBAI
=================

[](#laravel-ticketbai)

[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)[![PHP Version](https://camo.githubusercontent.com/c5e8da782b1a0673c08b4f474108036d2cc973470eed2d5d89d48e8c8475eee6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e322d626c75652e737667)](https://www.php.net/)

A Laravel package for generating and submitting TicketBAI (Ticket BAI) invoices for the Basque Country (Euskadi), Spain. This package provides a flexible and configurable solution for integrating TicketBAI compliance into your Laravel application.

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

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Database Configuration](#database-configuration)
- [API Reference](#api-reference)
- [Examples](#examples)
- [Testing](#testing)
- [Contributing](#contributing)
- [License](#license)

Features
--------

[](#features)

- ✅ Generate TicketBAI-compliant invoices
- ✅ Automatic invoice signing with X.509 certificates
- ✅ Queue-based invoice submission to TicketBAI API
- ✅ Flexible database table and column configuration
- ✅ Support for custom table structures
- ✅ Optional columns (signature, data, territory) for maximum flexibility
- ✅ **Encadenamiento**: firma y territorio siempre en columna JSON `data` bajo clave configurable (por defecto `ticketbai`)
- ✅ QR code generation for invoices
- ✅ Support for multiple territories (Araba, Bizkaia, Gipuzkoa)
- ✅ Automatic fingerprint calculation from previous invoices
- ✅ Artisan command to resend failed/pending invoices (`ticketbai:resend`)

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

[](#requirements)

- PHP &gt;= 8.2
- Laravel &gt;= 8.0 (tested with Laravel 10.x and 11.x)
- [barnetik/ticketbai](https://github.com/barnetik/ticketbai) package
- X.509 certificate (.p12 file) for signing invoices
- TicketBAI license and credentials

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

[](#installation)

Install the package via Composer:

```
composer require ebethus/laravel-ticketbai
```

### Publish Configuration

[](#publish-configuration)

Publish the configuration file:

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

This will create `config/ticketbai.php` where you can configure table and column mappings.

### Run Migrations

[](#run-migrations)

If you want to use the default invoice table structure:

```
php artisan migrate
```

**Note:** You can also use your own table structure by configuring column mappings (see [Database Configuration](#database-configuration)).

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

[](#configuration)

### Service Configuration

[](#service-configuration)

Add your TicketBAI credentials to `config/services.php`:

```
'ticketbai' => [
    'license' => env('TICKETBAI_LICENSE', ''),
    'nif' => env('TICKETBAI_NIF', ''),
    'appName' => env('TICKETBAI_APP_NAME', ''),
    'appVersion' => env('TICKETBAI_APP_VERSION', ''),
    'certPassword' => env('TICKETBAI_CERT_PASSWORD', ''),
    'disk' => env('TICKETBAI_DISK', 'local'),
],
```

### Environment Variables

[](#environment-variables)

Add these to your `.env` file:

```
TICKETBAI_LICENSE=TB12345678
TICKETBAI_NIF=B1111111
TICKETBAI_APP_NAME=My Application
TICKETBAI_APP_VERSION=1.0
TICKETBAI_CERT_PASSWORD=your_certificate_password
TICKETBAI_DISK=local
TICKETBAI_CERT_PATH=certificado.p12
```

Use `TICKETBAI_CERT_PATH` to override the certificate path. It can be a path relative to `storage_path()` (e.g. `certificado.p12` for `storage/certificado.p12`) or an absolute path (e.g. `/etc/certs/ticketbai.p12` on Linux).

### Certificate Setup

[](#certificate-setup)

By default the package looks for the X.509 certificate (`.p12`) at `storage/certificado.p12`. Set `TICKETBAI_CERT_PATH` in your `.env` to use a different path (relative to `storage_path()` or absolute). The certificate is used to sign invoices before submission.

Usage
-----

[](#usage)

### Basic Example

[](#basic-example)

```
use EBethus\LaravelTicketBAI\TicketBAI;

// Get TicketBAI instance (configured via service provider)
$ticketbai = app('ticketbai');

// Or use the facade
use TicketBAI;

// Set issuer information
$ticketbai->issuer(
    nif: 'B12345678',
    name: 'Company Name',
    idIssuer: 1,
    serie: '' // Optional
);

// Set VAT percentage
$ticketbai->setVat(21); // 21% VAT

// Add invoice items
$ticketbai->add(
    desc: 'Product description',
    unitPrice: 100.00,
    q: 2,
    discount: 0 // Optional
);

// Generate and sign invoice
$qrUrl = $ticketbai->invoice(
    territory: 'BIZKAIA', // or 'ARABA', 'GIPUZKOA'
    description: 'Invoice description'
);

// The invoice is automatically saved and queued for submission
// $qrUrl contains the QR code URL for the invoice
```

### Using Dependency Injection

[](#using-dependency-injection)

```
use EBethus\LaravelTicketBAI\TicketBAI;

class InvoiceController extends Controller
{
    public function __construct(
        protected TicketBAI $ticketbai
    ) {}

    public function create(Request $request)
    {
        $this->ticketbai->issuer(
            nif: $request->nif,
            name: $request->company_name,
            idIssuer: $request->issuer_id
        );

        $this->ticketbai->setVat(21);

        foreach ($request->items as $item) {
            $this->ticketbai->add(
                desc: $item['description'],
                unitPrice: $item['price'],
                q: $item['quantity'],
                discount: $item['discount'] ?? 0
            );
        }

        $qrUrl = $this->ticketbai->invoice(
            territory: 'BIZKAIA',
            description: $request->description
        );

        return response()->json(['qr_url' => $qrUrl]);
    }
}
```

### Adding Extra Data

[](#adding-extra-data)

You can attach additional JSON data to invoices:

```
$ticketbai->data([
    'order_id' => 12345,
    'customer_id' => 67890,
    'custom_field' => 'value'
]);
```

This data will be stored in the `data` column if configured (see [Database Configuration](#database-configuration)).

Database Configuration
----------------------

[](#database-configuration)

The library supports flexible table and column configuration, allowing you to use your existing database structure.

### Default Table Structure

[](#default-table-structure)

The default migration creates an `invoices` table with columns `issuer`, `provider_reference`, `path`, `data`, `sent`, and timestamps. TicketBAI stores signature and territory in the `data` JSON column under the key `ticketbai`.

### Custom Table Configuration

[](#custom-table-configuration)

If you use **your own table** with different column names (e.g. `transaction_id` instead of `issuer`), override the mappings via environment variables. Example: `TICKETBAI_COLUMN_ISSUER=transaction_id`, `TICKETBAI_COLUMN_NUMBER=invoice_number`, `TICKETBAI_COLUMN_SENT=attempted_at`.

Configure column mappings in `config/ticketbai.php`:

```
'table' => [
    'name' => env('TICKETBAI_TABLE_NAME', 'invoices'),
    'columns' => [
        // Defaults match the default migration. For your own table use env, e.g.:
        // TICKETBAI_COLUMN_ISSUER=transaction_id, TICKETBAI_COLUMN_NUMBER=invoice_number
        'issuer' => env('TICKETBAI_COLUMN_ISSUER', 'issuer'),
        'number' => env('TICKETBAI_COLUMN_NUMBER', 'provider_reference'),
        'territory' => env('TICKETBAI_COLUMN_TERRITORY', 'territory'),
        'signature' => env('TICKETBAI_COLUMN_SIGNATURE', 'signature'),
        'path' => env('TICKETBAI_COLUMN_PATH', 'path'),
        'data' => env('TICKETBAI_COLUMN_DATA', 'data'),
        'sent' => env('TICKETBAI_COLUMN_SENT', 'sent'),
        'created_at' => env('TICKETBAI_COLUMN_CREATED_AT', 'created_at'),
        'updated_at' => env('TICKETBAI_COLUMN_UPDATED_AT', 'updated_at'),
    ],
],
```

### Environment Variables for Column Mapping

[](#environment-variables-for-column-mapping)

Use these only when you have a **custom table** with different column names:

```
TICKETBAI_TABLE_NAME=invoices
TICKETBAI_COLUMN_ISSUER=transaction_id
TICKETBAI_COLUMN_NUMBER=provider_reference
TICKETBAI_COLUMN_TERRITORY=territory
TICKETBAI_COLUMN_SIGNATURE=signature
TICKETBAI_COLUMN_PATH=path
TICKETBAI_COLUMN_DATA=data
TICKETBAI_COLUMN_SENT=attempted_at
TICKETBAI_COLUMN_CREATED_AT=created_at
TICKETBAI_COLUMN_UPDATED_AT=updated_at
```

### TicketBAI payload in `data` (required for chaining)

[](#ticketbai-payload-in-data-required-for-chaining)

Signature and territory are **always** stored in the JSON `data` column under a configurable key so that encadenamiento (signature chaining) works. Default key: `ticketbai`. Set in `.env` or config:

```
TICKETBAI_DATA_KEY=ticketbai
```

The package stores and reads `signature` (first 100 chars) and `territory` under `data->ticketbai`. Path stays in the `path` column. Example:

```
{
  "ticketbai": {
    "signature": "first 100 chars of chain signature",
    "territory": "02"
  },
  "order_id": 12345
}
```

Your table needs: `id`, `issuer`, `number`, **`path`** (file path), **`data`** (JSON), `sent`, `created_at`, `updated_at`. Other providers can use other keys in `data` (e.g. `data->other_provider`).

### Optional column name override

[](#optional-column-name-override)

- **`data`**: Set to `null` or empty to use the default column name `'data'`.

### Required Columns

[](#required-columns)

- **`path`**: Required - stores the signed XML file path (filesystem).
- **`data`**: Required - JSON column where TicketBAI stores signature and territory under `TICKETBAI_DATA_KEY`.

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

[](#api-reference)

### TicketBAI Class

[](#ticketbai-class)

#### `issuer(string $nif, string $name, int $idIssuer, string $serie = '')`

[](#issuerstring-nif-string-name-int-idissuer-string-serie--)

Set the issuer information for the invoice.

- `$nif`: Tax identification number (NIF/CIF)
- `$name`: Company name
- `$idIssuer`: Internal issuer ID (used for database storage)
- `$serie`: Optional invoice series

#### `setVat(float $vatPerc)`

[](#setvatfloat-vatperc)

Set the VAT percentage for invoice items.

- `$vatPerc`: VAT percentage (e.g., 21 for 21%)

#### `add(string $desc, float $unitPrice, float $q, float $discount = null)`

[](#addstring-desc-float-unitprice-float-q-float-discount--null)

Add an item to the invoice.

- `$desc`: Item description
- `$unitPrice`: Unit price (including VAT)
- `$q`: Quantity
- `$discount`: Optional discount amount

#### `data(mixed $data)`

[](#datamixed-data)

Attach additional JSON data to the invoice.

- `$data`: Array or object to be stored as JSON

#### `invoice(string $territory, string $description)`

[](#invoicestring-territory-string-description)

Generate, sign, and save the invoice. Returns the QR code URL.

- `$territory`: Territory code: `'ARABA'`, `'BIZKAIA'`, or `'GIPUZKOA'` (or numeric codes `'01'`, `'02'`, `'03'`)
- `$description`: Invoice description

**Returns:** `string` - QR code URL

#### `getModel()`

[](#getmodel)

Get the Eloquent model instance for the saved invoice.

**Returns:** `Invoice`

#### `getTBAI()`

[](#gettbai)

Get the underlying TicketBAI object from the barnetik/ticketbai package.

**Returns:** `\Barnetik\Tbai\TicketBai`

Examples
--------

[](#examples)

### Complete Invoice Example

[](#complete-invoice-example)

```
use EBethus\LaravelTicketBAI\TicketBAI;

$ticketbai = app('ticketbai');

// Configure issuer
$ticketbai->issuer(
    nif: 'B12345678',
    name: 'My Company S.L.',
    idIssuer: 1
);

// Set VAT
$ticketbai->setVat(21);

// Add items
$ticketbai->add('Product A', 50.00, 2, 0);
$ticketbai->add('Product B', 30.00, 1, 5.00);

// Add extra data
$ticketbai->data([
    'order_id' => 12345,
    'customer_email' => 'customer@example.com'
]);

// Generate invoice
$qrUrl = $ticketbai->invoice(
    territory: 'BIZKAIA',
    description: 'Order #12345'
);

echo "QR Code: $qrUrl";
```

### Using with Custom Table

[](#using-with-custom-table)

```
// In config/ticketbai.php or .env
// TICKETBAI_TABLE_NAME=my_invoices
// TICKETBAI_COLUMN_ISSUER=user_id
// TICKETBAI_COLUMN_NUMBER=invoice_ref
// TICKETBAI_COLUMN_SIGNATURE=  (empty, disabled)
// TICKETBAI_COLUMN_DATA=  (empty, disabled)

$ticketbai = app('ticketbai');
$ticketbai->issuer('B12345678', 'Company', 1);
$ticketbai->setVat(21);
$ticketbai->add('Item', 100, 1);
$qrUrl = $ticketbai->invoice('BIZKAIA', 'Invoice');
```

### Accessing Saved Invoice

[](#accessing-saved-invoice)

```
$ticketbai = app('ticketbai');
// ... configure and generate invoice ...

$model = $ticketbai->getModel();
echo $model->provider_reference; // Invoice number (default column name)
echo $model->path;               // XML file path
```

Testing
-------

[](#testing)

Run the test suite:

```
composer test
```

Or with PHPUnit directly:

```
./vendor/bin/phpunit
```

Optional: run static analysis (PHPStan) and code style (Laravel Pint):

```
composer analyse   # PHPStan
composer format   # Pint (fixes style)
```

Queue Configuration
-------------------

[](#queue-configuration)

Invoice submission is **asynchronous**: after generating and signing an invoice, the package dispatches an `InvoiceSend` job to the Laravel queue. You must have at least one queue worker running for invoices to be sent to the TicketBAI API:

```
php artisan queue:work
```

- **Production:** Use a process manager (e.g. Supervisor) to keep `queue:work` running.
- **Testing / sync:** If you use `QUEUE_CONNECTION=sync`, jobs run immediately in the same process (no worker needed, but slower and no retries).

The `InvoiceSend` job submits the invoice to the TicketBAI API and updates the `sent` timestamp on success.

Resending Failed or Pending Invoices
------------------------------------

[](#resending-failed-or-pending-invoices)

Invoices that were not sent (e.g. API error or worker down) have `sent = null`. To re-queue them for sending:

```
# List and resend all pending invoices
php artisan ticketbai:resend --all

# Resend a single invoice by ID
php artisan ticketbai:resend --id=123

# Dry run: only list what would be resent
php artisan ticketbai:resend --all --dry-run
```

Resend requires **territory** and **path**: territory is read from `data[ticketbai_data_key]` (default `data->ticketbai`), path from the path column.

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

[](#troubleshooting)

### Certificate Errors

[](#certificate-errors)

- Ensure `storage/certificado.p12` exists and is readable
- Verify the certificate password is correct
- Check file permissions

### Database Column Errors

[](#database-column-errors)

- Verify column mappings in `config/ticketbai.php`
- Ensure required columns exist in your table
- Set optional columns to `null` if not needed

### Queue Issues

[](#queue-issues)

- Ensure queue worker is running
- Check queue connection configuration
- Review failed jobs: `php artisan queue:failed`

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

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE).

Credits
-------

[](#credits)

- Built on top of [barnetik/ticketbai](https://github.com/barnetik/ticketbai)
- Developed by [EBethus](https://github.com/ebethus)

Support
-------

[](#support)

For issues and feature requests, please use the [GitHub issue tracker](https://github.com/ebethus/laravel-ticketbai/issues).

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance57

Moderate activity, may be stable

Popularity25

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity11

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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/25f561a3fd260935cc3ea5dc049b4ff598c37408dfdbbc129d091221de6c2954?d=identicon)[alb\_be](/maintainers/alb_be)

---

Top Contributors

[![bethuxs](https://avatars.githubusercontent.com/u/191869?v=4)](https://github.com/bethuxs "bethuxs (44 commits)")

### Embed Badge

![Health badge](/badges/ebethus-laravel-ticketbai/health.svg)

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

###  Alternatives

[ipinfo/ipinfo

The official PHP library for IPinfo, the most reliable, accurate, and in-depth source of IP address data available anywhere. We process terabytes of data to produce our custom IP geolocation, company, carrier and IP type data sets. Visit our developer docs at https://ipinfo.io/developers.

2891.2M11](/packages/ipinfo-ipinfo)[craftcms/plugin-installer

Craft CMS Plugin Installer

283.3M4](/packages/craftcms-plugin-installer)[typo3/cms-recordlist

TYPO3 CMS Recordlist - Lists database records in the TYPO3 backend module (Web&gt;List).

178.0M48](/packages/typo3-cms-recordlist)[broadway/uuid-generator

UUID generator for broadway/broadway.

202.1M11](/packages/broadway-uuid-generator)

PHPackages © 2026

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