Skip to content

LibreCodeCoop/nfse-php

Repository files navigation

nfse-php

Framework-agnostic PHP library for issuing, querying, and cancelling Nota Fiscal de Serviço Eletrônica (NFS-e) via SEFIN Nacional (ABRASF 2.04 / SEFIN 1.0).

Latest Version PHP Version License: AGPL v3 CI codecov


Why nfse-php?

Emitting NFS-e in Brazil involves XML signing with ICP-Brasil certificates, SOAP/REST calls to multiple municipal gateways, and safe credential management — all of which most accounting software gets wrong.

nfse-php handles all of it correctly:

  • XML signing with PFX/PKCS#12 certificates (native PHP first, CLI repack fallback for OpenSSL legacy format)
  • Credential isolation — PFX passwords are never stored in your database; they live in OpenBao / HashiCorp Vault KV v2
  • Pluggable secret store — swap OpenBao for any SecretStoreInterface implementation
  • Tier-1 tests always run via donatj/mock-webserver (no real cert required in CI)
  • Strict PHP 8.2+ types throughout

Requirements

Dependency Version
PHP ^8.2
ext-openssl *
ext-dom *
ext-soap *

Installation

composer require librecodeoop/nfse-php

Quick Start

use LibreCodeCoop\NfsePHP\Http\NfseClient;
use LibreCodeCoop\NfsePHP\SecretStore\OpenBaoSecretStore;
use LibreCodeCoop\NfsePHP\Dto\DpsData;

$store  = new OpenBaoSecretStore(addr: 'http://localhost:8200', token: getenv('VAULT_TOKEN'));
$client = new NfseClient(secretStore: $store, sandboxMode: true);

$dps = new DpsData(
    cnpjPrestador: '11222333000181', // Example only: configure with your provider CNPJ
    municipioIbge: '3303302',
    // ... other fields
);

$receipt = $client->emit($dps);
echo $receipt->nfseNumber; // NFS-e number returned by the SEFIN gateway

Secret Storage with OpenBao

PFX passwords are never persisted in application databases. They are stored in OpenBao (or Vault) KV v2 under a path like nfse/pfx/{cnpj}.

The CNPJ values below are fictitious examples. Configure your own values through your application settings/environment.

use LibreCodeCoop\NfsePHP\SecretStore\OpenBaoSecretStore;

$store = new OpenBaoSecretStore(
    addr:      getenv('VAULT_ADDR'),   // e.g. http://openbao:8200
    roleId:    getenv('VAULT_ROLE_ID'),
    secretId:  getenv('VAULT_SECRET_ID'),
    mount:     'nfse',               // KV v2 mount
);

// Store the PFX password after upload
$store->put('pfx/11222333000181', ['password' => 'secret']);

// Retrieve during signing
$password = $store->get('pfx/11222333000181')['password'];

For development/CI without OpenBao, use NoOpSecretStore which reads directly from constructor arguments and never touches any server.


Roadmap

  • DPS issuance via SEFIN Nacional REST API
  • XML signing (PFX, ICP-Brasil)
  • OpenBao / Vault KV v2 secret store
  • Mock webserver for CI-friendly testing
  • NFS-e query (GET /dps/{id})
  • NFS-e cancellation
  • Webhook / event polling
  • Municipal gateway adapters beyond Niterói

Commercial Support

This library is the foundation of the akaunting-nfse module for Akaunting.

Need SLA-backed support, custom municipal adapters, or managed hosting?
Contact us: comercial@librecodecoop.org.br


Contributing

We welcome issues and pull requests. Please read CONTRIBUTING.md before opening a PR.

All commits must use Conventional Commits and be signed off (git commit -s).


Give us a star!

If this library saves you hours of integration pain, please ⭐ the repository.
It helps other developers discover the project and motivates the team to keep improving it.


License

GNU Affero General Public License v3.0 or later — see LICENSES/AGPL-3.0-or-later.txt.
© 2026 LibreCode Coop and contributors.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages