Problemas Comuns¶
Soluções rápidas para os problemas mais frequentes.
Webhook não recebe eventos¶
Sintomas¶
- Nayax envia webhook mas não chega no sistema
- Logs não mostram requisições
Diagnóstico¶
# Verificar se o serviço está rodando
curl http://localhost:3000/health
# Testar webhook manualmente
curl -X POST http://localhost:3000/webhooks/nayax \
-H "Authorization: Bearer SEU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"transactionKey":"test-123","storeCode":"LOJA001",...}'
Soluções¶
-
Firewall bloqueando
-
URL incorreta no Nayax
- Verificar se a URL está correta:
https://seu-dominio.com/webhooks/nayax -
Verificar se tem
/webhooks/nayaxno final -
Token incorreto
Jobs ficam em PENDING¶
Sintomas¶
- Jobs criados mas nunca processados
- Status permanece
PENDING
Diagnóstico¶
-- Ver jobs pendentes
SELECT id, "eventKey", status, "nextRunAt", "createdAt"
FROM "OutboxJob"
WHERE status = 'PENDING'
ORDER BY "createdAt" DESC
LIMIT 10;
Soluções¶
-
JobsProcessor não está rodando
-
nextRunAt no futuro
-
Credenciais Saipos não configuradas
Jobs ficam em PROCESSING¶
Sintomas¶
- Jobs marcados como
PROCESSINGhá muito tempo processingAtcom timestamp antigo
Diagnóstico¶
-- Encontrar jobs travados
SELECT id, "eventKey", "processingAt", "lockedBy"
FROM "OutboxJob"
WHERE status = 'PROCESSING'
AND "processingAt" < NOW() - INTERVAL '5 minutes'
ORDER BY "processingAt";
Soluções¶
- Aguardar o Reaper (automático)
- O reaper roda a cada 20 segundos
-
Reseta jobs
PROCESSING> 2 minutos automaticamente -
Reset manual
-
Verificar se processo morreu
Erro 400: order_id já existe¶
Sintomas¶
Job job_123 DLQ: Request failed with status code 400
Response: {"errorCode":400,"message":"order_id já existe"}
Causa¶
Em ambiente de teste, o mesmo transactionKey está sendo reutilizado.
Soluções¶
- Usar transações de teste
O sistema adiciona timestamp automaticamente quando isTestTransaction: true
-
Gerar transactionKey único
-
Deletar pedido no Saipos (não recomendado)
Erro 401/901/902: Autenticação Saipos¶
Sintomas¶
Diagnóstico¶
-- Verificar credenciais
SELECT "saiposIdPartner", "saiposSecret"
FROM "Restaurant"
WHERE id = 'restaurant_id';
Soluções¶
-
Credenciais expiradas/incorretas
-
Cache de token inválido
-
Ambiente errado
Soma dos pagamentos não fecha¶
Sintomas¶
Causa¶
Diferenças de arredondamento ou pagamentos com valores zero.
Solução¶
O mapper ajusta automaticamente, mas se o problema persistir:
// Verificar se há pagamentos com amount inválido
const payments = ev.payments.filter(p => {
const amount = Number(p?.amount ?? 0);
return isFinite(amount) && amount > 0;
});
Diagnóstico¶
-- Ver evento completo
SELECT *
FROM "NayaxEvent"
WHERE "transactionKey" = 'chave_problema';
-- Ver pagamentos
SELECT *
FROM "Payment"
WHERE "nayaxEventId" = 'event_id';
Jobs vão direto para DLQ¶
Sintomas¶
- Jobs vão para DLQ na primeira tentativa
- Sem retry
Causa¶
Erro HTTP 400 ou 422 (erro permanente)
Diagnóstico¶
-- Ver erro exato
SELECT "eventKey", "lastError"
FROM "OutboxJob"
WHERE status = 'DLQ'
ORDER BY "createdAt" DESC
LIMIT 5;
Soluções baseadas no erro¶
1. "Campo obrigatório ausente"¶
Solução: Verificar evento Nayax e mapper
2. "Código de produto não existe"¶
Solução: Cadastrar produto no Saipos ou mapear código diferente
3. "Loja não encontrada"¶
Solução: Verificar mapeamento
Lentidão no processamento¶
Sintomas¶
- Jobs demoram muito para processar
- Queue depth crescendo
Diagnóstico¶
-- Ver quantidade de jobs pendentes
SELECT status, COUNT(*)
FROM "OutboxJob"
GROUP BY status;
-- Ver jobs mais antigos
SELECT "eventKey", "createdAt", NOW() - "createdAt" as age
FROM "OutboxJob"
WHERE status = 'PENDING'
ORDER BY "createdAt"
LIMIT 10;
Soluções¶
-
Aumentar frequência do cron
-
Aumentar lote de processamento
-
Escalar horizontalmente
- Subir mais instâncias do serviço
-
Lock otimista evita duplicação
-
Otimizar queries
Reprocessar job manualmente¶
Quando usar¶
- Job em DLQ que precisa ser retentado
- Job com erro corrigido
Como fazer¶
-- Resetar job específico
UPDATE "OutboxJob"
SET status = 'PENDING',
"nextRunAt" = NOW(),
attempts = 0,
"lastError" = NULL,
"processingAt" = NULL,
"lockedBy" = NULL
WHERE id = 'job_id';
Reprocessar lote¶
-- Todos os jobs DLQ de uma loja
UPDATE "OutboxJob" o
SET status = 'PENDING',
"nextRunAt" = NOW(),
attempts = 0
FROM "NayaxEvent" e
WHERE o."eventKey" = e."transactionKey"
AND e."storeCode" = 'LOJA001'
AND o.status = 'DLQ';
Queries Úteis de Debug¶
Ver últimos eventos recebidos¶
SELECT "transactionKey", "storeCode", "totalAmount", "transactionDate"
FROM "NayaxEvent"
ORDER BY "transactionDate" DESC
LIMIT 20;
Ver taxa de sucesso¶
SELECT
status,
COUNT(*) as count,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (), 2) as percentage
FROM "OutboxJob"
WHERE "createdAt" > NOW() - INTERVAL '24 hours'
GROUP BY status;
Ver jobs falhando repetidamente¶
SELECT "eventKey", attempts, status, "lastError"
FROM "OutboxJob"
WHERE attempts > 3
ORDER BY attempts DESC
LIMIT 10;
Ver tempo médio de processamento¶
SELECT
AVG(EXTRACT(EPOCH FROM ("updatedAt" - "createdAt"))) as avg_seconds
FROM "OutboxJob"
WHERE status = 'SENT'
AND "createdAt" > NOW() - INTERVAL '1 day';