MeApi

Uma gem Ruby para integração completa com a API do Melhor Envio, permitindo calcular fretes, criar etiquetas, gerenciar envios e muito mais de forma simples e eficiente.

Gem Version

Documentação API Melhor Envio

Funcionalidades

  • Autenticação: Authorization code e refresh token
  • Cotação de frete: Calcular preços de envio
  • Gestão de etiquetas: Criar, pagar, gerar e imprimir etiquetas
  • Consultas: Dados da conta, saldo, pedidos
  • Suporte a sandbox: Ambiente de testes
  • Classes auxiliares: Volume e Product para facilitar o uso

Instalação

Adicione esta linha ao Gemfile da sua aplicação:

gem 'me_api'

E então execute:

$ bundle install

Ou instale diretamente com:

$ gem install me_api

Configuração

Para usar a gem, você precisa ter credenciais da API do Melhor Envio. Você pode obter essas credenciais criando uma aplicação no painel do desenvolvedor do Melhor Envio.

Criando um cliente

A gem suporta dois modos de operação:

  • Produção: Para uso em ambiente de produção
  • Sandbox: Para testes (use test_mode: true)
# Cliente de produção
client = MeApi::Client.new(
  access_token: "seu_access_token",
  refresh_token: "seu_refresh_token", 
  client_id: "seu_client_id",
  client_secret: "seu_client_secret",
  token_expires_at: Time.now + 3600
)

# Cliente de sandbox/teste
client = MeApi::Client.new(
  access_token: "seu_access_token",
  refresh_token: "seu_refresh_token",
  client_id: "seu_client_id", 
  client_secret: "seu_client_secret",
  token_expires_at: Time.now + 3600,
  test_mode: true
)

Uso

Formato das respostas

Todas as respostas dos métodos da API retornam objetos AcObject ou arrays de AcObject. Esses objetos permitem acesso aos dados de duas formas:

  • Notação de ponto: response.access_token
  • Notação de hash: response["access_token"]
  • Conversão para JSON: response.json (retorna um hash Ruby)
# Exemplo com refresh_token
response = client.refresh_token(
  client_id: "seu_client_id",
  client_secret: "seu_client_secret",
  refresh_token: "seu_refresh_token"
)

# Todas essas formas funcionam:
puts response.access_token          # "novo_access_token"
puts response["access_token"]       # "novo_access_token"
puts response.json["access_token"]  # "novo_access_token"

# Para ver toda a resposta como hash
puts response.json
# => {"access_token"=>"...", "refresh_token"=>"...", "expires_in"=>21600, "token_type"=>"Bearer"}

Autenticação

Autorizando uma aplicação

response = client.authorize(
  client_id: "seu_client_id",
  client_secret: "seu_client_secret", 
  code: "codigo_retornado_pela_api",
  redirect_url: "sua_url_de_redirect"
)

# Acessando dados da resposta
puts response.access_token   # "abcde12345"
puts response.refresh_token  # "asdfghjk123456"
puts response.expires_in     # 21600
puts response.token_type     # "Bearer"

# Ou usando notação de hash
puts response["access_token"]  # "abcde12345"
puts response["refresh_token"] # "asdfghjk123456"

Renovando token

response = client.refresh_token(
  client_id: "seu_client_id",
  client_secret: "seu_client_secret",
  refresh_token: "seu_refresh_token"
)

# Acessando dados da resposta
puts response.access_token   # "novo_access_token"
puts response.refresh_token  # "novo_refresh_token"
puts response.token_type     # "Bearer"

Cotação de frete

# Criar objeto de volume/dimensões
volume = MeApi::Volume.new(
  width_cm: 20,
  height_cm: 15, 
  length_cm: 30,
  weight_kg: 1.5
)

# Calcular frete (retorna array de AcObject)
rates = client.rates(
  from_postal_code: "13870329",
  to_postal_code: "88063500", 
  volume: volume,
  contents_value_brl: 50.00
)

# Acessando dados do primeiro resultado
puts rates.first.price          # Preço do frete mais barato
puts rates.first.service_name   # Nome do serviço (ex: "PAC")
puts rates.first.carrier_name   # Nome da transportadora (ex: "Correios")

# Ou usando notação de hash
puts rates.first["price"]        # Preço do frete
puts rates.first["service_name"] # Nome do serviço

Gestão de produtos e volumes

Criando produtos

products = [
  MeApi::Product.new(
    name: "Produto A",
    quantity: 2,
    unitary_value: 25.00
  ),
  MeApi::Product.new(
    name: "Produto B", 
    quantity: 1,
    unitary_value: 50.00
  )
]

Criando volumes

volumes = [
  MeApi::Volume.new(
    width_cm: 20,
    height_cm: 15,
    length_cm: 30, 
    weight_kg: 1.5
  )
]

Gestão de etiquetas

Adicionando etiqueta ao carrinho

response = client.add_label_to_cart(
  service_id: 1, # ID do serviço de entrega
  from_name: "Remetente",
  from_phone: "(11) 99999-9999",
  from_email: "[email protected]",
  from_address: "Rua do Remetente",
  from_address_complement: "Apto 123",
  from_address_number: "100",
  from_address_district: "Centro", 
  from_address_city: "São Paulo",
  from_postal_code: "01000000",
  from_address_state_abbr: "SP",
  from_tax_id: "12345678901", # CPF ou CNPJ
  to_name: "Destinatário",
  to_phone: "(11) 88888-8888", 
  to_email: "[email protected]",
  to_address: "Rua do Destinatário",
  to_address_complement: "",
  to_address_number: "200",
  to_address_district: "Vila Nova",
  to_address_city: "Rio de Janeiro", 
  to_postal_code: "20000000",
  to_address_state_abbr: "RJ",
  to_tax_id: "98765432109", # CPF ou CNPJ
  products: products,
  volumes: volumes,
  insurance_value: 100.00
)

# Acessando dados da resposta
order_id = response.id          # ID do pedido
puts response.protocol          # Protocolo do pedido
puts response["status"]         # Status do pedido

Pagando etiqueta

payment_response = client.pay_label(order_id)
puts payment_response.purchase_id    # ID da compra
puts payment_response["digitable_line"] # Linha digitável (se boleto)

Gerando etiqueta

generate_response = client.generate_label(order_id)
puts generate_response["status"]     # Status da geração

Imprimindo etiqueta

pdf_response = client.print_label(order_id)
puts pdf_response.first             # URL do PDF da etiqueta

Consultas

Dados da conta

 = client.
puts .firstname          # Nome do usuário
puts .email              # Email da conta
puts ["document"]        # CPF/CNPJ da conta
puts .json               # Todos os dados como hash

Saldo disponível

balance = client.get_balance
puts balance.current            # Saldo atual
puts balance["currency"]        # Moeda (BRL)

Detalhes de um pedido

order = client.get_label(order_id)
puts order.status               # Status do pedido
puts order.tracking             # Código de rastreamento
puts order["service_name"]      # Nome do serviço utilizado
puts order.json                 # Todos os dados do pedido

Classes auxiliares

MeApi::Volume

Representa as dimensões e peso de um pacote:

volume = MeApi::Volume.new(
  width_cm: 20,    # Largura em centímetros
  height_cm: 15,   # Altura em centímetros  
  length_cm: 30,   # Comprimento em centímetros
  weight_kg: 1.5   # Peso em quilogramas
)

# Converte para formato da API
volume.to_api_format
# => { width: 20, height: 15, length: 30, weight: 1.5 }

MeApi::Product

Representa um produto a ser enviado:

product = MeApi::Product.new(
  name: "Nome do produto",     # Nome do produto
  quantity: 2,                 # Quantidade
  unitary_value: 25.00        # Valor unitário em reais
)

# Converte para formato da API
product.to_api_format
# => { name: "Nome do produto", quantity: 2, unitary_value: 25.0 }

Exemplo completo

require 'me_api'

# Configurar cliente
client = MeApi::Client.new(
  access_token: "seu_access_token",
  refresh_token: "seu_refresh_token",
  client_id: "seu_client_id",
  client_secret: "seu_client_secret", 
  token_expires_at: Time.now + 3600
)

# Calcular frete
volume = MeApi::Volume.new(width_cm: 20, height_cm: 15, length_cm: 30, weight_kg: 1.5)
rates = client.rates(
  from_postal_code: "13870329",
  to_postal_code: "88063500",
  volume: volume,
  contents_value_brl: 50.00
)

puts "Melhor preço: R$ #{rates.first.price}"
puts "Serviço: #{rates.first.service_name}"

# Criar pedido
products = [MeApi::Product.new(name: "Produto A", quantity: 1, unitary_value: 50.00)]
volumes = [volume]

response = client.add_label_to_cart(
  service_id: rates.first.id,
  from_name: "Loja Online",
  from_phone: "(11) 99999-9999",
  from_email: "[email protected]",
  from_address: "Rua da Loja",
  from_address_number: "123",
  from_address_district: "Centro",
  from_address_city: "São Paulo", 
  from_postal_code: "13870329",
  from_address_state_abbr: "SP",
  from_tax_id: "12345678000123",
  to_name: "João Silva",
  to_phone: "(11) 88888-8888",
  to_email: "[email protected]", 
  to_address: "Rua do Cliente",
  to_address_number: "456",
  to_address_district: "Vila Nova",
  to_address_city: "Florianópolis",
  to_postal_code: "88063500", 
  to_address_state_abbr: "SC",
  to_tax_id: "98765432109",
  products: products,
  volumes: volumes,
  insurance_value: 50.00
)

order_id = response.id    # Usando notação de ponto
puts "Pedido criado: #{response.protocol}"

# Pagar e gerar etiqueta
payment = client.pay_label(order_id)
puts "Pagamento: #{payment.purchase_id}"

generate = client.generate_label(order_id)
puts "Status geração: #{generate.status}"

# Obter URL do PDF
pdf_response = client.print_label(order_id)
puts "Etiqueta: #{pdf_response.first}"