SDK em Go para geração de arquivos de remessa e leitura de arquivos de retorno no padrão CNAB 240 FEBRABAN, com arquitetura multi-banco.
O SDK separa três camadas independentes:
- Motor genérico (
internal/engine): sabe preencher campos, montar registros de 240 colunas, calcular sequenciais e trailers, e aplicar os limites do padrão FEBRABAN (70 lotes por arquivo, 10.000 movimentos por lote). Não conhece nenhum banco específico. - Descritores de layout (
cnab/layoute pacoteslayouts/<nome>): descrevem, campo a campo, o layout de um banco/produto. O layout de referênciafebraban240(padrão FEBRABAN puro, sem personalização de banco) já vem embutido. - API pública de domínio (
cnab): o que o desenvolvedor realmente usa. Nenhuma posição de campo aparece aqui, apenas conceitos como empresa, conta, favorecido e tipos de pagamento (crédito em conta, TED, PIX, boleto, tributos, cancelamento).
Veja ARQUITETURA.md para o detalhamento das três camadas e NOVO-BANCO.md para o passo a passo de como derivar o layout de um banco real a partir de febraban240. A referência completa de tipos, funções e constantes exportados está em API.md.
- Remessa CNAB 240 com múltiplos lotes, sequenciais e trailers calculados pelo próprio motor.
- Tipos de pagamento: crédito em conta, TED, PIX por chave, PIX por dados bancários, boleto, conta/tributo com código de barras, DARF, DARF Simples, GPS e cancelamento de um pagamento já enviado.
- Leitura de arquivo de retorno (
ParseReturn), com um movimento por Segmento A, J ou O e dados de autenticação do Segmento Z quando o layout do banco o implementa. - Conversão de linha digitável de boleto (47 dígitos) ou de conta/tributo (48 dígitos) em código de barras de 44 dígitos, com conferência dos dígitos verificadores (
ConvertToBarcode). - CNPJ alfanumérico da Receita Federal aceito em qualquer campo de documento, além do formato histórico todo numérico.
- Layouts plugáveis: registrados por nome em
init(), informados diretamente em tempo de execução (Config.LayoutSpec) ou carregados de um arquivo JSON (layout.NewFromJSON). - Nome do arquivo de remessa configurável por convenção de banco, por arquivo (
Config.FileNameLayout) ou global (SetRemittanceFileNameLayout). - Valores monetários sempre inteiros em centavos (
cnab.Cents), nuncafloat64. - Erros tipados (
ValidationError,FieldError,LimitExceededError,ReturnParseError, entre outros), identificáveis comerrors.As. - Zero dependências além da biblioteca padrão.
- Go 1.26 ou superior.
- Nenhuma dependência externa.
go get github.com/raykavin/gocnabpackage main
import (
"log"
"time"
"github.com/raykavin/gocnab/cnab"
)
func main() {
registration, err := cnab.NewCNPJ("11222333000181")
if err != nil {
log.Fatal(err)
}
file, err := cnab.NewRemittance(cnab.Config{
Layout: "febraban240",
Company: cnab.Company{
Name: "ACME LTDA",
Registration: registration,
Agreement: "1234",
},
Account: cnab.Account{Branch: "0116", Number: "75890", CheckDigit: "6"},
NSA: 1,
})
if err != nil {
log.Fatal(err)
}
batch, err := file.NewBatch(cnab.SupplierPayment, cnab.PixTransfer)
if err != nil {
log.Fatal(err)
}
payeeRegistration, _ := cnab.NewCNPJ("11444777000161")
err = batch.AddPayment(cnab.Pix{
Key: cnab.EmailKey("fornecedor@exemplo.com"),
Payee: cnab.Payee{Name: "COLABORADOR X", Registration: payeeRegistration},
Amount: cnab.Cents(25200), // R$ 252,00
Date: time.Now().AddDate(0, 0, 1),
})
if err != nil {
log.Fatal(err)
}
content, err := file.Generate()
if err != nil {
log.Fatal(err)
}
name, _ := file.FileName()
log.Printf("gerado %s com %d bytes", name, len(content))
}Valores monetários são sempre inteiros em centavos (cnab.Cents), nunca float64. Datas usam time.Time. Erros são tipados (cnab.ValidationError, cnab.LimitExceededError, cnab.FieldError, entre outros) e descritivos.
O par produto/serviço do lote (cnab.SupplierPayment, cnab.PixTransfer, ...) depende do manual do seu banco: alguns exigem produtos próprios para boleto (cnab.BoletoCollection) e para tributos (cnab.TaxPayment) em vez de aninhá-los em cnab.SupplierPayment.
BoletoPayment e BarcodeTax recebem o código de barras de 44 dígitos. Quando a entrada é a linha digitável, ConvertToBarcode normaliza os dois formatos e ainda diz para qual dos dois tipos de pagamento o resultado serve:
segment, barcode, err := cnab.ConvertToBarcode("34190.10438 51004.791029 01500.080005 1 91820000023000")
if err != nil {
log.Fatal(err) // dígito verificador não confere, tamanho inválido, caractere inesperado
}
switch segment {
case cnab.SegmentBankSlip:
err = batch.AddPayment(cnab.BoletoPayment{Barcode: barcode /* ... */})
case cnab.SegmentFeesOrTaxes:
err = batch.AddPayment(cnab.BarcodeTax{Barcode: barcode /* ... */})
}Todos os dígitos verificadores FEBRABAN são conferidos antes do retorno, então uma linha digitada errada é recusada aqui em vez de virar um código de barras plausível mas errado.
content, err := os.ReadFile("retorno_20260105.ret")
if err != nil {
log.Fatal(err)
}
result, err := cnab.ParseReturn("febraban240", content)
if err != nil {
log.Fatal(err)
}
for _, m := range result.Movements {
if m.Accepted() {
fmt.Printf("%s: liquidado em %s\n", m.YourNumber, m.SettlementDate.Format("2006-01-02"))
} else {
fmt.Printf("%s: rejeitado, códigos %v\n", m.YourNumber, m.OccurrenceCodes)
}
}ParseReturn gera um movimento por segmento principal encontrado: Segmento A (crédito em conta, TED, PIX), Segmento J (boleto) e Segmento O (conta/tributo com código de barras). De cada um extrai o "seu número" enviado na remessa, o valor instruído, a data e o valor reais de liquidação e os códigos de ocorrência/rejeição, o suficiente para reconciliar um pagamento. Um Segmento Z posterior preenche os dados de autenticação do movimento, quando o layout do banco o implementa. Os segmentos complementares (B, BPix, J-52) e o Segmento N são ignorados; veja "Processando retorno" em ARQUITETURA.md para o motivo.
A tabela de códigos de ocorrência é específica de cada banco: confirme com o manual dele antes de interpretar um código.
O layout febraban240 é o padrão FEBRABAN puro e já vem registrado; ele não representa nenhum banco real (o código de compensação é um "000" de referência). Há três formas de usar o layout de um banco:
- Registro por nome, o caminho usual para um layout que é constante do binário: o pacote do banco chama
layout.Registerno seuinit()e o chamador informa o nome emConfig.Layout. - Instância direta, para um layout que é dado resolvido em tempo de execução: preencha
Config.LayoutSpec(e useParseReturnWithLayoutna leitura de retorno). - Descritor JSON, para trocar o layout sem recompilar:
layout.NewFromJSON/layout.NewFromJSONFile, com validação completa já no carregamento.
O passo a passo para derivar o layout de um banco real a partir do manual dele está em NOVO-BANCO.md.
A pasta ./examples tem exemplos para cada cenário coberto pelo SDK:
| Pasta | Cenário |
|---|---|
examples/credit_account |
Crédito em conta corrente |
examples/ted |
TED |
examples/pix_key |
PIX por chave |
examples/pix_bank_data |
PIX por dados bancários |
examples/boleto |
Pagamento de boleto |
examples/barcode_tax |
Tributo/conta com código de barras |
examples/darf |
DARF |
examples/gps |
GPS |
examples/cancel_payment |
Cancelamento de pagamento |
examples/custom_layout_json |
Layout de banco carregado de um arquivo JSON (layout.NewFromJSON), em vez de escrito em Go |
examples/parse_return |
Leitura de um arquivo de retorno (cnab.ParseReturn) |
Cada exemplo roda isoladamente, por exemplo:
go run ./examples/pix_keycnab/ API pública de domínio: Config, File, Batch, tipos de pagamento, retorno
cnab/layout/ contrato de layout: Layout, FieldSpec, RecordSpec, vocabulário de Key, registro, carregador JSON
internal/engine/ motor genérico: campos, registros de 240 colunas, sequenciais, trailers, limites
layouts/febraban240/ layout de referência do padrão FEBRABAN puro
examples/ programas executáveis, um por cenário
go test ./... -coverO pacote internal/engine (o motor genérico) mantém cobertura de testes acima de 85%.
go build ./... # compila todos os pacotes
go vet ./... # análise estática
go run ./examples/ted # executa um exemplo- ARQUITETURA.md: as três camadas do SDK e as decisões de design.
- API.md: referência completa da API pública.
- NOVO-BANCO.md: passo a passo para implementar o descritor de um banco real a partir do manual CNAB dele.
Contribuições para o gocnab são bem-vindas! Veja algumas formas de ajudar:
- Reporte bugs e sugira funcionalidades abrindo issues no GitHub
- Envie pull requests com correções de bugs ou novas funcionalidades
- Melhore a documentação para ajudar outros usuários e desenvolvedores
gocnab é distribuído sob a Licença MIT. Para os termos e condições completos da licença, veja o arquivo LICENSE no repositório.