mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-18 21:32:27 +01:00
Fix several issues in cart
* Fix: Only USD currency with 2 decimals were properly handled for tips * Fix: All PoS apps would were sharing the same basket * Fix: Currency formatting was not using server side information * Fix: Various bug of formatting for decimal 0 and more than 2.
This commit is contained in:
parent
1f14bd6188
commit
cad602ad14
@ -41,6 +41,7 @@ namespace BTCPayServer.Controllers
|
||||
var currency = _AppsHelper.GetCurrencyData(settings.Currency, false);
|
||||
double step = currency == null ? 1 : Math.Pow(10, -(currency.Divisibility));
|
||||
|
||||
var numberFormatInfo = _AppsHelper.Currencies.GetNumberFormatInfo(currency.Code) ?? _AppsHelper.Currencies.GetNumberFormatInfo("USD");
|
||||
return View(new ViewPointOfSaleViewModel()
|
||||
{
|
||||
Title = settings.Title,
|
||||
@ -49,6 +50,14 @@ namespace BTCPayServer.Controllers
|
||||
ShowCustomAmount = settings.ShowCustomAmount,
|
||||
CurrencyCode = currency.Code,
|
||||
CurrencySymbol = currency.Symbol,
|
||||
CurrencyInfo = new ViewPointOfSaleViewModel.CurrencyInfoData()
|
||||
{
|
||||
CurrencySymbol = string.IsNullOrEmpty(currency.Symbol) ? currency.Code : currency.Symbol,
|
||||
Divisibility = currency.Divisibility,
|
||||
DecimalSeparator = numberFormatInfo.CurrencyDecimalSeparator,
|
||||
ThousandSeparator = numberFormatInfo.NumberGroupSeparator,
|
||||
Prefixed = new[] { 0, 2 }.Contains(numberFormatInfo.CurrencyPositivePattern)
|
||||
},
|
||||
Items = _AppsHelper.Parse(settings.Template, settings.Currency),
|
||||
ButtonText = settings.ButtonText,
|
||||
CustomButtonText = settings.CustomButtonText,
|
||||
@ -124,7 +133,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
ApplicationDbContextFactory _ContextFactory;
|
||||
CurrencyNameTable _Currencies;
|
||||
|
||||
public CurrencyNameTable Currencies => _Currencies;
|
||||
public AppsHelper(ApplicationDbContextFactory contextFactory, CurrencyNameTable currencies)
|
||||
{
|
||||
_ContextFactory = contextFactory;
|
||||
|
@ -22,6 +22,17 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
public bool Custom { get; set; }
|
||||
}
|
||||
|
||||
public class CurrencyInfoData
|
||||
{
|
||||
public bool Prefixed { get; set; }
|
||||
public string CurrencySymbol { get; set; }
|
||||
public string ThousandSeparator { get; set; }
|
||||
public string DecimalSeparator { get; set; }
|
||||
public int Divisibility { get; internal set; }
|
||||
}
|
||||
|
||||
public CurrencyInfoData CurrencyInfo { get; set; }
|
||||
|
||||
public bool EnableShoppingCart { get; set; }
|
||||
public bool ShowCustomAmount { get; set; }
|
||||
public string Step { get; set; }
|
||||
@ -29,7 +40,7 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
public Item[] Items { get; set; }
|
||||
public string CurrencyCode { get; set; }
|
||||
public string CurrencySymbol { get; set; }
|
||||
|
||||
public string AppId { get; set; }
|
||||
public string ButtonText { get; set; }
|
||||
public string CustomButtonText { get; set; }
|
||||
public string CustomTipText { get; set; }
|
||||
|
@ -5,7 +5,7 @@
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"BTCPAY_NETWORK": "regtest",
|
||||
"BTCPAY_BUNDLEJSCSS": "true",
|
||||
"BTCPAY_BUNDLEJSCSS": "false",
|
||||
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||
"BTCPAY_BTCLIGHTNING": "type=charge;server=http://127.0.0.1:54938/;api-token=foiewnccewuify",
|
||||
"BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true",
|
||||
@ -24,7 +24,7 @@
|
||||
"BTCPAY_NETWORK": "regtest",
|
||||
"BTCPAY_PORT": "14142",
|
||||
"BTCPAY_HttpsUseDefaultCertificate": "true",
|
||||
"BTCPAY_BUNDLEJSCSS": "true",
|
||||
"BTCPAY_BUNDLEJSCSS": "false",
|
||||
"BTCPAY_LTCEXPLORERURL": "http://127.0.0.1:32838/",
|
||||
"BTCPAY_BTCLIGHTNING": "type=charge;server=http://127.0.0.1:54938/;api-token=foiewnccewuify",
|
||||
"BTCPAY_BTCEXTERNALLNDGRPC": "type=lnd-grpc;server=https://lnd:lnd@127.0.0.1:53280/;allowinsecure=true",
|
||||
|
@ -61,7 +61,15 @@ namespace BTCPayServer.Services.Rates
|
||||
currencyInfo.CurrencySymbol = currency;
|
||||
return currencyInfo;
|
||||
}
|
||||
|
||||
public NumberFormatInfo GetNumberFormatInfo(string currency)
|
||||
{
|
||||
var curr = GetCurrencyProvider(currency);
|
||||
if (curr is CultureInfo cu)
|
||||
return cu.NumberFormat;
|
||||
if (curr is NumberFormatInfo ni)
|
||||
return ni;
|
||||
return null;
|
||||
}
|
||||
public IFormatProvider GetCurrencyProvider(string currency)
|
||||
{
|
||||
lock (_CurrencyProviders)
|
||||
|
@ -245,215 +245,48 @@ Cart.prototype.formatCurrency = function(amount, currency, symbol) {
|
||||
thousandsSep = '',
|
||||
decimalSep = ''
|
||||
prefix = '',
|
||||
postfix = '',
|
||||
currencyName = currency.toLowerCase();
|
||||
postfix = '';
|
||||
|
||||
// Currency symbols
|
||||
switch (currencyName) {
|
||||
case 'usd':
|
||||
case 'aud':
|
||||
case 'cad':
|
||||
case 'clp':
|
||||
case 'mxn':
|
||||
case 'nzd':
|
||||
case 'sgd':
|
||||
prefix = '$';
|
||||
break;
|
||||
case 'eur':
|
||||
postfix = ' €';
|
||||
break;
|
||||
case 'chf':
|
||||
prefix = 'CHF ';
|
||||
break;
|
||||
case 'gbp':
|
||||
prefix = '£';
|
||||
break;
|
||||
case 'jpy':
|
||||
case 'cny':
|
||||
prefix = '¥';
|
||||
break;
|
||||
case 'hkd':
|
||||
prefix = 'HK$';
|
||||
break;
|
||||
case 'ars':
|
||||
case 'cop':
|
||||
prefix = '$ ';
|
||||
break;
|
||||
case 'brl':
|
||||
prefix = 'R$ ';
|
||||
break;
|
||||
case 'bdt':
|
||||
postfix = '৳';
|
||||
break;
|
||||
case 'czk':
|
||||
postfix = ' Kč';
|
||||
break;
|
||||
case 'dkk':
|
||||
postfix = ' kr.';
|
||||
break;
|
||||
case 'huf':
|
||||
postfix = ' Ft';
|
||||
break;
|
||||
case 'hrk':
|
||||
postfix = ' HRK';
|
||||
break;
|
||||
case 'ils':
|
||||
postfix = ' ₪';
|
||||
break;
|
||||
case 'inr':
|
||||
prefix = '₹ ';
|
||||
break;
|
||||
case 'isk':
|
||||
postfix = ' ISK';
|
||||
break;
|
||||
case 'kzt':
|
||||
postfix = ' ₸';
|
||||
break;
|
||||
case 'myr':
|
||||
prefix = 'RM';
|
||||
break;
|
||||
case 'ngn':
|
||||
prefix = '₦';
|
||||
break;
|
||||
case 'nok':
|
||||
prefix = 'kr ';
|
||||
break;
|
||||
case 'php':
|
||||
prefix = '₱';
|
||||
break;
|
||||
case 'pen':
|
||||
prefix = 'S/';
|
||||
break;
|
||||
case 'pln':
|
||||
postfix = ' zł';
|
||||
break;
|
||||
case 'ron':
|
||||
postfix = ' RON';
|
||||
break;
|
||||
case 'rub':
|
||||
postifx = ' ₽';
|
||||
break;
|
||||
case 'sek':
|
||||
postfix = ' kr';
|
||||
break;
|
||||
case 'aed':
|
||||
prefix = 'د.إ. ';
|
||||
break;
|
||||
case 'egp':
|
||||
prefix = 'ج.م.';
|
||||
break;
|
||||
case 'irr':
|
||||
prefix = 'ریال';
|
||||
break;
|
||||
case 'pkr':
|
||||
prefix = ' ر';
|
||||
break;
|
||||
case 'sar':
|
||||
prefix = 'ر.س.';
|
||||
break;
|
||||
case 'try':
|
||||
prefix = '₺';
|
||||
break;
|
||||
case 'uah':
|
||||
postfix = ' ₴';
|
||||
break;
|
||||
case 'vnd':
|
||||
postfix = ' ₫';
|
||||
break;
|
||||
case 'zar':
|
||||
prefix = 'R';
|
||||
break;
|
||||
|
||||
default:
|
||||
prefix = symbol || currency;
|
||||
if (srvModel.currencyInfo.prefixed) {
|
||||
prefix = srvModel.currencyInfo.currencySymbol;
|
||||
}
|
||||
|
||||
// Currency separators
|
||||
switch (currencyName) {
|
||||
case 'eur':
|
||||
case 'czk':
|
||||
case 'huf':
|
||||
case 'kzt':
|
||||
case 'nok':
|
||||
case 'pln':
|
||||
case 'rub':
|
||||
case 'sek':
|
||||
case 'uah':
|
||||
case 'zar':
|
||||
thousandsSep = ' ';
|
||||
decimalSep = ',';
|
||||
break;
|
||||
|
||||
case 'chf':
|
||||
thousandsSep = '’';
|
||||
decimalSep = '.';
|
||||
break;
|
||||
|
||||
case 'cop':
|
||||
case 'clp':
|
||||
case 'idr':
|
||||
case 'isk':
|
||||
case 'vnd':
|
||||
thousandsSep = '.';
|
||||
break;
|
||||
|
||||
case 'jpy':
|
||||
thousandsSep = ',';
|
||||
break;
|
||||
|
||||
case 'ars':
|
||||
case 'brl':
|
||||
case 'dkk':
|
||||
case 'hrk':
|
||||
case 'ron':
|
||||
case 'try':
|
||||
thousandsSep = '.';
|
||||
decimalSep = ',';
|
||||
break;
|
||||
|
||||
case 'irr':
|
||||
case 'pkr':
|
||||
thousandsSep = '٬';
|
||||
break;
|
||||
|
||||
case 'egp':
|
||||
case 'sar':
|
||||
thousandsSep = '٬';
|
||||
decimalSep = '٫';
|
||||
break;
|
||||
|
||||
default:
|
||||
thousandsSep = ',';
|
||||
decimalSep = '.';
|
||||
else {
|
||||
postfix = srvModel.currencyInfo.currencySymbol;
|
||||
}
|
||||
thousandsSep = srvModel.currencyInfo.thousandSeparator;
|
||||
decimalSep = srvModel.currencyInfo.decimalSeparator;
|
||||
amt = amount.toFixed(srvModel.currencyInfo.divisibility);
|
||||
|
||||
if (decimalSep !== '') {
|
||||
// Replace decimal separator
|
||||
amt = amount.toFixed(2).replace(/.(\d{2})$/g, decimalSep + '\$1');
|
||||
} else {
|
||||
// No decimal separator
|
||||
amt = amount.toString();
|
||||
}
|
||||
// Add currency sign and thousands separator
|
||||
amt = prefix + amt.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep) + postfix;
|
||||
var splittedAmount = amt.split('.');
|
||||
amt = (splittedAmount[0] + '.').replace(/(\d)(?=(\d{3})+\.)/g, '$1' + thousandsSep);
|
||||
amt = amt.substr(0, amt.length - 1);
|
||||
if(splittedAmount.length == 2)
|
||||
amt = amt + '.' + splittedAmount[1];
|
||||
if (srvModel.currencyInfo.divisibility !== 0) {
|
||||
amt[amt.length - srvModel.currencyInfo.divisibility - 1] = decimalSep;
|
||||
}
|
||||
amt = prefix + amt + postfix;
|
||||
|
||||
return amt;
|
||||
}
|
||||
|
||||
Cart.prototype.toCents = function(num) {
|
||||
return num * 100;
|
||||
return num * Math.pow(10, srvModel.currencyInfo.divisibility);
|
||||
}
|
||||
|
||||
Cart.prototype.fromCents = function(num) {
|
||||
return num / 100;
|
||||
return num / Math.pow(10, srvModel.currencyInfo.divisibility);
|
||||
}
|
||||
|
||||
Cart.prototype.getStorageKey = function () { return ('cart' + srvModel.appId + srvModel.currencyCode); }
|
||||
|
||||
Cart.prototype.saveLocalStorage = function() {
|
||||
localStorage.setItem('cart', JSON.stringify(this.content));
|
||||
localStorage.setItem(this.getStorageKey(), JSON.stringify(this.content));
|
||||
}
|
||||
|
||||
Cart.prototype.loadLocalStorage = function() {
|
||||
this.content = $.parseJSON(localStorage.getItem('cart')) || [];
|
||||
this.content = $.parseJSON(localStorage.getItem(this.getStorageKey())) || [];
|
||||
|
||||
// Get number of cart items
|
||||
for (var key in this.content) {
|
||||
@ -464,9 +297,9 @@ Cart.prototype.loadLocalStorage = function() {
|
||||
}
|
||||
|
||||
Cart.prototype.destroy = function() {
|
||||
localStorage.removeItem('cart');
|
||||
localStorage.removeItem(this.getStorageKey());
|
||||
this.content = [];
|
||||
this.items = 0;
|
||||
this.totalAmount = 0;
|
||||
this.tip = 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user