Pull diário de pagamentos
Cenário: um job diário (cron, scheduler) precisa carregar todos os pagamentos do dia anterior para o seu data warehouse, ERP ou painel financeiro.
Escopo necessário: financeiro.read.
Fluxo
- Calcular a janela de busca: tipicamente
[ontem 00:00, hoje 00:00)em horário local do tenant. GET /v1/pagamentos?dtPagamentoInicial=...&dtPagamentoFinal=...&pageSize=200.- Iterar as páginas.
- Para cada pagamento, fazer upsert no destino usando
idPagamento(GUID) como chave única.
A chave idPagamento é um GUID estável: upsert é seguro mesmo se você reexecutar o job. Isso te dá idempotência de graça.
Implementação
- Python
- JavaScript
from datetime import datetime, timedelta, timezone
from banqer_client import paginar
def janela_diaria(dia_referencia=None):
"""Devolve (inicio_iso, fim_iso) do dia anterior em UTC."""
if dia_referencia is None:
dia_referencia = datetime.now(timezone.utc).date()
inicio = datetime.combine(
dia_referencia - timedelta(days=1),
datetime.min.time(),
tzinfo=timezone.utc,
)
fim = inicio + timedelta(days=1)
return inicio.strftime("%Y-%m-%dT%H:%M:%SZ"), fim.strftime("%Y-%m-%dT%H:%M:%SZ")
def baixar_pagamentos_do_dia(upsert_callback):
"""Itera os pagamentos do dia anterior e chama upsert_callback por item."""
inicio, fim = janela_diaria()
print(f"Janela: {inicio} ate {fim}")
contador = 0
for pagamento in paginar("/v1/pagamentos",
params={"dtPagamentoInicial": inicio,
"dtPagamentoFinal": fim},
key="pagamentos"):
upsert_callback(pagamento)
contador += 1
return contador
# Uso com SQLite como destino exemplo
import sqlite3
conn = sqlite3.connect("pagamentos.db")
conn.execute("""
CREATE TABLE IF NOT EXISTS pagamentos (
id_pagamento TEXT PRIMARY KEY,
id_pagamento_exibicao INTEGER,
id_ficha_cobranca TEXT,
data_pagamento TEXT,
valor_pagamento REAL,
id_produto INTEGER,
id_credor INTEGER
)
""")
def upsert(p):
conn.execute("""
INSERT INTO pagamentos VALUES (?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id_pagamento) DO UPDATE SET
valor_pagamento = excluded.valor_pagamento,
data_pagamento = excluded.data_pagamento
""", (
p["idPagamento"], p["idPagamentoExibicao"], p["idFichaCobranca"],
p["dataPagamento"], p["valorPagamento"],
p["idProduto"], p["idCredor"],
))
total = baixar_pagamentos_do_dia(upsert)
conn.commit()
print(f"Total upserted: {total}")
import { paginar } from './banqer-client.mjs';
function janelaDiaria(diaRef = new Date()) {
// Devolve [ontem 00:00 UTC, hoje 00:00 UTC) em ISO 8601.
const fim = new Date(Date.UTC(diaRef.getUTCFullYear(), diaRef.getUTCMonth(), diaRef.getUTCDate()));
const inicio = new Date(fim.getTime() - 24 * 60 * 60 * 1000);
const fmt = (d) => d.toISOString().replace(/\.\d{3}Z$/, 'Z');
return [fmt(inicio), fmt(fim)];
}
export async function baixarPagamentosDoDia(upsertCallback) {
const [inicio, fim] = janelaDiaria();
console.log(`Janela: ${inicio} ate ${fim}`);
let contador = 0;
for await (const pagamento of paginar('/v1/pagamentos', {
dtPagamentoInicial: inicio,
dtPagamentoFinal: fim,
})) {
await upsertCallback(pagamento);
contador++;
}
return contador;
}
// Uso com qualquer banco que suporte upsert (Postgres, SQL Server, etc.)
async function upsert(p) {
await db.query(`
INSERT INTO pagamentos (
id_pagamento, id_pagamento_exibicao, id_ficha_cobranca,
data_pagamento, valor_pagamento, id_produto, id_credor
) VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (id_pagamento) DO UPDATE SET
valor_pagamento = EXCLUDED.valor_pagamento,
data_pagamento = EXCLUDED.data_pagamento
`, [
p.idPagamento, p.idPagamentoExibicao, p.idFichaCobranca,
p.dataPagamento, p.valorPagamento,
p.idProduto, p.idCredor,
]);
}
const total = await baixarPagamentosDoDia(upsert);
console.log(`Total upserted: ${total}`);
Pontos importantes
- Timezone: a API retorna
dataPagamentoem UTC (...Zno final). Se sua planilha ou painel apresenta em fuso local, faça a conversão no seu lado. Não passe filtros de data com offset de fuso: use UTC. - Janela com sobreposição: se quer garantia de não perder nada em caso de falha, faça a janela de N+1 dias e use o upsert por
idPagamentocomo dedupe. Custa pouco a mais e elimina o risco de buraco. - Pagamentos podem ser estornados/ajustados: rerodar o pull do mesmo dia mais tarde pode retornar registros com valor diferente. Por isso o upsert é importante, não o insert puro.
- Volume típico: 1k-10k pagamentos/dia em operações médias. Esse pull roda em poucos segundos.
- Tarja de cobrança: existem três níveis de alocação do pagamento (parcela, contrato, título). Em V1 essa decomposição está disponível em
GET /v1/pagamentos/{id}(chamada separada). Inclua na receita só se sua aplicação precisar.
Quando usar webhook em vez de pull
A API V1 é pull-only. Se você precisa de latência menor que 1 dia, o caminho é reduzir o intervalo do cron (a cada hora, a cada 15 minutos) e aceitar a janela. Webhook push está fora do escopo de V1.