有没有更好的方法来获取 PHP 中的货币汇率?
Is there any better way to get Currency Exchange Rate in PHP?
以下代码的货币汇率有时有效,有时无效,而且一点也不可靠。在PHP中有没有更好的方法来获取货币汇率?
public function getJPYtoUSDExchangeRate(){
$from = 'JPY';
$to = 'USD';
$amount = 1;
$data = file_get_contents("https://finance.google.com/finance/converter?a=$amount&from=$from&to=$to");
preg_match("/<span class=bld>(.*)<\/span>/",$data, $converted);
$converted = preg_replace("/[^0-9.]/", "", $converted[1][0]);
return number_format(round($converted, 3),2);
}
您有几个问题:
- 您不是在调用实际的 API,您是在抓取网页,这意味着:
- 您很可能违反了 Google 的服务条款
- 如果您过于频繁地获取此页面,您更有可能在某个时候受到速率限制(或被检测为滥用和列入黑名单)
- 您依赖于对网页HTML结构所做的任何更改
- 每次需要将金额转换为另一种货币时,您都在抓取页面,这意味着任何失败都会导致您的货币转换失败。
你应该做什么:
- 从合法的 Feed 或 API
加载汇率
- 定期加载它们(例如通过 cron 作业)并将它们保存到本地数据库,这将是用于执行货币转换
这样,即使 API 调用失败,您仍然可以获得稍微过时的汇率,这在大多数情况下比失败要好。
您在哪里找到 trustable 汇率源?
有很多 API 提供此服务,无论是否免费。
我知道的一个很好的来源是欧洲中央银行,它提供了一个已经存在多年的 XML feed 并提供了 32 种货币相对于 EUR
.
的汇率
OpenExchangeRates 还提供每月 1,000 次请求限制的免费计划,这足以每小时刷新一次。它提供了 170 种货币的汇率,相对于 USD
。
如何将值存储在数据库中?
无论您选择哪个提要,您都需要解析它(如果 XML)或 json_decode()
它(如果 JSON)并将值存储在您的数据库中。理想情况下,每天甚至每小时为 运行 导入脚本设置一个 cron 作业。
实际的解析和导入步骤超出了这个问题的范围,但我们假设一个简单的 MySQL table 保存记录:
CREATE TABLE exchange_rate(
target_currency CHAR(3) COLLATE ascii_bin NOT NULL PRIMARY KEY,
exchange_rate DOUBLE NOT NULL
);
如何根据相对于单一货币的汇率正确处理货币换算?
这是我提出的问题 answered recently. The feeds above give you rates to convert the base currency (EUR
or USD
) to another currency, but do not give you a clue on how to convert between two arbitrary currencies. I would suggest you use a proper library that handles these conversions for you, such as brick/money - 免责声明:我是作者。
以下是如何配置它以从上面的 table 加载汇率:
use Brick\Money\CurrencyConverter;
use Brick\Money\ExchangeRateProvider\PDOProvider;
use Brick\Money\ExchangeRateProvider\PDOProviderConfiguration;
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;
// set to whatever your rates are relative to
$baseCurrency = 'USD';
// use your own credentials, or re-use your existing PDO connection
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$configuration = new PDOProviderConfiguration();
$configuration->tableName = 'exchange_rate';
$configuration->exchangeRateColumnName = 'exchange_rate';
$configuration->targetCurrencyColumnName = 'target_currency';
$configuration->sourceCurrencyCode = $baseCurrency;
// this provider loads exchange rates from your database
$provider = new PDOProvider($pdo, $configuration);
// this provider calculates exchange rates relative to the base currency
$provider = new BaseCurrencyProvider($provider, $baseCurrency);
// this currency converter can now handle any currency pair
$converter = new CurrencyConverter($provider);
以及您将如何使用它:
use Brick\Math\RoundingMode;
use Brick\Money\Money;
$money = Money::of(10, 'EUR'); // EUR 10.00
$converter->convert($money, 'CAD', RoundingMode::DOWN); // CAD 15.27
CurrencyFreaks API 以与多种编程语言兼容的 JSON 和 XML 格式为全球 179 种货币提供可靠的汇率。通过使用 CurrencyFreaks API,您还可以更改 'base' 货币并可以获得特定货币的汇率。
这是一个简单的货币汇率端点,使用PHP:
setUrl('https://api.currencyfreaks.com/latest
?apikey=YOUR_APIKEY
&base=GBP');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
JSON 响应将是:
{
"date": "2020-10-06 11:22:00+00",
"base": "GBP",
"rates": {
"FJD": "2.737385252915371",
"MXN": "27.74546375788785",
"STD": "27185.017172962733",
"LVL": "0.8482572402792966",
"SCR": "23.257414775003944",
"CDF": "2535.4260357935937",
"BBD": "2.585121591194042",
"GTQ": "10.055244048403818",
"CLP": "1031.8523300993463",
"HNL": "31.82062875327341",
"UGX": "4769.159332676713",
"ZAR": "21.445845580346873",
"TND": "3.542262860333636",
"CUC": "1.2926654930214643",
"BSD": "1.292560795597021",
"SLL": "12676.789824444395",
"SDG": "71.5109260164052",
"IQD": "1542.8992384231794",
"GMD": "66.89002117214584",
"CUP": "34.25286108332106",
"TWD": "37.17921872455271",
"RSD": "128.99756740058268",
"DOP": "75.46618143934401",
"KMF": "540.1610026652604",
.
.
.
[179 Currencies]
}
}
希望有用。
加拿大银行为以下货币提供 RSS 提要:
AUD、BRL、CNY、EUR、HKD、INR、IDR、JPY、MXN、NZD、NOK、PEN、RUB、SAR、SGD、ZAR、KRW、SEK、CHF、TWD、TRY、GBP、USD
这是一种无需 API 或第 3 方服务即可获得货币换算的方法:
<?php
class EXCHANGE {
public $Rates;
public $Rate;
public function __construct(){
$this->Rates = $this->fetchAllRates();
foreach($this->Rates as $currency => $rate){
$this->Rate[$currency] = $rate['latest'];
}
}
public function fetchAllRates(){
$currencies = ["AUD","BRL","CNY","EUR","HKD","INR","IDR","JPY","MXN","NZD","NOK","PEN","RUB","SAR","SGD","ZAR","KRW","SEK","CHF","TWD","TRY","GBP","USD"];
$cURL = curl_init();
curl_setopt($cURL, CURLOPT_URL, "https://www.bankofcanada.ca/valet/observations/group/FX_RATES_DAILY/json?start_date=2010-01-01");
curl_setopt($cURL, CURLOPT_RETURNTRANSFER, 1);
$rates = curl_exec($cURL);
curl_close($cURL);
$rates = json_decode($rates,true)['observations'];
foreach($currencies as $currency){
foreach($rates as $rate){
$AllRates[$currency][$rate['d']] = $rate['FX'.$currency.'CAD']['v'];
$AllRates[$currency]['latest'] = $rate['FX'.$currency.'CAD']['v'];
}
}
return $AllRates;
}
public function convert($value,$from,$to){
if($to == "CAD"){ return $value*$this->Rate[$from]; }
else { return ($value*$this->Rate[$from])/$this->Rate[$to]; }
}
}
$Exchange = new EXCHANGE();
foreach($Exchange->Rate as $currency => $rate){
echo $currency.': '.$rate."<br>\n"; // Listing all the exchange rates
}
echo "Converting 2.00 USD to CAD : ".$Exchange->convert(2,"USD","CAD")."\n"; //2022-02-23 = 2.5486
echo "Converting 2.00 USD to AUD : ".$Exchange->convert(2,"USD","AUD")."\n"; //2022-02-23 = 2.7708197434225
更新:
我最初忘记了转换方法。
信息:
class 使用的是加拿大银行的 RSS 提要。它不是最准确的数据,因为它每个工作日只更新一次。 $Rate 属性 包含 CAD 货币的汇率。因此要转换其他货币,它首先将初始货币转换为 CAD,然后再转换为新货币。因此,在上面提供的示例中,2.00 美元被转换为 2.5486 加元。然后除以澳元汇率得到2.7708197434225澳元。
以下代码的货币汇率有时有效,有时无效,而且一点也不可靠。在PHP中有没有更好的方法来获取货币汇率?
public function getJPYtoUSDExchangeRate(){
$from = 'JPY';
$to = 'USD';
$amount = 1;
$data = file_get_contents("https://finance.google.com/finance/converter?a=$amount&from=$from&to=$to");
preg_match("/<span class=bld>(.*)<\/span>/",$data, $converted);
$converted = preg_replace("/[^0-9.]/", "", $converted[1][0]);
return number_format(round($converted, 3),2);
}
您有几个问题:
- 您不是在调用实际的 API,您是在抓取网页,这意味着:
- 您很可能违反了 Google 的服务条款
- 如果您过于频繁地获取此页面,您更有可能在某个时候受到速率限制(或被检测为滥用和列入黑名单)
- 您依赖于对网页HTML结构所做的任何更改
- 每次需要将金额转换为另一种货币时,您都在抓取页面,这意味着任何失败都会导致您的货币转换失败。
你应该做什么:
- 从合法的 Feed 或 API 加载汇率
- 定期加载它们(例如通过 cron 作业)并将它们保存到本地数据库,这将是用于执行货币转换
这样,即使 API 调用失败,您仍然可以获得稍微过时的汇率,这在大多数情况下比失败要好。
您在哪里找到 trustable 汇率源?
有很多 API 提供此服务,无论是否免费。
我知道的一个很好的来源是欧洲中央银行,它提供了一个已经存在多年的 XML feed 并提供了 32 种货币相对于 EUR
.
OpenExchangeRates 还提供每月 1,000 次请求限制的免费计划,这足以每小时刷新一次。它提供了 170 种货币的汇率,相对于 USD
。
如何将值存储在数据库中?
无论您选择哪个提要,您都需要解析它(如果 XML)或 json_decode()
它(如果 JSON)并将值存储在您的数据库中。理想情况下,每天甚至每小时为 运行 导入脚本设置一个 cron 作业。
实际的解析和导入步骤超出了这个问题的范围,但我们假设一个简单的 MySQL table 保存记录:
CREATE TABLE exchange_rate(
target_currency CHAR(3) COLLATE ascii_bin NOT NULL PRIMARY KEY,
exchange_rate DOUBLE NOT NULL
);
如何根据相对于单一货币的汇率正确处理货币换算?
这是我提出的问题 answered recently. The feeds above give you rates to convert the base currency (EUR
or USD
) to another currency, but do not give you a clue on how to convert between two arbitrary currencies. I would suggest you use a proper library that handles these conversions for you, such as brick/money - 免责声明:我是作者。
以下是如何配置它以从上面的 table 加载汇率:
use Brick\Money\CurrencyConverter;
use Brick\Money\ExchangeRateProvider\PDOProvider;
use Brick\Money\ExchangeRateProvider\PDOProviderConfiguration;
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;
// set to whatever your rates are relative to
$baseCurrency = 'USD';
// use your own credentials, or re-use your existing PDO connection
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$configuration = new PDOProviderConfiguration();
$configuration->tableName = 'exchange_rate';
$configuration->exchangeRateColumnName = 'exchange_rate';
$configuration->targetCurrencyColumnName = 'target_currency';
$configuration->sourceCurrencyCode = $baseCurrency;
// this provider loads exchange rates from your database
$provider = new PDOProvider($pdo, $configuration);
// this provider calculates exchange rates relative to the base currency
$provider = new BaseCurrencyProvider($provider, $baseCurrency);
// this currency converter can now handle any currency pair
$converter = new CurrencyConverter($provider);
以及您将如何使用它:
use Brick\Math\RoundingMode;
use Brick\Money\Money;
$money = Money::of(10, 'EUR'); // EUR 10.00
$converter->convert($money, 'CAD', RoundingMode::DOWN); // CAD 15.27
CurrencyFreaks API 以与多种编程语言兼容的 JSON 和 XML 格式为全球 179 种货币提供可靠的汇率。通过使用 CurrencyFreaks API,您还可以更改 'base' 货币并可以获得特定货币的汇率。
这是一个简单的货币汇率端点,使用PHP:
setUrl('https://api.currencyfreaks.com/latest
?apikey=YOUR_APIKEY
&base=GBP');
$request->setMethod(HTTP_Request2::METHOD_GET);
$request->setConfig(array(
'follow_redirects' => TRUE
));
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}
JSON 响应将是:
{
"date": "2020-10-06 11:22:00+00",
"base": "GBP",
"rates": {
"FJD": "2.737385252915371",
"MXN": "27.74546375788785",
"STD": "27185.017172962733",
"LVL": "0.8482572402792966",
"SCR": "23.257414775003944",
"CDF": "2535.4260357935937",
"BBD": "2.585121591194042",
"GTQ": "10.055244048403818",
"CLP": "1031.8523300993463",
"HNL": "31.82062875327341",
"UGX": "4769.159332676713",
"ZAR": "21.445845580346873",
"TND": "3.542262860333636",
"CUC": "1.2926654930214643",
"BSD": "1.292560795597021",
"SLL": "12676.789824444395",
"SDG": "71.5109260164052",
"IQD": "1542.8992384231794",
"GMD": "66.89002117214584",
"CUP": "34.25286108332106",
"TWD": "37.17921872455271",
"RSD": "128.99756740058268",
"DOP": "75.46618143934401",
"KMF": "540.1610026652604",
.
.
.
[179 Currencies]
}
}
希望有用。
加拿大银行为以下货币提供 RSS 提要: AUD、BRL、CNY、EUR、HKD、INR、IDR、JPY、MXN、NZD、NOK、PEN、RUB、SAR、SGD、ZAR、KRW、SEK、CHF、TWD、TRY、GBP、USD
这是一种无需 API 或第 3 方服务即可获得货币换算的方法:
<?php
class EXCHANGE {
public $Rates;
public $Rate;
public function __construct(){
$this->Rates = $this->fetchAllRates();
foreach($this->Rates as $currency => $rate){
$this->Rate[$currency] = $rate['latest'];
}
}
public function fetchAllRates(){
$currencies = ["AUD","BRL","CNY","EUR","HKD","INR","IDR","JPY","MXN","NZD","NOK","PEN","RUB","SAR","SGD","ZAR","KRW","SEK","CHF","TWD","TRY","GBP","USD"];
$cURL = curl_init();
curl_setopt($cURL, CURLOPT_URL, "https://www.bankofcanada.ca/valet/observations/group/FX_RATES_DAILY/json?start_date=2010-01-01");
curl_setopt($cURL, CURLOPT_RETURNTRANSFER, 1);
$rates = curl_exec($cURL);
curl_close($cURL);
$rates = json_decode($rates,true)['observations'];
foreach($currencies as $currency){
foreach($rates as $rate){
$AllRates[$currency][$rate['d']] = $rate['FX'.$currency.'CAD']['v'];
$AllRates[$currency]['latest'] = $rate['FX'.$currency.'CAD']['v'];
}
}
return $AllRates;
}
public function convert($value,$from,$to){
if($to == "CAD"){ return $value*$this->Rate[$from]; }
else { return ($value*$this->Rate[$from])/$this->Rate[$to]; }
}
}
$Exchange = new EXCHANGE();
foreach($Exchange->Rate as $currency => $rate){
echo $currency.': '.$rate."<br>\n"; // Listing all the exchange rates
}
echo "Converting 2.00 USD to CAD : ".$Exchange->convert(2,"USD","CAD")."\n"; //2022-02-23 = 2.5486
echo "Converting 2.00 USD to AUD : ".$Exchange->convert(2,"USD","AUD")."\n"; //2022-02-23 = 2.7708197434225
更新: 我最初忘记了转换方法。
信息: class 使用的是加拿大银行的 RSS 提要。它不是最准确的数据,因为它每个工作日只更新一次。 $Rate 属性 包含 CAD 货币的汇率。因此要转换其他货币,它首先将初始货币转换为 CAD,然后再转换为新货币。因此,在上面提供的示例中,2.00 美元被转换为 2.5486 加元。然后除以澳元汇率得到2.7708197434225澳元。