Pagamentos via Terminais

Transações

Como gerenciar transações via API

A API da Nuvende permite o gerenciamento completo de transações de pagamento, incluindo criação, consulta, atualização e exclusão. As transações representam operações de pagamento realizadas através dos terminais e são fundamentais para qualquer sistema de pagamentos.

Conceitos Fundamentais

O que são Transações?

Transações são operações de pagamento realizadas através dos terminais, podendo incluir pagamentos com cartão de crédito, cartão de débito, Pix, voucher ou vale. Cada transação possui um identificador único (UUID) e está associada a um terminal específico, permitindo rastreamento completo do fluxo de pagamento.

Por que as Transações são Importantes?

As transações são o coração de qualquer sistema de pagamentos, pois:

  • Registram o Fluxo de Dinheiro: Cada transação representa uma movimentação financeira real
  • Permitem Rastreamento: Com identificadores únicos, é possível acompanhar todo o ciclo de vida do pagamento
  • Facilitam Auditoria: Histórico completo de todas as operações para fins de compliance
  • Habilitam Relatórios: Dados estruturados para análise de vendas e performance
  • Garantem Transparência: Cliente e comerciante têm visibilidade completa da operação

Funcionalidades Disponíveis

  • Listar Transações: Consultar todas as transações realizadas com paginação
  • Criar Transação: Processar nova transação de pagamento em tempo real
  • Exibir Transação: Consultar detalhes completos de transação específica
  • Atualizar Transação: Modificar dados de transação existente quando necessário
  • Excluir Transação: Cancelar ou excluir transação em casos específicos

Implementação Técnica

Endpoints Disponíveis

Baseado na especificação OpenAPI da Nuvende:

  • GET /api/v1/pagamentos/transactions - Listar todas as transações com paginação
  • POST /api/v1/pagamentos/transactions - Criar nova transação de pagamento
  • GET /api/v1/pagamentos/transactions/{id} - Exibir detalhes de transação específica
  • PUT /api/v1/pagamentos/transactions/{id} - Atualizar dados de transação existente
  • DELETE /api/v1/pagamentos/transactions/{id} - Excluir transação do sistema

Estrutura de Dados

Headers Obrigatórios

Authorization: Bearer {access_token}
Content-Type: application/json
Accept: application/json

Estrutura Completa de Transação

{
  "id": "string (UUID)",
  "status": "string",
  "payment_method": "string",
  "type": "string",
  "installments": "number",
  "merchant_code": "string|null",
  "transaction_identifier": "string|null",
  "authorization": "string|null",
  "customer_name": "string",
  "customer_identifier": "string",
  "value": "string",
  "discount_value": "string",
  "net_value": "string",
  "external_id": "string",
  "url": "string",
  "terminal_id": "string (UUID)",
  "payment_date": "datetime",
  "created_at": "datetime",
  "updated_at": "datetime"
}

Explicação Detalhada dos Campos

  • id: Identificador único da transação no sistema Nuvende (UUID)
  • status: Status atual da transação (pending, approved, rejected, cancelled)
  • payment_method: Método utilizado (credit, debit, pix, voucher, vale)
  • type: Tipo da transação (payment)
  • installments: Número de parcelas
  • merchant_code: Código do comerciante (pode ser null)
  • transaction_identifier: Identificador da transação (pode ser null)
  • authorization: Código de autorização (pode ser null)
  • customer_name: Nome do cliente
  • customer_identifier: Identificador do cliente (UUID)
  • value: Valor da transação em formato string
  • discount_value: Valor do desconto em formato string
  • net_value: Valor líquido em formato string
  • external_id: ID externo da transação
  • url: URL do webhook
  • terminal_id: ID do terminal que processou a transação (UUID)
  • payment_date: Data e hora do pagamento
  • created_at: Data e hora de criação da transação
  • updated_at: Data e hora da última atualização

Implementação em Código

Classe de Gerenciamento de Transações

const axios = require('axios');

class TransacaoService {
  constructor(baseUrl, accessToken) {
    this.baseUrl = baseUrl;
    this.accessToken = accessToken;
  }

  /**
   * Lista todas as transações com paginação
   * @param {Object} filtros - Filtros de busca (opcional)
   * @returns {Promise<Object>} Lista paginada de transações
   */
  async listarTransacoes(filtros = {}) {
    try {
      console.log('Iniciando listagem de transações...');
      console.log('Filtros aplicados:', filtros);
      
      const response = await axios.get(`${this.baseUrl}/api/v1/pagamentos/transactions`, {
        headers: {
          'Authorization': `Bearer ${this.accessToken}`,
          'Accept': 'application/json'
        },
        params: filtros
      });

      console.log(`✅ ${response.data.data.length} transações encontradas`);
      console.log('Primeira transação:', response.data.data[0] || 'Nenhuma transação encontrada');
      
      return response.data;
      
    } catch (error) {
      console.error('❌ Erro ao listar transações:', error.response?.data || error.message);
      throw this.tratarErro(error);
    }
  }

  /**
   * Cria uma nova transação de pagamento
   * @param {Object} dadosTransacao - Dados completos da transação
   * @returns {Promise<Object>} Transação criada com sucesso
   */
  async criarTransacao(dadosTransacao) {
    try {
      console.log('Iniciando criação de transação...');
      console.log('Dados da transação:', {
        terminal_id: dadosTransacao.terminal_id,
        value: dadosTransacao.value,
        payment_method: dadosTransacao.payment_method
      });
      
      // Validar dados antes de enviar
      const validacao = this.validarDadosTransacao(dadosTransacao);
      if (!validacao.valido) {
        throw new Error(`Dados inválidos: ${validacao.erros.join(', ')}`);
      }
      
      const response = await axios.post(`${this.baseUrl}/api/v1/pagamentos/transactions`, dadosTransacao, {
        headers: {
          'Authorization': `Bearer ${this.accessToken}`,
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      });

      console.log('✅ Transação criada com sucesso');
      console.log('ID da transação:', response.data.id);
      console.log('Status:', response.data.status);
      
      return response.data;
      
    } catch (error) {
      console.error('❌ Erro ao criar transação:', error.response?.data || error.message);
      throw this.tratarErro(error);
    }
  }

  /**
   * Exibe detalhes completos de uma transação específica
   * @param {string} id - ID único da transação (UUID)
   * @returns {Promise<Object>} Dados completos da transação
   */
  async exibirTransacao(id) {
    try {
      console.log(`Buscando detalhes da transação: ${id}`);
      
      const response = await axios.get(`${this.baseUrl}/api/v1/pagamentos/transactions/${id}`, {
        headers: {
          'Authorization': `Bearer ${this.accessToken}`,
          'Accept': 'application/json'
        }
      });

      console.log('✅ Transação encontrada');
      console.log('Status atual:', response.data.status);
      console.log('Valor:', response.data.value);
      console.log('Método de pagamento:', response.data.payment_method);
      
      return response.data;
      
    } catch (error) {
      console.error('❌ Erro ao exibir transação:', error.response?.data || error.message);
      throw this.tratarErro(error);
    }
  }

  /**
   * Atualiza dados de uma transação existente
   * @param {string} id - ID da transação a ser atualizada (UUID)
   * @param {Object} dadosAtualizacao - Novos dados para a transação
   * @returns {Promise<Object>} Transação atualizada
   */
  async atualizarTransacao(id, dadosAtualizacao) {
    try {
      console.log(`Atualizando transação: ${id}`);
      console.log('Dados de atualização:', dadosAtualizacao);
      
      const response = await axios.put(`${this.baseUrl}/api/v1/pagamentos/transactions/${id}`, dadosAtualizacao, {
        headers: {
          'Authorization': `Bearer ${this.accessToken}`,
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        }
      });

      console.log('✅ Transação atualizada com sucesso');
      console.log('Novo status:', response.data.status);
      
      return response.data;
      
    } catch (error) {
      console.error('❌ Erro ao atualizar transação:', error.response?.data || error.message);
      throw this.tratarErro(error);
    }
  }

  /**
   * Exclui uma transação do sistema
   * @param {string} id - ID da transação a ser excluída (UUID)
   * @returns {Promise<Object>} Confirmação da exclusão
   */
  async excluirTransacao(id) {
    try {
      console.log(`Excluindo transação: ${id}`);
      
      const response = await axios.delete(`${this.baseUrl}/api/v1/pagamentos/transactions/${id}`, {
        headers: {
          'Authorization': `Bearer ${this.accessToken}`
        }
      });

      console.log('✅ Transação excluída com sucesso');
      
      return response.data;
      
    } catch (error) {
      console.error('❌ Erro ao excluir transação:', error.response?.data || error.message);
      throw this.tratarErro(error);
    }
  }

  /**
   * Valida dados de transação de forma completa
   * @param {Object} dados - Dados a serem validados
   * @returns {Object} Resultado detalhado da validação
   */
  validarDadosTransacao(dados) {
    const erros = [];

    console.log('Iniciando validação de dados da transação...');

    // Validação do terminal_id
    if (!dados.terminal_id || dados.terminal_id.trim().length === 0) {
      erros.push('ID do terminal é obrigatório - toda transação deve estar associada a um terminal');
    }

    // Validação do valor
    if (!dados.value) {
      erros.push('Valor é obrigatório - informe o valor da transação');
    } else if (typeof dados.value !== 'string') {
      erros.push('Valor deve ser uma string - use formato decimal (ex: "100.50")');
    }

    // Validação do método de pagamento
    if (!dados.payment_method || dados.payment_method.trim().length === 0) {
      erros.push('Método de pagamento é obrigatório');
    } else {
      const metodosPermitidos = ['credit', 'debit', 'pix', 'voucher', 'vale'];
      if (!metodosPermitidos.includes(dados.payment_method.toLowerCase())) {
        erros.push(`Método de pagamento deve ser um dos seguintes: ${metodosPermitidos.join(', ')}`);
      }
    }

    // Validação do external_id
    if (!dados.external_id || dados.external_id.trim().length === 0) {
      erros.push('ID externo é obrigatório');
    }

    // Validação do customer_name
    if (!dados.customer_name || dados.customer_name.trim().length === 0) {
      erros.push('Nome do cliente é obrigatório');
    }

    // Validação do customer_identifier
    if (!dados.customer_identifier || dados.customer_identifier.trim().length === 0) {
      erros.push('Identificador do cliente é obrigatório');
    }

    const resultado = {
      valido: erros.length === 0,
      erros: erros
    };

    console.log(`Validação concluída: ${erros.length} erros`);
    
    return resultado;
  }

  /**
   * Trata erros da API de forma didática e informativa
   * @param {Error} error - Erro capturado
   * @returns {Error} Erro tratado com informações claras
   */
  tratarErro(error) {
    const status = error.response?.status;
    const data = error.response?.data;

    console.log('Tratando erro da API...');
    console.log('Status HTTP:', status);
    console.log('Dados do erro:', data);

    switch (status) {
      case 400:
        return new Error(`Dados inválidos enviados: ${data?.message || 'Verifique os parâmetros enviados e tente novamente'}`);
      case 401:
        return new Error('Token de acesso inválido ou expirado - faça login novamente');
      case 403:
        return new Error('Permissões insuficientes para gerenciar transações - verifique suas credenciais');
      case 404:
        return new Error('Transação não encontrada - verifique o ID fornecido');
      case 422:
        return new Error(`Dados não processáveis: ${data?.message || 'Verifique o formato dos dados enviados'}`);
      case 429:
        return new Error('Muitas requisições - aguarde um momento antes de tentar novamente');
      case 500:
        return new Error('Erro interno do servidor - tente novamente mais tarde ou entre em contato com o suporte');
      default:
        return new Error(`Erro inesperado: ${error.message} - entre em contato com o suporte técnico`);
    }
  }
}

// Exemplo de uso prático
async function exemploCompletoGerenciamentoTransacoes() {
  console.log('🚀 Iniciando exemplo completo de gerenciamento de transações');
  
  const transacaoService = new TransacaoService(
    'https://api-h.nuvende.com.br',
    'seu_access_token_aqui'
  );

  try {
    // 1. Listar transações existentes
    console.log('\n📋 Passo 1: Listando transações existentes...');
    const transacoes = await transacaoService.listarTransacoes();
    console.log(`Encontradas ${transacoes.data.length} transações`);

    // 2. Criar nova transação
    console.log('\n💳 Passo 2: Criando nova transação...');
    const novaTransacao = await transacaoService.criarTransacao({
      type: 'payment',
      installments: 1,
      external_id: 'ext-12345',
      terminal_id: '32a080cb-eb8a-4a51-9e6b-d1e2d22cbdb9',
      payment_date: '2024-12-24T14:15:22Z',
      payment_method: 'credit',
      merchant_id: '9dd1b184-a167-4131-b68a-27be0c20c2b9',
      customer_name: 'João Silva',
      customer_identifier: '123.456.789-00',
      value: '100.50',
      discount_value: '0.00',
      net_value: '100.50',
      url: 'https://webhook-test.com/d6df4d27ec979d9bb6e78fc06c4d44b5'
    });
    console.log('✅ Transação criada:', novaTransacao.id);

    // 3. Consultar detalhes
    console.log('\n🔍 Passo 3: Consultando detalhes...');
    const detalhes = await transacaoService.exibirTransacao(novaTransacao.id);
    console.log('Detalhes:', detalhes.status);

  } catch (error) {
    console.error('\n❌ Erro durante execução:', error.message);
  }
}

exemploCompletoGerenciamentoTransacoes();

2025 © Nuvende - CNPJ 38.297.374/0001-93