PHP code example of westng / doudian-sdk

1. Go to this page and download the library: Download westng/doudian-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

westng / doudian-sdk example snippets



DouDianSdk\Core\Client\DouDianSdk;

// 初始化SDK
$sdk = new DouDianSdk('your_app_key', 'your_app_secret');

// 获取访问令牌 (通过店铺ID)
$accessToken = $sdk->getAccessToken('your_shop_id', 2); // 2 = 店铺ID模式

// 检查令牌是否获取成功
if (!$accessToken->isSuccess()) {
    throw new Exception('获取访问令牌失败: ' . $accessToken->getMessage());
}

// 调用API - 获取订单列表
$result = $sdk->callApi(
    'order_searchList\OrderSearchListRequest',
    'order_searchList\param\OrderSearchListParam',
    [
        'page' => 1,
        'size' => 20,
        'order_status' => 1,
        'start_time' => date('Y-m-d H:i:s', strtotime('-7 days')),
        'end_time' => date('Y-m-d H:i:s'),
    ],
    $accessToken
);

// 处理结果
if (isset($result['code']) && $result['code'] === 10000) {
    echo "获取订单成功\n";
    print_r($result['data']);
}



use DouDianSdk\Core\Client\DouDianSdk;

$appASdk = new DouDianSdk($appAKey, $appASecret);
$appBSdk = new DouDianSdk($appBKey, $appBSecret);

$appAResult = $appASdk->callApi(
    'order_searchList\OrderSearchListRequest',
    'order_searchList\param\OrderSearchListParam',
    ['page' => 1, 'size' => 10],
    $appAAccessToken
);

$appBResult = $appBSdk->callApi(
    'order_searchList\OrderSearchListRequest',
    'order_searchList\param\OrderSearchListParam',
    ['page' => 1, 'size' => 10],
    $appBAccessToken
);


use DouDianSdk\Core\Client\DouDianSdk;

$sdk = new DouDianSdk('your_app_key', 'your_app_secret', [
    'debug' => true,
    'timeout' => [
        'connect' => 5000,  // 连接超时5秒
        'read' => 10000     // 读取超时10秒
    ],
    'retry' => [
        'enable' => true,
        'max_times' => 3,
        'interval' => 1000
    ],
    // Swoole 环境连接池配置
    'pool' => [
        'max_connections' => 50,  // 最大连接数
        'max_idle_time' => 60,    // 空闲超时(秒)
        'wait_timeout' => 3.0     // 等待超时(秒)
    ]
]);

// 每次 HTTP 请求
$client = $pool->get();      // 1. 从池获取连接(或等待)
try {
    $response = $client->request(...);  // 2. 发送请求
    return $response;
} finally {
    $pool->put($client);     // 3. 归还连接(无论成功失败)
}


use DouDianSdk\Core\Client\DouDianSdk;

// 方式1:构造函数配置
$sdk = new DouDianSdk('your_app_key', 'your_app_secret', [
    'pool' => [
        'max_connections' => 50,   // 最大连接数(默认50)
        'max_idle_time' => 60,     // 空闲超时秒数(默认60)
        'wait_timeout' => 3.0      // 等待超时秒数(默认3.0)
    ]
]);

// 方式2:运行时配置
$sdk->setPoolConfig(100, 120, 5.0);


use DouDianSdk\Core\Client\DouDianSdk;

// 初始化 SDK(在 Worker 启动时)
$sdk = new DouDianSdk('your_app_key', 'your_app_secret', [
    'pool' => ['max_connections' => 50]
]);

$count = 0;

while (true) {
    $job = $queue->pop();
    
    // 每个协程共享同一个连接池
    go(function() use ($sdk, $job) {
        $accessToken = getAccessTokenFromCache($job['shop_id']);
        
        $result = $sdk->callApi(
            'order_orderDetail\OrderOrderDetailRequest',
            'order_orderDetail\param\OrderOrderDetailParam',
            ['order_id' => $job['order_id']],
            $accessToken
        );
        
        // 处理结果...
        // 请求完成,连接自动归还到池中
    });
    
    $count++;
    
    // 定期查看连接池状态
    if ($count % 1000 === 0) {
        $stats = $sdk->getPoolStats();
        echo sprintf(
            "连接池: 活跃=%d, 空闲=%d, 等待=%d, 总请求=%d\n",
            $stats['active_connections'],
            $stats['idle_connections'],
            $stats['wait_queue_size'],
            $stats['total_requests']
        );
    }
}

$stats = $sdk->getPoolStats();

// 返回结构:
// [
//     'pool_size' => 50,           // 池大小配置
//     'total_created' => 50,       // 总创建连接数
//     'active_connections' => 30,  // 正在使用的连接
//     'idle_connections' => 20,    // 空闲可用的连接
//     'wait_queue_size' => 5,      // 等待获取连接的协程数
//     'total_requests' => 10000,   // 总请求数
// ]

// 调优建议:
// - wait_queue_size 经常 > 0 → 增加 max_connections
// - idle_connections 经常很高 → 减少 max_connections

// 在长时间运行的进程中,可以主动释放资源
$sdk->shutdown();

// 或者在 Worker 退出时调用
Swoole\Process::signal(SIGTERM, function() use ($sdk) {
    $sdk->shutdown();
    exit(0);
});


// 1. 安装 hyperf/guzzle(如果还没安装)
// composer e\Client\DouDianSdk::class => function() {
        return new \DouDianSdk\Core\Client\DouDianSdk(
            env('DOUDIAN_APP_KEY'),
            env('DOUDIAN_APP_SECRET'),
            [
                'pool' => [
                    'max_connections' => 50,  // Hyperf PoolHandler 会使用这个配置
                    'max_idle_time' => 60,
                ]
            ]
        );
    },
];

// 3. 在 Controller 或 Service 中使用
class OrderService
{
    public function __construct(
        private \DouDianSdk\Core\Client\DouDianSdk $sdk
    ) {}
    
    public function getOrder(string $orderId, string $accessToken)
    {
        return $this->sdk->callApi(...);
        // SDK 自动使用 Hyperf PoolHandler,无需额外配置
    }
}

$stats = $sdk->getPoolStats();
echo $stats['mode'];  
// 'hyperf-pool-handler' - 使用 Hyperf 内置连接池(最优)
// 'sdk-pool-with-hyperf-handler' - SDK 连接池 + Hyperf 协程
// 'sdk-pool-native' - SDK 连接池 + 原生 Swoole

// 检查当前环境
echo $sdk->getEnvironment();  
// 'swoole-coroutine' - Swoole 协程环境
// 'swoole-sync' - Swoole 同步环境
// 'fpm' - PHP-FPM 环境

echo $sdk->isSwooleCoroutine() ? '协程环境' : '非协程环境';


use DouDianSdk\Core\Client\DouDianSdk;

$sdk = new DouDianSdk('your_app_key', 'your_app_secret');

// 获取令牌
$accessToken = $sdk->getAccessToken('your_shop_id', 2);

if ($accessToken->isSuccess()) {
    echo "访问令牌: " . $accessToken->getAccessToken() . "\n";
    echo "有效期: " . $accessToken->getExpireIn() . " 秒\n";
    echo "店铺ID: " . $accessToken->getShopId() . "\n";
    
    // 刷新令牌
    if ($refreshToken = $accessToken->getRefreshToken()) {
        $newToken = $sdk->refreshAccessToken($refreshToken);
    }
} else {
    echo "错误: " . $accessToken->getMessage() . "\n";
    echo "子错误码: " . $accessToken->getSubCode() . "\n";
}


use DouDianSdk\Core\Client\DouDianSdk;
use DouDianSdk\Core\Exception\DouDianException;
use DouDianSdk\Core\Exception\ApiException;
use DouDianSdk\Core\Exception\HttpException;

try {
    $result = $sdk->callApi(...);
} catch (HttpException $e) {
    // HTTP 错误(网络问题、超时、连接池耗尽等)
    echo "HTTP 错误: " . $e->getMessage() . "\n";
} catch (ApiException $e) {
    // API 错误(参数错误、签名错误等)
    echo "API 错误: " . $e->getMessage() . "\n";
} catch (DouDianException $e) {
    // 其他 SDK 错误
    echo "SDK 错误: " . $e->getMessage() . "\n";
}
text
tests/
├── Api/
│   ├── Product/
│   │   └── ProductGetRecommendCategoryApiTest.php
│   └── Shop/
│       ├── ShopGetShopCategoryApiTest.php
│       └── ShopCategory2PublishWorkflowTest.php
├── Support/
│   └── ProductPublishTestHelper.php
└── fixtures/
    ├── product_add_v2_payload.example.json
    └── product_get_recommend_category_payload.example.json
bash
# 单独运行店铺类目测试
./vendor/bin/phpunit tests/Api/Shop/ShopGetShopCategoryApiTest.php

# 单独运行推荐类目测试
./vendor/bin/phpunit tests/Api/Product/ProductGetRecommendCategoryApiTest.php

# 单独运行商品发布链路测试
./vendor/bin/phpunit tests/Api/Shop/ShopCategory2PublishWorkflowTest.php