Handle Evolution LID replies in bridge

This commit is contained in:
Tiago
2026-09-29 16:29:18 -03:00
parent 61964ea05a
commit 2d2b55128a
2 changed files with 15 additions and 1 deletions
@@ -80,6 +80,7 @@ public final class Main {
router.post("/api/auth/login", authHandlers.funcionarioLogin());
router.post("/api/master/webhooks/abacatepay", abacatePayWebhookHandler);
router.post("/api/webhooks/evolution/respostas", externalBridgeHandler);
router.prefix("/api/webhooks/evolution/respostas/", externalBridgeHandler);
router.post("/api/integracao/mensagens", authMiddleware.exigirApiKey(externalBridgeHandler));
router.prefix("/api/master/", authMiddleware.exigirMaster(masterHandlers));
router.prefix("/api/financeiro/", authMiddleware.exigirFuncionario(financeiroHandlers));
@@ -45,6 +45,7 @@ public final class ExternalBridgeHandler implements HttpHandler {
try {
route(ex);
} catch (IllegalArgumentException e) {
System.err.println("Webhook/integracao rejeitado: " + e.getMessage());
HttpResponses.json(ex, 400, Map.of("erro", "requisicao_invalida", "mensagem", e.getMessage()));
} catch (Exception e) {
e.printStackTrace(System.err);
@@ -59,7 +60,7 @@ public final class ExternalBridgeHandler implements HttpHandler {
enviarMensagem(ex, (long) ex.getAttribute(AuthMiddleware.ATTR_EMPRESA_ID));
return;
}
if ("/api/webhooks/evolution/respostas".equals(path) && "POST".equals(method)) {
if ((path.equals("/api/webhooks/evolution/respostas") || path.startsWith("/api/webhooks/evolution/respostas/")) && "POST".equals(method)) {
receberRespostaEvolution(ex);
return;
}
@@ -105,20 +106,30 @@ public final class ExternalBridgeHandler implements HttpHandler {
private void receberRespostaEvolution(HttpExchange ex) throws Exception {
validarWebhookEvolution(ex);
String raw = rawBody(ex);
if (isFromMe(raw)) {
HttpResponses.json(ex, 200, Map.of("ok", true, "encaminhado", false, "motivo", "mensagem_enviada_pelo_sistema"));
return;
}
String numero = telefoneWhatsapp(firstNonBlank(extract(raw, "remoteJidAlt"), extract(raw, "remoteJid"), extract(raw, "from"), extract(raw, "number"), extract(raw, "sender")));
String texto = firstNonBlank(extract(raw, "conversation"), extract(raw, "text"), extract(raw, "body"), extract(raw, "message"));
if (numero.isBlank()) {
System.err.println("Webhook Evolution sem numero identificavel. Payload inicial: " + raw.substring(0, Math.min(raw.length(), 500)));
HttpResponses.json(ex, 400, Map.of("erro", "numero_nao_identificado"));
return;
}
try (Connection c = masterDs.getMasterConnection()) {
Map<String,Object> envio = one(c, "SELECT * FROM integracao_mensagens WHERE telefone=? AND callback_url IS NOT NULL AND status='enviado' ORDER BY criado_em DESC,id DESC LIMIT 1", numero);
if (envio == null && raw.contains("@lid")) {
envio = one(c, "SELECT * FROM integracao_mensagens WHERE callback_url IS NOT NULL AND status='enviado' AND criado_em >= now() - interval '24 hours' ORDER BY criado_em DESC,id DESC LIMIT 1");
}
if (envio == null) {
System.out.println("Webhook Evolution sem envio correspondente. numero=" + numero + ", texto=" + resumo(texto));
HttpResponses.json(ex, 200, Map.of("ok", true, "encaminhado", false, "motivo", "envio_nao_encontrado"));
return;
}
long respostaId = registrarResposta(c, ((Number)envio.get("id")).longValue(), raw, texto);
boolean encaminhado = encaminharCallback(envio, respostaId, numero, texto);
System.out.println("Webhook Evolution resposta registrada. mensagem_id=" + envio.get("id") + ", resposta_id=" + respostaId + ", numero=" + numero + ", encaminhado=" + encaminhado);
HttpResponses.json(ex, 200, Map.of("ok", true, "encaminhado", encaminhado, "mensagem_id", envio.get("id"), "resposta_id", respostaId));
}
}
@@ -255,6 +266,8 @@ public final class ExternalBridgeHandler implements HttpHandler {
private String emptyToNull(String v){return v==null||v.isBlank()?null:v;}
private String firstNonBlank(String... values){for(String v:values)if(v!=null&&!v.isBlank())return v;return "";}
private String extract(String raw,String key){String marker="\""+key+"\"";int p=raw.indexOf(marker);if(p<0)return null;int colon=raw.indexOf(':',p);if(colon<0)return null;int q=raw.indexOf('"',colon+1);int e=q<0?-1:raw.indexOf('"',q+1);if(q<0||e<0)return null;return raw.substring(q+1,e).split("@")[0];}
private boolean isFromMe(String raw){String marker="\"fromMe\"";int p=raw.indexOf(marker);if(p<0)return false;int colon=raw.indexOf(':',p);if(colon<0)return false;String tail=raw.substring(colon+1,Math.min(raw.length(),colon+12)).trim();return tail.startsWith("true");}
private String resumo(String value){if(value==null)return "";return value.length()>120?value.substring(0,120):value;}
private record Destinatario(String tipo,long id,String nome,String telefone){}
private record ApiKeyConfig(String sistemaExterno,String callbackUrl,String callbackSecret){}
}