# PHP 示例

## 配置

```php
<?php

$EASEBG_API_KEY = getenv('EASEBG_API_KEY') ?: 'your_api_key_here';
$EASEBG_API_BASE = getenv('EASEBG_API_BASE') ?: 'https://api.easebg.com/api/v1';

function apiRequest(string $method, string $path, ?array $body = null): array {
    global $EASEBG_API_KEY, $EASEBG_API_BASE;

    $ch = curl_init($EASEBG_API_BASE . $path);

    $headers = [
        'X-API-Key: ' . $EASEBG_API_KEY,
        'Content-Type: application/json',
    ];

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_TIMEOUT        => 30,
    ]);

    if ($body !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    if ($error) {
        throw new RuntimeException("cURL error: $error");
    }

    $data = json_decode($response, true);

    if ($httpCode >= 400) {
        $errorMsg = $data['error']['message'] ?? 'Unknown error';
        $errorCode = $data['error']['code'] ?? 'UNKNOWN';
        throw new EaseBGApiException($httpCode, $errorCode, $errorMsg);
    }

    return $data;
}

class EaseBGApiException extends Exception {
    public string $code;
    public function __construct(int $statusCode, string $code, string $message) {
        parent::__construct("[$code] $message", $statusCode);
        $this->code = $code;
    }
}
```

## 1. 创建抠图任务

```php
function createTask(string $imageUrl, string $modelVersion = 'easebg-2.0', ?string $callbackUrl = null): array {
    $payload = [
        'imageUrl' => $imageUrl,
        'modelVersion' => $modelVersion,
    ];
    if ($callbackUrl) {
        $payload['callbackUrl'] = $callbackUrl;
    }

    return apiRequest('POST', '/open/developer/tasks', $payload);
}

// 使用示例
try {
    $result = createTask('https://example.com/photo.jpg', null, 'https://your-app.com/webhooks/easebg');
    echo "Task created: " . $result['data']['id'] . "\n";
} catch (EaseBGApiException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
```

## 2. 查询任务状态

```php
function getTask(string $taskId): array {
    return apiRequest('GET', '/open/developer/tasks/' . $taskId);
}

function waitForTask(string $taskId, int $intervalMs = 2000, int $maxAttempts = 60): array {
    for ($i = 0; $i < $maxAttempts; $i++) {
        $result = getTask($taskId);
        $status = $result['data']['status'];

        if ($status === 'succeeded') {
            return $result['data'];
        }
        if ($status === 'failed') {
            throw new RuntimeException("Task failed: " . ($result['data']['errorMessage'] ?? 'Unknown'));
        }

        usleep($intervalMs * 1000);
    }
    throw new RuntimeException("Task timed out");
}
```

## 3. 获取任务结果

```php
function downloadResult(string $taskId, string $outputPath): void {
    $result = getTask($taskId);
    $data = $result['data'];

    if ($data['status'] !== 'succeeded' || empty($data['resultUrl'])) {
        throw new RuntimeException("Task not completed or no result");
    }

    $imageData = file_get_contents($data['resultUrl']);
    if ($imageData === false) {
        throw new RuntimeException("Failed to download result");
    }

    file_put_contents($outputPath, $imageData);
    echo "Result saved to $outputPath\n";
}
```

## 4. 取消任务

```php
function cancelTask(string $taskId): void {
    global $EASEBG_API_BASE, $EASEBG_API_KEY;
    $ch = curl_init($EASEBG_API_BASE . '/open/developer/tasks/' . $taskId);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST  => 'DELETE',
        CURLOPT_HTTPHEADER     => ['X-API-Key: ' . $EASEBG_API_KEY],
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    switch ($httpCode) {
        case 204:
            echo "Task canceled successfully\n";
            break;
        case 409:
            throw new RuntimeException("Task cannot be canceled in current state");
        default:
            throw new RuntimeException("Cancel failed: HTTP $httpCode");
    }
}
```

## 5. 创建批量任务

```php
function createBatchTask(array $imageUrls, string $modelVersion = 'easebg-2.0', ?string $callbackUrl = null): array {
    $payload = [
        'imageUrls' => $imageUrls,
        'modelVersion' => $modelVersion,
    ];
    if ($callbackUrl) {
        $payload['callbackUrl'] = $callbackUrl;
    }

    return apiRequest('POST', '/open/developer/batch-tasks', $payload);
}

// 使用示例
$batch = createBatchTask([
    'https://example.com/photo1.jpg',
    'https://example.com/photo2.jpg',
    'https://example.com/photo3.jpg',
], 'easebg-2.0', 'https://your-app.com/webhooks/easebg');
```

## 6. Webhook 签名验证

```php
function verifyWebhookSignature(string $payload, string $signature, string $secret): bool {
    $computed = hash_hmac('sha256', $payload, $secret);
    return hash_equals($computed, $signature);
}

// 在 Webhook 接收端点中使用
/*
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_EASEBG_SIGNATURE'] ?? '';
$secret = getenv('EASEBG_WEBHOOK_SECRET');

if (!verifyWebhookSignature($payload, $signature, $secret)) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}

$event = json_decode($payload, true);
error_log("Received webhook: " . $event['event'] . " - " . $event['taskId']);

switch ($event['event']) {
    case 'task.succeeded':
        error_log("Result URL: " . ($event['resultUrl'] ?? ''));
        break;
    case 'task.failed':
        error_log("Error: " . ($event['errorMessage'] ?? ''));
        break;
}

http_response_code(200);
echo json_encode(['received' => true]);
*/
```

## 7. 错误处理

```php
try {
    $result = apiRequest('POST', '/open/developer/tasks', [
        'imageUrl' => 'https://example.com/photo.jpg',
    ]);
} catch (EaseBGApiException $e) {
    switch ($e->code) {
        case 'INSUFFICIENT_CREDITS':
            echo "积分不足，请充值\n";
            break;
        case 'RATE_LIMIT_EXCEEDED':
            echo "请求频率超限，请稍后重试\n";
            break;
        case 'INVALID_API_KEY':
            echo "API Key 无效\n";
            break;
        default:
            echo "API 错误: " . $e->getMessage() . "\n";
    }
} catch (RuntimeException $e) {
    echo "网络错误: " . $e->getMessage() . "\n";
}
```

## 8. 分页查询

```php
function listTasks(int $page = 1, int $pageSize = 20, ?string $status = null): array {
    $queryParams = http_build_query(array_filter([
        'page' => $page,
        'pageSize' => $pageSize,
        'status' => $status,
    ]));

    return apiRequest('GET', '/open/developer/tasks?' . $queryParams);
}

function getAllTasks(?string $status = null): array {
    $allTasks = [];
    $page = 1;
    $totalPages = 1;

    while ($page <= $totalPages) {
        $result = listTasks($page, 20, $status);
        $allTasks = array_merge($allTasks, $result['data']);
        $totalPages = $result['meta']['totalPages'];
        $page++;
    }

    return $allTasks;
}
```
