> ## 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.

# C#

> 使用 Dodo Payments C# SDK 从 .NET 创建结账会话、客户和订阅，并获得类型化模型、自动重试和分页支持。

C# SDK 为 .NET 应用提供对 Dodo Payments REST API 的类型化访问。每个 API 方法都是异步的，并返回 `Task`，请求和响应均为类型化类，客户端还会自动为你重试失败的请求。

<Info>
  C# SDK 当前处于测试阶段。我们正在积极改进，欢迎您的反馈。
</Info>

从[NuGet](https://www.nuget.org/packages/DodoPayments.Client)安装该包：

使用 .NET CLI 安装 SDK：

<Info>
  SDK 要求使用 .NET Standard 2.0 或更高版本，同时也提供 .NET 8 构建版本。它适用于 ASP.NET Core、控制台应用以及其他类型的 .NET 项目。本页面中的示例使用 C# 12 语法，例如集合表达式。
</Info>

<Info>
  该 SDK 需要 .NET Standard 2.0 或更高版本。它适用于 ASP.NET Core、控制台应用程序以及其他 .NET 项目类型。
</Info>

创建客户端，然后创建结账会话：

```csharp theme={null}
using System;
using DodoPayments.Client;
using DodoPayments.Client.Models.CheckoutSessions;

// Configured using the DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_WEBHOOK_KEY, and DODO_PAYMENTS_BASE_URL environment variables
DodoPaymentsClient client = new();

CheckoutSessionCreateParams parameters = new()
{
    ProductCart =
    [
        new()
        {
            ProductID = "pdt_123",
            Quantity = 1,
        },
    ],
};

var checkoutSessionResponse = await client.CheckoutSessions.Create(parameters);

Console.WriteLine(checkoutSessionResponse.SessionID);
```

如果未设置 `BearerToken`，客户端会读取 `DODO_PAYMENTS_API_KEY` 环境变量。如果未设置 `BaseUrl` 或 `DODO_PAYMENTS_BASE_URL`，客户端会连接到 live mode。要使用 test mode，请参阅 [环境](#environments)。test mode API key 只能在 test mode 中使用。

<Warning>
  请将 API key 保存在环境变量、用户机密或 Azure Key Vault 中。切勿将其硬编码到源代码中，也不要将其提交到版本控制系统。
</Warning>

## 核心功能

<CardGroup cols={2}>
  <Card title="Async/Await" icon="bolt">
    每个 API 方法都会返回 `Task`，并接受可选的 `CancellationToken`。
  </Card>

  <Card title="Strong Typing" icon="shield-check">
    提供类型化的请求和响应类，并带有可空引用类型注解。
  </Card>

  <Card title="Smart Retries" icon="repeat">
    默认重试两次；对于连接错误和可重试的状态码，使用指数退避。
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation">
    为每个常见 HTTP 错误状态提供一个异常类，其中包含状态码和响应正文。
  </Card>
</CardGroup>

## 配置

### 环境变量

将 API key 存储在环境变量中：

```bash .env theme={null}
DODO_PAYMENTS_API_KEY=your_api_key_here
```

使用 `new()` 创建的客户端会从环境中读取设置：

```csharp theme={null}
// Automatically reads from environment variables
DodoPaymentsClient client = new();
```

未设置相应属性时，客户端会读取以下环境变量：

| Property | Environment variable | Required | Default value |
| - | - | - | - |
| `BearerToken` | `DODO_PAYMENTS_API_KEY` | true | - |
| `WebhookKey` | `DODO_PAYMENTS_WEBHOOK_KEY` | false | - |
| `BaseUrl` | `DODO_PAYMENTS_BASE_URL` | true | `"https://live.dodopayments.com"` |

如果既未设置 `BearerToken`，也未设置 `DODO_PAYMENTS_API_KEY`，客户端会抛出 `DodoPaymentsInvalidDataException`。`WebhookKey` 保存 webhook signing secret，但 C# SDK 没有验证 webhook signatures 的方法。要验证它们，请参阅 [Webhooks](/developer-resources/webhooks)。

### 手动配置

在客户端上设置属性，以覆盖环境变量：

```csharp theme={null}
DodoPaymentsClient client = new() { BearerToken = "My Bearer Token" };
```

### 环境

客户端默认连接到 live mode（`https://live.dodopayments.com`）。要使用 test mode（`https://test.dodopayments.com`），请将 `BaseUrl` 设置为 `EnvironmentUrl.TestMode`：

```csharp theme={null}
using DodoPayments.Client.Core;

DodoPaymentsClient client = new() { BaseUrl = EnvironmentUrl.TestMode };
```

### 重试

SDK 会重试连接错误，以及状态为 408、409、429 或 500 及以上的响应。默认重试两次，并使用指数退避。设置 `MaxRetries` 可更改重试次数，或将其设置为 `0` 以关闭重试：

```csharp theme={null}
// Custom retry count
DodoPaymentsClient client = new() { MaxRetries = 3 };
```

### 超时

默认情况下，每次请求尝试会在 1 分钟后超时。超时时间不包括重试。设置 `Timeout` 可更改该值：

```csharp theme={null}
DodoPaymentsClient client = new() { Timeout = TimeSpan.FromSeconds(30) };
```

### 单个请求的覆盖设置

要更改单次调用的设置，请在客户端或服务上调用 `WithOptions`。该方法会返回一个修改后的副本，并与原客户端共享同一个连接池；原客户端不会发生变化：

```csharp theme={null}
var response = await client
    .WithOptions(options => options with
    {
        Timeout = TimeSpan.FromSeconds(10),
        MaxRetries = 5,
    })
    .CheckoutSessions.Create(parameters);
```

## 常见操作

本节中的示例使用 [快速开始](#quick-start) 中的 `client`。

### 创建结账会话

创建结账会话，然后将客户重定向到返回的 `CheckoutUrl`：

```csharp theme={null}
var parameters = new CheckoutSessionCreateParams
{
    ProductCart =
    [
        new()
        {
            ProductID = "pdt_123",
            Quantity = 1
        }
    ],
    ReturnUrl = "https://yourdomain.com/return"
};

var session = await client.CheckoutSessions.Create(parameters);
Console.WriteLine($"Checkout URL: {session.CheckoutUrl}");
```

每个结账 URL 只能使用一次，并会在 24 小时后过期。有关每个会话选项，请参阅 [Checkout Sessions](/developer-resources/checkout-session)。

### 管理客户

使用电子邮件地址和姓名创建客户，然后通过 ID 获取该客户：

```csharp theme={null}
using DodoPayments.Client.Models.Customers;

// Create a customer
var customer = await client.Customers.Create(new CustomerCreateParams
{
    Email = "customer@example.com",
    Name = "John Doe"
});

// Retrieve customer
var retrieved = await client.Customers.Retrieve(new CustomerRetrieveParams { CustomerID = "cus_123" });
Console.WriteLine($"Customer: {retrieved.Name} ({retrieved.Email})");
```

`Customers.Retrieve` 也接受字符串形式的 ID，例如 `client.Customers.Retrieve("cus_123")`。

### 处理订阅

创建订阅，然后在其为按需订阅时向其收费。

<Warning>
  `POST /subscriptions`（SDK 的 `Subscriptions.Create` 方法）已被弃用。它仍适用于现有集成，但新集成应通过 [Checkout Session](/developer-resources/checkout-session) 创建订阅。
</Warning>

```csharp theme={null}
using DodoPayments.Client.Models.Payments;
using DodoPayments.Client.Models.Subscriptions;

// Create a subscription
var subscription = await client.Subscriptions.Create(new SubscriptionCreateParams
{
    Billing = new BillingAddress
    {
        Country = "US",
        City = "San Francisco",
        State = "CA",
        Street = "1 Market St",
        Zipcode = "94105",
    },
    Customer = new AttachExistingCustomer { CustomerID = "cus_123" },
    ProductID = "pdt_456",
    Quantity = 1,
});

// Charge an on-demand subscription
// ProductPrice is in the lowest currency denomination (e.g., 2500 = $25.00 USD)
var charge = await client.Subscriptions.Charge(new SubscriptionChargeParams
{
    SubscriptionID = subscription.SubscriptionID,
    ProductPrice = 2500,
});
```

<Info>
  `Billing` 只需要 `Country`，即两字母 ISO 国家代码。`Customer` 接受 `AttachExistingCustomer` 以关联现有客户，或接受 `NewCustomer` 以创建客户。`Charge` 用于[按需订阅](/developer-resources/ondemand-subscriptions)，而 `ProductPrice` 使用最小货币单位表示。
</Info>

## 错误处理

当 API 返回错误状态时，SDK 会抛出 `DodoPaymentsApiException` 的子类，该类包含 `StatusCode` 和 `ResponseBody` 属性。异常类取决于状态码。所有 4xx 异常都继承自 `DodoPayments4xxException`。

| Status | Exception |
| - | - |
| 400 | `DodoPaymentsBadRequestException` |
| 401 | `DodoPaymentsUnauthorizedException` |
| 403 | `DodoPaymentsForbiddenException` |
| 404 | `DodoPaymentsNotFoundException` |
| 422 | `DodoPaymentsUnprocessableEntityException` |
| 429 | `DodoPaymentsRateLimitException` |
| 5xx | `DodoPayments5xxException` |
| others | `DodoPaymentsUnexpectedStatusCodeException` |

没有专属类的 4xx 状态（例如 409）会抛出 `DodoPayments4xxException`。`DodoPaymentsUnexpectedStatusCodeException` 覆盖 4xx 和 5xx 范围之外的状态。

SDK 还会抛出以下异常：

* `DodoPaymentsIOException`：I/O 或网络错误。
* `DodoPaymentsInvalidDataException`：SDK 无法解析响应数据，例如缺少必需属性时。
* `DodoPaymentsException`：所有 SDK 异常的基类。

## 分页

列表方法会返回一页结果。你可以遍历每个项目，也可以自行在各页面之间移动。

### 自动分页

`Paginate` 返回一个 `IAsyncEnumerable`，并在需要时获取下一页：

```csharp theme={null}
var page = await client.Payments.List();
await foreach (var item in page.Paginate())
{
    Console.WriteLine(item);
}
```

### 手动分页

要逐页处理，请读取 `Items`，然后调用 `HasNext()` 和 `Next()`：

```csharp theme={null}
var page = await client.Payments.List();
while (true)
{
    foreach (var item in page.Items)
    {
        Console.WriteLine(item);
    }
    if (!page.HasNext())
    {
        break;
    }
    page = await page.Next();
}
```

要设置页面大小，请从 `DodoPayments.Client.Models.Payments` 命名空间传入一个 `PaymentListParams`，例如 `client.Payments.List(new PaymentListParams { PageSize = 50 })`。

## ASP.NET Core 集成

在依赖注入容器中将一个客户端注册为单例，并从配置中读取 API key：

```csharp Program.cs theme={null}
using DodoPayments.Client;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<DodoPaymentsClient>(sp =>
{
    var configuration = sp.GetRequiredService<IConfiguration>();
    return new DodoPaymentsClient
    {
        BearerToken = configuration["DodoPayments:ApiKey"]
    };
});

var app = builder.Build();
app.Run();
```

将 key 添加到配置中，例如添加到 `appsettings.json`：

```json appsettings.json theme={null}
{
  "DodoPayments": {
    "ApiKey": "your_api_key_here"
  }
}
```

<Tip>
  在开发环境中，请使用 [user secrets](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets) 存储 key，而不是将其存储在 `appsettings.json` 中：

  ```bash theme={null}
  dotnet user-secrets init
  dotnet user-secrets set "DodoPayments:ApiKey" "your_api_key_here"
  ```
</Tip>

## 资源

<CardGroup cols={2}>
  <Card title="NuGet Package" icon="box" href="https://www.nuget.org/packages/DodoPayments.Client">
    软件包版本和安装命令。
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/dodopayments/dodopayments-csharp">
    源代码、版本发布和示例。
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    每个 endpoint、参数和响应。
  </Card>

  <Card title="Discord Community" icon="discord" href="https://discord.gg/bYqAp4ayYh">
    提出问题并与其他开发者交流。
  </Card>
</CardGroup>

## 支持

如需 C# SDK 帮助：

* **Discord**：加入[社区服务器](https://discord.gg/bYqAp4ayYh)获取实时帮助。
* **Email**：联系 [support@dodopayments.com](mailto:support@dodopayments.com)。
* **GitHub**：在[代码仓库](https://github.com/dodopayments/dodopayments-csharp)中提交 issue。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.