Skip to content

Commit

Permalink
feat: apilayer currency data service
Browse files Browse the repository at this point in the history
  • Loading branch information
florianv committed Dec 11, 2022
1 parent 327785b commit 6b8aff1
Show file tree
Hide file tree
Showing 8 changed files with 455 additions and 12 deletions.
126 changes: 126 additions & 0 deletions src/Service/ApiLayer/CurrencyData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

declare(strict_types=1);

/*
* This file is part of Exchanger.
*
* (c) Florian Voutzinos <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Exchanger\Service\ApiLayer;

use Exchanger\Contract\CurrencyPair;
use Exchanger\Contract\ExchangeRateQuery;
use Exchanger\Contract\HistoricalExchangeRateQuery;
use Exchanger\Exception\Exception;
use Exchanger\Exception\UnsupportedCurrencyPairException;
use Exchanger\ExchangeRate;
use Exchanger\Service\HttpService;
use Exchanger\Service\SupportsHistoricalQueries;
use Exchanger\StringUtil;
use Exchanger\Contract\ExchangeRate as ExchangeRateContract;

/**
* ApiLayer Currency Data Service (https://apilayer.com/marketplace/currency_data-api).
*
* @author Florian Voutzinos <[email protected]>
*/
final class CurrencyData extends HttpService
{
use SupportsHistoricalQueries;

const API_KEY_OPTION = 'api_key';

const LATEST_URL = 'https://api.apilayer.com/currency_data/live?apikey=%s&currencies=%s';

const HISTORICAL_URL = 'https://api.apilayer.com/currency_data/historical?apikey=%s&date=%s';

/**
* {@inheritdoc}
*/
public function processOptions(array &$options): void
{
if (!isset($options[self::API_KEY_OPTION])) {
throw new \InvalidArgumentException('The "api_key" option must be provided to use CurrencyData (https://apilayer.com/marketplace/currency_data-api).');
}
}

/**
* {@inheritdoc}
*/
protected function getLatestExchangeRate(ExchangeRateQuery $exchangeQuery): ExchangeRateContract
{
$currencyPair = $exchangeQuery->getCurrencyPair();

$url = sprintf(
self::LATEST_URL,
$this->options[self::API_KEY_OPTION],
$currencyPair->getQuoteCurrency()
);

return $this->doCreateRate($url, $currencyPair);
}

/**
* {@inheritdoc}
*/
protected function getHistoricalExchangeRate(HistoricalExchangeRateQuery $exchangeQuery): ExchangeRateContract
{
$url = sprintf(
self::HISTORICAL_URL,
$this->options[self::API_KEY_OPTION],
$exchangeQuery->getDate()->format('Y-m-d')
);

return $this->doCreateRate($url, $exchangeQuery->getCurrencyPair());
}

/**
* {@inheritdoc}
*/
public function supportQuery(ExchangeRateQuery $exchangeQuery): bool
{
return true;
}

/**
* Creates a rate.
*
* @param string $url
* @param CurrencyPair $currencyPair
*
* @return ExchangeRate|null
*
* @throws Exception
*/
private function doCreateRate($url, CurrencyPair $currencyPair): ExchangeRate
{
$content = $this->request($url);
$data = StringUtil::jsonToArray($content);

if (empty($data['success'])) {
throw new Exception($data['error']['info']);
}

$date = (new \DateTime())->setTimestamp($data['timestamp']);
$hash = $currencyPair->getBaseCurrency().$currencyPair->getQuoteCurrency();

if ($data['source'] === $currencyPair->getBaseCurrency() && isset($data['quotes'][$hash])) {
return $this->createRate($currencyPair, (float) ($data['quotes'][$hash]), $date);
}

throw new UnsupportedCurrencyPairException($currencyPair, $this);
}

/**
* {@inheritdoc}
*/
public function getName(): string
{
return 'apilayer_currency_data';
}
}
12 changes: 6 additions & 6 deletions src/Service/ApiLayer/Fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@
use Exchanger\Contract\ExchangeRate as ExchangeRateContract;

/**
* Fixer Service (https://apilayer.com/marketplace/fixer-api).
* ApiLayer Fixer Service (https://apilayer.com/marketplace/fixer-api).
*
* @author Florian Voutzinos <[email protected]>
*/
final class Fixer extends HttpService
{
use SupportsHistoricalQueries;

const ACCESS_KEY_OPTION = 'access_key';
const API_KEY_OPTION = 'api_key';

const LATEST_URL = 'https://api.apilayer.com/fixer/latest?base=%s&apikey=%s';

Expand All @@ -44,8 +44,8 @@ final class Fixer extends HttpService
*/
public function processOptions(array &$options): void
{
if (!isset($options[self::ACCESS_KEY_OPTION])) {
throw new \InvalidArgumentException('The "access_key" option must be provided to use https://apilayer.com/marketplace/fixer-api');
if (!isset($options[self::API_KEY_OPTION])) {
throw new \InvalidArgumentException('The "api_key" option must be provided to use Fixer (https://apilayer.com/marketplace/fixer-api).');
}
}

Expand All @@ -59,7 +59,7 @@ protected function getLatestExchangeRate(ExchangeRateQuery $exchangeQuery): Exch
$url = sprintf(
self::LATEST_URL,
$exchangeQuery->getCurrencyPair()->getBaseCurrency(),
$this->options[self::ACCESS_KEY_OPTION]
$this->options[self::API_KEY_OPTION]
);

return $this->doCreateRate($url, $currencyPair);
Expand All @@ -76,7 +76,7 @@ protected function getHistoricalExchangeRate(HistoricalExchangeRateQuery $exchan
self::HISTORICAL_URL,
$exchangeQuery->getDate()->format('Y-m-d'),
$exchangeQuery->getCurrencyPair()->getBaseCurrency(),
$this->options[self::ACCESS_KEY_OPTION]
$this->options[self::API_KEY_OPTION]
);

return $this->doCreateRate($url, $currencyPair);
Expand Down
3 changes: 2 additions & 1 deletion src/Service/Registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public static function getServices(): array
'fastforex' => FastForex::class,
'abstract_api' => AbstractApi::class,
'exchangeratehost' => ExchangerateHost::class,
'apilayer_fixer' => ApiLayer\Fixer::class
'apilayer_fixer' => ApiLayer\Fixer::class,
'apilayer_currency_data' => ApiLayer\CurrencyData::class
];
}
}
8 changes: 8 additions & 0 deletions tests/Fixtures/Service/ApiLayer/CurrencyData/error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"success": false,
"error": {
"code": 101,
"type": "invalid_access_key",
"info": "You have not supplied a valid API Access Key. [Technical Support: [email protected]]"
}
}
179 changes: 179 additions & 0 deletions tests/Fixtures/Service/ApiLayer/CurrencyData/historical_success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
{
"success": true,
"terms": "https:\/\/currencylayer.com\/terms",
"privacy": "https:\/\/currencylayer.com\/privacy",
"historical": true,
"date": "2015-05-05",
"timestamp": 1430870399,
"source": "USD",
"quotes": {
"USDAED": 3.673069,
"USDAFN": 58.160267,
"USDALL": 125.971999,
"USDAMD": 478.706002,
"USDANG": 1.78954,
"USDAOA": 109.314001,
"USDARS": 8.910188,
"USDAUD": 1.260714,
"USDAWG": 1.7925,
"USDAZN": 1.04915,
"USDBAM": 1.749085,
"USDBBD": 2,
"USDBDT": 77.789719,
"USDBGN": 1.74921,
"USDBHD": 0.377207,
"USDBIF": 1568.935867,
"USDBMD": 1,
"USDBND": 1.331299,
"USDBOB": 6.900772,
"USDBRL": 3.053759,
"USDBSD": 1,
"USDBTC": 0.004235,
"USDBTN": 63.515033,
"USDBWP": 9.833948,
"USDBYR": 14374.316667,
"USDBZD": 1.997894,
"USDCAD": 1.208877,
"USDCDF": 923.5605,
"USDCHF": 0.928519,
"USDCLF": 0.024602,
"USDCLP": 610.728796,
"USDCNY": 6.185728,
"USDCOP": 2388.811663,
"USDCRC": 531.94912,
"USDCUC": 1,
"USDCUP": 1.000038,
"USDCVE": 98.654687,
"USDCZK": 24.4979,
"USDDJF": 177.377399,
"USDDKK": 6.675821,
"USDDOP": 44.77952,
"USDDZD": 97.40122,
"USDEEK": 13.999775,
"USDEGP": 7.622161,
"USDERN": 15.1151,
"USDETB": 20.51218,
"USDEUR": 0.894203,
"USDFJD": 2.028702,
"USDFKP": 0.659043,
"USDGBP": 0.659043,
"USDGEL": 2.319325,
"USDGGP": 0.659043,
"USDGHS": 3.864928,
"USDGIP": 0.659043,
"USDGMD": 43.0138,
"USDGNF": 7312.395,
"USDGTQ": 7.746544,
"USDGYD": 206.185002,
"USDHKD": 7.75158,
"USDHNL": 21.95625,
"USDHRK": 6.782218,
"USDHTG": 47.60719,
"USDHUF": 271.684098,
"USDIDR": 13031.9,
"USDILS": 3.875593,
"USDIMP": 0.659043,
"USDINR": 63.45038,
"USDIQD": 1190.3009,
"USDIRR": 28255.667967,
"USDISK": 131.851,
"USDJEP": 0.659043,
"USDJMD": 115.103,
"USDJOD": 0.70845,
"USDJPY": 119.957,
"USDKES": 95.039721,
"USDKGS": 59.521667,
"USDKHR": 4045.91835,
"USDKMF": 440.441716,
"USDKPW": 900.09,
"USDKRW": 1081.599998,
"USDKWD": 0.301784,
"USDKYD": 0.821907,
"USDKZT": 185.8362,
"USDLAK": 8089.616732,
"USDLBP": 1508.5,
"USDLKR": 133.1648,
"USDLRD": 84.720001,
"USDLSL": 11.99574,
"USDLTL": 2.933833,
"USDLVL": 0.62865,
"USDLYD": 1.36872,
"USDMAD": 9.71972,
"USDMDL": 18.03774,
"USDMGA": 3061.686699,
"USDMKD": 55.07277,
"USDMMK": 1087.42,
"USDMNT": 1955.166667,
"USDMOP": 7.988893,
"USDMRO": 308.661333,
"USDMUR": 34.92106,
"USDMVR": 15.276788,
"USDMWK": 443.125199,
"USDMXN": 15.38044,
"USDMYR": 3.593208,
"USDMZN": 35.283833,
"USDNAD": 11.99574,
"USDNGN": 198.924,
"USDNIO": 26.83499,
"USDNOK": 7.584483,
"USDNPR": 101.4441,
"USDNZD": 1.32795,
"USDOMR": 0.385045,
"USDPAB": 1,
"USDPEN": 3.144932,
"USDPGK": 2.693605,
"USDPHP": 44.61504,
"USDPKR": 101.797999,
"USDPLN": 3.607051,
"USDPYG": 5018.168262,
"USDQAR": 3.641438,
"USDRON": 3.963029,
"USDRSD": 107.7551,
"USDRUB": 50.8311,
"USDRWF": 695.9579,
"USDSAR": 3.750335,
"USDSBD": 7.734353,
"USDSCR": 13.58486,
"USDSDG": 5.959468,
"USDSEK": 8.356247,
"USDSGD": 1.331973,
"USDSHP": 0.659043,
"USDSLL": 4332.5,
"USDSOS": 697.386702,
"USDSRD": 3.317,
"USDSTD": 21951.433333,
"USDSVC": 8.738193,
"USDSYP": 188.929501,
"USDSZL": 11.99574,
"USDTHB": 33.29961,
"USDTJS": 6.275233,
"USDTMT": 3.4999,
"USDTND": 1.914979,
"USDTOP": 2.025876,
"USDTRY": 2.706331,
"USDTTD": 6.3385,
"USDTWD": 30.69802,
"USDTZS": 1975.558325,
"USDUAH": 20.95269,
"USDUGX": 2995.7,
"USDUSD": 1,
"USDUYU": 26.34045,
"USDUZS": 2509.996683,
"USDVEF": 6.318751,
"USDVND": 21638.333333,
"USDVUV": 105.151666,
"USDWST": 2.442526,
"USDXAF": 587.832418,
"USDXAG": 0.060369,
"USDXAU": 0.000838,
"USDXCD": 2.70102,
"USDXDR": 0.713827,
"USDXOF": 587.207858,
"USDXPF": 106.83024,
"USDYER": 215.025199,
"USDZAR": 11.99449,
"USDZMK": 5253.075255,
"USDZMW": 7.382381,
"USDZWL": 322.355006
}
}
10 changes: 10 additions & 0 deletions tests/Fixtures/Service/ApiLayer/CurrencyData/success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"success": true,
"terms": "https:\/\/currencylayer.com\/terms",
"privacy": "https:\/\/currencylayer.com\/privacy",
"timestamp": 1399748450,
"source": "USD",
"quotes": {
"USDEUR": 0.726804
}
}
Loading

0 comments on commit 6b8aff1

Please sign in to comment.