Разбираем различные решения по работе с валютами (не мультивалютность, это отдельная тема).
Курс в другой валюте
Если мы торгуем на сайте в рублях, но нам нужно чтобы рядом с каждой ценой отображалась цена в евро. Нашел готовое решение от searchingman:
add_filter('woocommerce_get_price', 'my_woocommerce_get_price',100,2);
function my_woocommerce_get_price($price, $_product) {
// параметры ------------------------------------
$kurs_base = 58; // фиксированный базовый курс валюты
$kurs_current = 60; // текущий курс валюты по умолчанию
$kurs_cb = get_currency_cb('EUR'); // получить курс EUR
// $kurs_cb = get_currency_cb('USD'); // получить курс USD
// --------------------------------------------------
$kurs_base = ($kurs_base <= 0) ? 1 : $kurs_base;
$kurs_current = ($kurs_cb['kurs'] <= 0) ? $kurs_current : $kurs_cb['kurs'];
$new_price = $price * ($kurs_current / $kurs_base);
return $new_price; // новая цена
}
function get_currency_cb($code_valute = 'USD', $time_cash = '60' ) {
// параметры -------------------;
if ($code_valute != 'USD' && $code_valute != 'EUR') $code_valute = 'USD';
if ($time_cash <= 0) $time_cash = 60; // время кеширования в минутах
// ------------------------------
$name_cash = 'cash_kurs_cb';
$cached = get_transient($name_cash);
if ($cached !== false && $cached['code'] == $code_valute) {
$kurs_cb = $cached;
return $kurs_cb;
}
else {
libxml_use_internal_errors(true);
$kurs_cb_xml = simplexml_load_file("http://www.cbr.ru/scripts/XML_daily.asp");
if ($kurs_cb_xml === false) {
echo "Ошибка загрузки XML\n";
foreach(libxml_get_errors() as $error) {
echo "\t", $error->message;
}
$kurs_cb = $cached;
return $kurs_cb;
}
else
{
foreach ($kurs_cb_xml->Valute as $valute) {
if ((string)$valute->CharCode == $code_valute) {
$kurs_cb['date'] = (string)$kurs_cb_xml['Date'];
$kurs_cb['kurs'] = (string)$valute->Value;
$kurs_cb['code'] = $code_valute;
break;
}
}
$kurs_cb['kurs'] = round(str_replace(',','.',$kurs_cb['kurs']),2);
set_transient($name_cash, $kurs_cb, MINUTE_IN_SECONDS * $time_cash);
return $kurs_cb;
}
}
}
Фишкой данного решения является то что функция get_currency_cb парсит выгрузку ЦБ РФ (http://www.cbr.ru/scripts/XML_daily.asp) и выдает актуальный курс. Но саму логику замены цены я не проверял и переделал скрипт под свою задачу:
add_filter('woocommerce_after_shop_loop_item_title', 'my_woocommerce_get_price', 15);
function my_woocommerce_get_price($product) {
global $product;
$cur_price = $product->get_price();
$kurs_cb = get_currency_cb('EUR'); // получить курс EUR
$new_price = $cur_price / ($kurs_cb['kurs']); // делим рудли на EUR
$new_price = round($new_price, 0, PHP_ROUND_HALF_DOWN); // округлить до целого числа
//$new_price .= ' €';
echo '<span class="price"><span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">€</span>';
echo $new_price;
echo '</span></span>';
}
function get_currency_cb($code_valute = 'EUR', $time_cash = '60' ) {
if ($code_valute != 'USD' && $code_valute != 'EUR') $code_valute = 'EUR';
if ($time_cash <= 0) $time_cash = 60; // время кеширования в минутах
$name_cash = 'cash_kurs_cb';
$cached = get_transient($name_cash);
if ($cached !== false && $cached['code'] == $code_valute) {
$kurs_cb = $cached;
return $kurs_cb;
}
else {
libxml_use_internal_errors(true);
$kurs_cb_xml = simplexml_load_file("http://www.cbr.ru/scripts/XML_daily.asp");
if ($kurs_cb_xml === false) {
echo "Ошибка загрузки XML\n";
foreach(libxml_get_errors() as $error) {
echo "\t", $error->message;
}
$kurs_cb = $cached;
return $kurs_cb;
}
else
{
foreach ($kurs_cb_xml->Valute as $valute) {
if ((string)$valute->CharCode == $code_valute) {
$kurs_cb['date'] = (string)$kurs_cb_xml['Date'];
$kurs_cb['kurs'] = (string)$valute->Value;
$kurs_cb['code'] = $code_valute;
break;
}
}
$kurs_cb['kurs'] = round(str_replace(',','.',$kurs_cb['kurs']),2);
set_transient($name_cash, $kurs_cb, MINUTE_IN_SECONDS * $time_cash);
return $kurs_cb;
}
}
}
Теперь после цены в рублях выводится цена в EUR.
Немного изменил функцию вывода цены в евро:
add_filter( 'woocommerce_cart_product_price' , 'my_woocommerce_get_price', 10, 2);
add_filter( 'woocommerce_get_price_html' , 'my_woocommerce_get_price', 10, 2);
function my_woocommerce_get_price($price) {
global $product;
$cur_price = $product->get_price();
$kurs_cb = get_currency_cb('EUR'); // получить курс EUR
$new_price = $cur_price / ($kurs_cb['kurs']); // делим рудли на EUR
$new_price = round($new_price, 0, PHP_ROUND_HALF_DOWN); // округлить до целого числа
$price .= '<br>';
$price .= '<span class="woocommerce-Price-amount amount">';
$price .= '<span class="woocommerce-Price-currencySymbol">€</span>' ;
$price .= $new_price;
$price .= '</span>';
return $price;
}
Доброго дня!
Не знаете, как сделать, чтобы при ошибке загрузки XML выводилось не сообщение об ошибке, а, например, подгружались цены из кэша? (предыдущие цены — как я понимаю, цены ведь парсятся и обновляются каждый час?)
Буду очень признателен за совет или подсказку)))
Судя по функции — так и настроено, при ошибке парсинга должна выводится цифра из кэша. Но я тоже обратил внимание, что периодически появляется текст ошибки. Я закомментировал вывод ошибки и у меня стало все норм: