> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ruby

> 将 Dodo Payments 集成到您的 Ruby 应用程序中，使用优雅的 Ruby 原生 SDK

Ruby SDK 提供了一种简单直观的方式，将 Dodo Payments 集成到您的 Ruby 应用程序中。它遵循 Ruby 的约定和最佳实践，提供全面的错误处理、分页和中间件支持。

## 安装

将 gem 添加到您的 Gemfile：

```ruby Gemfile theme={null}
gem "dodopayments", "~> 2.9"
```

<Tip>
  始终使用最新的 SDK 版本以访问最新的 Dodo Payments 功能。定期运行 `bundle update dodopayments` 以保持更新。
</Tip>

然后运行：

```bash theme={null}
bundle install
```

<Info>
  该 SDK 支持 Ruby 3.2.0 及更高版本，提供完善的类型、错误处理和重试机制。
</Info>

## 快速开始

初始化客户端并创建结账会话：

```ruby theme={null}
require "bundler/setup"
require "dodopayments"

dodo_payments = Dodopayments::Client.new(
  bearer_token: ENV["DODO_PAYMENTS_API_KEY"], # This is the default and can be omitted
  environment: "test_mode" # defaults to "live_mode"
)

checkout_session_response = dodo_payments.checkout_sessions.create(
  product_cart: [{product_id: "product_id", quantity: 1}]
)

puts(checkout_session_response.session_id)
```

<Warning>
  使用环境变量安全存储 API 密钥。切勿将其提交到版本控制或在代码中暴露。
</Warning>

## 核心功能

<CardGroup cols={2}>
  <Card title="Ruby Conventions" icon="gem">
    遵循 Ruby 命名约定和惯用模式
  </Card>

  <Card title="Elegant Syntax" icon="code">
    提供清晰、易读的 API，让 Ruby 开发者感觉自然
  </Card>

  <Card title="Auto-Pagination" icon="arrows-rotate">
    为列表响应提供内置自动分页迭代器
  </Card>

  <Card title="Type Safety" icon="shield-check">
    可选的 Sorbet 类型以增强类型安全
  </Card>
</CardGroup>

## 配置

### 超时配置

配置请求超时：

```ruby theme={null}
# Configure default for all requests (default is 60 seconds)
dodo_payments = Dodopayments::Client.new(
  timeout: nil # disable timeout
)

# Or, configure per-request
dodo_payments.checkout_sessions.create(
  product_cart: [{product_id: "product_id", quantity: 1}],
  request_options: {timeout: 5}
)
```

### 重试配置

配置自动重试行为：

```ruby theme={null}
# Configure default for all requests (default is 2)
dodo_payments = Dodopayments::Client.new(
  max_retries: 0 # disable retries
)

# Or, configure per-request
dodo_payments.checkout_sessions.create(
  product_cart: [{product_id: "product_id", quantity: 1}],
  request_options: {max_retries: 5}
)
```

## 常见操作

### 创建结账会话

生成结账会话：

```ruby theme={null}
session = dodo_payments.checkout_sessions.create(
  product_cart: [
    {
      product_id: "prod_123",
      quantity: 1
    }
  ],
  return_url: "https://yourdomain.com/return"
)

# Redirect to checkout
redirect_to session.checkout_url
```

### 管理客户

创建和检索客户信息：

```ruby theme={null}
# Create a customer
customer = dodo_payments.customers.create(
  email: "customer@example.com",
  name: "John Doe",
  metadata: {
    user_id: "12345"
  }
)

# Retrieve customer
customer = dodo_payments.customers.retrieve("cus_123")
puts "Customer: #{customer.name} (#{customer.email})"
```

### 处理订阅

创建和管理定期订阅：

```ruby theme={null}
# Create a subscription
subscription = dodo_payments.subscriptions.create(
  billing: {
    country: "US",
    city: "San Francisco",
    state: "CA",
    street: "1 Market St",
    zipcode: "94105"
  },
  customer: { customer_id: "cus_123" }, # or { email: "...", name: "..." } for a new customer
  product_id: "pdt_456",
  quantity: 1
)

# Charge an on-demand subscription
# product_price is in the lowest currency denomination (e.g., 2500 = $25.00 USD)
charge = dodo_payments.subscriptions.charge(
  subscription.subscription_id,
  product_price: 2500
)

# Update subscription metadata
updated = dodo_payments.subscriptions.update(
  subscription.subscription_id,
  metadata: { plan_type: "premium" }
)
```

<Info>
  `billing` 至少需要两个字母的 ISO `country` 代码。`customer` 接受 `{ customer_id: "..." }` 来附加现有客户或 `{ email: "...", name: "..." }` 来创建新客户。`product_price` 是最低的货币面额。
</Info>

## 分页

### 自动分页

自动遍历所有页面：

```ruby theme={null}
page = dodo_payments.payments.list

# Fetch single item from page
payment = page.items[0]
puts(payment.brand_id)

# Automatically fetches more pages as needed
page.auto_paging_each do |payment|
  puts(payment.brand_id)
end
```

### 手动分页

对分页进行更多控制：

```ruby theme={null}
page = dodo_payments.payments.list

if page.next_page?
  new_page = page.next_page
  puts(new_page.items[0].brand_id)
end
```

## 错误处理

处理各种 Dodo Payments API 错误：

```ruby theme={null}
begin
  checkout_session = dodo_payments.checkout_sessions.create(
product_cart: [{product_id: "product_id", quantity: 1}]
  )
rescue Dodopayments::Errors::APIConnectionError => e
  puts("The server could not be reached")
  puts(e.cause)  # an underlying Exception, likely raised within `net/http`
rescue Dodopayments::Errors::RateLimitError => e
  puts("A 429 status code was received; we should back off a bit.")
rescue Dodopayments::Errors::APIStatusError => e
  puts("Another non-200-range status code was received")
  puts(e.status)
end
```

<Tip>
  通过指数退避的重试逻辑来处理速率限制错误，以确保您的应用程序优雅地处理高流量场景。
</Tip>

## 使用 Sorbet 保证类型安全

使用 Sorbet 确保请求参数的类型安全：

```ruby theme={null}
# Type-safe using Sorbet RBI definitions
dodo_payments.checkout_sessions.create(
  product_cart: [
    Dodopayments::ProductItemReq.new(
      product_id: "product_id",
      quantity: 1
    )
  ]
)

# Hashes work, but are not typesafe
dodo_payments.checkout_sessions.create(
  product_cart: [{product_id: "product_id", quantity: 1}]
)

# You can also splat a full Params class
params = Dodopayments::CheckoutSessionCreateParams.new(
  product_cart: [
    Dodopayments::ProductItemReq.new(
      product_id: "product_id",
      quantity: 1
    )
  ]
)
dodo_payments.checkout_sessions.create(**params)
```

## 高级用法

### 未记录的端点

请求未记录的端点：

```ruby theme={null}
response = dodo_payments.request(
  method: :post,
  path: '/undocumented/endpoint',
  query: {"dog": "woof"},
  headers: {"useful-header": "interesting-value"},
  body: {"hello": "world"}
)
```

### 未记录的参数

发送未记录的参数：

```ruby theme={null}
checkout_session_response = dodo_payments.checkout_sessions.create(
  product_cart: [{product_id: "product_id", quantity: 1}],
  request_options: {
    extra_query: {my_query_parameter: value},
    extra_body: {my_body_parameter: value},
    extra_headers: {"my-header": value}
  }
)

# Access undocumented response properties
puts(checkout_session_response[:my_undocumented_property])
```

## Rails 集成

### 创建初始化器

创建 `config/initializers/dodo_payments.rb`：

```ruby theme={null}
require "dodopayments"

DODO_CLIENT = Dodopayments::Client.new(
  bearer_token: Rails.application.credentials.dodo_api_key,
  environment: Rails.env.production? ? "live_mode" : "test_mode"
)
```

### 服务对象模式

创建支付服务：

```ruby theme={null}
# app/services/payment_service.rb
class PaymentService
  def initialize
    @client = DODO_CLIENT
  end

  def create_checkout(items)
    @client.checkout_sessions.create(
      product_cart: items,
      return_url: Rails.application.routes.url_helpers.checkout_return_url
    )
  end

  def process_payment(amount:, currency:, customer_id:)
    @client.payments.create(
      amount: amount,
      currency: currency,
      customer_id: customer_id
    )
  end
end
```

### 控制器集成

在 Rails 控制器中使用：

```ruby theme={null}
# app/controllers/checkouts_controller.rb
class CheckoutsController < ApplicationController
  def create
    service = PaymentService.new
    session = service.create_checkout(checkout_params[:items])
    
    redirect_to session.checkout_url, allow_other_host: true
  rescue Dodopayments::Errors::APIError => e
    flash[:error] = "Payment error: #{e.message}"
    redirect_to cart_path
  end

  private

  def checkout_params
    params.require(:checkout).permit(items: [:product_id, :quantity])
  end
end
```

## Sinatra 集成

与 Sinatra 应用程序一起使用：

```ruby theme={null}
require "sinatra"
require "dodopayments"

configure do
  set :dodo_client, Dodopayments::Client.new(
    bearer_token: ENV["DODO_API_KEY"]
  )
end

post "/create-checkout" do
  content_type :json
  
  begin
    session = settings.dodo_client.checkout_sessions.create(
      product_cart: JSON.parse(request.body.read)["items"],
      return_url: "#{request.base_url}/return"
    )
    
    { checkout_url: session.checkout_url }.to_json
  rescue Dodopayments::Errors::APIError => e
    status 400
    { error: e.message }.to_json
  end
end
```

## 资源

<CardGroup cols={2}>
  <Card title="GitHub Repository" icon="github" href="https://github.com/dodopayments/dodopayments-ruby">
    查看源代码并贡献
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    完整 API 文档
  </Card>

  <Card title="Discord Community" icon="discord" href="https://discord.gg/bYqAp4ayYh">
    获取帮助并与开发者联系
  </Card>

  <Card title="Report Issues" icon="bug" href="https://github.com/dodopayments/dodopayments-ruby/issues">
    报告错误或请求功能
  </Card>
</CardGroup>

## 支持

需要 Ruby SDK 帮助？

* **Discord**: 加入我们的[社区服务器](https://discord.gg/bYqAp4ayYh)获得实时支持
* **电子邮件**: 联系我们：[support@dodopayments.com](mailto:support@dodopayments.com)
* **GitHub**: 在[仓库](https://github.com/dodopayments/dodopayments-ruby)上提交问题

## 贡献

我们欢迎贡献！查看[贡献指南](https://github.com/dodopayments/dodopayments-ruby/blob/main/CONTRIBUTING.md)以开始。
