1
头图

关键词:PHP API开发、金融市场数据、WebSocket实时数据、cURL实战


一、项目概述

StockTV作为全球领先的金融数据平台,提供覆盖股票、外汇、期货和加密货币的实时行情服务。本文将手把手教你使用PHP实现以下核心功能:

  • REST API调用:获取历史行情数据
  • WebSocket订阅:实时价格推送
  • 生产级特性:异常重试、速率控制、数据缓存
  • 高性能优化:连接池、异步处理

二、环境准备

1. 运行环境要求

  • PHP ≥ 7.4
  • cURL扩展
  • JSON扩展
  • Composer包管理器

2. 申请API密钥

访问StockTV开发者门户,联系客服后获取API Key。


三、项目搭建

1. 初始化项目

mkdir stocktv-php && cd stocktv-php
composer init --name="yourname/stocktv-php"

2. 安装依赖

composer require ratchet/pawl guzzlehttp/guzzle

3. 项目结构

stocktv-php/
├── src/
│   ├── StockClient.php    # 股票数据客户端
│   └── WebsocketClient.php # 实时数据客户端
├── examples/              # 使用示例
├── vendor/                # 依赖库
└── composer.json

四、核心功能实现

1. HTTP客户端封装(src/StockClient.php)

<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class StockClient {
    private $client;
    private $apiKey;

    public function __construct(string $apiKey) {
        $this->apiKey = $apiKey;
        $this->client = new Client([
            'base_uri' => 'https://api.stocktv.top',
            'timeout'  => 10.0,
        ]);
    }

    /**
     * 获取股票列表
     * @param int $countryId 国家ID
     * @param int $pageSize 每页数量
     * @param int $page 页码 
     */
    public function getStockList(int $countryId, int $pageSize = 10, int $page = 1): array {
        try {
            $response = $this->client->get('/stock/stocks', [
                'query' => [
                    'key' => $this->apiKey,
                    'countryId' => $countryId,
                    'pageSize' => $pageSize,
                    'page' => $page
                ]
            ]);
            
            return json_decode($response->getBody(), true);
        } catch (GuzzleException $e) {
            throw new Exception("API请求失败: ".$e->getMessage());
        }
    }
}

2. WebSocket客户端(src/WebsocketClient.php)

<?php

require 'vendor/autoload.php';

use Ratchet\Client\WebSocket;
use React\EventLoop\Factory;

class WebsocketClient {
    private $apiKey;

    public function __construct(string $apiKey) {
        $this->apiKey = $apiKey;
    }

    public function connect(callable $messageCallback) {
        $loop = Factory::create();
        $connector = new \Ratchet\Client\Connector($loop);

        $wsUrl = "wss://ws-api.stocktv.top/connect?key={$this->apiKey}";

        $connector($wsUrl)->then(
            function (WebSocket $conn) use ($loop, $messageCallback) {
                $conn->on('message', function($msg) use ($messageCallback) {
                    $messageCallback(json_decode($msg, true));
                });

                $conn->on('close', function($code = null, $reason = null) {
                    echo "连接关闭 ({$code} - {$reason})\n";
                });
            },
            function (\Exception $e) use ($loop) {
                echo "连接失败: {$e->getMessage()}\n";
                $loop->stop();
            }
        );

        $loop->run();
    }
}

五、使用示例

1. 获取股票数据(examples/stock_example.php)

<?php

require __DIR__.'/../vendor/autoload.php';
require __DIR__.'/../src/StockClient.php';

$apiKey = 'YOUR_API_KEY';
$client = new StockClient($apiKey);

try {
    // 获取印度股票第一页数据
    $data = $client->getStockList(14, 20, 1);
    
    echo "=== 印度股票市场数据 ===\n";
    foreach ($data['data']['records'] as $stock) {
        printf("%-20s 最新价: %.2f 涨跌幅: %.2f%%\n", 
            $stock['name'], 
            $stock['last'],
            $stock['chgPct']
        );
    }
} catch (Exception $e) {
    echo "错误: ".$e->getMessage();
}

2. 实时数据订阅(examples/websocket_example.php)

<?php

require __DIR__.'/../vendor/autoload.php';
require __DIR__.'/../src/WebsocketClient.php';

$apiKey = 'YOUR_API_KEY';
$wsClient = new WebsocketClient($apiKey);

echo "开始接收实时行情...\n";

$wsClient->connect(function($data) {
    if ($data['type'] === 'stock') {
        echo "[股票] {$data['symbol']} 价格: {$data['last']} ";
        echo "变动: ".($data['pcp'] >= 0 ? '↑' : '↓').abs($data['pcp'])."%\n";
    }
});

六、高级功能扩展

1. 请求重试机制

class RetryableClient extends StockClient {
    public function getStockListWithRetry(
        int $countryId, 
        int $maxRetries = 3,
        int $retryDelay = 1000
    ): array {
        $retryCount = 0;
        
        while ($retryCount < $maxRetries) {
            try {
                return $this->getStockList($countryId);
            } catch (Exception $e) {
                $retryCount++;
                usleep($retryDelay * 1000);
            }
        }
        
        throw new Exception("请求失败,已达最大重试次数");
    }
}

2. 数据缓存层

class CachedStockClient extends StockClient {
    private $cache;
    
    public function __construct(string $apiKey, int $ttl = 60) {
        parent::__construct($apiKey);
        $this->cache = new \Symfony\Component\Cache\Adapter\FilesystemAdapter('', $ttl);
    }

    public function getCachedStockList(int $countryId): array {
        $cacheKey = "stocks_{$countryId}";
        $item = $this->cache->getItem($cacheKey);
        
        if (!$item->isHit()) {
            $data = $this->getStockList($countryId);
            $item->set($data);
            $this->cache->save($item);
        }
        
        return $item->get();
    }
}

七、最佳实践

  1. 安全建议

    • 使用环境变量存储API密钥

      $apiKey = getenv('STOCKTV_API_KEY');
  2. 性能优化

    • 启用HTTP持久连接

      new Client([
        'base_uri' => 'https://api.stocktv.top',
        'curl' => [
            CURLOPT_TCP_KEEPALIVE => 1,
            CURLOPT_TCP_KEEPIDLE => 30,
        ]
      ]);
  3. 错误监控

    try {
        // API调用代码
    } catch (Exception $e) {
        error_log("[StockTV Error] ".date('Y-m-d H:i:s')." - ".$e->getMessage());
        // 发送到监控平台
        $monitor->report($e);
    }

八、常见问题排查

问题现象可能原因解决方案
返回403错误API密钥无效检查密钥是否包含特殊字符
WebSocket频繁断开防火墙限制检查服务器出站规则
获取的数据为旧版本缓存未更新清除缓存或降低TTL值
CPU占用过高未限制请求频率添加速率限制器

九、资源推荐


通过本文的指导,您已掌握了使用PHP对接StockTV金融数据的核心技能。建议在实际项目中结合业务需求,扩展数据存储、可视化展示等功能,构建专业的金融数据分析系统。


CryptoRzz
1 声望0 粉丝