122 lines
3.6 KiB
PHP
122 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace app\api\controller;
|
|
|
|
use app\api\logic\CryptoLogic;
|
|
use app\api\validate\CryptoValidate;
|
|
use think\facade\Cache;
|
|
use think\facade\Log;
|
|
|
|
class CryptoController extends BaseApiController
|
|
{
|
|
public array $notNeedLogin = ['proxy', 'market'];
|
|
|
|
/**
|
|
* 人民币加密行情与市场概览
|
|
*/
|
|
public function market()
|
|
{
|
|
try {
|
|
return $this->data(CryptoLogic::market());
|
|
} catch (\Throwable $e) {
|
|
Log::error('[CryptoMarket] controller failed: ' . $e->getMessage());
|
|
return $this->fail('行情加载失败,请稍后重试');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 当前账号的加密自选列表
|
|
*/
|
|
public function favorites()
|
|
{
|
|
if ($this->userId <= 0) {
|
|
return $this->fail('请先登录', [], 401);
|
|
}
|
|
return $this->data(['symbols' => CryptoLogic::favorites($this->userId)]);
|
|
}
|
|
|
|
/**
|
|
* 加入加密自选
|
|
*/
|
|
public function addFavorite()
|
|
{
|
|
if ($this->userId <= 0) {
|
|
return $this->fail('请先登录', [], 401);
|
|
}
|
|
$params = (new CryptoValidate())->post()->goCheck('favorite');
|
|
if (!CryptoLogic::addFavorite($this->userId, (string) $params['symbol'])) {
|
|
return $this->fail(CryptoLogic::getError());
|
|
}
|
|
return $this->success('已加入自选');
|
|
}
|
|
|
|
/**
|
|
* 取消加密自选
|
|
*/
|
|
public function cancelFavorite()
|
|
{
|
|
if ($this->userId <= 0) {
|
|
return $this->fail('请先登录', [], 401);
|
|
}
|
|
$params = (new CryptoValidate())->post()->goCheck('favorite');
|
|
if (!CryptoLogic::cancelFavorite($this->userId, (string) $params['symbol'])) {
|
|
return $this->fail(CryptoLogic::getError());
|
|
}
|
|
return $this->success('已取消自选');
|
|
}
|
|
|
|
/**
|
|
* Binance API 代理(解决客户端直连被墙问题)
|
|
* GET /api/crypto/proxy?path=/api/v3/ticker/24hr&symbols=...
|
|
*/
|
|
public function proxy()
|
|
{
|
|
$path = $this->request->get('path', '');
|
|
if (empty($path) || !str_starts_with($path, '/api/v3/')) {
|
|
return $this->fail('无效的API路径');
|
|
}
|
|
|
|
// 构建完整URL,将除 path 外的参数透传
|
|
$params = $this->request->get();
|
|
unset($params['path']);
|
|
ksort($params);
|
|
$query = http_build_query($params);
|
|
$url = 'https://api.binance.com' . $path . ($query ? '?' . $query : '');
|
|
|
|
$cacheKey = 'binance_proxy_' . md5($path . '|' . $query);
|
|
$cached = Cache::get($cacheKey);
|
|
if ($cached !== null) {
|
|
return json($cached, 200);
|
|
}
|
|
|
|
Log::info('[CryptoProxy] request url=' . $url);
|
|
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 15,
|
|
CURLOPT_CONNECTTIMEOUT => 5,
|
|
CURLOPT_SSL_VERIFYPEER => false,
|
|
CURLOPT_HTTPHEADER => ['Accept: application/json'],
|
|
]);
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$error = curl_error($ch);
|
|
curl_close($ch);
|
|
|
|
if ($error) {
|
|
Log::error('[CryptoProxy] curl_error=' . $error . ' url=' . $url);
|
|
return $this->fail('API请求失败: ' . $error);
|
|
}
|
|
|
|
Log::info('[CryptoProxy] http_code=' . $httpCode . ' response_preview=' . substr((string) $response, 0, 500));
|
|
|
|
$data = json_decode($response, true);
|
|
if ($httpCode === 200 && $data !== null) {
|
|
Cache::set($cacheKey, $data, 3);
|
|
}
|
|
return json($data, $httpCode);
|
|
}
|
|
}
|