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

# PHP

> 将 Dodo Payments 集成到您的 PHP 应用程序中，使用现代的、符合 PSR-4 的 SDK

PHP SDK 提供了一种强大而灵活的方式，将 Dodo Payments 集成到您的 PHP 应用程序中。它遵循现代 PHP 标准，使用 PSR-4 自动加载，提供广泛的测试覆盖和详细的文档。

## 安装

使用 Composer 安装 SDK：

```bash theme={null}
composer require "dodopayments/client 6.7.1"
```

<Info>
  SDK 需要 PHP 8.1.0 或更高版本，并使用 Composer 管理依赖项。
</Info>

## 快速开始

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

```php theme={null}
<?php

use Dodopayments\Client;

$client = new Client(
  bearerToken: getenv('DODO_PAYMENTS_API_KEY') ?: 'My Bearer Token',
  environment: 'test_mode',
);

$checkoutSessionResponse = $client->checkoutSessions->create(
  productCart: [["productID" => "product_id", "quantity" => 1]]
);

var_dump($checkoutSessionResponse->session_id);
```

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

## 核心功能

<CardGroup cols={2}>
  <Card title="PSR-4 Compliant" icon="check">
    遵循现代 PHP 开发的 PHP 标准建议
  </Card>

  <Card title="Modern PHP" icon="php">
    为 PHP 8.1+ 构建，包含类型声明和严格类型
  </Card>

  <Card title="Extensive Testing" icon="vial">
    提供全面的测试覆盖，确保可靠性和稳定性
  </Card>

  <Card title="Exception Handling" icon="shield-check">
    为不同错误场景提供清晰的异常类型
  </Card>
</CardGroup>

## 值对象

SDK 使用命名参数指定可选参数。您可以使用静态 `with` 构造函数初始化值对象：

```php theme={null}
<?php

use Dodopayments\Customers\AttachExistingCustomer;

// Recommended: Use static 'with' constructor with named parameters
$customer = AttachExistingCustomer::with(customerID: "customer_id");
```

也可以使用构建器作为可选模式：

```php theme={null}
<?php

use Dodopayments\Customers\AttachExistingCustomer;

// Alternative: Use builder pattern
$customer = (new AttachExistingCustomer)->withCustomerID("customer_id");
```

## 配置

### 重试配置

某些错误默认为自动重试 2 次，并进行短暂的指数退避。以下错误会触发自动重试：

* 连接错误（网络连接问题）
* 408 请求超时
* 409 冲突
* 429 速率限制
* 500 以上的内部错误
* 超时

全局或针对每个请求配置重试行为：

```php theme={null}
<?php

use Dodopayments\Client;

// Configure default for all requests (disable retries)
$client = new Client(requestOptions: ['maxRetries' => 0]);

// Or, configure per-request
$result = $client->checkoutSessions->create(
  productCart: [["productID" => "product_id", "quantity" => 1]],
  requestOptions: ['maxRetries' => 5],
);
```

## 常见操作

### 创建结账会话

生成结账会话：

```php theme={null}
$session = $client->checkoutSessions->create(
  productCart: [
    ["productID" => "prod_123", "quantity" => 1]
  ],
  returnUrl: "https://yourdomain.com/return"
);

header('Location: ' . $session->checkout_url);
```

### 管理客户

创建并检索客户信息：

```php theme={null}
// Create a customer
$customer = $client->customers->create(
  email: "customer@example.com",
  name: "John Doe",
  metadata: [
    "user_id" => "12345"
  ]
);

// Retrieve customer
$customer = $client->customers->retrieve("cus_123");
echo "Customer: {$customer->name} ({$customer->email})";
```

### 处理订阅

创建并管理循环订阅：

```php theme={null}
use Dodopayments\Customers\AttachExistingCustomer;
use Dodopayments\Payments\BillingAddress;

// Create a subscription
$subscription = $client->subscriptions->create(
  billing: BillingAddress::with(
    country: 'US',
    city: 'San Francisco',
    state: 'CA',
    street: '1 Market St',
    zipcode: '94105',
  ),
  customer: AttachExistingCustomer::with(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)
$charge = $client->subscriptions->charge(
  $subscription->subscription_id,
  productPrice: 2500,
);
```

<Info>
  `billing` 至少需要两个字母的 ISO `country` 代码。传递 `AttachExistingCustomer::with(customerID: '...')` 来附加一个现有客户，或传递 `NewCustomer::with(email: '...', name: '...')` 来创建一个客户。`productPrice` 是最低货币面额。
</Info>

## 分页

处理分页列表响应：

```php theme={null}
$page = $client->payments->list();

var_dump($page);

// Fetch items from the current page
foreach ($page->getItems() as $item) {
  var_dump($item->brand_id);
}

// Auto-paginate: fetch items from all pages
foreach ($page->pagingEachItem() as $item) {
  var_dump($item->brand_id);
}
```

## 错误处理

当库无法连接到 API 或收到失败状态码（4xx 或 5xx）时，将抛出 `APIException` 的子类异常：

```php theme={null}
<?php

use Dodopayments\Core\Exceptions\APIConnectionException;
use Dodopayments\Core\Exceptions\RateLimitException;
use Dodopayments\Core\Exceptions\APIStatusException;

try {
  $checkoutSessionResponse = $client->checkoutSessions->create(
    productCart: [["productID" => "product_id", "quantity" => 1]]
  );
} catch (APIConnectionException $e) {
  echo "The server could not be reached", PHP_EOL;
  var_dump($e->getPrevious());
} catch (RateLimitException $_) {
  echo "A 429 status code was received; we should back off a bit.", PHP_EOL;
} catch (APIStatusException $e) {
  echo "Another non-200-range status code was received", PHP_EOL;
  echo $e->getMessage();
}
```

### 错误类型

| 原因          | 错误类型                           |
| ----------- | ------------------------------ |
| HTTP 400    | `BadRequestException`          |
| HTTP 401    | `AuthenticationException`      |
| HTTP 403    | `PermissionDeniedException`    |
| HTTP 404    | `NotFoundException`            |
| HTTP 409    | `ConflictException`            |
| HTTP 422    | `UnprocessableEntityException` |
| HTTP 429    | `RateLimitException`           |
| HTTP >= 500 | `InternalServerException`      |
| 其他 HTTP 错误  | `APIStatusException`           |
| 超时          | `APITimeoutException`          |
| 网络错误        | `APIConnectionException`       |

<Tip>
  始终在 try-catch 块中包装 API 调用，以便优雅地处理潜在错误并为用户提供有意义的反馈。
</Tip>

## 高级用法

### 未记录的端点

请求未记录的端点：

```php theme={null}
<?php

$response = $client->request(
  method: "post",
  path: '/undocumented/endpoint',
  query: ['dog' => 'woof'],
  headers: ['useful-header' => 'interesting-value'],
  body: ['hello' => 'world']
);
```

### 未记录的参数

向任何端点发送未记录的参数或读取未记录的响应属性：

```php theme={null}
<?php

use Dodopayments\RequestOptions;

$checkoutSessionResponse = $client->checkoutSessions->create(
  productCart: [["productID" => "product_id", "quantity" => 1]],
  requestOptions: [
    'extraQueryParams' => ["my_query_parameter" => "value"],
    'extraBodyParams' => ["my_body_parameter" => "value"],
    'extraHeaders' => ["my-header" => "value"],
  ],
);
```

<Note>
  同名的 `extra*` 参数将覆盖记录的参数。
</Note>

## 框架集成

### Laravel

为 Laravel 应用程序创建一个服务：

```php theme={null}
<?php

namespace App\Services;

use Dodopayments\Client;

class PaymentService
{
    protected $client;

    public function __construct()
    {
        $this->client = new Client(
            bearerToken: config('services.dodo.api_key')
        );
    }

    public function createCheckout(array $items)
    {
        return $this->client->checkoutSessions->create(
            productCart: $items,
            returnUrl: route('checkout.return')
        );
    }
}
```

在 `config/services.php` 中添加配置：

```php theme={null}
'dodo' => [
    'api_key' => env('DODO_API_KEY'),
    'environment' => env('DODO_ENVIRONMENT', 'sandbox')
],
```

### Symfony

在 Symfony 中创建一个服务：

```php theme={null}
<?php

namespace App\Service;

use Dodopayments\Client;

class DodoPaymentService
{
    private Client $client;

    public function __construct(string $apiKey)
    {
        $this->client = new Client(bearerToken: $apiKey);
    }

    public function createPayment(int $amount, string $currency, string $customerId): object
    {
        return $this->client->payments->create(
            amount: $amount,
            currency: $currency,
            customerID: $customerId
        );
    }
}
```

在 `config/services.yaml` 中注册：

```yaml theme={null}
services:
  App\Service\DodoPaymentService:
    arguments:
      $apiKey: "%env(DODO_API_KEY)%"
```

## 资源

<CardGroup cols={2}>
  <Card title="GitHub Repository" icon="github" href="https://github.com/dodopayments/dodopayments-php">
    查看源代码并进行贡献
  </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-php/issues">
    报告错误或请求功能
  </Card>
</CardGroup>

## 支持

需要 PHP SDK 的帮助？

* **Discord**: 加入我们的[社区服务器](https://discord.gg/bYqAp4ayYh)，以获得实时支持
* **电子邮件**: 通过 [support@dodopayments.com](mailto:support@dodopayments.com) 联系我们
* **GitHub**: 在[仓库](https://github.com/dodopayments/dodopayments-php)上打开一个问题

## 贡献

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