本文目录导读:

在 PHP 中进行汇率转换,核心思路是:获取最新汇率 → 计算转换金额。
根据你的需求(是否需要实时汇率),有以下几种实现方案:
使用免费API获取实时汇率(推荐)
这是最常用的方法,适合需要实时数据(如外贸、金融类网站)的场景,推荐使用 exchangerate-api.com 或 open.er-api.com(免费且无需密钥)。
完整代码示例(使用 file_get_contents)
<?php
/**
* 获取实时汇率并转换
* @param float $amount 金额
* @param string $from 原货币(如 USD)
* @param string $to 目标货币(如 CNY)
* @return float|string 转换后金额,失败返回错误信息
*/
function convertCurrency($amount, $from, $to) {
// 1. 调用API获取最新汇率(以USD为基准)
$api_url = "https://open.er-api.com/v6/latest/USD";
try {
// 2. 获取数据(如果服务器禁用了 file_get_contents,改用 cURL)
$response = file_get_contents($api_url);
if ($response === false) {
throw new Exception("无法连接汇率服务");
}
$data = json_decode($response, true);
if ($data['result'] !== 'success') {
throw new Exception("汇率获取失败");
}
// 3. 检查货币代码是否有效
$rates = $data['rates'];
if (!isset($rates[$from]) || !isset($rates[$to])) {
throw new Exception("不支持的货币代码");
}
// 4. 计算交叉汇率(先转USD,再转目标货币)
$amount_in_usd = $amount / $rates[$from];
$converted = $amount_in_usd * $rates[$to];
// 5. 格式化保留2位小数
return round($converted, 2);
} catch (Exception $e) {
// 失败时返回错误信息(生产环境建议记录日志)
return "Error: " . $e->getMessage();
}
}
// 使用示例:将100美元转换为人民币
echo convertCurrency(100, 'USD', 'CNY');
// 输出示例:719.32(取决于当前汇率)
?>
更健壮的版本(使用 cURL + 缓存)
很多服务器不允许 file_get_contents 访问外网,且频繁请求API会变慢,推荐用 cURL + 缓存:
<?php
function getExchangeRate($from, $to) {
$cache_file = __DIR__ . '/rates_cache.json';
$cache_time = 3600; // 缓存1小时
// 1. 检查缓存是否存在且未过期
if (file_exists($cache_file) && (time() - filemtime($cache_file) < $cache_time)) {
$cached = json_decode(file_get_contents($cache_file), true);
} else {
// 2. 使用cURL获取新数据
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://open.er-api.com/v6/latest/USD");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($response === false) {
throw new Exception("cURL Error: " . $error);
}
$data = json_decode($response, true);
if ($data['result'] !== 'success') {
throw new Exception("API Error: " . ($data['error-type'] ?? 'unknown'));
}
// 3. 写入缓存
file_put_contents($cache_file, json_encode($data));
$cached = $data;
}
$rates = $cached['rates'];
if (!isset($rates[$from]) || !isset($rates[$to])) {
throw new Exception("货币代码无效: {$from} -> {$to}");
}
// 计算交叉汇率
$rate = $rates[$to] / $rates[$from];
return $rate;
}
// 使用
try {
$rate = getExchangeRate('USD', 'EUR');
echo "1 USD = " . $rate . " EUR<br>";
echo "100 USD = " . round(100 * $rate, 2) . " EUR";
} catch (Exception $e) {
echo "错误:" . $e->getMessage();
}
?>
使用固定汇率(离线 / 手动更新)
如果项目不需要实时汇率,或者内网环境无法访问外网,可以使用硬编码汇率表(定期手动更新)。
<?php
class CurrencyConverter {
// 基准汇率(以USD = 1为基准,手动维护)
private static $rates = [
'USD' => 1.0,
'CNY' => 7.19, // 人民币
'EUR' => 0.92, // 欧元
'JPY' => 149.50, // 日元
'GBP' => 0.79, // 英镑
'HKD' => 7.83, // 港币
'AUD' => 1.53, // 澳元
'CAD' => 1.36, // 加元
'CHF' => 0.88, // 瑞士法郎
];
public static function convert($amount, $from, $to) {
if (!isset(self::$rates[$from]) || !isset(self::$rates[$to])) {
return null;
}
// 转成USD再转目标
$usd_amount = $amount / self::$rates[$from];
return round($usd_amount * self::$rates[$to], 2);
}
// 显示当前汇率表
public static function showRates() {
foreach (self::$rates as $code => $rate) {
echo "USD 1 = {$code} {$rate}<br>";
}
}
}
// 使用
echo CurrencyConverter::convert(100, 'USD', 'CNY'); // 719
?>
使用Composer包(功能全面)
如果项目较大,建议使用成熟的PHP库,如 brick/money 或 moneyphp/money,但这类库通常还需要配合汇率服务。
安装示例(moneyphp/money):
composer require moneyphp/money
<?php
use Money\Money;
use Money\Currency;
use Money\Exchange\FixedExchange;
use Money\Converter;
// 定义固定汇率
$exchange = new FixedExchange([
'USD' => [
'CNY' => '7.19',
],
'CNY' => [
'USD' => '0.139',
],
]);
$converter = new Converter($exchange);
$money = new Money(10000, new Currency('USD')); // 金额单位是分
$converted = $converter->convert($money, new Currency('CNY'));
echo $converted->getAmount(); // 71900
?>
注意事项
- 货币代码:必须使用ISO 4217标准代码(
USD、CNY、EUR等)。 - 精度问题:涉及金额计算建议使用整数(分)或
BCMath扩展,避免浮点数误差(使用round()或number_format()格式化输出)。 - 异常处理:API请求失败时要有降级方案(如使用上次缓存)。
- 法律合规:如果涉及金融交易,请使用正规汇率服务(如
exchangerate.host、currencylayer等有授权的API)。
| 场景 | 推荐方案 |
|---|---|
| 实时汇率(电商、金融机构) | 方案一(API + 缓存) |
| 内网/离线环境 | 方案二(固定汇率表) |
| 大型复杂项目 | 方案三(Composer包) |
如果你的服务器无法访问外网,可以在后台定时任务(cron)中执行方案一获取汇率到本地数据库,然后前端从数据库取数。