Extensões para Fiscal.io Monitor

Extensões para Fiscal.io Monitor

O Fiscal.io Monitor permite criar e instalar extensões (plugins) em .NET para acrescentar botões, canais de envio e tarefas periódicas — sem alterar o núcleo do produto.

Este manual explica como criar uma extensão, com exemplo de código. Para só instalar um ZIP pronto, veja: Instalando uma extensão de integração no Fiscal.io Monitor.

O que uma extensão pode fazer

  • Botões no menu Extensões, agindo sobre documentos selecionados.
  • Canal de saída (Integrar → Extensão → Enviar) — XML/PDF/NOTFIS/CONEMB para ERP, WMS, API ou qualquer plataforma.
  • Canal de entrada (Integrar → Extensão → Receber) — puxar XML do seu sistema para a base do Monitor.
  • Tarefa periódica (timer em minutos) para sync em segundo plano.
  • Etiquetas e observações automáticas nos documentos.
  • Conciliação fiscal (registro de escrituração) e manifestação (confirmação da operação).
  • Parâmetros persistidos (URL, token, opções da integração).

Recurso de plano: MON-FUNC-630 (Extensões). Permissão típica de instalação: PLUGIN-MANAGER.

Arquitetura (resumo técnico)

  1. Você cria uma Class Library .NET Framework 4.5.2 referenciando plugin.fiscal.io.dll.
  2. A classe principal deve se chamar clsMainClass e implementar IPlugin.
  3. O DLL de saída precisa se chamar MainFile.dll e ir em um ZIP (junto com dependências, se houver).
  4. No Monitor: Extensões → Gerenciar Extensões → + e importe o ZIP.
  5. Na carga, o Monitor extrai em Plugins\{banco}_{guid}_{versao}, carrega MainFile.dll e instancia clsMainClass.

Passo a passo para criar

1) Criar o projeto

  1. No Visual Studio, crie uma Class Library com destino .NET Framework 4.5.2.
  2. Adicione referência a plugin.fiscal.io.dll (pasta de instalação / build do Monitor).
  3. Referências mínimas do framework: System, System.Drawing.

2) Metadados do Assembly (obrigatórios)

Os atributos do assembly precisam bater exatamente com as propriedades Guid e Name da classe:

using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("Minha Extensão Demo")]
[assembly: AssemblyDescription("Exemplo de extensão para o Fiscal.io Monitor")]
[assembly: AssemblyCompany("Minha Empresa")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Guid("11111111-2222-3333-4444-555555555555")]
  • Guid (assembly) = IPlugin.Guid
  • AssemblyTitle = IPlugin.Name
  • AssemblyFileVersion → versão exibida no Monitor
  • AssemblyDescription / AssemblyCompany → descrição e autor

3) Implementar clsMainClass

Nome da classe: clsMainClass (sem exceção). Exemplo mínimo com botão + canal de envio:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using plugin.fiscal.io;

namespace MinhaEmpresa.FiscalIo.PluginDemo
{
    /// <summary>
    /// Nome OBRIGATÓRIO da classe principal: clsMainClass
    /// </summary>
    public class clsMainClass : IPlugin
    {
        public string Guid => "11111111-2222-3333-4444-555555555555";
        public string Name => "Minha Extensão Demo";
        public Bitmap Icon => new Bitmap(16, 16);

        public List<IButton> ButtonList { get; } = new List<IButton>
        {
            new clsBotaoDemo()
        };

        public event EventOnFiscalChangedHandler EventOnFiscalChanged;
        public event EventOnTagChangedHandler EventOnTagChanged;
        public event EventGetParameterHandler EventGetParameter;
        public event EventSetParameterHandler EventSetParameter;
        public event EventSetChannelInHandler EventSetChannelIn;

        // Canal de ENVIO (Integrar → Extensão → Enviar arquivos XML)
        public bool IsChannelSender => true;
        public bool IsChannelReceiver => false;

        public clsRetFunc funcExecuteChannelSender(clsDocScope pclsScope, string pFilePath, string pFileType)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(pFilePath) || !File.Exists(pFilePath))
                {
                    return new clsRetFunc { Type = "E", Number = "1", Message = "Arquivo não encontrado." };
                }

                // Exemplo: ler o XML e enviar para o seu ERP/API
                var xml = File.ReadAllText(pFilePath);
                // SeuCodigo.Enviar(xml, pFileType, pclsScope);

                return new clsRetFunc { Type = "S", Number = "0", Message = "XML enviado com sucesso." };
            }
            catch (Exception ex)
            {
                return new clsRetFunc { Type = "E", Number = "999", Message = ex.Message };
            }
        }

        public clsRetFunc funcExecuteChannelReceiver(string pChannel)
        {
            return new clsRetFunc { Type = "S", Number = "0", Message = "Receiver não utilizado neste exemplo." };
        }

        // Tarefa periódica (opcional)
        public bool IsTaskEnabled => false;
        public int TaskFrequency => 60; // minutos

        public clsRetFunc funcExecuteTask()
        {
            return new clsRetFunc { Type = "S", Number = "0", Message = "OK" };
        }
    }

    public class clsBotaoDemo : IButton
    {
        public string ibGuid => "btn-demo-001";
        public string ibName => "Demo: marcar documentos";
        public Bitmap ibIcon => new Bitmap(16, 16);
        public List<string> ibTabList => new List<string>();

        public bool funcExecute(object pDocList)
        {
            // pDocList: lista de documentos selecionados na tela
            return true;
        }

        public bool funcExecute(object pDocList, object pRefList)
        {
            return funcExecute(pDocList);
        }
    }
}

4) Empacotar o ZIP

  1. Compile em Release.
  2. Renomeie o DLL gerado para MainFile.dll (ou configure o AssemblyName do projeto como MainFile).
  3. Crie um ZIP contendo MainFile.dll e, se necessário, DLLs dependentes na raiz do ZIP (sem pastas aninhadas).
  4. Não altere nomes internos depois de instalar.

5) Instalar e testar no Monitor

  1. Extensões → Gerenciar Extensões → aba Extensões → botão + → selecione o ZIP → Salvar.
  2. Reinicie o Monitor se a extensão não aparecer imediatamente.
  3. Botões da extensão ficam sob o menu Extensões.
  4. Para envio automático: Integrar → Gerenciar Canais de Integração → Adicionar
    • Meio: Extensão
    • Objetivo: Enviar arquivos XML
    • Aba Extensão: escolha a extensão instalada

Exemplos extras (escolha o que precisa)

Os trechos abaixo são independentes. Copie só o que for usar na sua clsMainClass. Não precisa ligar tudo de uma vez.

A) Canal de entrada (receber XML no Monitor)

Use quando o seu sistema gera o XML e o Monitor deve importar. Em Integrar, configure Meio = Extensão e Objetivo = Receber.

public bool IsChannelReceiver => true;

public clsRetFunc funcExecuteChannelReceiver(string pChannel)
{
    try
    {
        // 1) Busque o XML no seu ERP/API/pasta
        string xml = SeuCodigo.BuscarProximoXml();
        if (string.IsNullOrWhiteSpace(xml))
            return new clsRetFunc { Type = "S", Number = "0", Message = "Nada novo." };

        // 2) Empurre o XML para o Monitor processar na entrada
        var handler = EventSetChannelIn;
        if (handler != null)
        {
            handler(this, new EventSetChannelInEventArgs
            {
                Channel = pChannel,
                XmlContent = xml
            });
        }

        return new clsRetFunc { Type = "S", Number = "0", Message = "XML recebido no Monitor." };
    }
    catch (Exception ex)
    {
        return new clsRetFunc { Type = "E", Number = "999", Message = ex.Message };
    }
}

B) Tarefa recorrente (timer)

Roda sozinha no Gerenciador de tarefas. Ideal para sync periódico.

public bool IsTaskEnabled => true;
public int TaskFrequency => 30; // a cada 30 minutos

public clsRetFunc funcExecuteTask()
{
    try
    {
        // SeuCodigo.Sincronizar();
        return new clsRetFunc { Type = "S", Number = "0", Message = "Tarefa concluída." };
    }
    catch (Exception ex)
    {
        return new clsRetFunc { Type = "E", Number = "999", Message = ex.Message };
    }
}

C) Atribuir etiqueta e observação

Útil para triagem automática depois de um sync ou botão.

void AplicarEtiqueta(string chave, string etiqueta, string nota)
{
    var handler = EventOnTagChanged;
    if (handler == null) return;

    handler(this, new EventOnTagChangedEventArgs
    {
        Filial = "",
        Chave = chave,          // chave do DFe
        Tag = etiqueta,         // nome da etiqueta
        SetTag = true,
        DocNote = nota,         // observação
        SetDocNote = true
    });
}

// Exemplo:
// AplicarEtiqueta("3524...chave...", "Recebido no ERP", "Sync automático");

D) Conciliação fiscal + manifestação

Depois que o ERP lançou a nota, registre no Monitor. Se quiser, agenda a Confirmação da Operação.

void RegistrarEscrituracao(
    string filial, string chave,
    string dtReg, string usuario, string dtEnt, string numErp,
    bool confirmarOperacao, int atrasoHoras)
{
    var handler = EventOnFiscalChanged;
    if (handler == null) return;

    handler(this, new EventOnFiscalChangedEventArgs
    {
        Filial = filial,
        Chave = chave,
        DtRegFisc = dtReg,              // data do registro
        UsRegFisc = usuario,            // usuário
        DtEntFisc = dtEnt,              // data de lançamento
        DcNumFisc = numErp,             // número no ERP
        DoManifest = confirmarOperacao, // true = agenda manifestação
        ManifestDelay = atrasoHoras     // horas após a leitura
    });
}

E) Guardar URL / token da integração

string Ler(string nome)
{
    var h = EventGetParameter;
    if (h == null) return "";
    return h(this, new EventGetParameterEventArgs { Param = nome, Global = true }) ?? "";
}

void Salvar(string nome, string valor)
{
    var h = EventSetParameter;
    if (h == null) return;
    h(this, new EventSetParameterEventArgs { Param = nome, Value = valor, Global = true });
}

// Salvar("api_url", "https://meu-erp/api");
// var url = Ler("api_url");

Receitas rápidas

  • Só enviar XML para o ERP → canal de envio (exemplo do passo 3).
  • Puxar do legado + etiquetar → A + C (e B se for periódico).
  • Confirmar escrituração após RPA/planilha → botão + D.
  • Sync Comex / Portal Único → B (+ canal de envio se precisar entregar XML).
  • Entregar para qualquer plataforma → canal de envio chamando a API/protocolo do destino.

Visão comercial e catálogo: Criar extensão · Hub de Integrações.

Contrato IPlugin (referência)

  • Guid, Name, Icon, ButtonList
  • Eventos: EventOnFiscalChanged, EventOnTagChanged, EventGetParameter, EventSetParameter, EventSetChannelIn
  • Canal: IsChannelSender / IsChannelReceiver + funcExecuteChannelSender / funcExecuteChannelReceiver
  • Tarefa: IsTaskEnabled, TaskFrequency (minutos), funcExecuteTask
  • Retorno: clsRetFunc — use Type = "E" para erro e "S" (ou outro não-erro) para sucesso; Message aparece no rastreio.

Tipos úteis no envio: clsDocScope (documento, itens, eventos, vínculos) e pFileType (ex.: XML, PDF, NOTFIS, CONEMB).

Eventos do host (plugin → Monitor)

  • EventSetParameter / EventGetParameter — grava/lê parâmetros persistidos (chave montada com o nome da extensão).
  • EventOnTagChanged — define etiqueta / observação do documento.
  • EventOnFiscalChanged — registro fiscal (datas, usuário, número no ERP) e opcionalmente agenda manifestação.
  • EventSetChannelIn — envia conteúdo XML para o Monitor processar como entrada em um canal informado.

Checklist de erros comuns

  • ZIP sem MainFile.dll → falha na importação.
  • Classe principal com outro nome (não é clsMainClass) → não carrega.
  • Guid/Name do assembly diferentes da classe → rejeitado na importação.
  • Framework diferente de 4.5.2 / dependências faltando no ZIP → erro ao carregar.
  • Recurso de extensões não liberado no plano → instale após liberar MON-FUNC-630.

Artigos relacionados

Dúvidas de homologação ou parcerias: suporte@fiscal.io.