⚠️ 重要提醒: 原文使用的 download.finance.yahoo.com 介面已於 2017 年停止服務,以下提供現代、可維護的替代方案與最佳實踐代碼。
| 服務 | 免費額度 | 特色 | 註冊 |
|---|---|---|---|
| exchangerate.host | 無限制、無需 Key | 開源、支援歷史匯率、CDN 快取 | 不需 |
| ExchangeRate-API | 1,500 req/月 | 穩定、支援 HTTPS、Base 貨幣可調 | 需 |
| CurrencyLayer | 250 req/月 | 企業級、SLA、支援加密貨幣 | 需 |
| Open Exchange Rates | 1,000 req/月 | 歷史資料完整、SDK 豐富 | 需 |
<?php
// composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
function getExchangeRate(string $from, string $to, float $amount = 1.0): ?float
{
$client = new Client([
'base_uri' => 'https://api.exchangerate.host/',
'timeout' => 5.0,
]);
try {
$response = $client->get('convert', [
'query' => [
'from' => strtoupper($from),
'to' => strtoupper($to),
'amount' => $amount,
],
'headers' => ['Accept' => 'application/json'],
]);
$data = json_decode($response->getBody()->getContents(), true);
return $data['result'] ?? null;
} catch (Throwable $e) {
// 記錄錯誤、拋出自訂例外或回傳 null
error_log('匯率查詢失敗: ' . $e->getMessage());
return null;
}
}
// 使用範例
$rate = getExchangeRate('CNY', 'USD', 100);
echo "100 CNY ≈ {$rate} USD"; // 100 CNY ≈ 13.85 USD
file_get_contents + stream context)<?php
function getRateNative(string $from, string $to): ?float
{
$url = 'https://api.exchangerate.host/latest?base=' . urlencode($from) . '&symbols=' . urlencode($to);
$ctx = stream_context_create([
'http' => [
'method' => 'GET',
'timeout' => 5,
'header' => 'Accept: application/json',
],
'ssl' => ['verify_peer' => true, 'verify_peer_name' => true],
]);
$json = @file_get_contents($url, false, $ctx);
if ($json === false) return null;
$data = json_decode($json, true);
return $data['rates'][$to] ?? null;
}
匯率不需即時到毫秒級,建議快取 10–60 分鐘:
<?php
// 使用 Redis / APCu / 檔案快取
function getCachedRate(string $from, string $to): float
{
$key = "fx:{$from}:{$to}";
$cached = apcu_fetch($key);
if ($cached !== false) return $cached;
$rate = getExchangeRate($from, $to) ?? 0;
if ($rate > 0) apcu_store($key, $rate, 1800); // 30 分鐘
return $rate;
}
並實作 Circuit Breaker、Fallback(如使用上一筆成功匯率)避免上游失效導致服務雪崩。
以此現代化架構替換舊代碼,即可獲得穩定、安全、可擴展的匯率轉換服務。