# PHP / Laravel SDK

基于当前公共接口文档整理的 PHP / Laravel SDK，覆盖：

- 创建收款订单
- 查询收款订单状态
- 创建独享钱包
- 创建代付订单
- 请求签名
- 回调验签

## 目录结构

- `src/UUGateClient.php`：主客户端
- `src/Support/Signature.php`：开放接口签名工具
- `src/Support/CallbackVerifier.php`：回调验签工具
- `src/UUGateServiceProvider.php`：Laravel 服务提供者
- `src/Facades/UUGate.php`：Laravel Facade
- `config/uugate-sdk.php`：Laravel 配置

## 在 Laravel 中接入

如果直接从当前仓库引入，可以在 Laravel 项目里配置本地 path 仓库：

```bash
composer config repositories.uugate-sdk path ./sdk/php-laravel
composer require uugate/openapi-laravel-sdk:*
```

发布配置：

```bash
php artisan vendor:publish --tag=uugate-sdk-config
```

`.env` 示例：

```dotenv
UUGATE_BASE_URL=https://api.uugate.com
UUGATE_MERCHANT_UID=880001
UUGATE_API_KEY=mch_xxxxxxxxxxxxxxxxxxxx
UUGATE_TIMEOUT=10
UUGATE_CONNECT_TIMEOUT=5
```

## Laravel 用法

```php
use UUGate\OpenApi\Facades\UUGate;

$order = UUGate::createPayinOrder([
    'chainCode' => 'TRON',
    'tokenSymbol' => 'USDT',
    'merchantOrderNo' => 'M202604170001',
    'amount' => '100.00',
    'notifyUrl' => 'https://merchant.example.com/api/uugate/payin-notify',
]);
```

## 可用方法

```php
$client->createPayinOrder(array $payload);
$client->getPayinOrder(string $orderNo);
$client->createExclusiveBinding(array $payload);
$client->createPayoutOrder(array $payload);
$client->request(string $method, string $path, ?array $body = null, array $query = []);
$client->verifyCallbackSignature(array $headers, string $rawBody, ?string $apiKey = null);
```

## 回调验签

回调使用创建该订单时的 API Key，无需额外配置密钥。`$client->verifyCallbackSignature($headers, $rawBody)` 默认读取 `api_key`；可通过第三个参数指定原订单使用的 API Key。轮换前应处理完未完成订单。接收端还需检查时间戳（建议 5 分钟）、nonce 和订单幂等性。

```php
use UUGate\OpenApi\Support\CallbackVerifier;

$rawBody = $request->getContent();
$valid = CallbackVerifier::verify(
    apiKey: config('uugate-sdk.api_key'),
    timestamp: $request->header('x-callback-timestamp'),
    nonce: $request->header('x-callback-nonce'),
    signature: $request->header('x-callback-signature'),
    rawBody: $rawBody,
);
```

注意：

- 验签必须使用原始请求体字符串 `$request->getContent()`。
- `notifyUrl` 是创建收款订单和创建代付订单时的必填字段，平台会按订单维度回调到对应地址。
- `createExclusiveBinding(array $payload)` 也支持可选 `notifyUrl`，用于给这条专属地址绑定独立的会员充值回调地址；同一 `bindKey` 重复提交会幂等返回同一条绑定和地址。
- `getPayinOrder(string $orderNo)` 在会员充值场景下会返回 `bindKey`；`deposit_completed` 回调也会带上 `bindKey`，可直接用来定位会员。
- SDK 使用和服务端一致的 HMAC-SHA256、规范化路径、规范化 query、规范化 JSON 规则。
