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

# PHP SDK 快速入门：KYC、AML 与交易监控集成

> Didit 官方 PHP SDK 快速入门：通过任意 PSR-18 HTTP 客户端类型化调用服务端 API，并进行 Webhook 验证与 token 校验。

这是 Didit 官方的 PHP 库。它需要 PHP 8.1 或更高版本，并可与任何 PSR-18 HTTP 客户端配合使用，Guzzle 是常用的选择。有关所有 SDK 共享的内容，请参阅[服务端 SDK 概览](https://docs.didit.me/zh/integration/server-sdks/overview.md)。

## 安装

```bash theme={null}
composer require didit-protocol/sdk-php guzzlehttp/guzzle
```

该包发布在 [Packagist 上的 `didit-protocol/sdk-php`](https://packagist.org/packages/didit-protocol/sdk-php)。其源代码和更新日志位于 GitHub 上的 [didit-protocol/sdk-php](https://github.com/didit-protocol/sdk-php)。

基于 [Authentication](#验证-authentication-令牌) 的令牌验证还需要 `openssl` 扩展。

## 配置客户端

`new DiditClient()` 会从环境变量中读取 `DIDIT_API_KEY`。如需覆盖它，或设置应用级调用（案件、网络、监管报告）所需的组织和应用 ID，请传入具名参数。请求字段是使用 API 自身字段名的一个数组；响应则是只读对象，具有驼峰式属性和 `toArray()` 方法。

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

require 'vendor/autoload.php';

use Didit\DiditClient;
use Didit\RequestOptions;

$didit = new DiditClient(
    apiKey: getenv('DIDIT_API_KEY') ?: null,
    organizationId: getenv('DIDIT_ORGANIZATION_ID') ?: null,
    applicationId: getenv('DIDIT_APPLICATION_ID') ?: null,
    timeout: 30.0,
    maxRetries: 2,
);

// Options for a single call.
$decision = $didit->sessions->retrieveDecision(
    '11111111-2222-3333-4444-555555555555',
    [],
    new RequestOptions(timeout: 5.0, maxRetries: 0),
);
echo $decision->status, "\n";
```

## 创建会话

为某个工作流创建[验证会话](https://docs.didit.me/zh/sessions-api/create-session.md)，并将用户引导至其 URL。

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

require 'vendor/autoload.php';

use Didit\DiditClient;

$didit = new DiditClient();

$session = $didit->sessions->create([
    'workflow_id' => '11111111-2222-3333-4444-555555555555',
    'vendor_data' => 'user-123',
    'callback' => 'https://example.com/verification/done',
]);
echo $session->url, "\n";
```

## 读取决策

用户完成操作后（或收到 Webhook 时），请[读取决策](https://docs.didit.me/zh/sessions-api/retrieve-session.md)。每个功能结果都是一个列表，每个工作流节点对应一个条目。

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

require 'vendor/autoload.php';

use Didit\DiditClient;

$didit = new DiditClient();

$decision = $didit->sessions->retrieveDecision('11111111-2222-3333-4444-555555555555');
echo $decision->status, "\n";
foreach ($decision->idVerifications ?? [] as $verification) {
    echo $verification->status, "\n";
}
```

## 验证 Webhook

传入原始请求体（按接收时的原样）和请求头。对于任何不是有效且及时的投递，`verify` 都会抛出 `WebhookVerificationException`；否则返回类型化的事件。

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

require 'vendor/autoload.php';

use Didit\DiditClient;
use Didit\Exception\WebhookVerificationException;
use Didit\Webhooks\Events\StatusUpdatedEvent;
use Psr\Http\Message\MessageInterface;

$didit = new DiditClient();

/** @param array<string, string|list<string>>|MessageInterface $headers */
function handleWebhook(DiditClient $didit, string $rawBody, array|MessageInterface $headers, string $secret): int
{
    try {
        $event = $didit->webhooks->verify($rawBody, $headers, $secret);
    } catch (WebhookVerificationException $e) {
        error_log('rejected: ' . $e->reason);
        return 400;
    }
    if ($event instanceof StatusUpdatedEvent) {
        error_log($event->sessionId . ' ' . $event->status);
    }
    return 200;
}

http_response_code(handleWebhook(
    $didit,
    (string) file_get_contents('php://input'),
    getallheaders(),
    (string) getenv('DIDIT_WEBHOOK_SECRET'),
));
```

在 Laravel 和 Symfony 中，传入 `$request->getContent()` 和 `$request->headers->all()`；使用 PSR-7 请求时，直接将请求对象本身作为请求头传入。轮换密钥期间，请同时传入两者：`[$newSecret, $oldSecret]`。有关事件和签名方案，请参阅 [Webhook](https://docs.didit.me/zh/integration/webhooks.md)。

## 交易筛查

将付款、提现或加密货币转账提交至[交易监控](https://docs.didit.me/zh/transaction-monitoring/overview.md)；响应中包含其状态和风险评分。

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

require 'vendor/autoload.php';

use Didit\DiditClient;

$didit = new DiditClient();

$transaction = $didit->transactions->create([
    'transaction_id' => 'txn-1001',
    'transaction_category' => 'finance',
    'transaction_details' => ['direction' => 'outbound', 'amount' => 1500.0, 'currency' => 'EUR'],
    'subject' => ['entity_type' => 'individual', 'vendor_data' => 'user-123', 'full_name' => 'Maria Garcia'],
]);
echo $transaction->status, ' ', $transaction->score, "\n";
```

## 验证 Authentication 令牌

`Authentication` 会在您的后端检查您的 [Authentication](https://docs.didit.me/zh/authentication/overview.md) 颁发方所签名的访问令牌，无需为每个请求调用 Didit。传入 PSR-16 缓存，使颁发方的密钥只获取一次，而不是每次请求都获取。它还可以交换授权码、刷新令牌、检查和撤销会话，以及执行加强认证。

> [!NOTE]
>
> 令牌验证会针对您应用的颁发方和签名密钥，执行[在您的服务器上验证令牌](https://docs.didit.me/zh/authentication/tokens-and-jwks.md#在服务器上验证令牌)中的各项检查。

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

require 'vendor/autoload.php';

use Didit\Authentication\Authentication;
use Didit\Authentication\TokenVerificationException;

// The publishable key (pk_live_... or pk_test_...) carries your issuer URL.
$auth = Authentication::fromPublishableKey('pk_live_...');

function currentUser(Authentication $auth, string $accessToken): ?string
{
    try {
        $claims = $auth->verifyAccessToken($accessToken, audience: 'your-application-id');
    } catch (TokenVerificationException $e) {
        error_log('rejected: ' . $e->reason);
        return null;
    }
    return $claims->sub;
}
```

## 错误

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

require 'vendor/autoload.php';

use Didit\DiditClient;
use Didit\Exception\ApiStatusException;
use Didit\Exception\NotFoundException;

$didit = new DiditClient();

try {
    $didit->sessions->retrieveDecision('11111111-2222-3333-4444-555555555555');
} catch (NotFoundException $e) {
    echo "no such session\n";
} catch (ApiStatusException $e) {
    echo $e->status, ' ', $e->requestId, "\n";
}
```

## 列表和文件

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

require 'vendor/autoload.php';

use Didit\DiditClient;
use Didit\File;

$didit = new DiditClient();

// Lists page through every result.
foreach ($didit->sessions->list(['status' => 'Approved']) as $session) {
    echo $session->sessionId, "\n";
}

// Uploads take File::fromPath, File::fromBytes or File::fromStream.
$result = $didit->idVerification->verify([
    'front_image' => File::fromPath('id-front.jpg'),
    'back_image' => File::fromPath('id-back.jpg'),
]);
print_r($result->toArray());
```

[API 参考](https://docs.didit.me/zh/api-reference/overview.md)中的服务端端点页面，都为其操作提供了 PHP 示例，但 1.0.1 版本尚未发布的端点和字段除外，这些内容在[概览](https://docs.didit.me/zh/integration/server-sdks/overview.md)中有所列明。


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