You have several issues:
- You're not calling an actual API, you're scraping a web page, which means that:
- you're most likely violating Google's TOS
- you're more likely to get rate-limited (or be detected as abuse and be blacklisted) at some point if you're fetching this page too often
- you're dependent on any change made in the HTML structure of the web page
- You're scraping the page every single time you need to convert an amount to another currency, which means that any failure makes your currency conversion fail.
What you should do:
- load exchange rates from a legitimate feed or API
-
load them on a regular basis (via a cron job for example) and save them to a local database, that will be used to perform currency conversions
This way, even if an API call fails, you still have access to a slightly outdated exchange rate, which is better than a failure in most cases.
Where do you find a trustable exchange rate feed?
There are plenty of APIs, free or not, that offer this service.
A good source I know of is the European Central Bank, who provides an XML feed that's been there for years and provides exchange rates for 32 currencies relative to EUR
.
OpenExchangeRates also offers a free plan with a limit of 1,000 requests per month, which is enough to refresh rates every hour. It provides exchange rates for 170 currencies, relative to USD
.
How do you store the values in your database?
Whichever feed you choose, you need to parse it (if XML) or json_decode()
it (if JSON) and store the values in your database. Ideally, set up a cron job to run your import script daily or even hourly.
The actual parsing and importing steps are outside the scope of this question, but let's assume a simple MySQL table that holds the records:
CREATE TABLE exchange_rate(
target_currency CHAR(3) COLLATE ascii_bin NOT NULL PRIMARY KEY,
exchange_rate DOUBLE NOT NULL
);
How to properly handle currency conversions based on rates relative to a single currency?
This is a question I've 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 - disclaimer: I'm the author.
Here is how you would configure it to load your exchange rates from the table above:
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);
And how you would use it:
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