# Ruby 示例

## 配置

```ruby
require 'net/http'
require 'uri'
require 'json'
require 'openssl'
require 'base64'

EASEBG_API_KEY = ENV.fetch('EASEBG_API_KEY', 'your_api_key_here')
EASEBG_API_BASE = ENV.fetch('EASEBG_API_BASE', 'https://api.easebg.com/api/v1')

def api_request(method, path, body = nil)
  uri = URI("#{EASEBG_API_BASE}#{path}")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'
  http.read_timeout = 30

  request = case method
            when 'GET'    then Net::HTTP::Get.new(uri)
            when 'POST'   then Net::HTTP::Post.new(uri)
            when 'DELETE' then Net::HTTP::Delete.new(uri)
            when 'PATCH'  then Net::HTTP::Patch.new(uri)
            end

  request['X-API-Key'] = EASEBG_API_KEY
  request['Content-Type'] = 'application/json'

  if body
    request.body = JSON.generate(body)
  end

  response = http.request(request)
  json = JSON.parse(response.body) rescue {}

  if response.code.to_i >= 400
    error = json.fetch('error', {})
    raise EaseBGApiError.new(response.code.to_i, error.fetch('code', 'UNKNOWN'), error.fetch('message', 'Request failed'))
  end

  json
end

class EaseBGApiError < StandardError
  attr_reader :status_code, :code

  def initialize(status_code, code, message)
    @status_code = status_code
    @code = code
    super("[#{code}] #{message}")
  end
end
```

## 1. 创建抠图任务

```ruby
def create_task(image_url, model_version: 'easebg-2.0', callback_url: nil, metadata: nil)
  payload = { imageUrl: image_url, modelVersion: model_version }
  payload[:callbackUrl] = callback_url if callback_url
  payload[:metadata] = metadata if metadata

  api_request('POST', '/open/developer/tasks', payload)
end

# 使用示例
begin
  result = create_task('https://example.com/photo.jpg', callback_url: 'https://your-app.com/webhooks/easebg')
  puts "Task created: #{result['data']['id']}"
rescue EaseBGApiError => e
  puts "Error: #{e.message}"
end
```

## 2. 查询任务状态

```ruby
def get_task(task_id)
  api_request('GET', "/open/developer/tasks/#{task_id}")
end

def wait_for_task(task_id, interval: 2, max_attempts: 60)
  max_attempts.times do
    result = get_task(task_id)
    data = result['data']
    status = data['status']

    return data if status == 'succeeded'
    raise "Task failed: #{data['errorMessage']}" if status == 'failed'

    sleep(interval)
  end

  raise 'Task timed out'
end
```

## 3. 获取任务结果

```ruby
def download_result(task_id, output_path)
  result = get_task(task_id)
  data = result['data']

  if data['status'] != 'succeeded' || data['resultUrl'].nil?
    raise 'Task not completed or no result available'
  end

  uri = URI(data['resultUrl'])
  Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
    response = http.get(uri.path)
    File.binwrite(output_path, response.body)
  end

  puts "Result saved to #{output_path}"
end
```

## 4. 取消任务

```ruby
def cancel_task(task_id)
  uri = URI("#{EASEBG_API_BASE}/open/developer/tasks/#{task_id}")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'

  request = Net::HTTP::Delete.new(uri)
  request['X-API-Key'] = EASEBG_API_KEY

  response = http.request(request)

  case response.code.to_i
  when 204
    puts 'Task canceled successfully'
  when 409
    raise 'Task cannot be canceled in current state'
  else
    raise "Cancel failed: HTTP #{response.code}"
  end
end
```

## 5. 创建批量任务

```ruby
def create_batch_task(image_urls, model_version: 'easebg-2.0', callback_url: nil)
  payload = { imageUrls: image_urls, modelVersion: model_version }
  payload[:callbackUrl] = callback_url if callback_url

  api_request('POST', '/open/developer/batch-tasks', payload)
end

# 使用示例
batch = create_batch_task([
  'https://example.com/photo1.jpg',
  'https://example.com/photo2.jpg',
  'https://example.com/photo3.jpg',
], callback_url: 'https://your-app.com/webhooks/easebg')
```

## 6. Webhook 签名验证

```ruby
def verify_webhook_signature(payload, signature, secret)
  computed = OpenSSL::HMAC.hexdigest('sha256', secret, payload)
  # 使用固定时间比较防止时序攻击
  Rack::Utils.secure_compare(computed, signature)
end

# Sinatra 示例
=begin
require 'sinatra'
require 'json'

post '/webhooks/easebg' do
  payload = request.body.read
  signature = request.env['HTTP_X_EASEBG_SIGNATURE']
  secret = ENV.fetch('EASEBG_WEBHOOK_SECRET')

  unless verify_webhook_signature(payload, signature, secret)
    status 401
    return JSON.generate(error: 'Invalid signature')
  end

  event = JSON.parse(payload)
  puts "Received webhook: #{event['event']} - #{event['taskId']}"

  case event['event']
  when 'task.succeeded'
    puts "Result URL: #{event['resultUrl']}"
  when 'task.failed'
    puts "Error: #{event['errorMessage']}"
  end

  JSON.generate(received: true)
end
=end
```

## 7. 错误处理

```ruby
begin
  result = api_request('POST', '/open/developer/tasks', {
    imageUrl: 'https://example.com/photo.jpg'
  })
rescue EaseBGApiError => e
  case e.code
  when 'INSUFFICIENT_CREDITS'
    puts '积分不足，请充值'
  when 'RATE_LIMIT_EXCEEDED'
    puts '请求频率超限，请稍后重试'
  when 'INVALID_API_KEY'
    puts 'API Key 无效'
  else
    puts "API 错误: #{e.message}"
  end
rescue StandardError => e
  puts "网络错误: #{e.message}"
end
```

## 8. 分页查询

```ruby
def list_tasks(page: 1, page_size: 20, status: nil, start_date: nil, end_date: nil)
  params = { page: page, pageSize: page_size }
  params[:status] = status if status
  params[:startDate] = start_date if start_date
  params[:endDate] = end_date if end_date

  query_string = URI.encode_www_form(params)
  api_request('GET', "/open/developer/tasks?#{query_string}")
end

def get_all_tasks(status: nil)
  all_tasks = []
  page = 1
  total_pages = 1

  while page <= total_pages
    result = list_tasks(page: page, status: status)
    all_tasks.concat(result['data'])
    total_pages = result['meta']['totalPages']
    page += 1
  end

  all_tasks
end
```
