REF-901-08: ISSNet NFSe Integration (Brasília/DF)
ADR: ADR-901 — IntegrationsEscopo: Emissão de NFSe via SOAP (ABRASF 2.04), campos RPS, fluxo de emissão, tratamento de erros, ambientes
1. Contexto
ISSNet é o sistema de emissão de Nota Fiscal de Serviço Eletrônica (NFSe) da prefeitura de Brasília/DF, baseado no padrão ABRASF. middag-account emite NFSe automaticamente quando um pagamento é confirmado, vinculando TaxInvoice (domínio) à nota fiscal emitida.
Dependências:
- Domínio TaxInvoice (ADR-301, REF-301-04)
- Domínio Invoice (para dados financeiros)
- Certificado digital A1 (.pfx) válido
- Inscrição municipal ativa em Brasília/DF
2. Configuração (wp_options)
Armazenada com prefixo middag_issnet_*:
| Option Key | Tipo | Descrição | Exemplo |
|---|---|---|---|
middag_issnet_cnpj_prestador | string | CNPJ da empresa emissora (somente dígitos) | 12345678000190 |
middag_issnet_inscricao_municipal | string | Inscrição municipal do prestador | 0123456789 |
middag_issnet_certificado_path | string | Caminho absoluto do .pfx (fora do webroot) | /etc/ssl/middag.pfx |
middag_issnet_certificado_senha | string | Senha do certificado A1 (encrypted em wp_options) | *** |
middag_issnet_ambiente | string | homologacao | producao | homologacao |
middag_issnet_codigo_servico | string | Código LC 116/2003 | 1.01 |
middag_issnet_aliquota_iss | decimal | Alíquota ISS aplicável | 0.05 (5%) |
Segurança: certificado_path DEVE apontar para diretório fora do webroot. certificado_senha armazenada com encryption (wp_options não é plaintext para este campo).
3. Campos do RPS (Recibo Provisório de Serviço)
| Campo | Tipo | Valor / Regra |
|---|---|---|
| Número | int | Sequencial por série (auto-incrementado) |
| Série | string | "A" (configurável) |
| Tipo | int | 1 (RPS) |
| Data de emissão | date | Y-m-d (data da emissão) |
| Status | int | 1 (Normal) |
| Prestador | ||
| └── CNPJ | string | middag_issnet_cnpj_prestador |
| └── Inscrição municipal | string | middag_issnet_inscricao_municipal |
| Tomador | ||
| └── CPF ou CNPJ | string | Da Organization (billing_document) |
| └── Razão social | string | Da Organization (legal_name) |
| └── Endereço completo | string | Da Organization (billing_address) |
| Discriminação | text | Description da TaxInvoice |
| Valor bruto dos serviços | decimal | Valor total da TaxInvoice (10,2) |
| Valor ISS retido | decimal | 0.00 (prestador recolhe) |
| Alíquota ISS | decimal | middag_issnet_aliquota_iss |
| Código do serviço | string | middag_issnet_codigo_servico (LC 116/2003) |
| Código município prestador | string | 5300108 (Brasília/DF — código IBGE) |
4. Fluxo de Emissão
OrderService dispara evento `middag_order_payment_confirmed`
│
▼
ISSNetListener recebe evento
│
├── Verifica: domínio TaxInvoice habilitado? Config ISSNet presente?
│ └── NÃO → Log warning, retorna (graceful degradation)
│
├── Cria TaxInvoice com status PENDING
│
▼
ISSNetService::generateRPS(TaxInvoice)
│
├── Monta XML RPS conforme §3
├── Assina XML com certificado A1 (.pfx)
│
▼
SOAP POST `RecepcionarLoteRps`
│
├── Retorna protocolo de recebimento
│
├── TaxInvoice atualizado: status PROCESSING, protocolo armazenado
│
▼
Polling via WP-Cron (intervalo: 30s, 1min, 2min, 5min — backoff)
│
├── SOAP `ConsultarSituacaoLoteRps` com protocolo
│
├── Status 1 (Não Recebido) → Aguardar próximo polling
├── Status 2 (Não Processado) → Aguardar próximo polling
├── Status 3 (Processado com Erro) → §5 tratamento de erros
├── Status 4 (Processado com Sucesso) →
│
▼
SOAP `ConsultarNfseServicoPrestado`
│
├── Extrai: NumeroNfse, CodigoVerificacao, LinkNfse
│
▼
TaxInvoice atualizado:
├── status → ISSUED
├── nfse_number → NumeroNfse
├── nfse_verification_code → CodigoVerificacao
├── nfse_url → LinkNfse
└── nfse_issued_at → datetime da emissão5. Erros e Retry
| Cenário | Ação |
|---|---|
| Código de erro SOAP | Log detalhado + TaxInvoice status → FAILED + mensagem em admin notice |
| Certificado expirado | Bloquear emissão + notificar admin via email + admin notice |
| Timeout SOAP | Retentar via WP-Cron (máximo 3 tentativas com backoff exponencial) |
| Config ISSNet incompleta | Log warning + admin notice. Emissão não tentada. |
| CNPJ/CPF tomador inválido | TaxInvoice status → FAILED + mensagem específica |
| Certificado não encontrado | Bloquear emissão + notificar admin |
Retry policy:
Tentativa 1: imediato (no mesmo request)
Tentativa 2: +2 minutos (WP-Cron)
Tentativa 3: +10 minutos (WP-Cron)
Após 3 falhas: TaxInvoice status → FAILED, admin notificadoAdmin pode reprocessar manualmente via ação no admin UI.
6. Ambientes
Versão ABRASF: 2.04
| Ambiente | WSDL Endpoint |
|---|---|
| Homologação | https://www.issnetonline.com.br/homologaabrasf/webservicenfse204/nfse.asmx |
| Produção | Configurável via middag_issnet_wsdl_producao em wp_options (mesmo host, path diferente) |
Nota: Toggle middag_issnet_ambiente (homologacao | producao) seleciona o endpoint automaticamente. Endpoint de produção é configurável — MIDDAG pode trocar sem deploy. Testar em homologação antes de qualquer alteração em produção.
7. SOAP Operations
| Operação | Direção | Quando |
|---|---|---|
RecepcionarLoteRps | Saída | Submissão de lote (1 RPS por lote) |
ConsultarSituacaoLoteRps | Polling | Verificar status do lote (protocolo) |
ConsultarNfseServicoPrestado | Polling | Obter dados da NFSe emitida |
CancelarNfse | Saída | Cancelamento de NFSe (admin, com justificativa) |
Cancelamento de NFSe
Prazo legal: 15 dias após emissão (Brasília/DF). Após 15 dias, cancelamento não é possível via SOAP — requer processo administrativo na prefeitura. Sistema deve bloquear ação de cancelamento após prazo expirado.
8. Hooks Disparados
| Hook | Quando | Payload |
|---|---|---|
middag_taxinvoice_pending | TaxInvoice criada | $tax_invoice_id |
middag_taxinvoice_issued | NFSe emitida com sucesso | $tax_invoice_id, $nfse_number |
middag_taxinvoice_failed | Emissão falhou | $tax_invoice_id, $error |
middag_taxinvoice_cancelled | NFSe cancelada | $tax_invoice_id, $nfse_number |
middag_issnet_certificate_expiring | Certificado expira em < 30d | $days_remaining |
9. Herança do Tema
Implementação ISSNet no tema v4 estava quase pronta. Agente implementador pode herdar código do tema como referência — adaptar para DDD Light (Domain/ puro, WordPress/ como adapter).