feat: fetch full order details and format payload
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m19s

This commit is contained in:
Cauê Faleiros
2026-04-09 17:27:42 -03:00
parent bb072af130
commit 246bc03124
2 changed files with 58 additions and 19 deletions

View File

@@ -12,6 +12,7 @@ services:
- N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL}
- TINY_WEBHOOK_SECRET=${TINY_WEBHOOK_SECRET}
- N8N_AUTH_TOKEN=${N8N_AUTH_TOKEN}
- TINY_API_TOKEN=${TINY_API_TOKEN}
# Optional: If you use a shared Docker network for Nginx Proxy Manager, you can attach it here:
# networks:
# - nginx-proxy-manager-network

View File

@@ -1,5 +1,6 @@
import { Request, Response } from 'express';
import { sendToN8n } from '../services/n8n.service';
import axios from 'axios';
export const handleTinyOrderUpdate = async (req: Request, res: Response): Promise<void> => {
try {
@@ -15,39 +16,76 @@ export const handleTinyOrderUpdate = async (req: Request, res: Response): Promis
let payload = req.body;
// Parse 'dados' if it comes as a JSON string
if (typeof payload.dados === 'string') {
try {
payload.dados = JSON.parse(payload.dados);
} catch (e) {
console.error('Could not parse "dados" as JSON string.', e);
}
} catch (e) {}
}
console.log('Received webhook from Tiny:', JSON.stringify(payload, null, 2));
console.log('Received webhook from Tiny. Acknowledging immediately...');
// Acknowledge Tiny immediately
// Acknowledge Tiny immediately to prevent timeouts
res.status(200).send('OK');
if (!payload || Object.keys(payload).length === 0) {
console.warn('Received empty payload from Tiny webhook.');
return;
const orderId = payload?.dados?.id;
if (!orderId) {
console.warn('No order ID found in webhook payload. Cannot fetch details.');
return;
}
const transformedData = {
source: 'tiny_webhook_middleware',
event: payload.tipo || 'atualizacao_pedido',
dados: payload.dados,
raw_payload: payload
const tinyApiToken = process.env.TINY_API_TOKEN;
let fullOrderDetails: any = null;
if (tinyApiToken) {
try {
console.log(`Fetching full details for Order ID: ${orderId} from Tiny API...`);
const params = new URLSearchParams();
params.append('token', tinyApiToken);
params.append('id', orderId);
params.append('formato', 'JSON');
const response = await axios.post('https://api.tiny.com.br/api2/pedido.obter.php', params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
if (response.data?.retorno?.status === 'OK') {
fullOrderDetails = response.data.retorno.pedido;
console.log(`Successfully fetched order details! Found phone: ${fullOrderDetails.cliente?.celular || fullOrderDetails.cliente?.fone || 'None'}`);
} else {
console.error('Tiny API returned an error:', response.data?.retorno?.erros || 'Unknown error');
}
} catch (apiError: any) {
console.error('Failed to fetch from Tiny API:', apiError.message);
}
} else {
console.warn('TINY_API_TOKEN is not set in environment variables. Skipping full details fetch.');
}
// Build the exact flat JSON payload requested by the user
const finalPayload = {
id: fullOrderDetails?.id || payload.dados?.id || "",
numero: fullOrderDetails?.numero || payload.dados?.numero || "",
numero_ecommerce: fullOrderDetails?.numero_ecommerce || payload.dados?.idPedidoEcommerce || "",
data_pedido: fullOrderDetails?.data_pedido || payload.dados?.data || "",
data_prevista: fullOrderDetails?.data_prevista || "",
nome: fullOrderDetails?.cliente?.nome || payload.dados?.cliente?.nome || "",
valor: parseFloat(fullOrderDetails?.valor_pedido || fullOrderDetails?.valor_total || "0"),
id_vendedor: fullOrderDetails?.vendedor?.id || "",
nome_vendedor: fullOrderDetails?.vendedor?.nome || "",
whatsapp_vendedor: "", // Tiny doesn't expose this natively on the order
situacao: fullOrderDetails?.situacao || payload.dados?.descricaoSituacao || "",
fone: fullOrderDetails?.cliente?.celular || fullOrderDetails?.cliente?.telefone || fullOrderDetails?.cliente?.fone || "",
email: fullOrderDetails?.cliente?.email || "",
status_processamento: fullOrderDetails?.status_processamento || "",
forma_envio: fullOrderDetails?.forma_envio || "",
codigo_rastreamento: fullOrderDetails?.codigo_rastreamento || "",
url_rastreamento: fullOrderDetails?.url_rastreamento || ""
};
// Forward to n8n asynchronously
await sendToN8n(transformedData);
console.log('Forwarding formatted payload to n8n...');
await sendToN8n(finalPayload);
} catch (error) {
console.error('Error handling Tiny webhook:', error);
if (!res.headersSent) {
res.status(500).json({ error: 'Internal server error processing webhook.' });
}
}
};