要在 PHP 中获取实时金价,请使用原生 cURL 向 api.goldprice.dev/v1/spot/XAU-USD-SPOT 发送 GET 请求,并在 X-API-Key 请求头中传入 API 密钥,无需 Composer。解析 JSON 后保留价格字符串,用 BCMath 精确计算。按交易符号缓存 60 秒。免费套餐每月含 5,000 次调用,无需信用卡。已于 2026 年六月在 PHP 8.3 上测试。
获取 goldprice.dev API 密钥
前往 goldprice.dev/onboarding 注册免费账户。验证邮箱后,控制台会显示以 ga_live_ 开头的密钥。将其设为环境变量:
export GOLDPRICE_API_KEY=ga_live_replace_with_your_key_here免费套餐每月含 5,000 次调用,支持以 31 种货币报价的黄金现货价格。无需信用卡。
确认所需扩展
无需 Composer 包。PHP 8 自带 curl 和 json,bcmath 则是用于精确十进制计算的标准扩展。请确认这三个扩展均已启用:
php -m | grep -E '^(curl|json|bcmath)$'# curl# json# bcmath <- if missing, install php8.3-bcmath (or enable in php.ini)编写 goldprice 客户端
将代码保存为 goldprice.php。spot() 按交易符号在静态数组中缓存 60 秒,遇到 429 时按指数退避最多重试 3 次。返回解析后的数组,价格保留为字符串,供 BCMath 精确计算。
<?php// php: goldprice.php, native cURL + BCMath, no Composer// curl-equivalent: https://api.goldprice.dev/v1/spot/XAU-USD-SPOTdeclare(strict_types=1);const API_BASE = 'https://api.goldprice.dev';const TIMEOUT = 5; // secondsconst TTL = 60; // secondsfinal class RateLimitedException extends RuntimeException {}final class GoldpriceClient{ private string $apiKey; /** @var array<string, array{data: array, expires: int}> */ private static array $cache = []; public function __construct() { $key = getenv('GOLDPRICE_API_KEY'); if ($key === false || $key === '') { throw new RuntimeException('GOLDPRICE_API_KEY not set'); } $this->apiKey = $key; } /** * Fetch live spot price. Cached 60s per symbol, retries 3x on 429. * Prices stay as strings for BCMath. */ public function spot(string $symbol = 'XAU-USD-SPOT'): array { $now = time(); if (isset(self::$cache[$symbol]) && self::$cache[$symbol]['expires'] > $now) { return self::$cache[$symbol]['data']; } for ($attempt = 0; $attempt < 3; $attempt++) { try { $data = $this->fetch($symbol); self::$cache[$symbol] = ['data' => $data, 'expires' => $now + TTL]; return $data; } catch (RateLimitedException) { sleep(1 << $attempt); // 1s, 2s, 4s } } throw new RateLimitedException('goldprice: 429 after 3 retries'); } private function fetch(string $symbol): array { $ch = curl_init(API_BASE . '/v1/spot/' . rawurlencode($symbol)); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => TIMEOUT, CURLOPT_HTTPHEADER => ['X-API-Key: ' . $this->apiKey], ]); $body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE); curl_close($ch); if ($code === 429) { throw new RateLimitedException('rate limited'); } if ($code !== 200 || $body === false) { throw new RuntimeException("goldprice: unexpected status {$code}"); } return json_decode((string) $body, true, 512, JSON_THROW_ON_ERROR); }}$client = new GoldpriceClient();$r = $client->spot('XAU-USD-SPOT');// Prices are strings; use BCMath for exact math (e.g. price for 5 oz):$fiveOz = bcmul($r['price'], '5', 4);printf("%s-%s: %s (computed %s)\n", $r['symbol'], $r['quote_currency'], $r['price'], $r['computed_at']);printf("5 troy oz = %s %s\n", $fiveOz, $r['quote_currency']);运行代码
在导出 GOLDPRICE_API_KEY 的同一终端中,通过 CLI 运行文件。首次调用会请求 API,同一进程内 60 秒内的后续 spot() 调用返回缓存数组。静态缓存仅在进程内有效。在 PHP-FPM 下,可使用 APCu 或 Redis 跨请求共享缓存。
php goldprice.php# XAU-USD: 4012.75 (computed 2026-10-23T07:00:18.221118+00:00)# 5 troy oz = 20063.7500 USD切换货币或金属
交易符号格式为 METAL-CURRENCY-SPOT。可向 spot() 传入使用任意一种受支持的 31 种现货报价货币的交易符号。每个符号在静态数组中独立缓存。页面显示 5 个符号时,最多发出 5 次未命中缓存的调用,缓存有效期内再次渲染可复用结果。
$client = new GoldpriceClient();// USD spot, default$client->spot('XAU-USD-SPOT');$client->spot('XAU-INR-SPOT');$client->spot('XAU-EUR-SPOT');// Silver in USD$client->spot('XAG-USD-SPOT');预期输出
{ "symbol": "XAU", "quote_currency": "USD", "unit": "troy_ounce", "contract_type": "spot", "price": "4012.75", "is_stale": false, "computed_at": "2026-10-23T07:00:18.221118+00:00"}CLI 输出两行:交易符号、货币、价格和时间戳,以及用 BCMath 算出的 5 金衡盎司总价。下游代码使用解析后的数组,价格始终保留为字符串。
常见错误
| 代码 | 现象 | 解决方法 |
|---|---|---|
| 401 | 出现 RuntimeException: goldprice: unexpected status 401 | API 密钥缺失或无效。运行 php -r 'echo getenv("GOLDPRICE_API_KEY");' 确认 PHP 能读取变量。PHP-FPM 不共享 CLI 环境变量,请通过 fastcgi_param 或进程管理器设置密钥。如果为空,请从控制台重新复制。 |
| 429 | 按退避间隔重试三次仍返回 429,随后抛出 RateLimitedException | 已达到每分钟调用上限。60 秒缓存可避免稳定流量触及此限制。PHP-FPM 下的静态缓存仅限当前请求,请改用 APCu(apcu_fetch / apcu_store)跨请求共享。持续大量调用可查看 /pricing 的付费套餐。 |
| N/A | 将价格转为浮点数计算时出现舍入误差 | 计算前不要将价格转为 (float),PHP 浮点数在累加时会损失精度。保留 API 返回的字符串,使用 bcadd、bcmul 和 bccomp,并明确指定小数位数。如果提示函数未定义,请启用 bcmath 扩展。 |
进阶用法
- 将静态缓存改为
apcu_store/apcu_fetch,让所有 PHP-FPM 工作进程在完整的 60 秒内复用一次获取的结果 - 为
/v1/bars?symbol=XAU-USD-SPOT&interval=1d&from=...&to=...添加bars()方法,通过模板引擎将返回的数据绘制成图表 - 用简单的 Laravel 或 Symfony 服务封装
spot(),并绑定到容器中以便依赖注入 - 多个工作进程轮询同一符号时,添加
If-None-Match/ ETag 检查,跳过未变化的响应内容 - 使用
bcdiv按金衡盎司与克的换算系数计算,显示适合零售场景的每克价格