DEV Community

Marcelo Magario
Marcelo Magario

Posted on • Edited on

Desafio de Integração: Conectando um Backend Node.js a um Web Service SOAP (.ASMX)

Olá pessoal!

Hoje quero compartilhar uma experiência de um projeto recente que envolveu um desafio clássico: fazer o novo conversar com o antigo. Especificamente, como consumir um Web Service baseado em SOAP a partir de uma aplicação moderna escrita em Node.js.

Muitas vezes, precisamos integrar nossas aplicações com sistemas legados de clientes ou parceiros, e entender como criar essa ponte é uma habilidade valiosa.

**O Problema de Negócio: Uma Nova Fonte de Dados

De forma resumida, o cenário era o seguinte:

  • A Plataforma: Nós gerenciamos uma plataforma web para um cliente, com o backend construído em Node.js e servindo uma API REST para o frontend.
  • O Cliente: O cliente, uma grande instituição do setor financeiro, armazena e gerencia seus dados em um sistema interno.
  • A Fonte de Dados: Para nos fornecer os dados, o cliente expõe um Web Service ASP.NET (.ASMX), que é uma tecnologia baseada no protocolo SOAP.
  • A Nova Demanda: O cliente precisava exibir uma nova categoria de produtos em seu site. Para isso, eles criaram um novo método dentro do Web Service existente, e nossa tarefa era consumir esse novo método para alimentar a nova página.

Nosso objetivo era criar um novo endpoint em nossa API Node.js (ex: GET /api/produtos/nova-categoria) que, por debaixo dos panos, chamasse o novo método SOAP do cliente, tratasse os dados e os devolvesse em um formato JSON limpo e moderno para o frontend.

A Solução Técnica: Usando node-soap para a Mágica Acontecer

Para interagir com um serviço SOAP em Node.js, a biblioteca mais popular e robusta é a node-soap. Ela faz o trabalho pesado de analisar o arquivo WSDL (Web Services Description Language) do serviço, permitindo que a gente chame os métodos remotos como se fossem funções JavaScript comuns.

Vamos ao passo a passo da implementação.

Passo 1: Estruturando o Novo Endpoint na API

A primeira parte é simples: definir a rota em nossa aplicação Express.js. Isso expõe um novo caminho que nosso frontend poderá chamar.

// Em algum arquivo de rotas, como 'productRoutes.js' const express = require('express'); const router = express.Router(); // Importamos nosso "service", que conterá a lógica de negócio const productService = require('../services/productService'); // Quando uma requisição GET chegar em '/products/new-category', // a função fetchNewCategoryData será chamada. router.get('/products/new-category', productService.fetchNewCategoryData); module.exports = router; 
Enter fullscreen mode Exit fullscreen mode

Passo 2: Criando o Cliente SOAP

Agora, no arquivo productService.js, é onde a mágica acontece. O primeiro passo é usar a node-soap para se conectar ao Web Service do cliente.

const soap = require('soap'); const config = require('../config'); // Arquivo com nossas configurações // A URL do Web Service do cliente, geralmente terminando em .asmx?WSDL const wsdlUrl = config.clientWebService.productsUrl; async function fetchNewCategoryData(req, res, next) { try { // 1. Cria um cliente SOAP a partir da URL do WSDL const client = await soap.createClientAsync(wsdlUrl); // Se chegou aqui, a conexão foi bem-sucedida e o WSDL foi analisado. // O próximo passo é chamar o método que precisamos. } catch (err) { // É crucial tratar erros aqui! O serviço do cliente pode estar fora do ar. console.error('Falha ao conectar com o Web Service SOAP:', err); res.status(500).json({ message: 'Serviço externo indisponível.' }); } } 
Enter fullscreen mode Exit fullscreen mode

Passo 3: Chamando o Método Específico e Tratando a Resposta

Com o client criado, podemos ver todos os métodos disponíveis e chamar o que foi criado para nós. Vamos chamá-lo de GetNewProductData em nosso exemplo.

As respostas de serviços SOAP .NET costumam vir em uma estrutura XML bem aninhada. A biblioteca node-soap converte isso para um objeto JSON, mas a estrutura aninhada permanece. É nosso trabalho navegar por esse objeto para encontrar os dados de que precisamos.

// ... continuação da função fetchNewCategoryData try { // 2. Chama o método remoto específico (Ex: 'GetNewProductData') // O primeiro argumento é um objeto com os parâmetros que o método espera. // Neste caso, ele não esperava nenhum. const result = await client.GetNewProductDataAsync({}); // 3. Navega na estrutura complexa da resposta para encontrar a lista de dados. // Este caminho pode variar, mas é comum em serviços .NET. const rawDataArray = result[0].GetNewProductDataResult.diffgram.NewDataSet.Table; // 4. Formata os dados para o padrão da nossa API const formattedData = rawDataArray.map(formatProductData); res.status(200).json(formattedData); } catch (err) { console.error('Falha ao chamar o método ou processar a resposta:', err); res.status(500).json({ message: 'Erro ao obter dados do serviço externo.' }); } // Função auxiliar para deixar os dados mais limpos function formatProductData(productFromSoap) { return { id: productFromSoap.ID_PRODUTO, name: productFromSoap.NOME_PRODUTO, category: productFromSoap.CATEGORIA, // ... e assim por diante, transformando os nomes e valores conforme necessário }; } 
Enter fullscreen mode Exit fullscreen mode

Desafios e Aprendizados

**- Estruturas de Dados: **O maior desafio foi entender a estrutura exata da resposta SOAP. O console.log(result) e ferramentas como o Postman ou SoapUI são seus melhores amigos para inspecionar e entender como navegar no objeto de resposta.

- Comunicação é Chave: A troca de e-mails com a equipe técnica do cliente foi fundamental. Sem uma comunicação clara sobre qual era o nome do novo método e qual a estrutura de dados esperada, o trabalho seria impossível.

**- Error Handling Robusto: **Em integrações, tudo pode dar errado: a rede pode falhar, o serviço do cliente pode estar fora do ar, ou a estrutura dos dados pode mudar inesperadamente. Envolver a lógica em blocos try...catch e prever cenários de falha é essencial para a estabilidade da sua aplicação.

Top comments (0)