VA service Exchange rates

Verze pro PHP 8.5.x a Kubernetes. Služba běží v kontejneru z base image
docker/php-8/8.5:latest-skeletnext-regular. Starší verze na PHP 7.4 nasazovaná přestools/deploymentje na větvimaster.
VA služba pro získávání a přepočet měnových kurzů vůči domácí měně - Česká koruna CZK - historie změn
Strojová dokumentace API (OpenAPI 3) - ZDE
Vývoj
Veškerá práce probíhá v kontejneru — obsahuje PHP 8.5 se všemi potřebnými extensions.
cp docker-compose.override.yml.example docker-compose.override.yml
docker compose up -d
docker compose exec php composer install
Služba pak běží na http://localhost:3868.
| Příkaz | Co dělá |
|---|---|
docker compose exec php composer test |
testy (nette/tester) |
docker compose exec php composer phpstan |
statická analýza (level 5 + baseline) |
docker compose exec php composer rector |
návrh refaktoringu na PHP 8.5 (dry-run) |
docker compose exec php composer lint:cs |
kontrola PSR-12 |
docker compose exec php composer import |
ruční import kurzů z ČNB |
Simulace produkčního běhu: docker compose -f docker-compose-run.yml up --build
Nasazení za reverzní proxy / k8s ingress
Za proxy je REMOTE_ADDR adresa proxy, ne klienta — kontrola IP i logování by pak pracovaly
se špatnou hodnotou a všechny požadavky by vypadaly, že jdou z jedné adresy.
Proto je potřeba nastavit proměnnou TRUSTED_PROXIES na rozsah, ze kterého proxy chodí:
TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
Teprve pak služba čte skutečnou IP klienta z hlavičky X-Forwarded-For.
Import kurzů
bin/importExchangeRates [dateFrom] [dateTo] stahuje kurzovní lístek ČNB.
- bez parametrů — dnešní den
- jeden parametr — konkrétní den
- dva parametry — rozsah od–do
Je to periodická úloha a musí ji něco pravidelně spouštět, jinak se kurzy přestanou
aktualizovat. Ručně ji lze vyvolat i přes API metodu 4 (/api/import).
Pozn.: ČNB publikuje lístek kolem 14:30. Dotaz na dnešek před tím vrátí poslední starší lístek — služba to řeší dohledáváním nejbližšího staršího kurzu.
API metody
1. GET /api/rate - vyhledá kurz pro měnu a datum
Vyhledá kurz na zadanou měnu a den. Pokud není kurz dostupný pro daný den, vrátí nejbližší starší do max. tolerance (3 měsíce).
Query parametry:
currency- povinný parametr, zadává se jako třípísmenný kód (akceptuje malé i velké písmena) ve formátu ISO 4217 - https://en.wikipedia.org/wiki/ISO_4217, např.eur|EUR|usddate- nepovinný parametr, datum (den) pro vyhledání kurzu, výchozí dnešní datumtoday- dohledává se vždy nejbližší možný nejstarší kurz do maximální tolerance do minulosti (3 měsíce), formát je validní datum ve formátuY-m-d(rok-měsíc-den) neboY-m(rok-měsíc) neboY(rok), lze také používat relativní notace typu mínus 5 dní atd. Příklady hodnot:2021|2020-05|2020-05-21|2018-06-06|-5day|-year|-3months|yesterdayatd.
Příklady:
- /api/rate?currency=usd - Kurz na americký dolar dnes
- /api/rate?currency=usd&date=yesterday - Kurz na americký dolar včera
- /api/rate?currency=usd&date=-5day - Kurz na americký dolar před pěti dny
- /api/rate?currency=usd&date=2020-12-24 - Kurz na americký dolar 24. prosince 2020
- /api/rate?currency=eur&date=2019-03 - Kurz na euro na začátku března 2019
- /api/rate?currency=eur&date=2018 - Kurz na euro na začátku roku 2018
- /api/rate?currency=golden+coins - Nevalidně zadaná měna, HTTP odpověď 400
- /api/rate?currency=abc - Neexistující měna, HTTP odpověď 404
Odpověď je JSON ve tvaru:
{
"found": true,
"date_requested": "2021-02-14",
"currency": "USD",
"date": "2021-02-10",
"amount": 1,
"rate": 21.301
}
Pozn.:
- Všechny datumy se vždy vrací ve formátu
Y-m-d date_requestedje požadované datum adatenejbližší nalezené datum do minulosti (do max. tolerance).foundje bool hodnota určující, zda byl záznam nalezencurrencyje požadovaná/nalezená měna, vrací se vždy ve velkých písmenech
Odpověď HTTP 404 v případě NEnalezení záznamu:
{
"found": false,
"date_requested": "2004-01-01",
"currency": "USD"
}
2. GET /api/rates - vyhledá všechny kurzy pro datum
Vyhledá nejbližší kurzy (stejná logika jako u 1.) na zadaný den pro všechny dostupné měny
Query parametry:
date- viz API metoda 1., stejný parametr (formát zadávání)currency- filtr pro specifické měny, lze zadávat jako měny v ISO 4217 oddělené čárkou, např.eur,usd,gbp
Příklady:
- /api/rates - Kurzy na všechny měny dnes
- /api/rates?date=yesterday - Kurzy na všechny měny včera
- /api/rates?date=2018-03 - Kurzy na všechny měny na začátku března 2018
- /api/rates?date=2021 - Kurzy na všechny měny na začátku roku 2021
- /api/rates?date=2021¤cy=eur,usd,gbp - Kurzy na měny na začátku roku 2021 - specifické měny
- /api/rates?date=2020-35-99 - Nevalidní datum, HTTP odpověď 400
Tvar odpovědi, záznamy se sloučí do struktury [currency]{item}
{
"count": 3,
"date_requested": "2018-03-01",
"items": {
"EUR": {
"date": "2018-03-01",
"currency": "EUR",
"amount": 1,
"rate": 25.435
},
"GBP": {
"date": "2018-03-01",
"currency": "GBP",
"amount": 1,
"rate": 28.735
},
...
}
}
3. GET /api/rates-history - prohledá historii kurzů
Vyhledá kurzy v rozsahu zadaných datumů pro měny - vrací pouze reálně nalezené položky (dny, které nemají kurz se nevrací!)
Route parametry:
Query parametry:
from- formát viz API metoda 1. - parametrdate- datum odkud hledat kurzy, výchozí datum před 1 měsícem ode dneška-1monthto- formát viz API metoda 1. - parametrdate- datum pokud hledat kurzy, výchozí dnešní datumtodaycurrency- filtr pro specifické měny, viz API metoda 2.limit- omezení počtu vrácených záznamů zadává se jako číslo1-n, výchozí365- pozn. limit a stránkování se nepoužívá u slučování (vizgroup)!page- stránkování vrácených záznamů, číslo1-ngroup- možnost slučování vrácených záznamů do struktury, povolené hodnoty:none- neslučovat, nechat lineární pole objektů - výchozí hodnotacurrency- záznamy se sloučí do struktury[currency][{item1}, {item2}, {item3}...]date- záznamy se sloučí do struktury[date][{item1}, {item2}, {item3}...]
Příklady:
- /api/rates-history - Kurzy na všechny nalezené měny měsíc nazpět po dnešek
- /api/rates-history?currency=usd,eur - Kurzy na euro a americký dolar měsíc nazpět po dnešek
- /api/rates-history?limit=10&page=2 - Kurzy na všechny nalezené měny měsíc nazpět po dnešek, limit 10 záznamů, stránka 2
- /api/rates-history?from=2018&to=2019-04&limit=30 - Kurzy na všechny nalezené měny od začátku roku 2018 do dubna 2019, limit 30 záznamů
- /api/rates-history?from=-5days&to=yesterday¤cy=eur - Kurzy na euro od 5 dnů na zpět do včerejška
- /api/rates-history?from=-50days&to=today¤cy=eur,usd,gbp&group=currency - Kurzy na euro, americký dolar a britskou libru od 50 dnů na zpět do dneška, slučené podle měny
- /api/rates-history?from=2018&to=2018-12-31&group=date - Kurzy na všechny dny v roce 2018, slučené podle data
Tvar odpovědi, group=none:
{
"limit": 365,
"page": 1,
"num_pages": 1,
"count": 3,
"total": 3,
"date_from_requested": "2021-02-12",
"date_to_requested": "2021-02-16",
"items": [
{
"date": "2021-02-16",
"currency": "EUR",
"amount": 1,
"rate": 25.755
},
{
"date": "2021-02-15",
"currency": "EUR",
"amount": 1,
"rate": 25.68
},
...
]
}
Tvar odpovědi, group=currency:
{
...
"date_from_requested": "2020-12-29",
"date_to_requested": "2021-02-17",
"items": {
"EUR": [
{
"date": "2021-02-16",
"currency": "EUR",
"amount": 1,
"rate": 25.755
},
...
],
"GBP": [
{
"date": "2021-02-16",
"currency": "GBP",
"amount": 1,
"rate": 29.493
},
...
],
...
}
}
Tvar odpovědi, group=date:
{
...
"date_from_requested": "2018-01-01",
"date_to_requested": "2018-12-31",
"items": {
"2018-12-31": [
{
"date": "2018-12-31",
"currency": "EUR",
"amount": 1,
"rate": 25.725
},
...
],
"2018-12-28": [
{
"date": "2018-12-28",
"currency": "EUR",
"amount": 1,
"rate": 25.78
},
...
],
...
}
}
4. GET /api/import - import kurzů z ČNB
Stáhne kurzovní lístek ČNB a uloží ho do databáze. Běžně se spouští periodicky, tento endpoint slouží k ručnímu vyvolání.
Query parametry:
date- den, ke kterému se má import provést, výchozítoday, formát viz API metoda 1.
Odpověď: {"status": "ok"}