Visão Geral
O CTN Extrator é uma API Flask que faz scraping autenticado no sistema CTN para extrair dados financeiros por unidade (franquia):
Movimentações Diárias
Receitas e despesas por conta e subconta num intervalo de datas. Equivale à tela ConsultaReceitaDespesa do CTN.
Saldos Diários
Fechamento de caixa do dia + saldo atual por conta bancária. Equivale às telas ConsultaSaldoDiario e ContainerRelatorio.
Refresh Automático
Rota protegida que renova os cookies do CTN automaticamente via login + 2captcha. Ideal para acionar via n8n no cron diário.
Como funciona
A autenticação usa cookies de sessão (CTN.Auth, id_menu_clicado, TiPMix) salvos no .env.
A cada chamada, uma sessão HTTP é criada com esses cookies e o CTN é consultado diretamente.
Os cookies são renovados automaticamente toda manhã via POST /refresh.
Estrutura do Projeto
├── app.py # API Flask (porta 2007)
├── refresh_auth.py # Renovação automática de cookies via 2captcha
├── session_ctn.py # Utilitários: cookies, sessão, formulário, xlsx
├── .env # Credenciais e cookies de autenticação
├── Dockerfile # Imagem Docker (python:3.12-slim)
├── docker-compose.yml # Sobe a API em container
└── service/
├── movimentacoes_diarias.py # Extração de movimentações
└── saldos_diarios.py # Extração de saldos
Configuração — arquivo .env
| Variável | Descrição | Atualização |
|---|---|---|
CTN_LOGIN | E-mail de acesso ao CTN | Manual (uma vez) |
CTN_SENHA | Senha de acesso ao CTN | Manual (uma vez) |
TWOCAPTCHA_API_KEY | Chave da API do 2captcha (resolve reCAPTCHA do login) | Manual (uma vez) |
API_SECRET | Senha que protege a rota POST /refresh | Manual (uma vez) |
CTN_AUTH | Cookie de autenticação CTN — token longo | Auto — via /refresh |
ID_MENU_CLICADO | Cookie de estado de menu do CTN | Auto — via /refresh |
TIPMIX | Cookie interno do CTN | Auto — via /refresh |
ASPNET_SESSION_ID | Cookie de sessão ASP.NET | Manual se necessário |
FRANQUIA_IDS | Mapeamento NOME:ID das unidades, separado por vírgula | Manual (uma vez) |
Subindo com Docker
git pull
docker-compose up -d --build
# Forçar refresh manual logo após subir (garante cookies frescos)
curl -X POST http://localhost:2007/refresh \
-H "X-API-Secret: <API_SECRET>"
Rotas da API
Verifica se a API está no ar.
{ "status": "ok" }
Retorna resumo por conta e detalhes de lançamentos de receitas e despesas.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
franquia_id | string | Sim | ID numérico da franquia |
data_inicio | string | Sim | YYYY-MM-DD ou DD/MM/YYYY |
data_fim | string | Sim | YYYY-MM-DD ou DD/MM/YYYY |
tipo_movimentacao | string | Não | "" todos · "1" receita · "2" despesa |
historico | string | Não | Filtro de histórico (texto livre) |
valor | string | Não | Filtro por valor |
Resposta
{
"franquia_id": "535",
"data_inicio": "2026-04-01",
"data_fim": "2026-04-06",
"resumo": [
{ "Conta": "CAIXA DINHEIRO", "Entrada": "R$ 1.200,00", "Saida": "R$ 300,00", "Total": "R$ 900,00" }
],
"detalhes": [
{ "Conta": "CAIXA DINHEIRO", "SubConta": "VENDAS", "Tipo Mov.": "Receita",
"Funcionário/Sócio": "JOÃO SILVA", "Data Lan.": "01/04/2026", "Valor": "R$ 1.200,00" }
]
}
Retorna fechamento de caixa e saldo por conta para uma data específica.
Body (JSON)
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
franquia_id | string | Sim | ID numérico da franquia |
data | string | Sim | YYYY-MM-DD ou DD/MM/YYYY |
Resposta
{
"franquia_id": "535",
"data": "2026-04-01",
"fechamento": [
{ "Data": "01/04/2026", "Saldo Anterior": "R$ 5.000,00",
"Entrada": "R$ 1.200,00", "Saída": "R$ 300,00", "Saldo Atual": "R$ 5.900,00" }
],
"saldo_contas": [
{ "Data": "2026-04-01", "Contas": "CAIXA DINHEIRO",
"Saldo Anterior": "R$ 5.000,00", "Movimentação Dia": "R$ 900,00", "Saldo Atual": "R$ 5.900,00" }
]
}
Renova os cookies do CTN (CTN.Auth, ID_MENU_CLICADO, TIPMIX) via login automático + 2captcha. Atualiza o .env em disco — sem necessidade de reiniciar a API.
Header obrigatório
| Header | Valor |
|---|---|
X-API-Secret | Valor de API_SECRET no .env |
Respostas
// Sucesso
{ "status": "ok", "mensagem": "Cookies renovados com sucesso." }
// Não autorizado (secret errado)
HTTP 401 — { "status": "erro", "mensagem": "Não autorizado" }
// Falha no login / 2captcha
HTTP 500 — { "status": "erro", "mensagem": "..." }
0 7 * * 1-5 (seg–sex às 07h):
método POST, URL http://sua-vps:2007/refresh,
header X-API-Secret: <API_SECRET>.
O refresh demora ~2 minutos (tempo de resolução do reCAPTCHA pelo 2captcha).
Exemplos de Uso
cURL — Movimentações
curl -X POST http://localhost:2007/movimentacoes \
-H "Content-Type: application/json" \
-d '{ "franquia_id": "535", "data_inicio": "2026-04-01", "data_fim": "2026-04-06" }'
cURL — Saldos
curl -X POST http://localhost:2007/saldos \
-H "Content-Type: application/json" \
-d '{ "franquia_id": "535", "data": "2026-04-01" }'
cURL — Refresh
curl -X POST http://localhost:2007/refresh \
-H "X-API-Secret: sua_senha_forte"
IDs de franquia disponíveis
| Unidade | franquia_id |
|---|---|
| CARTAO DE ARAUCARIA | 440 |
| CARTAO DE FRANCISCO BELTRAO | 569 |
| CARTAO DE SAO JOAO DEL REI | 535 |
Refresh Automático — Como Funciona
Os cookies do CTN expiram diariamente. O fluxo de renovação é totalmente automático:
- n8n aciona
POST /refreshcom oX-API-Secrettodo dia útil às 07h. - A API acessa
ctn.sistematodos.com.br→ é redirecionada para a página de login OAuth. - Credenciais são preenchidas e o reCAPTCHA é enviado ao 2captcha (~100s para resolver).
- Após login, os cookies novos são capturados e salvos no
.env. - A partir da próxima requisição, a API já usa os cookies atualizados — sem reiniciar.
.env puxado do repositório pode ter cookies desatualizados.
Execute um refresh manual imediatamente após subir o container.
Custo do 2captcha
Cada resolução de reCAPTCHA custa aproximadamente $0.0017. Com 20 renovações mensais (seg–sex):
20 × $0.0017 = $0.034 / mês → $3 de crédito ≈ 7 anos de uso
Erros Comuns
| Situação | Causa provável | Solução |
|---|---|---|
Listas vazias (resumo, fechamento) |
Cookies expirados ou data sem dados | Chame POST /refresh e tente novamente. |
| HTTP 500 na extração | Cookies inválidos ou CTN fora do ar | Verifique com POST /refresh. Se persistir, verifique o CTN manualmente. |
| HTTP 400 — campos obrigatórios | Body JSON incompleto | Confirme que todos os campos obrigatórios estão presentes. |
HTTP 401 no /refresh |
Header X-API-Secret ausente ou incorreto |
Confira o valor de API_SECRET no .env. |
| Saldos vazios para hoje | Fechamento ainda não realizado | Normal — consulte apenas datas anteriores ao dia atual. |
| Timeout de conexão | CTN indisponível ou rede instável | Aguarde e tente novamente. Timeout configurado em 60s. |