Получение курсов валют с сайта Центробанка

Валюты

При разработке интернет-магазинов или различных информеров для сайтов часто приходится реализовывать получение актуальных курсов валют. Не все разработчики знают, что достаточно удобно получать курсы на любую дату используя API сайта Центрального банка РФ.

Курсы на сутки вперёд доступны в формате XML по адресу

http://www.cbr.ru/scripts/XML_daily.asp

Для получения данных на любую прошедшую дату нужно воспользоваться параметром date_req

http://www.cbr.ru/scripts/XML_daily.asp?date_req=12.07.2012

Теперь на нашем сайте нам достаточно распарсить XML файл и выбрать нужные валюты. Для выбора элементов из дерева можно использовать DOM или другие расширения для работы с XML.

Напишем класс, загружающий данные о курсах валют:

/**
 * @author ElisDN <mail@elisdn.ru>
 * @link http://www.elisdn.ru
 */
class CBRAgent
{
    protected $list = array();
 
    public function load()
    {
        $xml = new DOMDocument();
        $url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=' . date('d.m.Y');
 
        if (@$xml->load($url))
        {
            $this->list = array(); 
 
            $root = $xml->documentElement;
            $items = $root->getElementsByTagName('Valute');
 
            foreach ($items as $item)
            {
                $code = $item->getElementsByTagName('CharCode')->item(0)->nodeValue;
                $curs = $item->getElementsByTagName('Value')->item(0)->nodeValue;
                $this->list[$code] = floatval(str_replace(',', '.', $curs));
            }
 
            return true;
        } 
        else
            return false;
    }
 
    public function get($cur)
    {
        return isset($this->list[$cur]) ? $this->list[$cur] : 0;
    }
}

Теперь мы можем загружать и считывать значения курса любой валюты относительно рубля:

$cbr = new CBRAgent();
if ($cbr->load()){    
    $usd_curs = $cbr->get('USD');
}

Обновление курсов нескольких валют в Yii Framework может, например, выглядеть так:

public function updateCurrencies()
{
    $cbr = new CBRAgent();
    if ($cbr->load())
    {    
        $models = Currency::model()->findAll()
        foreach ($models as $model)
        {                
            $model->curs = $cbr->get($model->name);
            $model->save();
        }  
    }
}

или так:

public function updateCurrencies()
{
    $cbr = new CBRAgent();
    if ($cbr->load())
    {    
        $currencies = array('USD', 'EUR');
 
        foreach($currencies as $currency)
        {                    
            Yii::app()->config->set('SHOP.CURS_' . $currency, $cbr->get($currency));
        }    
    }
}

если хранение курсов производится в каком-либо компоненте.

Этот метод можно поместить в контроллер магазина и вызывать по таймауту или поместить в консольную команду и вызывать по Cron.

Комментарии

 

Виталий

Не могу понять, какого хрена http://www.cbr.ru/scripts/XML_daily.asp возвращает контент 1 раз из 20-и... Пробовал через file_get_contents, через curl, через сокеты, теперь вот напрямую с помощью DOMDocument...

Через браузер вроде все ок. Иногда сбрасываются соединения, но не так безбожно.

Это руки у меня кривые или это фаервол такой?

Ответить

 

Дмитрий Елисеев

Тоже не открывается. Значит админы уже Новый Год празднуют.

Ответить

 

Андрей

Подскажите как выдернуть дату из ответа <valcurs date="10.04.2014" name="Foreign Currency Market" />

Ответить

 

Дмитрий Елисеев
$valcurs = $root->getElementsByTagName('valcurs');
echo $valcurs[0]->getAttribute('date');
Ответить

 

Андрей

Спасибо, но

Fatal error: Call to undefined method DOMNodeList::getAttribute()

не работает(

Еще замечено, что очень часто попытка загрузки через php url http://www.cbr.ru/scripts/XML_daily.asp выводит пустой ответ, на локалке лечится открытием этого урла в браузере, на хостинге - урла через wget.
Как побороть кто знает? Curl?

Ответить

 

Дмитрий Елисеев

Тогда можно попробовать что-то вроде:

echo $valcurs->item(0)->getAttribute('date');

В общем, выцепить из массива первый элемент.

Ответить

 

Akej

а как запустить контроллер по таймауту??

Ответить

 

Akej

Вернее запустить метод контроллера по таймауту?

Ответить

 

Дмитрий Елисеев

Оформить как консольную команду и настроить её запуск по Cron (должен быть в панели управления хостинга) как здесь.

Ответить

 

Дмитрий

от 06.11.2014

class CBRAgent{
	protected $list = array();
 
	public function load(){
		$url = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req='.date('d.m.Y', time());
		$xml = simplexml_load_file($url);
	
		if($xml){
			foreach ($xml as $item){
				$code = strval($item->CharCode);
				$curs = $item->Value;
				$this->list[$code] = floatval(str_replace(',', '.', $curs));
			}
			return true;
		}else{
			return false;
		}
	}
 
	public function get($cur){
		return isset($this->list[$cur]) ? $this->list[$cur] : 0;
	}
}

$cbr = new CBRAgent();
if ($cbr->load()){    
	$usd_curs = $cbr->get('USD');
}
Ответить

 

Евгений

простое кэширование на диске(public_html) раз в день по запросу без всяких кронов

class CBRAgent
{
    protected $list = array();
    public function load()
    {
        $xml = new \DOMDocument();
        $filepath = 'curs_valute_'.date('d.m.Y').'.xml';
        if(file_exists($filepath)){
            $tosave = false;
            $path = $filepath;
        } else {
            $tosave = true;
            $path = 'http://www.cbr.ru/scripts/XML_daily.asp?date_req=' . date('d.m.Y');
        }
        if (@$xml->load($path))
        {
            if($tosave){
                array_map('unlink', glob('curs_valute_*.xml'));
                @$xml->save($filepath);
            }
            $this->list = array();
            $root = $xml->documentElement;
            $items = $root->getElementsByTagName('Valute');
            foreach ($items as $item)
            {
                $code = $item->getElementsByTagName('CharCode')->item(0)->nodeValue;
                $curs = $item->getElementsByTagName('Value')->item(0)->nodeValue;
                $this->list[$code] = floatval(str_replace(',', '.', $curs));
            }
            return true;
        }
        else
            return false;
    }

    public function get($cur)
    {
        return isset($this->list[$cur]) ? $this->list[$cur] : 0;
    }
}
Ответить

 

Влад

Добрый день Дмитрий. Помогите создать 2 информера курса валют: евро и доллара. Я далек от программирования. Буду признателен.

Ответить

 

Дмитрий Елисеев

Скопируйте себе HTML-код готовых вроде этих.

Ответить

 

kursvaliut

kursvaliut.ru позволяет взять бесплатный ежедневный обновленный курс валют ЦБ или в том числе конвертер валют включив простой JavaScript :)

Ответить

Оставить комментарий

Войти | Завести аккаунт


(никто не увидит)



Можно использовать теги <p> <ul> <li> <b> <i> <a> <pre>