/** * Certa Fiscal — exemplo de integração em Node.js 18+ (fetch nativo). * * Uso: node certafiscal-exemplo.js cf_test_SUACHAVE ULID_DA_EMPRESA * * Demonstra: Bearer, Idempotency-Key (retry nunca duplica), X-Correlation-Id, * retry com backoff p/ 429/5xx e leitura dos achados. */ const BASE_URL = 'http://127.0.0.1:8000/api/v1'; // produção: https://.../api/v1 const [apiKey, empresaId] = process.argv.slice(2); if (!apiKey || !empresaId) { console.error('Uso: node certafiscal-exemplo.js '); process.exit(2); } const dormir = (ms) => new Promise((r) => setTimeout(r, ms)); async function chamar(metodo, caminho, corpo, idempotencyKey = '') { for (let tentativa = 1; tentativa <= 4; tentativa++) { const headers = { Accept: 'application/json', Authorization: `Bearer ${apiKey}`, 'X-Correlation-Id': crypto.randomUUID(), }; if (corpo) headers['Content-Type'] = 'application/json'; if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey; let status = 0; let json = null; try { const resp = await fetch(BASE_URL + caminho, { method: metodo, headers, body: corpo ? JSON.stringify(corpo) : undefined, signal: AbortSignal.timeout(30_000), }); status = resp.status; json = await resp.json().catch(() => null); } catch { status = 0; // falha de rede } // 401/403/422 = erro de configuração/dados: devolve sem repetir. const repetir = (status === 0 || status === 429 || status >= 500) && tentativa < 4; if (!repetir) return { status, json }; const espera = 1000 * 2 ** (tentativa - 1); // 1s, 2s, 4s — MESMA chave console.error(`HTTP ${status} — repetindo em ${espera / 1000}s...`); await dormir(espera); } } (async () => { const health = await chamar('GET', '/health'); if (health.status !== 200) { console.error(`API indisponível (HTTP ${health.status})`); process.exit(3); } console.log('Health-check: OK'); const { status, json } = await chamar('POST', '/analyses/operation', { company_id: empresaId, origin_uf: 'RS', destination_uf: 'SC', ncm: '22021000', cest: '0301100', cfop: '6102', csosn: '102', value: 1500.0, product_description: 'Refrigerante Cola 2 L (exemplo Node.js)', }, `pedido-${crypto.randomUUID()}`); // no ERP: ID do teu registro if (status !== 200 && status !== 201) { console.error(`Erro HTTP ${status}:`, json?.error?.message ?? json); process.exit(1); } const dados = json.data; console.log(`Análise ${dados.reference} | risco=${dados.risk_level} | pontuação=${dados.score} | motor=${dados.engine_version}`); let bloquear = false; for (const achado of dados.findings) { console.log(` [${achado.severity} ${achado.rule_code}] ${achado.title} (confiança ${achado.confidence}%)`); console.log(` Sugestão: ${achado.suggestion}`); if (achado.severity === 'high' || achado.severity === 'critical') bloquear = true; } console.log(bloquear ? 'VEREDITO: NÃO emitir — corrigir os achados primeiro.' : 'VEREDITO: liberado para emitir.'); })();