Emite automaticamente Notas Fiscais de Serviço Eletrônicas (NFS-e) junto à Prefeitura de São Paulo, integrando diretamente com o webservice oficial "Nota Fiscal Paulistana" (SOAP, com certificado digital A1). Pensado para rodar como Cron Job no Render.
Cada regra em config/regras.yml define: em qual dia útil do mês emitir, para qual
destinatário, com que valor, e com que texto (com placeholders %{mes_corrente} /
%{mes_anterior}). A cada execução, um email de resumo é sempre enviado, informando se
alguma nota foi emitida naquele dia (ou por quê não).
bin/emitir_notasroda uma vez por dia (dia útil) via cron.- Para cada regra em
config/regras.yml, verifica se hoje é o N-ésimo dia útil do mês configurado (considerando apenas segunda-sexta, sem feriados). - Se for, monta o RPS, assina digitalmente (RPS + mensagem XML inteira) com o certificado A1 do prestador, e envia ao webservice da PMSP.
- Ao final, envia um email de resumo por SMTP com o resultado de cada regra.
Não existe um host de homologação separado. O "modo teste" do webservice da PMSP é o
método SOAP TesteEnvioLoteRPS (mesmo endpoint de produção, faz todas as validações, mas
não gera NF-e real). A variável NFE_AMBIENTE controla isso:
NFE_AMBIENTE=homologacao(padrão) → usaTesteEnvioLoteRPS. Seguro para testar.NFE_AMBIENTE=producao→ usaEnvioLoteRPS. Emite notas fiscais reais e irreversíveis. Só troque para produção manualmente, depois de validar todo o fluxo em homologação.
bundle install
cp config/regras.yml.example config/regras.yml
# edite config/regras.yml com os dados reais do prestador e das regras de emissão
bundle exec rake test| Variável | Descrição |
|---|---|
NFE_AMBIENTE |
homologacao (padrão) ou producao |
CERTIFICADO_PFX_PATH |
Caminho do arquivo .pfx do certificado A1 |
CERTIFICADO_PFX_SENHA |
Senha do certificado |
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASSWORD |
Credenciais SMTP para o email de resumo (ex: Gmail com senha de app) |
EMAIL_DESTINATARIO |
Para quem enviar o resumo de cada execução |
REGRAS_YAML_PATH |
(opcional) caminho alternativo para regras.yml |
Rodar manualmente:
NFE_AMBIENTE=homologacao \
CERTIFICADO_PFX_PATH=/caminho/certificado.pfx \
CERTIFICADO_PFX_SENHA=... \
SMTP_HOST=smtp.gmail.com SMTP_PORT=587 SMTP_USER=voce@gmail.com SMTP_PASSWORD=... \
EMAIL_DESTINATARIO=voce@gmail.com \
bin/emitir_notas- Suba este repositório para um remoto Git (GitHub/GitLab) — o Render Blueprint (
render.yaml) lê a partir daí. - No painel do Render, crie um Blueprint apontando para o repositório. Isso cria o Cron Job
emissor-nfse-sp(schedule padrão:0 11 * * 1-5, ou seja 08:00 horário de Brasília, dias úteis — ajuste se necessário). - Configure o certificado como Secret File (não como env var — é um arquivo binário):
no serviço, vá em "Environment" → "Secret Files", adicione um arquivo com o path
/etc/secrets/certificado.pfxe cole o conteúdo do.pfx. - Preencha as demais variáveis de ambiente marcadas
sync: falsenorender.yamldiretamente no painel do Render (CERTIFICADO_PFX_SENHA,SMTP_*,EMAIL_DESTINATARIO). - Antes de confiar no agendamento automático, dispare um "Run Job" manual no painel do
Render para validar o fluxo de ponta a ponta (com
NFE_AMBIENTE=homologacao). - Só depois de validar em homologação, troque
NFE_AMBIENTEparaproducaomanualmente no painel — isso não deve ser feito por commit/deploy automático.
bundle exec rake testOs testes de assinatura (test/rps_signature_test.rb) e XML (test/xml_builder_test.rb,
test/xml_signer_test.rb) validam a implementação contra os XSDs e exemplos oficiais
baixados da Prefeitura de São Paulo (test/fixtures/schemas, test/fixtures/exemplos-xml),
usando um certificado RSA gerado só para o teste — nenhum dado real é necessário para rodar
a suíte.
bin/emitir_notas # entrypoint do cron
config/regras.yml # regras de emissão (não versionado -- copie de regras.yml.example)
lib/nfse/
config.rb # carrega/valida regras.yml + env vars
dia_util.rb # N-ésimo dia útil do mês (seg-sex, sem feriados)
template.rb # placeholders %{mes_corrente} / %{mes_anterior}
rps.rb # struct do RPS a partir de uma regra
rps_signature.rb # assinatura do RPS (string de 86 posições + RSA-SHA1)
xml_builder.rb # monta PedidoEnvioLoteRPS (layout v1)
xml_signer.rb # assinatura XML enveloped da mensagem inteira
client.rb # SOAP + mTLS contra o webservice da PMSP
retorno_envio_lote_rps.rb # parser do retorno
emissor.rb # orquestra: avalia regras, emite, coleta resultados
notificador.rb # email de resumo da execução
Implementado a partir do Manual de Utilização Web Service NFS-e SP, versão 3.3.7 (Prefeitura de São Paulo). Layout usado: versão 1 (a versão 2, da Reforma Tributária 2026/IBS-CBS, ainda não é obrigatória em produção no momento em que este projeto foi criado — conferir o changelog do manual antes de migrar).