Zjišťování aktuální měnových kurzů v PHP

Internet nám mimo jiné umožňuje efektivně oslovovat zákazníky z celého světa. Představme si jednu hypotetickou situaci. Máte webový obchod, ve kterém prodáváte nějaké unikátní výrobky (třeba speciální sádrové trpaslíky), které jinde sehnat nejdou. Američan si chce nějakého speciálního trpaslíka zakoupit, narazí na vaši stránku, ale místo cen v nějaké jemu známé měně (USD) vidí jen čísla doplněná zkratkou CZK nebo Kč. Jak zajistit, aby si američan mohl zobrazit cenu v amerických dolarech, a ta byla pořád aktuální?

V tomto článku si ukážeme, jak přepočítávat ceny zboží podle aktuálního kurzu. Základem je najít vhodný zdroj dat. K tomuto účelu nám vhodně poslouží stránky České národní banky, na které najdeme odkaz na textový soubor, ve kterém jsou uloženy aktuální kurzy:

http://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt

Adresu souboru s kurzy si uložíme do konstanty SOUBOR_KURZY. Tuto konstantu je potřeba definovat před spuštěním následujících funkcí, jinak ukázka nebude fungovat.

Define("SOUBOR_KURZY", "http://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt");

Tento soubor má velmi jednoduchý formát – na jednom řádku jsou informace o jedné měně, a to v pořadí země, název měny, množství měny, třípísmenný kód měny a kurz. Na prvním řádku je ještě informace o dni, pro který jsou kurzy platné. Pro zjištění kurzu můžeme použít následující funkci:

  function zjistiKurz($mena) {
    // vstupnim parametrem je tripismenny kod meny, jejiz kurz chceme zjistit
    $kurzy = file(SOUBOR_KURZY);
    foreach ($kurzy as $v) {
      $h = explode("|", $v);
      if ((count($h) >= 5) && ($h[3] == $mena)) {
        return $h[2]." ".$h[3]." = ".$h[4]." CZK";
      }
    }
  }

Chceme-li například zjistit, jaký je kurz pro Euro, zavoláme echo zjistiKurz("EUR");. Výsledkem je 1 EUR = 28,145 CZK.

Chceme-li převést konkrétní částku v cizí měně na české koruny, použijeme následující funkci:

  function prevedNaKoruny($mena, $mnozstvi = 1, $long = false) {
    // vstupnimi parametry jsou tripismenny kod meny a mnozstvi (vychozi hodnota je 1 jednotka)
    // a take prepinac, ktery urci, jaky chceme vystup - zda-li jen cislo ($long == false)
    // nebo "dlouhy zapis"
    $kurzy = file(SOUBOR_KURZY);
    foreach ($kurzy as $v) {
      $h = explode("|", $v);
      if (isset($h[4])) $h[4] = str_replace(",", ".", $h[4]); // prevod desetinne carky na tecku
      if ((count($h) >= 5) && ($h[3] == $mena)) {
        if ($long) return "$mnozstvi ".$h[3]." = ".($mnozstvi * $h[4] / (float)$h[2])." CZK";
        else return ($mnozstvi * $h[4] / (float)$h[2]);
      }
    }
    return -1; // zadana mena nebyla nalezena
  }

Zavoláme přepočet 10 EUR na české koruny – echo prevedNaKoruny("EUR", 10, true); a dostaneme výsledek 10 EUR = 281.45 CZK. Chtěli-li bychom výsledek vhodný například pro zobrazení v e-shopu, zavoláme funkci následovně – echo prevedNaKoruny("EUR", 10); a dostaneme pouze číselnou hodnotu 281.45.

Poslední možností je převedení finanční částky z českých korun do cizí měny.

  function prevedNaCizi($mena, $pocetKorun = 1, $long = false) {
    // vstupnimi parametry jsou tripismenny kod meny a mnozstvi korun (vychozi hodnota je 1 Kc)
    // a take prepinac, ktery urci, jaky chceme vystup - zda-li jen cislo ($long == false)
    // nebo "dlouhy zapis"
    $kurzy = file(SOUBOR_KURZY);
    foreach ($kurzy as $v) {
      $h = explode("|", $v);
      if (isset($h[4])) $h[4] = str_replace(",", ".", $h[4]); // prevod desetinne carky na tecku
      if ((count($h) >= 5) && ($h[3] == $mena)) {
        if ($long) return $pocetKorun." CZK = ".($pocetKorun / (float)$h[4] * $h[2])." $mena";
        else return ($pocetKorun / (float)$h[4] * $h[2]);
      }
    }
    return -1 // zadana mena nebyla nalezena
  }

Výše uvedená funkce nám třeba převede 100 Kč na Eura – echo prevedNaCizi("EUR", 100, true);. Výsledkem je 100 CZK = 3.55 EUR. Chtěli-li bychom, aby výstup z funkce byl použitelný například v internetové prodejně, zavoláme funkci následovně – echo prevedNaCizi("EUR", 100); – výsledkem bude jen číselná hodnota, tedy 3.55

U navštěvovanějších internetových obchodů by mohlo opakované načítání jednak zbytečně zatěžovat server ČNB, druhak způsobovat zbytečné prodlevy při zobrazování webových stránek. Proto je nanejvýš vhodné soubor s kurzy stahovat pouze čas od času – například jednou za hodinu pomocí úlohy v cronu a ve skriptech načítat lokální kopii tohoto souboru.

Kurzy exotičtějších měn

Skript je taktéž možno doplnit o možnost přepočtu kurzů exotičtějších měn – k tomu nám poslouží následující soubor:

http://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_ostatnich_men/kurzy.txt

Formát je stejný jako u výše uvedeného souboru, liší se jen četnost aktualizací – soubor s exotickými měnami je vydáván jednou měsíčně (vždy na konci měsíce), zatímco ostatní měny jsou aktualizovány každý pracovní den.

Tanto příspěvek byl zařazen do kategorie PHP a označen štítkem , . Do oblíbených si můžete uložit trvalý odkaz.

15 komentářů k Zjišťování aktuální měnových kurzů v PHP

  1. lukas napsal(a):

    chtel bych upozornit ze strankach CNB pravdepodobne doslo k zmene url .
    Funkcni odkaz je (7.11.2008) http://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt

  2. admin napsal(a):

    Díky za upozornění, odkazy v článku jsem aktualizoval.

  3. Michal napsal(a):

    Díky moc za návod, možná by stálo za to (pro nás, neználky) do toho zapracovat i nějaký kontrolní mechanizmus, zda url existuje :)

  4. cestmir napsal(a):

    Dobrý den.Je to super, jen mám problém.Nedokážu přijít na to, proč při volání fce echo „prevedNaKoruny(„EUR“, 10, true);“ se mi vždy zobrazí celá, zaokrouhlená částka, což vede k velkým nepřesnostem při převodu.Ideální by byla dvě desetiná místa.Co s tím?

  5. admin napsal(a):

    cestmir: kód pro funkci prevedNaKoruny() byl špatný, protože nefungoval převod desetinné čárky na tečku – teď už je to opraveno a vrací ho hodnoty na dvě desetinná místa

  6. Tom napsal(a):

    Diky za script, bylo by mozne doplnit jak do skriptu doplnit aktualni datum zobrazovane na kurz. listku cnb?

  7. Duk napsal(a):

    Perfektní skript.

  8. Jura napsal(a):

    To prave vsude hledal :o )
    Bylo by mozne zjistit ten script complekt?

  9. admin napsal(a):

    Jura: prosím ještě jednou, česky a srozumitelně

  10. grim napsal(a):

    díky mockrát za ušetření hodiny práce ;)

  11. Lukáš napsal(a):

    Mám problém, na mém localním serveru to funguje bez problému, ale jak to nahodím na webový server (webhosting onebit, verze php 5.2.9) tak to nefunguje. Když jsem se snažil zjistit kde se to zarazí, tak hned na začátku při načítání toho textového souboru do proměnné. Proměnná je totiž prázdná. Prosím o pomoc.

  12. admin napsal(a):

    @Lukáš: tipuji zakázané allow_url_fopen, bez konkrétní chybové hlášky se lepší odpovědi nedočkáš

  13. Lukáš napsal(a):

    Ano je to na serveru zakázané.

  14. admin napsal(a):

    Lukáš: v tom případě je potřeba povolit, případně to zkusit obejít pomocí curl

  15. Milan napsal(a):

    doporučuji k práci s měnou a přepočtem využít http://addons.nette.org/cs/cnb pracuje i bez nette frameworku

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

*

Můžete používat následující HTML značky a atributy: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>