Configuração¶
Guia completo de configuração da integração Nayax → Saipos.
Variáveis de Ambiente¶
Arquivo .env¶
Todas as configurações são gerenciadas através de variáveis de ambiente no arquivo .env:
# =============================================================================
# DATABASE
# =============================================================================
DATABASE_URL="postgresql://usuario:senha@localhost:5432/nayax_saipos?schema=public"
# =============================================================================
# SERVER
# =============================================================================
PORT=3000
NODE_ENV=development
# =============================================================================
# JWT (Autenticação de Usuários)
# =============================================================================
JWT_SECRET="sua_chave_secreta_jwt_muito_forte_aqui"
JWT_EXPIRES_IN="7d"
# =============================================================================
# NAYAX (Webhook)
# =============================================================================
NAYAX_BEARER_TOKEN="token_fornecido_pelo_nayax"
# =============================================================================
# SAIPOS (API Destino)
# =============================================================================
# Homologação
SAIPOS_BASE="https://homolog-order-api.saipos.com"
# Produção
# SAIPOS_BASE="https://order-api.saipos.com"
# =============================================================================
# JOBS (Processamento Assíncrono)
# =============================================================================
PROCESSING_TTL_MS=120000
LOG_SAIPOS_BODY=false
# =============================================================================
# LOGGING
# =============================================================================
LOG_LEVEL=debug
Variáveis Obrigatórias¶
| Variável | Descrição | Exemplo |
|---|---|---|
DATABASE_URL | String de conexão PostgreSQL | postgresql://user:pass@localhost:5432/db |
JWT_SECRET | Chave secreta para JWT | minha_chave_super_secreta_123 |
Variáveis Opcionais¶
| Variável | Padrão | Descrição |
|---|---|---|
PORT | 3000 | Porta do servidor |
NODE_ENV | development | Ambiente (development, staging, production) |
JWT_EXPIRES_IN | 7d | Tempo de expiração do JWT |
SAIPOS_BASE | (homolog) | URL base da API Saipos |
PROCESSING_TTL_MS | 120000 | Tempo máximo de processamento (ms) |
LOG_SAIPOS_BODY | false | Logar corpo das requisições Saipos |
LOG_LEVEL | info | Nível de log (debug, info, warn, error) |
Configuração do Banco de Dados¶
1. Criar Database¶
-- Conectar como postgres
psql -U postgres
-- Criar database
CREATE DATABASE nayax_saipos
WITH
OWNER = postgres
ENCODING = 'UTF8'
LC_COLLATE = 'pt_BR.UTF-8'
LC_CTYPE = 'pt_BR.UTF-8'
TEMPLATE = template0;
-- Criar usuário (produção)
CREATE USER nayax_user WITH PASSWORD 'senha_forte_aqui';
GRANT ALL PRIVILEGES ON DATABASE nayax_saipos TO nayax_user;
-- Sair
\q
2. Executar Migrations¶
# Aplicar migrations
npx prisma migrate deploy
# Ou em dev (cria nova migration se necessário)
npx prisma migrate dev --name init
3. Verificar Schema¶
# Abrir Prisma Studio
npx prisma studio
# Ou via psql
psql -U postgres -d nayax_saipos
# Listar tabelas
\dt
# Ver schema de uma tabela
\d "User"
4. Popular com Dados Iniciais (Seed)¶
O seed cria:
- Usuário admin:
- Email:
admin@example.com - Senha:
admin123 -
Role:
OWNER -
Configurações:
NAYAX_BEARER_TOKENSAIPOS_BASE-
PROCESSING_TTL_MS -
Restaurante exemplo (apenas dev):
- Nome: "Restaurante Teste"
- Slug: "restaurante-teste"
Alterar senha padrão
Em produção, sempre altere a senha do usuário admin após o primeiro login.
Configuração por Restaurante¶
Cada restaurante precisa ser configurado com suas credenciais Saipos:
Via SQL¶
-- Atualizar credenciais Saipos
UPDATE "Restaurant"
SET
"codeStoreNayax" = 'LOJA001', -- Código no Nayax
"codeStoreSaipos" = 'LOJA_SAIPOS_001', -- Código no Saipos
"saiposIdPartner" = 'partner_123', -- ID do parceiro
"saiposSecret" = 'secret_xyz' -- Chave secreta
WHERE slug = 'restaurante-teste';
Via API (recomendado)¶
# Criar restaurante
curl -X POST http://localhost:3000/restaurants \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Meu Restaurante",
"slug": "meu-restaurante",
"codeStoreSaipos": "LOJA_SAIPOS_001",
"saiposIdPartner": "partner_123",
"saiposSecret": "secret_xyz"
}'
# Atualizar credenciais
curl -X PATCH http://localhost:3000/restaurants/{id} \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"saiposIdPartner": "novo_partner",
"saiposSecret": "novo_secret"
}'
Configuração do Webhook Nayax¶
1. Obter URL do Webhook¶
2. Configurar no Painel Nayax¶
Acesse o painel administrativo do Nayax e configure:
URL do Webhook: https://seu-dominio.com/webhooks/nayax
Método: POST
Headers:
Eventos: Selecione "Transaction Complete" ou "All Events"
3. Testar Webhook¶
# Teste manual
curl -X POST http://localhost:3000/webhooks/nayax \
-H "Authorization: Bearer $NAYAX_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"transactionKey": "test-'$(date +%s)'",
"transactionNumber": "TEST123",
"transactionDate": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"storeCode": "LOJA001",
"posCode": "POS01",
"totalAmount": 10.00,
"isTestTransaction": true,
"items": [{
"itemCode": "PROD001",
"itemName": "Café",
"quantity": 1,
"price": 10.00
}],
"payments": [{
"tenderType": 1,
"tenderName": "Dinheiro",
"amount": 10.00
}]
}'
Resposta esperada (200 OK):
Configuração do Saipos¶
1. Obter Credenciais¶
Entre em contato com o suporte Saipos para obter:
- idPartner: ID do parceiro
- secret: Chave secreta
- cod_store: Código da loja no Saipos
2. Testar Conexão¶
# Teste de autenticação
curl -X POST https://homolog-order-api.saipos.com/auth \
-H "id-partner: $ID_PARTNER" \
-H "secret: $SECRET" \
-H "Content-Type: application/json"
3. Ambientes¶
| Ambiente | URL Base | Uso |
|---|---|---|
| Homologação | https://homolog-order-api.saipos.com | Desenvolvimento e testes |
| Produção | https://order-api.saipos.com | Produção |
Ambiente de testes
Use sempre homologação durante desenvolvimento. Mude para produção apenas após testes completos.
Configuração de Logs¶
Níveis de Log¶
Configure via LOG_LEVEL:
Logs Detalhados do Saipos¶
Exemplo de log:
[SAIPOS][CREATE] Request body:
{
"order_id": "550e8400-...",
"cod_store": "LOJA_001",
"total_amount": 50.00,
"items": [...]
}
Performance
Nunca use LOG_SAIPOS_BODY=true em produção - gera logs muito grandes.
Configuração de Jobs¶
TTL de Processamento¶
Tempo máximo que um job pode ficar em PROCESSING:
Após esse tempo, o Reaper reseta o job para FAILED.
Backoff de Retry¶
O backoff é hardcoded mas pode ser ajustado editando src/jobs/jobs.processor.ts:
function backoffMs(attempts: number) {
const table = [
30_000, // 30s - tentativa 1
120_000, // 2min - tentativa 2
300_000, // 5min - tentativa 3
900_000, // 15min - tentativa 4
1_800_000, // 30min - tentativa 5
3_600_000 // 60min - tentativa 6+
];
const base = table[Math.min(attempts - 1, table.length - 1)];
const jitter = Math.floor(base * (Math.random() * 0.4 - 0.2));
return base + jitter;
}
Configuração de Segurança¶
JWT Secret¶
Gere uma chave forte:
# Gerar secret aleatório
node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
# Ou usando openssl
openssl rand -hex 64
Adicione no .env:
Senha do Admin¶
Após seed, altere a senha do admin:
-- Gerar hash bcrypt manualmente (10 rounds)
-- Senha: nova_senha_forte
UPDATE "User"
SET "passwordHash" = '$2b$10$...' -- Use bcrypt para gerar
WHERE email = 'admin@example.com';
Ou via API:
curl -X PATCH http://localhost:3000/users/me/password \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"currentPassword": "admin123",
"newPassword": "nova_senha_forte"
}'
Configuração de CORS¶
Edite src/main.ts para permitir origens específicas:
app.enableCors({
origin: [
'https://seu-frontend.com',
'https://admin.seu-dominio.com'
],
credentials: true,
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
});
Configuração de Rate Limiting¶
Para proteger o webhook, adicione rate limiting:
// src/app.module.ts
import { ThrottlerModule } from '@nestjs/throttler';
@Module({
imports: [
ThrottlerModule.forRoot([{
ttl: 60000, // 1 minuto
limit: 100, // 100 requisições
}])
]
})
Verificar Configuração¶
Checklist¶
-
.envcriado com todas as variáveis - Database criada e migrations aplicadas
- Seed executado (dados iniciais)
- Webhook Nayax configurado
- Credenciais Saipos testadas
- Restaurante(s) configurado(s)
- JWT secret forte gerado
- Senha admin alterada (produção)
- Logs configurados corretamente
- CORS configurado (se necessário)
Script de Verificação¶
#!/bin/bash
echo "🔍 Verificando configuração..."
# 1. Variáveis obrigatórias
if [ -z "$DATABASE_URL" ]; then
echo "❌ DATABASE_URL não configurada"
else
echo "✅ DATABASE_URL configurada"
fi
if [ -z "$JWT_SECRET" ]; then
echo "❌ JWT_SECRET não configurada"
else
echo "✅ JWT_SECRET configurada"
fi
if [ -z "$NAYAX_BEARER_TOKEN" ]; then
echo "❌ NAYAX_BEARER_TOKEN não configurada"
else
echo "✅ NAYAX_BEARER_TOKEN configurada"
fi
# 2. Banco de dados
psql $DATABASE_URL -c "SELECT 1;" > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "✅ Conexão com banco OK"
else
echo "❌ Erro ao conectar no banco"
fi
# 3. Aplicação
curl -s http://localhost:3000/health > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "✅ Aplicação rodando"
else
echo "❌ Aplicação não está rodando"
fi
echo "✨ Verificação completa!"
Configurações Avançadas¶
Multi-tenant Isolation¶
Para isolar dados entre restaurantes, use Row Level Security (RLS) no PostgreSQL:
-- Habilitar RLS
ALTER TABLE "NayaxEvent" ENABLE ROW LEVEL SECURITY;
-- Criar policy
CREATE POLICY restaurant_isolation ON "NayaxEvent"
USING ("restaurantId" = current_setting('app.restaurant_id')::uuid);
Cache de Tokens¶
Para melhorar performance, implemente cache de tokens Saipos usando Redis:
Monitoramento¶
Configure variáveis para integração com ferramentas:
# Sentry
SENTRY_DSN="https://...@sentry.io/..."
# DataDog
DD_API_KEY="..."
DD_SITE="datadoghq.com"
# Prometheus
METRICS_PORT=9090
Próximos Passos¶
Configuração completa! Agora faça o primeiro deploy: