Skip to content

Commit 6b8aff1

Browse files
committed
feat: apilayer currency data service
1 parent 327785b commit 6b8aff1

File tree

8 files changed

+455
-12
lines changed

8 files changed

+455
-12
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of Exchanger.
7+
*
8+
* (c) Florian Voutzinos <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Exchanger\Service\ApiLayer;
15+
16+
use Exchanger\Contract\CurrencyPair;
17+
use Exchanger\Contract\ExchangeRateQuery;
18+
use Exchanger\Contract\HistoricalExchangeRateQuery;
19+
use Exchanger\Exception\Exception;
20+
use Exchanger\Exception\UnsupportedCurrencyPairException;
21+
use Exchanger\ExchangeRate;
22+
use Exchanger\Service\HttpService;
23+
use Exchanger\Service\SupportsHistoricalQueries;
24+
use Exchanger\StringUtil;
25+
use Exchanger\Contract\ExchangeRate as ExchangeRateContract;
26+
27+
/**
28+
* ApiLayer Currency Data Service (https://apilayer.com/marketplace/currency_data-api).
29+
*
30+
* @author Florian Voutzinos <[email protected]>
31+
*/
32+
final class CurrencyData extends HttpService
33+
{
34+
use SupportsHistoricalQueries;
35+
36+
const API_KEY_OPTION = 'api_key';
37+
38+
const LATEST_URL = 'https://api.apilayer.com/currency_data/live?apikey=%s&currencies=%s';
39+
40+
const HISTORICAL_URL = 'https://api.apilayer.com/currency_data/historical?apikey=%s&date=%s';
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function processOptions(array &$options): void
46+
{
47+
if (!isset($options[self::API_KEY_OPTION])) {
48+
throw new \InvalidArgumentException('The "api_key" option must be provided to use CurrencyData (https://apilayer.com/marketplace/currency_data-api).');
49+
}
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
protected function getLatestExchangeRate(ExchangeRateQuery $exchangeQuery): ExchangeRateContract
56+
{
57+
$currencyPair = $exchangeQuery->getCurrencyPair();
58+
59+
$url = sprintf(
60+
self::LATEST_URL,
61+
$this->options[self::API_KEY_OPTION],
62+
$currencyPair->getQuoteCurrency()
63+
);
64+
65+
return $this->doCreateRate($url, $currencyPair);
66+
}
67+
68+
/**
69+
* {@inheritdoc}
70+
*/
71+
protected function getHistoricalExchangeRate(HistoricalExchangeRateQuery $exchangeQuery): ExchangeRateContract
72+
{
73+
$url = sprintf(
74+
self::HISTORICAL_URL,
75+
$this->options[self::API_KEY_OPTION],
76+
$exchangeQuery->getDate()->format('Y-m-d')
77+
);
78+
79+
return $this->doCreateRate($url, $exchangeQuery->getCurrencyPair());
80+
}
81+
82+
/**
83+
* {@inheritdoc}
84+
*/
85+
public function supportQuery(ExchangeRateQuery $exchangeQuery): bool
86+
{
87+
return true;
88+
}
89+
90+
/**
91+
* Creates a rate.
92+
*
93+
* @param string $url
94+
* @param CurrencyPair $currencyPair
95+
*
96+
* @return ExchangeRate|null
97+
*
98+
* @throws Exception
99+
*/
100+
private function doCreateRate($url, CurrencyPair $currencyPair): ExchangeRate
101+
{
102+
$content = $this->request($url);
103+
$data = StringUtil::jsonToArray($content);
104+
105+
if (empty($data['success'])) {
106+
throw new Exception($data['error']['info']);
107+
}
108+
109+
$date = (new \DateTime())->setTimestamp($data['timestamp']);
110+
$hash = $currencyPair->getBaseCurrency().$currencyPair->getQuoteCurrency();
111+
112+
if ($data['source'] === $currencyPair->getBaseCurrency() && isset($data['quotes'][$hash])) {
113+
return $this->createRate($currencyPair, (float) ($data['quotes'][$hash]), $date);
114+
}
115+
116+
throw new UnsupportedCurrencyPairException($currencyPair, $this);
117+
}
118+
119+
/**
120+
* {@inheritdoc}
121+
*/
122+
public function getName(): string
123+
{
124+
return 'apilayer_currency_data';
125+
}
126+
}

src/Service/ApiLayer/Fixer.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
use Exchanger\Contract\ExchangeRate as ExchangeRateContract;
2626

2727
/**
28-
* Fixer Service (https://apilayer.com/marketplace/fixer-api).
28+
* ApiLayer Fixer Service (https://apilayer.com/marketplace/fixer-api).
2929
*
3030
* @author Florian Voutzinos <[email protected]>
3131
*/
3232
final class Fixer extends HttpService
3333
{
3434
use SupportsHistoricalQueries;
3535

36-
const ACCESS_KEY_OPTION = 'access_key';
36+
const API_KEY_OPTION = 'api_key';
3737

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

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

@@ -59,7 +59,7 @@ protected function getLatestExchangeRate(ExchangeRateQuery $exchangeQuery): Exch
5959
$url = sprintf(
6060
self::LATEST_URL,
6161
$exchangeQuery->getCurrencyPair()->getBaseCurrency(),
62-
$this->options[self::ACCESS_KEY_OPTION]
62+
$this->options[self::API_KEY_OPTION]
6363
);
6464

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

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

src/Service/Registry.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public static function getServices(): array
5353
'fastforex' => FastForex::class,
5454
'abstract_api' => AbstractApi::class,
5555
'exchangeratehost' => ExchangerateHost::class,
56-
'apilayer_fixer' => ApiLayer\Fixer::class
56+
'apilayer_fixer' => ApiLayer\Fixer::class,
57+
'apilayer_currency_data' => ApiLayer\CurrencyData::class
5758
];
5859
}
5960
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"success": false,
3+
"error": {
4+
"code": 101,
5+
"type": "invalid_access_key",
6+
"info": "You have not supplied a valid API Access Key. [Technical Support: [email protected]]"
7+
}
8+
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
{
2+
"success": true,
3+
"terms": "https:\/\/currencylayer.com\/terms",
4+
"privacy": "https:\/\/currencylayer.com\/privacy",
5+
"historical": true,
6+
"date": "2015-05-05",
7+
"timestamp": 1430870399,
8+
"source": "USD",
9+
"quotes": {
10+
"USDAED": 3.673069,
11+
"USDAFN": 58.160267,
12+
"USDALL": 125.971999,
13+
"USDAMD": 478.706002,
14+
"USDANG": 1.78954,
15+
"USDAOA": 109.314001,
16+
"USDARS": 8.910188,
17+
"USDAUD": 1.260714,
18+
"USDAWG": 1.7925,
19+
"USDAZN": 1.04915,
20+
"USDBAM": 1.749085,
21+
"USDBBD": 2,
22+
"USDBDT": 77.789719,
23+
"USDBGN": 1.74921,
24+
"USDBHD": 0.377207,
25+
"USDBIF": 1568.935867,
26+
"USDBMD": 1,
27+
"USDBND": 1.331299,
28+
"USDBOB": 6.900772,
29+
"USDBRL": 3.053759,
30+
"USDBSD": 1,
31+
"USDBTC": 0.004235,
32+
"USDBTN": 63.515033,
33+
"USDBWP": 9.833948,
34+
"USDBYR": 14374.316667,
35+
"USDBZD": 1.997894,
36+
"USDCAD": 1.208877,
37+
"USDCDF": 923.5605,
38+
"USDCHF": 0.928519,
39+
"USDCLF": 0.024602,
40+
"USDCLP": 610.728796,
41+
"USDCNY": 6.185728,
42+
"USDCOP": 2388.811663,
43+
"USDCRC": 531.94912,
44+
"USDCUC": 1,
45+
"USDCUP": 1.000038,
46+
"USDCVE": 98.654687,
47+
"USDCZK": 24.4979,
48+
"USDDJF": 177.377399,
49+
"USDDKK": 6.675821,
50+
"USDDOP": 44.77952,
51+
"USDDZD": 97.40122,
52+
"USDEEK": 13.999775,
53+
"USDEGP": 7.622161,
54+
"USDERN": 15.1151,
55+
"USDETB": 20.51218,
56+
"USDEUR": 0.894203,
57+
"USDFJD": 2.028702,
58+
"USDFKP": 0.659043,
59+
"USDGBP": 0.659043,
60+
"USDGEL": 2.319325,
61+
"USDGGP": 0.659043,
62+
"USDGHS": 3.864928,
63+
"USDGIP": 0.659043,
64+
"USDGMD": 43.0138,
65+
"USDGNF": 7312.395,
66+
"USDGTQ": 7.746544,
67+
"USDGYD": 206.185002,
68+
"USDHKD": 7.75158,
69+
"USDHNL": 21.95625,
70+
"USDHRK": 6.782218,
71+
"USDHTG": 47.60719,
72+
"USDHUF": 271.684098,
73+
"USDIDR": 13031.9,
74+
"USDILS": 3.875593,
75+
"USDIMP": 0.659043,
76+
"USDINR": 63.45038,
77+
"USDIQD": 1190.3009,
78+
"USDIRR": 28255.667967,
79+
"USDISK": 131.851,
80+
"USDJEP": 0.659043,
81+
"USDJMD": 115.103,
82+
"USDJOD": 0.70845,
83+
"USDJPY": 119.957,
84+
"USDKES": 95.039721,
85+
"USDKGS": 59.521667,
86+
"USDKHR": 4045.91835,
87+
"USDKMF": 440.441716,
88+
"USDKPW": 900.09,
89+
"USDKRW": 1081.599998,
90+
"USDKWD": 0.301784,
91+
"USDKYD": 0.821907,
92+
"USDKZT": 185.8362,
93+
"USDLAK": 8089.616732,
94+
"USDLBP": 1508.5,
95+
"USDLKR": 133.1648,
96+
"USDLRD": 84.720001,
97+
"USDLSL": 11.99574,
98+
"USDLTL": 2.933833,
99+
"USDLVL": 0.62865,
100+
"USDLYD": 1.36872,
101+
"USDMAD": 9.71972,
102+
"USDMDL": 18.03774,
103+
"USDMGA": 3061.686699,
104+
"USDMKD": 55.07277,
105+
"USDMMK": 1087.42,
106+
"USDMNT": 1955.166667,
107+
"USDMOP": 7.988893,
108+
"USDMRO": 308.661333,
109+
"USDMUR": 34.92106,
110+
"USDMVR": 15.276788,
111+
"USDMWK": 443.125199,
112+
"USDMXN": 15.38044,
113+
"USDMYR": 3.593208,
114+
"USDMZN": 35.283833,
115+
"USDNAD": 11.99574,
116+
"USDNGN": 198.924,
117+
"USDNIO": 26.83499,
118+
"USDNOK": 7.584483,
119+
"USDNPR": 101.4441,
120+
"USDNZD": 1.32795,
121+
"USDOMR": 0.385045,
122+
"USDPAB": 1,
123+
"USDPEN": 3.144932,
124+
"USDPGK": 2.693605,
125+
"USDPHP": 44.61504,
126+
"USDPKR": 101.797999,
127+
"USDPLN": 3.607051,
128+
"USDPYG": 5018.168262,
129+
"USDQAR": 3.641438,
130+
"USDRON": 3.963029,
131+
"USDRSD": 107.7551,
132+
"USDRUB": 50.8311,
133+
"USDRWF": 695.9579,
134+
"USDSAR": 3.750335,
135+
"USDSBD": 7.734353,
136+
"USDSCR": 13.58486,
137+
"USDSDG": 5.959468,
138+
"USDSEK": 8.356247,
139+
"USDSGD": 1.331973,
140+
"USDSHP": 0.659043,
141+
"USDSLL": 4332.5,
142+
"USDSOS": 697.386702,
143+
"USDSRD": 3.317,
144+
"USDSTD": 21951.433333,
145+
"USDSVC": 8.738193,
146+
"USDSYP": 188.929501,
147+
"USDSZL": 11.99574,
148+
"USDTHB": 33.29961,
149+
"USDTJS": 6.275233,
150+
"USDTMT": 3.4999,
151+
"USDTND": 1.914979,
152+
"USDTOP": 2.025876,
153+
"USDTRY": 2.706331,
154+
"USDTTD": 6.3385,
155+
"USDTWD": 30.69802,
156+
"USDTZS": 1975.558325,
157+
"USDUAH": 20.95269,
158+
"USDUGX": 2995.7,
159+
"USDUSD": 1,
160+
"USDUYU": 26.34045,
161+
"USDUZS": 2509.996683,
162+
"USDVEF": 6.318751,
163+
"USDVND": 21638.333333,
164+
"USDVUV": 105.151666,
165+
"USDWST": 2.442526,
166+
"USDXAF": 587.832418,
167+
"USDXAG": 0.060369,
168+
"USDXAU": 0.000838,
169+
"USDXCD": 2.70102,
170+
"USDXDR": 0.713827,
171+
"USDXOF": 587.207858,
172+
"USDXPF": 106.83024,
173+
"USDYER": 215.025199,
174+
"USDZAR": 11.99449,
175+
"USDZMK": 5253.075255,
176+
"USDZMW": 7.382381,
177+
"USDZWL": 322.355006
178+
}
179+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"success": true,
3+
"terms": "https:\/\/currencylayer.com\/terms",
4+
"privacy": "https:\/\/currencylayer.com\/privacy",
5+
"timestamp": 1399748450,
6+
"source": "USD",
7+
"quotes": {
8+
"USDEUR": 0.726804
9+
}
10+
}

0 commit comments

Comments
 (0)