feat: Improve currency exchange rate fetching in BillingManager by adding a primary source from the Central Bank of Russia and a fallback to an alternative API, along with updates to currency formatting for better precision.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m17s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m17s
This commit is contained in:
@@ -116,8 +116,28 @@ function BillingManager() {
|
|||||||
const fetchExchangeRates = async () => {
|
const fetchExchangeRates = async () => {
|
||||||
setRatesLoading(true);
|
setRatesLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('https://api.exchangerate-api.com/v4/latest/USD');
|
// Основной источник: ЦБ РФ (base = RUB)
|
||||||
const rates = response.data.rates;
|
const cbr = await axios.get('https://www.cbr-xml-daily.ru/latest.js');
|
||||||
|
const rubPerUsd = cbr.data && cbr.data.rates?.USD ? 1 / Number(cbr.data.rates.USD) : null;
|
||||||
|
const rubPerEur = cbr.data && cbr.data.rates?.EUR ? 1 / Number(cbr.data.rates.EUR) : null;
|
||||||
|
|
||||||
|
if (rubPerUsd) {
|
||||||
|
const eurPerUsd = rubPerEur ? rubPerUsd / rubPerEur : 1;
|
||||||
|
setExchangeRates({
|
||||||
|
USD: 1,
|
||||||
|
EUR: eurPerUsd, // сколько EUR за 1 USD
|
||||||
|
RUB: rubPerUsd // сколько RUB за 1 USD
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('ЦБ недоступен, пробуем резервный источник:', error?.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Резервный источник: open.er-api
|
||||||
|
const response = await axios.get('https://open.er-api.com/v6/latest/USD');
|
||||||
|
const rates = response.data?.rates || {};
|
||||||
setExchangeRates({
|
setExchangeRates({
|
||||||
USD: 1,
|
USD: 1,
|
||||||
EUR: rates.EUR || 1,
|
EUR: rates.EUR || 1,
|
||||||
@@ -125,7 +145,8 @@ function BillingManager() {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка при загрузке курсов валют:', error);
|
console.error('Ошибка при загрузке курсов валют:', error);
|
||||||
setExchangeRates({ USD: 1, EUR: 0.85, RUB: 95 });
|
// Фолбек на разумные значения
|
||||||
|
setExchangeRates({ USD: 1, EUR: 1.05, RUB: 95 });
|
||||||
} finally {
|
} finally {
|
||||||
setRatesLoading(false);
|
setRatesLoading(false);
|
||||||
}
|
}
|
||||||
@@ -233,11 +254,12 @@ function BillingManager() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatCurrency(amount, currency = 'USD') {
|
function formatCurrency(amount, currency = 'USD') {
|
||||||
if (!amount) return '—';
|
if (amount === undefined || amount === null || amount === '') return '—';
|
||||||
return new Intl.NumberFormat('ru-RU', {
|
return new Intl.NumberFormat('ru-RU', {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
currency: currency,
|
currency: currency,
|
||||||
maximumFractionDigits: 0
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2
|
||||||
}).format(amount);
|
}).format(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +268,8 @@ function BillingManager() {
|
|||||||
return new Intl.NumberFormat('ru-RU', {
|
return new Intl.NumberFormat('ru-RU', {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
currency: 'RUB',
|
currency: 'RUB',
|
||||||
maximumFractionDigits: 0
|
minimumFractionDigits: 2,
|
||||||
|
maximumFractionDigits: 2
|
||||||
}).format(rubAmount);
|
}).format(rubAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user