NXGate SDK para Elixir

SDK oficial da NXGATE para integração com a API PIX em aplicações Elixir.

Funcionalidades

Requisitos

Instalação

Adicione nxgate às suas dependências no mix.exs:

def deps do
  [
    {:nxgate, "~> 0.1.0"}
  ]
end

Configuração

Início Rápido

# Iniciar o client (geralmente no seu application supervisor)
{:ok, client} = NXGate.start_link(
  client_id: "nxgate_xxx",
  client_secret: "secret",
  hmac_secret: "opcional"  # opcional - ativa assinatura HMAC
)

Uso com Supervisor

Adicione o client ao seu supervisor para gerenciamento automático do ciclo de vida:

defmodule MyApp.Application do
  use Application

  @impl true
  def start(_type, _args) do
    children = [
      {NXGate,
       client_id: System.fetch_env!("NXGATE_CLIENT_ID"),
       client_secret: System.fetch_env!("NXGATE_CLIENT_SECRET"),
       hmac_secret: System.get_env("NXGATE_HMAC_SECRET"),
       name: :nxgate}
    ]

    opts = [strategy: :one_for_one, name: MyApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Opções de Configuração

Opção Tipo Obrigatório Padrão Descrição
client_idstring Sim - ID do client OAuth2
client_secretstring Sim - Secret do client OAuth2
hmac_secretstring Não nil Secret para assinatura HMAC-SHA256
base_urlstring Não https://api.nxgate.com.br URL base da API
timeoutinteger Não 15000 Timeout em milissegundos
max_retriesinteger Não 2 Máximo de retentativas em erro 503

Uso

Gerar Cobrança PIX (Cash-in)

Gera uma cobrança PIX e retorna o QR Code para pagamento:

{:ok, charge} = NXGate.pix_generate(client, %{
  valor: 100.00,
  nome_pagador: "João da Silva",
  documento_pagador: "12345678901",
  webhook: "https://meusite.com/webhook",
  descricao: "Pagamento do pedido #123"
})

# Resposta:
# %{
#   "status" => "success",
#   "message" => "...",
#   "paymentCode" => "00020126...",
#   "idTransaction" => "abc123",
#   "paymentCodeBase64" => "data:image/png;base64,..."
# }

Parâmetros

Parâmetro Tipo Obrigatório Descrição
valorfloat Sim Valor em reais
nome_pagadorstring Sim Nome do pagador
documento_pagadorstring Sim CPF ou CNPJ do pagador
forcar_pagadorboolean Não Forçar dados do pagador
email_pagadorstring Não Email do pagador
celularstring Não Celular do pagador
descricaostring Não Descrição da cobrança
webhookstring Não URL de callback
magic_idstring Não ID mágico para referência
api_keystring Não Chave de API
split_userslist Não Split de pagamento

Split de Pagamento

{:ok, charge} = NXGate.pix_generate(client, %{
  valor: 100.00,
  nome_pagador: "Maria Santos",
  documento_pagador: "98765432100",
  split_users: [
    %{username: "loja_principal", percentage: 90.0},
    %{username: "parceiro", percentage: 10.0}
  ]
})

Saque PIX (Cash-out)

Realiza uma transferência PIX para a chave informada:

{:ok, withdrawal} = NXGate.pix_withdraw(client, %{
  valor: 50.0,
  chave_pix: "joao@email.com",
  tipo_chave: :email,
  webhook: "https://meusite.com/webhook"
})

# Resposta:
# %{
#   "status" => "success",
#   "message" => "...",
#   "internalreference" => "ref_xyz"
# }

Tipos de Chave PIX

Atom Valor Descrição
:cpfCPF CPF do destinatário
:cnpjCNPJ CNPJ do destinatário
:phonePHONE Telefone do destinatário
:emailEMAIL Email do destinatário
:randomRANDOM Chave aleatória

Consultar Saldo

{:ok, balance} = NXGate.get_balance(client)

# Resposta:
# %{
#   "balance" => 1000.00,
#   "blocked" => 50.00,
#   "available" => 950.00
# }

Consultar Transação

# Cash-in
{:ok, tx} = NXGate.get_transaction(client, :cash_in, "id_transacao")

# Cash-out
{:ok, tx} = NXGate.get_transaction(client, :cash_out, "id_transacao")

# Resposta:
# %{
#   "idTransaction" => "...",
#   "status" => "PAID",
#   "amount" => 100.0,
#   "paidAt" => "2026-01-15T10:30:00Z",
#   "endToEnd" => "..."
# }

Webhooks

O módulo NXGate.Webhook facilita o processamento de notificações recebidas da NXGATE.

Configuração no Phoenix

defmodule MyAppWeb.WebhookController do
  use MyAppWeb, :controller

  def nxgate(conn, params) do
    case NXGate.Webhook.parse(params) do
      {:ok, %{type: "QR_CODE_COPY_AND_PASTE_PAID", category: :cash_in} = event} ->
        # Pagamento PIX recebido
        IO.inspect(event.data.amount, label: "Valor recebido")
        IO.inspect(event.data.tx_id, label: "ID da transação")
        json(conn, %{ok: true})

      {:ok, %{type: "QR_CODE_COPY_AND_PASTE_REFUNDED"} = event} ->
        # Pagamento estornado
        handle_refund(event)
        json(conn, %{ok: true})

      {:ok, %{type: "PIX_CASHOUT_SUCCESS"} = event} ->
        # Saque realizado com sucesso
        IO.inspect(event.data.id_transaction, label: "Saque confirmado")
        json(conn, %{ok: true})

      {:ok, %{type: "PIX_CASHOUT_ERROR"} = event} ->
        # Erro no saque
        handle_cashout_error(event)
        json(conn, %{ok: true})

      {:ok, %{type: "PIX_CASHOUT_REFUNDED"} = event} ->
        # Saque estornado
        handle_cashout_refund(event)
        json(conn, %{ok: true})

      {:error, reason} ->
        Logger.warning("Webhook NXGATE inválido: #{inspect(reason)}")
        conn |> put_status(400) |> json(%{error: "invalid payload"})
    end
  end
end

Tipos de Evento

Cash-in (PIX Recebido)

Tipo Descrição
QR_CODE_COPY_AND_PASTE_PAID QR Code pago com sucesso
QR_CODE_COPY_AND_PASTE_REFUNDED QR Code estornado

Cash-out (PIX Enviado)

Tipo Descrição
PIX_CASHOUT_SUCCESS Saque realizado com sucesso
PIX_CASHOUT_ERROR Erro no saque
PIX_CASHOUT_REFUNDED Saque estornado

Funções Auxiliares

# Verificar se é evento de cash-in
NXGate.Webhook.cash_in?("QR_CODE_COPY_AND_PASTE_PAID")  # true

# Verificar se é evento de cash-out
NXGate.Webhook.cash_out?("PIX_CASHOUT_SUCCESS")  # true

# Listar todos os tipos conhecidos
NXGate.Webhook.known_types()

Assinatura HMAC

Quando o hmac_secret é configurado, todas as requisições incluem automaticamente os seguintes headers:

Header Descrição
X-Client-ID Identificador do client
X-HMAC-Signature Assinatura HMAC-SHA256 codificada em Base64
X-HMAC-Timestamp Timestamp ISO 8601 da requisição
X-HMAC-Nonce String única por requisição

A string de assinatura é composta por:

METHOD\nPATH\nTIMESTAMP\nNONCE\nBODY

Tratamento de Erros

Todas as funções retornam {:ok, result} ou {:error, %NXGate.Error{}}.

case NXGate.pix_generate(client, params) do
  {:ok, charge} ->
    # Sucesso
    IO.puts("QR Code: #{charge["paymentCode"]}")

  {:error, %NXGate.Error{reason: :validation_error} = err} ->
    # Erro de validação dos parâmetros
    IO.puts("Parâmetros inválidos: #{err.message}")

  {:error, %NXGate.Error{reason: :auth_error}} ->
    # Erro de autenticação
    IO.puts("Verifique suas credenciais")

  {:error, %NXGate.Error{reason: :api_error, status_code: code} = err} ->
    # Erro retornado pela API
    IO.puts("Erro HTTP #{code}: #{err.message}")

  {:error, %NXGate.Error{reason: :connection_error}} ->
    # Erro de rede/conexão
    IO.puts("Verifique sua conexão")

  {:error, %NXGate.Error{reason: :timeout}} ->
    # Timeout na requisição
    IO.puts("A requisição expirou")

  {:error, %NXGate.Error{reason: :max_retries}} ->
    # Serviço indisponível após retentativas
    IO.puts("Serviço temporariamente indisponível")
end

Tipos de Erro

Reason Descrição
:validation_error Parâmetros de entrada inválidos
:auth_error Falha na autenticação OAuth2
:api_error Erro retornado pela API NXGATE
:connection_error Erro de rede/conexão
:timeout Timeout na requisição
:max_retries Máximo de retentativas atingido (503)

Retry Automático

O SDK realiza retry automático com backoff exponencial quando recebe HTTP 503 (Service Unavailable):

O número máximo de retentativas pode ser configurado via opção :max_retries.

Gerenciamento de Token

O token OAuth2 é gerenciado automaticamente pelo NXGate.TokenManager:

Desenvolvimento

# Clonar o repositório
git clone https://github.com/nxgate/sdk-elixir.git
cd sdk-elixir

# Instalar dependências
mix deps.get

# Executar testes
mix test

# Verificar formatação
mix format --check-formatted

Licença

Este projeto está licenciado sob a licença MIT - veja o arquivo LICENSE para detalhes.