feat: fetch full order details and format payload
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m19s
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m19s
This commit is contained in:
@@ -12,6 +12,7 @@ services:
|
|||||||
- N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL}
|
- N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL}
|
||||||
- TINY_WEBHOOK_SECRET=${TINY_WEBHOOK_SECRET}
|
- TINY_WEBHOOK_SECRET=${TINY_WEBHOOK_SECRET}
|
||||||
- N8N_AUTH_TOKEN=${N8N_AUTH_TOKEN}
|
- 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:
|
# Optional: If you use a shared Docker network for Nginx Proxy Manager, you can attach it here:
|
||||||
# networks:
|
# networks:
|
||||||
# - nginx-proxy-manager-network
|
# - nginx-proxy-manager-network
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { sendToN8n } from '../services/n8n.service';
|
import { sendToN8n } from '../services/n8n.service';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
export const handleTinyOrderUpdate = async (req: Request, res: Response): Promise<void> => {
|
export const handleTinyOrderUpdate = async (req: Request, res: Response): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
@@ -15,39 +16,76 @@ export const handleTinyOrderUpdate = async (req: Request, res: Response): Promis
|
|||||||
|
|
||||||
let payload = req.body;
|
let payload = req.body;
|
||||||
|
|
||||||
// Parse 'dados' if it comes as a JSON string
|
|
||||||
if (typeof payload.dados === 'string') {
|
if (typeof payload.dados === 'string') {
|
||||||
try {
|
try {
|
||||||
payload.dados = JSON.parse(payload.dados);
|
payload.dados = JSON.parse(payload.dados);
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
console.error('Could not parse "dados" as JSON string.', 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');
|
res.status(200).send('OK');
|
||||||
|
|
||||||
if (!payload || Object.keys(payload).length === 0) {
|
const orderId = payload?.dados?.id;
|
||||||
console.warn('Received empty payload from Tiny webhook.');
|
if (!orderId) {
|
||||||
|
console.warn('No order ID found in webhook payload. Cannot fetch details.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const transformedData = {
|
const tinyApiToken = process.env.TINY_API_TOKEN;
|
||||||
source: 'tiny_webhook_middleware',
|
let fullOrderDetails: any = null;
|
||||||
event: payload.tipo || 'atualizacao_pedido',
|
|
||||||
dados: payload.dados,
|
if (tinyApiToken) {
|
||||||
raw_payload: payload
|
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
|
console.log('Forwarding formatted payload to n8n...');
|
||||||
await sendToN8n(transformedData);
|
await sendToN8n(finalPayload);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error handling Tiny webhook:', error);
|
console.error('Error handling Tiny webhook:', error);
|
||||||
if (!res.headersSent) {
|
|
||||||
res.status(500).json({ error: 'Internal server error processing webhook.' });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user