Download the PHP package risetechapps/fusion-report-client without Composer

On this page you can find all versions of the php package risetechapps/fusion-report-client. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package fusion-report-client

fusion-report-client

Laravel client package para comunicação com o fusion-report-server — API fluente e tipada para geração de relatórios JasperSoft.


Requisitos


Instalação

Publique o arquivo de configuração:


Configuração

.env:

api_key é obrigatória. É ela que vai no header X-API-KEY, a única credencial que o client usa. Sem ela, qualquer chamada — inclusive file($id)->download() — lança AuthenticationException antes de a requisição sair, em vez de partir anônima e voltar como 401 genérico.

A chave é lida do config a cada requisição, não uma vez na inicialização. Aplicações que a definem em runtime (bootstrapper de tenant, worker de fila que troca de contexto) são atendidas com o valor do contexto corrente.


Templates JRXML

Listar

Retorna todos os templates registrados. O endpoint do servidor é paginado (per_page padrão 50, máximo 100), mas list() percorre as páginas internamente — não é preciso paginar na aplicação.

Buscar por ID

Cadastrar

Atualizar por ID

Atualizar por nome

Baixar o .jrxml registrado

Devolve o XML cru (application/xml), não o envelope JSON do resto da API. Útil para conferir o que está publicado antes de reenviar.

Excluir por ID

Excluir por nome

Histórico de gerações

Indisponível via X-API-KEY — ambas as rotas são restritas ao dashboard (Sanctum) e retornam 401. Para histórico na integração por API key, use a tabela local fusion_report_generations. Ver Métodos indisponíveis via X-API-KEY.


Geração de Relatórios

Report Definitions (recomendado)

Crie uma classe que estende ReportDefinition:

Context no fluxo assíncrono. Em onGenerated (síncrono) o $context chega direto por parâmetro. No onWebhookReceived (assíncrono) o callback é uma requisição nova, então o context informado no disparo é persistido com a geração e o package o recarrega e injeta automaticamente no segundo parâmetro — você não precisa consultar nada. Requer log_generations habilitado (default).

O package ainda injeta no context o locale efetivo da geração (o de ->locale() ou, na falta, o defaults.locale do config), disponível como $context['locale'] nos dois hooks. Um locale que você já tenha colocado no context manualmente é preservado (não é sobrescrito).

webhookParams() — os parâmetros retornados são anexados como query string à URL base (webhook.url) apenas no generateAsync(). A URL final fica, por exemplo, https://seu-app.com/fusion/webhook?tenant_id=abc. Recebe os params já mesclados da geração, então você pode derivar valores do próprio relatório. Retorne [] (default) para não anexar nada.

Registre no config:

Sincronizar templates com o servidor

O comando fusion-report:sync registra no servidor os templates definidos em fusion-report.reports, expandindo o themes() de cada definition: cada ThemeFusion vira um template (name + theme) independente. Ele primeiro lista o que já existe no servidor (templates()->list(), indexado por name + theme) e decide a ação por tema:

Situação sync sync --force sync --all
Tema novo (name + theme) cadastra (upload) não toca¹ cadastra (upload)
Tema já registrado ignora atualiza só se selecionado atualiza (updateByName)
themes() vazio falha (pula a definition) — falha (pula a definition)
ThemeFusion sem ->from() / arquivo inexistente falha (pula o tema) falha (pula o tema) falha (pula o tema)

¹ --force é cirúrgico: lista só os temas já registrados num seletor (multiselect), processa apenas os marcados e ignora todo o resto — a barra de progresso reflete só o trabalho real. Para cadastrar temas novos use o sync normal ou --all.

Geração síncrona

Geração assíncrona

O resultado da geração assíncrona chega pelo webhook, não por polling. FusionReport::generation($id)->get() bate em GET /api/v1/generations/{id}, que o servidor restringe ao dashboard (Sanctum). Autenticado por X-API-KEY, retorna 401 → FusionReportException. Ver Métodos indisponíveis via X-API-KEY.

Configure webhook.url e implemente onWebhookReceived() na sua ReportDefinition — é o caminho suportado para saber que o relatório ficou pronto.

Formatos

O servidor exige pelo menos um formato em toda geração. Quando você não chama ->format(), vale o defaults.format do config (pdf de fábrica):

Entrada é normalizada: espaços são removidos, maiúsculas viram minúsculas ('PDF' → 'pdf') e duplicatas caem fora.

Válidos: pdf, xlsx, xls, docx, odt, csv, html, frp.

Definir defaults.format como null ou '' volta ao comportamento anterior: o payload omite format e o servidor responde 422 se a geração não informar um.

Parâmetros

O servidor recebe params como lista de strings CHAVE=valor. A conversão é feita pelo package:

Tipo PHP Vira
string, int, float o próprio valor
bool true / false
null string vazia
array JSON (["a","b"], {"x":1})
BackedEnum o value do case
DateTimeInterface ISO-8601 (DATE_ATOM)
Stringable __toString()
qualquer outro FusionReportException

Geração pelo builder (sem registry)

Geração por ID do template


Datasources

Nenhum datasource

JSON inline

CSV inline

URL JSON externa

Perfil pré-configurado no servidor


Proteção de documentos


Arquivos Gerados

Re-exportar uma geração inteira

Quando você tem o ID da geração e não o do arquivo, o servidor localiza o .frp sozinho:

Formatos aceitos: pdf, xlsx, xls, docx, odt, csv, html. O frp não entra na lista — é o próprio intermediário.

Lança ReportNotFoundException quando a geração não tem .frp disponível ou ele já expirou.


Webhook

O package registra automaticamente a rota do callback (default POST /fusion/webhook). Quando a geração assíncrona termina, o servidor faz POST nessa rota e o package:

  1. Verifica a assinatura HMAC (obrigatória — ver Verificação de assinatura).
  2. Atualiza o registro em fusion_report_generations (status + URLs).
  3. Descarta reentregas: se o status gravado já é o do payload, para aqui.
  4. Dispara ReportGenerationCompleted / ReportGenerationFailed.
  5. Chama onWebhookReceived() da ReportDefinition cujo name() bate com o template_name do payload.

Entrega duplicada. O servidor reentrega o callback até 3 vezes (backoff 10s/60s/180s) sempre que não recebe resposta — e o timeout dele é de 15s, contados enquanto o seu handler ainda está rodando. Um onWebhookReceived() lento aumenta a própria chance de ser reexecutado.

O passo 3 protege contra isso comparando o status já gravado com o do payload. Ainda assim, mantenha o hook leve: prefira dispatch() de um job a fazer o trabalho pesado inline.

Processamento em fila (recomendado)

Por padrão o callback é processado dentro da requisição: o 200 só sai depois do update, dos eventos e do onWebhookReceived(). Como o servidor concede 15s e reentrega até 3 vezes, um hook que manda e-mail ou sobe arquivo passa desse limite — o trabalho é feito, mas o servidor registra Client webhook gave up after all attempts e reentrega. O log passa a mentir sobre o que aconteceu.

Ligando a fila, a assinatura é verificada, o payload é enfileirado e o 200 sai em milissegundos:

O job é o ProcessFusionReportWebhook (tries = 3, backoff 10s/60s/180s).

Exige worker rodando. Sem queue:work consumindo a fila, os callbacks ficam parados e o fluxo assíncrono não completa. Por isso o padrão é false.

Contexto (tenancy, auth). O job é despachado de dentro da requisição, onde o middleware de webhook.middleware já estabeleceu o contexto. Pacotes de tenancy com suporte a fila propagam esse contexto automaticamente. Se o seu não faz isso, mantenha queue => false ou trate a propagação no seu próprio WebhookHandler.

Validação de payload malformado continua acontecendo antes do enfileiramento, então o 422 segue valendo — depois do 200 não haveria como avisar o servidor.

Deduplicação

A deduplicação usa dois guards, e basta um acusar entrega anterior:

Guard Força Limite
Status já gravado na linha Durável, sobrevive a flush de cache Só existe com log_generations ligado
Cache::add() da chave fusion-report:webhook:{uuid}:{status} Atômico — fecha a corrida de entregas simultâneas Perde efeito se o cache for limpo, ou com driver null

O TTL do cache sai de webhook.deduplication_ttl (minutos, padrão 1440). O servidor reentrega no máximo por ~4 minutos, então 24h cobre com folga.

Com log_generations = false não existe registro, e com ele some o $context — que chega sempre vazio em onWebhookReceived() e nos eventos — e o $owner, que vem null. A deduplicação passa a depender só do cache. Os hooks continuam disparando; antes desta versão, o callback virava no-op silencioso.

Se você usa ->context([...]) ou ->for($model), mantenha o log ligado.

Registro ausente com o log ligado é tratado como anomalia, não como duplicata: o package registra Log::warning e não dispara nada. Em apps multi-tenant isso normalmente significa que o middleware de webhook.middleware não inicializou o tenant antes do controller — a consulta caiu no banco errado.

1. Reagindo ao callback — onWebhookReceived() (recomendado)

Basta implementar onWebhookReceived() na sua ReportDefinition (ver exemplo na seção Report Definitions). O package faz o roteamento pelo template_name automaticamente — você não precisa de rota nem handler próprios.

2. Handler customizado (opcional)

Para lógica global (independente de template), rebinde o contrato WebhookHandler num service provider seu:

Contexto da requisição (multi-tenant, auth, etc.)

O callback chega do servidor externo sem o contexto da sua aplicação. Como o package é agnóstico de contexto, a rota do webhook usa o middleware definido em webhook.middleware — é aí que a app hospedeira estabelece o que precisar antes do handler rodar.

Exemplo multi-tenant: a definition anexa o tenant_id na URL via webhookParams(), e um middleware seu lê esse valor e inicializa o tenant — assim a query da geração já cai no banco correto:

API do payload

Verificação de assinatura

A verificação HMAC é feita automaticamente pelo package.

webhook.secret é obrigatório. Sem ele a rota responde 503 e não processa nada — a alternativa seria aceitar payload não assinado, permitindo que qualquer POST alterasse status e URLs de download das suas gerações e disparasse os eventos da aplicação.

Para desenvolvimento local sem segredo, e só para isso:

Com essa flag o package registra um Log::warning a cada callback aceito sem verificação.

Respostas da rota de webhook:

Situação HTTP
Processado 200
Assinatura ausente ou inválida 401
Payload sem id ou status 422 (o servidor para de retentar)
webhook.secret não configurado 503

Para uso manual:


Monitoramento Jasper

Indisponível via X-API-KEY. As cinco rotas /api/v1/jasper/* são exclusivas do dashboard (Sanctum) — expõem estado global do servidor Java, que não é escopado por cliente. Chamadas autenticadas por API key retornam 401. Os métodos seguem no package para quem autentica de outra forma.


Tratamento de Erros

Todas as exceptions do package herdam de FusionReportException, então um único catch continua capturando tudo. As específicas existem para quem precisa distinguir o caso.

Falha de conexão fica de fora. Timeout e rede indisponível lançam Illuminate\Http\Client\ConnectionException, que não herda de FusionReportException — não há resposta HTTP para o package traduzir. Capture separadamente quando isso importar:

HTTP Situação Exception
— api_key não configurada — nenhuma requisição chega a sair AuthenticationException
401 Credencial ausente/inválida, ou rota só de dashboard AuthenticationException
403 Recurso pertence a outra conta AuthorizationException
422 Campo obrigatório ausente ou arquivo inválido FusionReportException
429 Cota de requisições do plano esgotada RateLimitException
404 ID não encontrado (route model binding) ReportNotFoundException
410 Nome não encontrado, conflito ou erro interno ReportNotFoundException / FusionReportException

Eventos

O package dispara eventos em todo ciclo de geração. Use quando quiser reagir sem ser dono da ReportDefinition — o hook onGenerated()/onWebhookReceived() continua funcionando e os dois convivem.

Evento Quando
ReportGenerationStarted O servidor aceitou a requisição (síncrona e assíncrona)
ReportGenerationCompleted Concluída — na síncrona, pela resposta; na assíncrona, pelo webhook
ReportGenerationFailed Falhou, pelos mesmos dois caminhos

Todos expõem as mesmas propriedades públicas:

ReportGenerationFailed tem ainda $event->error.

Na geração síncrona o Started é seguido imediatamente por Completed/Failed, no mesmo ciclo — a resposta já vem finalizada. Na assíncrona só o Started sai na hora; o desfecho chega pelo webhook.

$event->error costuma vir null no caminho assíncrono: o servidor mantém error_message em $hidden. Ver Campos sempre vazios.


Métodos indisponíveis via X-API-KEY

O client autentica exclusivamente por X-API-KEY. Parte das rotas do servidor é restrita ao dashboard e exige Bearer token do Sanctum — chamá-las com API key retorna 401, que o package converte em FusionReportException.

Os métodos abaixo continuam existindo (podem ser usados por quem autentica de outra forma), mas não funcionam na integração por API key:

Método Rota Alternativa
generation($id)->get() GET /api/v1/generations/{id} webhook (onWebhookReceived())
generation($id)->status() GET /api/v1/generations/{id} webhook
generation($id)->cancel() DELETE /api/v1/generations/{id} —
templates()->generations($id) GET /api/v1/reports/{id}/generations tabela fusion_report_generations
templates()->generationsByName($n) GET /api/v1/reports/name/{n}/generations tabela fusion_report_generations
jasper()->formats() GET /api/v1/jasper/formats —
jasper()->status() GET /api/v1/jasper/status —
jasper()->jobs() GET /api/v1/jasper/jobs —
jasper()->fontsStatus() GET /api/v1/jasper/fonts/status —
jasper()->fontsSync() POST /api/v1/jasper/fonts/sync —

Para histórico de gerações, use o log local do próprio package (fusion_report_generations), alimentado na geração e atualizado pelo webhook — ver Report Definitions e a trait HasFusionReportGenerations.

Campos sempre vazios

O servidor mantém alguns campos em $hidden, então nunca chegam no JSON. Estes accessors retornam sempre o valor padrão, independentemente da autenticação:

Accessor Retorna sempre
GenerationResource::errorMessage() null
GenerationResource::progressPercent() 0
WebhookPayload::error() null
TemplateResource::filePath() ''
TemplateResource::resourcesPath() null

Na prática: quando uma geração assíncrona falha, o webhook chega com status: 'failed' e sem motivo. O texto do erro só aparece na geração síncrona, na mensagem da FusionReportException.


Limitações conhecidas

Comportamentos que valem saber antes de integrar. Nenhum é acidental — todos estão registrados aqui em vez de serem descobertos em produção.

Timeout menor que o do servidor

O client espera 60s por resposta. O servidor concede 90s ao Jasper numa geração síncrona, e ainda gasta tempo depois disso baixando e armazenando os arquivos.

Numa geração síncrona pesada, o client desiste antes de o servidor terminar:

Duas consequências práticas:

Para relatórios grandes, prefira generateAsync() com webhook.

Sem retry automático

Um 5xx transitório ou soluço de rede vira exceção direto no chamador. Retry não foi adicionado de propósito: seria seguro apenas em leituras (get, download) e perigoso em generate, async, upload e export, que criam estado e consomem cota — o servidor cobra por requisição recebida, então três tentativas de uma geração seriam três débitos.

Se precisar, implemente o retry na sua aplicação, envolvendo só as leituras.

URL do servidor não é configurável

FusionReportHttp::BASE_URL é uma constante. Não há config nem variável de ambiente para apontar o client a outra instância — trocar exige editar o package.

Replay de webhook

O servidor assina apenas o corpo, sem timestamp, então o par corpo+assinatura é válido indefinidamente. A deduplicação limita muito o estrago: um replay do mesmo status não reexecuta os efeitos. Proteção completa exigiria timestamp assinado, o que é mudança no servidor.

Com log_generations = false a deduplicação depende só do cache — expirado o TTL, um replay volta a disparar os hooks.

Outros


Referência completa — Endpoints cobertos

Rotas marcadas com ⚠️ exigem Sanctum e não funcionam via X-API-KEY (ver seção acima).

Endpoint Método do package
GET /api/v1/reports templates()->list()
POST /api/v1/reports templates()->upload(...)
GET /api/v1/reports/{id} templates()->find($id)
POST /api/v1/reports/{id} templates()->update($id, ...)
POST /api/v1/reports/name/{name} templates()->updateByName($name, ...)
GET /api/v1/reports/{id}/jrxml templates()->downloadJrxml($id)
DELETE /api/v1/reports/{id} templates()->delete($id)
DELETE /api/v1/reports/name/{name} templates()->deleteByName($name, $theme)
GET /api/v1/reports/{id}/generations templates()->generations($id) ⚠️
GET /api/v1/reports/name/{name}/generations templates()->generationsByName($name) ⚠️
POST /api/v1/generate report('name')->generate()
POST /api/v1/async report('name')->generateAsync()
POST /api/v1/reports/{id}/generate reportById($id)->generate()
POST /api/v1/reports/{id}/async reportById($id)->generateAsync()
GET /api/v1/generations/{id} generation($id)->get() ⚠️
DELETE /api/v1/generations/{id} generation($id)->cancel() ⚠️
GET /api/v1/files/{id}/download file($id)->download()
POST /api/v1/files/{id}/export file($id)->export($format)
POST /api/v1/generations/{id}/export generation($id)->export($format)
GET /api/v1/jasper/formats jasper()->formats() ⚠️
GET /api/v1/jasper/status jasper()->status() ⚠️
GET /api/v1/jasper/jobs jasper()->jobs() ⚠️
GET /api/v1/jasper/fonts/status jasper()->fontsStatus() ⚠️
POST /api/v1/jasper/fonts/sync jasper()->fontsSync() ⚠️

All versions of fusion-report-client with dependencies

PHP Build Version
Package Version
Requires php Version ^8.4
illuminate/bus Version ^12
illuminate/contracts Version ^12
illuminate/http Version ^12
illuminate/queue Version ^12
illuminate/support Version ^12
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package risetechapps/fusion-report-client contains the following files

Loading the files please wait ...