在 PHP 与 Laravel 中使用汇率

使用 Laravel HTTP 客户端、bearer 认证、有限超时与新鲜度字段获取并缓存实时汇率。

exchangerate.devJul 17, 20266 分钟阅读

一个小型 Laravel 服务可以调用 exchangerate.dev、拒绝错误响应,并把完整汇率观测缓存 60 秒。密钥放在配置中,并与汇率一起返回 source、market_session 与 data_updated_at。

要点
使用 Laravel HTTP 客户端的 bearer 认证、超时与 throw()。
完整成功响应缓存 60 秒,从而稳稳留在 Free 层每分钟 10 次请求的限制之内。
密钥保存在 config/services.php 中,通过 EXCHANGERATE_API_KEY 读取,不要写进应用代码。
需要精确金额计算时使用十进制库。

构建一个带缓存的汇率服务

该服务用基础货币与排序后的代码生成稳定缓存键。throw() 会在 Laravel 写入缓存之前抛出,因此错误响应不会变成汇率数据。

php · app/Services/ExchangeRateService.php
<?php

namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;

final class ExchangeRateService
{
    public function latest(string $base, array $symbols): array
    {
        sort($symbols);
        $symbolList = implode(',', $symbols);
        $cacheKey = "fx:latest:{$base}:{$symbolList}";

        return Cache::remember($cacheKey, now()->addSeconds(60), function () use (
            $base,
            $symbolList,
        ): array {
            return Http::acceptJson()
                ->withToken(config('services.exchangerate.key'))
                ->timeout(5)
                ->get(
                    "https://api.exchangerate.dev/v1/latest/{$base}",
                    ['symbols' => $symbolList],
                )
                ->throw()
                ->json();
        });
    }
}

在源代码之外配置密钥

php · config/services.php and .env
// config/services.php
'exchangerate' => [
    'key' => env('EXCHANGERATE_API_KEY'),
],

// .env (never commit the real value)
EXCHANGERATE_API_KEY=exr_live_...

读取汇率及其观测字段

调用 $service->latest("USD", ["EUR", "GBP"]),然后读取 $result["rates"]["EUR"]。在视图模型或记录中保留 $result["source"]、$result["market_session"] 与 $result["data_updated_at"]。

不要把错误缓存成汇率
401 表示密钥或请求头错误。429 表示超出请求限制。让请求失败,适当退避,并且只在保留原始更新时间时继续使用此前成功观测。
  • 生成缓存键前排序货币代码。
  • 设置有限 HTTP 超时。
  • 读取并缓存 JSON 前调用 throw。
  • 只舍入最终金额,不舍入 API 汇率。
ER
exchangerate.dev
面向使用外汇数据的开发者的集成指南。

继续阅读