SDK Ruby
Exemplos com net/http e faraday.
Cliente com net/http
# fast_deliv_client.rb
require 'net/http'
require 'json'
require 'uri'
require 'bigdecimal'
class FastDelivClient
BASE_URL = "https://fast-deliv-backend.vercel.app"
SUPABASE_URL = ENV.fetch('SUPABASE_URL')
SUPABASE_ANON = ENV.fetch('SUPABASE_ANON_KEY')
def initialize(email, password)
@email = email
@password = password
@token = nil
@refresh = nil
@expires = Time.now - 1
end
# --- Auth ---
def authenticate
resp = post_json(
URI("#{SUPABASE_URL}/auth/v1/token?grant_type=password"),
{ email: @email, password: @password },
extra_headers: { 'apikey' => SUPABASE_ANON }
)
@token = resp['access_token']
@refresh = resp['refresh_token']
@expires = Time.now + resp.fetch('expires_in', 3600).to_i - 60
end
def refresh_token
resp = post_json(
URI("#{SUPABASE_URL}/auth/v1/token?grant_type=refresh_token"),
{ refresh_token: @refresh },
extra_headers: { 'apikey' => SUPABASE_ANON }
)
@token = resp['access_token']
@expires = Time.now + resp.fetch('expires_in', 3600).to_i - 60
end
def auth_headers
authenticate if @token.nil?
refresh_token if Time.now >= @expires
{ 'Authorization' => "Bearer #{@token}" }
end
# --- HTTP helpers ---
def http_for(uri)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == 'https'
http
end
def post_json(uri, body, extra_headers: {})
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
extra_headers.each { |k, v| req[k] = v }
req.body = JSON.dump(body)
resp = http_for(uri).request(req)
raise "HTTP #{resp.code}: #{resp.body}" unless resp.is_a?(Net::HTTPSuccess)
JSON.parse(resp.body)
end
def get(path, params: {})
uri = URI("#{BASE_URL}#{path}")
uri.query = URI.encode_www_form(params) unless params.empty?
req = Net::HTTP::Get.new(uri)
auth_headers.each { |k, v| req[k] = v }
resp = http_for(uri).request(req)
raise "HTTP #{resp.code}: #{resp.body}" unless resp.is_a?(Net::HTTPSuccess)
JSON.parse(resp.body)
end
def post(path, body)
uri = URI("#{BASE_URL}#{path}")
post_json(uri, body, extra_headers: auth_headers)
end
def patch(path)
uri = URI("#{BASE_URL}#{path}")
req = Net::HTTP::Patch.new(uri)
auth_headers.each { |k, v| req[k] = v }
resp = http_for(uri).request(req)
raise "HTTP #{resp.code}: #{resp.body}" unless resp.is_a?(Net::HTTPSuccess)
JSON.parse(resp.body)
end
def put(path, body)
uri = URI("#{BASE_URL}#{path}")
req = Net::HTTP::Put.new(uri)
req['Content-Type'] = 'application/json'
auth_headers.each { |k, v| req[k] = v }
req.body = JSON.dump(body)
resp = http_for(uri).request(req)
raise "HTTP #{resp.code}: #{resp.body}" unless resp.is_a?(Net::HTTPSuccess)
JSON.parse(resp.body)
end
# --- Entregas ---
def list_deliveries(status: nil)
params = status ? { status: status } : {}
get('/api/v1/deliveries', params: params)
end
def create_delivery(title:, origin_address:, origin_lat:, origin_lng:,
destination_address:, destination_lat:, destination_lng:)
post('/api/v1/deliveries', {
title: title,
origin_address: origin_address,
origin_lat: origin_lat,
origin_lng: origin_lng,
destination_address: destination_address,
destination_lat: destination_lat,
destination_lng: destination_lng
})
end
def assign_delivery(id) = patch("/api/v1/deliveries/#{id}/assign")
def start_delivery(id) = patch("/api/v1/deliveries/#{id}/start")
def complete_delivery(id) = patch("/api/v1/deliveries/#{id}/complete")
def cancel_delivery(id) = patch("/api/v1/deliveries/#{id}/cancel")
# --- Motoristas ---
def list_drivers = get('/api/v1/drivers')
# --- Carteira ---
def get_wallet = get('/api/v1/wallets/me')
def get_transactions = get('/api/v1/wallets/me/transactions')
def withdraw(amount:, pix_key:, pix_key_type:)
post('/api/v1/wallets/withdraw', {
amount: amount,
pix_key: pix_key,
pix_key_type: pix_key_type
})
end
# --- Localizacao ---
def update_location(lat:, lng:, heading: nil)
body = { lat: lat, lng: lng }
body[:heading] = heading if heading
put('/api/v1/locations/me', body)
end
def list_locations = get('/api/v1/locations')
# --- Precos ---
def get_pricing = get('/api/v1/pricing')
def update_pricing(**attrs)
put('/api/v1/pricing', attrs)
end
end
Uso basico
require_relative 'fast_deliv_client'
client = FastDelivClient.new('admin@empresa.com', 'senha123')
# Listar entregas pendentes
pending = client.list_deliveries(status: 'pending')
puts "#{pending.length} entregas pendentes"
# Criar entrega
delivery = client.create_delivery(
title: 'Entrega Setor Sul',
origin_address: 'Rua das Flores, 100, Goiania',
origin_lat: -16.6869,
origin_lng: -49.2648,
destination_address: 'Av. T-63, 800, Goiania',
destination_lat: -16.7012,
destination_lng: -49.2789
)
puts "Criada: #{delivery['id']}"
Versao com Faraday
# Gemfile: gem 'faraday', '~> 2.0'
require 'faraday'
require 'faraday/net_http'
require 'json'
class FastDelivFaradayClient
BASE_URL = "https://fast-deliv-backend.vercel.app"
def initialize(token)
@conn = Faraday.new(url: BASE_URL) do |f|
f.request :json
f.response :json
f.headers['Authorization'] = "Bearer #{token}"
f.adapter :net_http
end
end
def list_deliveries(status: nil)
params = status ? { status: status } : {}
@conn.get('/api/v1/deliveries', params).body
end
def create_delivery(payload)
resp = @conn.post('/api/v1/deliveries', payload)
raise "#{resp.status}: #{resp.body}" unless resp.success?
resp.body
end
def cancel_delivery(id)
resp = @conn.patch("/api/v1/deliveries/#{id}/cancel")
resp.body
end
def list_drivers
@conn.get('/api/v1/drivers').body
end
def get_wallet
@conn.get('/api/v1/wallets/me').body
end
def get_transactions
@conn.get('/api/v1/wallets/me/transactions').body
end
def get_pricing
@conn.get('/api/v1/pricing').body
end
end
# Uso
client = FastDelivFaradayClient.new(ENV['FAST_DELIV_TOKEN'])
puts client.list_deliveries(status: 'completed').length
Calculo de ganho do motorista
require 'bigdecimal'
require 'bigdecimal/util'
def calc_driver_earnings(distance_km, pricing)
base = BigDecimal(pricing['base_fare'])
min_km = pricing['min_km'].to_f
per_km = BigDecimal(pricing['price_per_km'])
return base if distance_km <= min_km
base + (BigDecimal(distance_km.to_s) - BigDecimal(min_km.to_s)) * per_km
end
pricing = client.get_pricing
puts "Rota 12km: R$ #{calc_driver_earnings(12, pricing)}" # R$ 29.00
puts "Rota 3km: R$ #{calc_driver_earnings(3, pricing)}" # R$ 15.00
Polling de status
def wait_for_completion(client, delivery_id, timeout: 3600)
deadline = Time.now + timeout
terminal = %w[completed cancelled]
loop do
raise "Timeout aguardando entrega #{delivery_id}" if Time.now > deadline
deliveries = client.list_deliveries
delivery = deliveries.find { |d| d['id'] == delivery_id }
raise "Entrega #{delivery_id} nao encontrada" unless delivery
status = delivery['status']
puts "Status: #{status}"
return delivery if terminal.include?(status)
sleep 30
end
end