mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
Extracting public portion of app controller
This commit is contained in:
committed by
nicolas.dorier
parent
0abd62dfe8
commit
7341be76bb
@@ -121,6 +121,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Content Update="Views\Apps\_ViewImports.cshtml">
|
||||||
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
|
<Pack>$(IncludeRazorContentInPack)</Pack>
|
||||||
|
</Content>
|
||||||
<Content Update="Views\Server\SSHService.cshtml">
|
<Content Update="Views\Server\SSHService.cshtml">
|
||||||
<Pack>$(IncludeRazorContentInPack)</Pack>
|
<Pack>$(IncludeRazorContentInPack)</Pack>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@@ -1,25 +1,11 @@
|
|||||||
using System;
|
using System.Text;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using System.Text.Encodings.Web;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Models;
|
|
||||||
using BTCPayServer.Models.AppViewModels;
|
using BTCPayServer.Models.AppViewModels;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using NBitcoin.DataEncoders;
|
|
||||||
using NBitcoin;
|
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using Newtonsoft.Json;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using YamlDotNet.RepresentationModel;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.IO;
|
|
||||||
using BTCPayServer.Services.Rates;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Encodings.Web;
|
|
||||||
using Microsoft.AspNetCore.Cors;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers
|
namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
@@ -87,7 +73,7 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var items = Parse(settings.Template, settings.Currency);
|
var items = _AppsHelper.Parse(settings.Template, settings.Currency);
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
builder.AppendLine($"<form method=\"POST\" action=\"{encoder.Encode(appUrl)}\">");
|
builder.AppendLine($"<form method=\"POST\" action=\"{encoder.Encode(appUrl)}\">");
|
||||||
builder.AppendLine($" <input type=\"hidden\" name=\"email\" value=\"customer@example.com\" />");
|
builder.AppendLine($" <input type=\"hidden\" name=\"email\" value=\"customer@example.com\" />");
|
||||||
@@ -109,11 +95,11 @@ namespace BTCPayServer.Controllers
|
|||||||
[Route("{appId}/settings/pos")]
|
[Route("{appId}/settings/pos")]
|
||||||
public async Task<IActionResult> UpdatePointOfSale(string appId, UpdatePointOfSaleViewModel vm)
|
public async Task<IActionResult> UpdatePointOfSale(string appId, UpdatePointOfSaleViewModel vm)
|
||||||
{
|
{
|
||||||
if (_Currencies.GetCurrencyData(vm.Currency, false) == null)
|
if (_AppsHelper.GetCurrencyData(vm.Currency, false) == null)
|
||||||
ModelState.AddModelError(nameof(vm.Currency), "Invalid currency");
|
ModelState.AddModelError(nameof(vm.Currency), "Invalid currency");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Parse(vm.Template, vm.Currency);
|
_AppsHelper.Parse(vm.Template, vm.Currency);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -138,131 +124,6 @@ namespace BTCPayServer.Controllers
|
|||||||
return RedirectToAction(nameof(ListApps));
|
return RedirectToAction(nameof(ListApps));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
[Route("{appId}/pos")]
|
|
||||||
public async Task<IActionResult> ViewPointOfSale(string appId)
|
|
||||||
{
|
|
||||||
var app = await GetApp(appId, AppType.PointOfSale);
|
|
||||||
if (app == null)
|
|
||||||
return NotFound();
|
|
||||||
var settings = app.GetSettings<PointOfSaleSettings>();
|
|
||||||
var currency = _Currencies.GetCurrencyData(settings.Currency, false);
|
|
||||||
double step = currency == null ? 1 : Math.Pow(10, -(currency.Divisibility));
|
|
||||||
|
|
||||||
return View(new ViewPointOfSaleViewModel()
|
|
||||||
{
|
|
||||||
Title = settings.Title,
|
|
||||||
Step = step.ToString(CultureInfo.InvariantCulture),
|
|
||||||
ShowCustomAmount = settings.ShowCustomAmount,
|
|
||||||
Items = Parse(settings.Template, settings.Currency)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<AppData> GetApp(string appId, AppType appType)
|
|
||||||
{
|
|
||||||
using (var ctx = _ContextFactory.CreateContext())
|
|
||||||
{
|
|
||||||
return await ctx.Apps
|
|
||||||
.Where(us => us.Id == appId &&
|
|
||||||
us.AppType == appType.ToString())
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ViewPointOfSaleViewModel.Item[] Parse(string template, string currency)
|
|
||||||
{
|
|
||||||
var input = new StringReader(template);
|
|
||||||
YamlStream stream = new YamlStream();
|
|
||||||
stream.Load(input);
|
|
||||||
var root = (YamlMappingNode)stream.Documents[0].RootNode;
|
|
||||||
return root
|
|
||||||
.Children
|
|
||||||
.Select(kv => new { Key = (kv.Key as YamlScalarNode)?.Value, Value = kv.Value as YamlMappingNode })
|
|
||||||
.Where(kv => kv.Value != null)
|
|
||||||
.Select(c => new ViewPointOfSaleViewModel.Item()
|
|
||||||
{
|
|
||||||
Id = c.Key,
|
|
||||||
Title = c.Value.Children
|
|
||||||
.Select(kv => new { Key = (kv.Key as YamlScalarNode)?.Value, Value = kv.Value as YamlScalarNode })
|
|
||||||
.Where(kv => kv.Value != null)
|
|
||||||
.Where(cc => cc.Key == "title")
|
|
||||||
.FirstOrDefault()?.Value?.Value ?? c.Key,
|
|
||||||
Price = c.Value.Children
|
|
||||||
.Select(kv => new { Key = (kv.Key as YamlScalarNode)?.Value, Value = kv.Value as YamlScalarNode })
|
|
||||||
.Where(kv => kv.Value != null)
|
|
||||||
.Where(cc => cc.Key == "price")
|
|
||||||
.Select(cc => new ViewPointOfSaleViewModel.Item.ItemPrice()
|
|
||||||
{
|
|
||||||
Value = decimal.Parse(cc.Value.Value, CultureInfo.InvariantCulture),
|
|
||||||
Formatted = FormatCurrency(cc.Value.Value, currency)
|
|
||||||
})
|
|
||||||
.Single()
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
string FormatCurrency(string price, string currency)
|
|
||||||
{
|
|
||||||
return decimal.Parse(price, CultureInfo.InvariantCulture).ToString("C", _Currencies.GetCurrencyProvider(currency));
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
[Route("{appId}/pos")]
|
|
||||||
[IgnoreAntiforgeryToken]
|
|
||||||
[EnableCors(CorsPolicies.All)]
|
|
||||||
public async Task<IActionResult> ViewPointOfSale(string appId,
|
|
||||||
decimal amount,
|
|
||||||
string email,
|
|
||||||
string orderId,
|
|
||||||
string notificationUrl,
|
|
||||||
string redirectUrl,
|
|
||||||
string choiceKey)
|
|
||||||
{
|
|
||||||
var app = await GetApp(appId, AppType.PointOfSale);
|
|
||||||
if (string.IsNullOrEmpty(choiceKey) && amount <= 0)
|
|
||||||
{
|
|
||||||
return RedirectToAction(nameof(ViewPointOfSale), new { appId = appId });
|
|
||||||
}
|
|
||||||
if (app == null)
|
|
||||||
return NotFound();
|
|
||||||
var settings = app.GetSettings<PointOfSaleSettings>();
|
|
||||||
if (string.IsNullOrEmpty(choiceKey) && !settings.ShowCustomAmount)
|
|
||||||
{
|
|
||||||
return RedirectToAction(nameof(ViewPointOfSale), new { appId = appId });
|
|
||||||
}
|
|
||||||
string title = null;
|
|
||||||
var price = 0.0m;
|
|
||||||
if (!string.IsNullOrEmpty(choiceKey))
|
|
||||||
{
|
|
||||||
var choices = Parse(settings.Template, settings.Currency);
|
|
||||||
var choice = choices.FirstOrDefault(c => c.Id == choiceKey);
|
|
||||||
if (choice == null)
|
|
||||||
return NotFound();
|
|
||||||
title = choice.Title;
|
|
||||||
price = choice.Price.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!settings.ShowCustomAmount)
|
|
||||||
return NotFound();
|
|
||||||
price = amount;
|
|
||||||
title = settings.Title;
|
|
||||||
}
|
|
||||||
var store = await GetStore(app);
|
|
||||||
var invoice = await _InvoiceController.CreateInvoiceCore(new NBitpayClient.Invoice()
|
|
||||||
{
|
|
||||||
ItemDesc = title,
|
|
||||||
Currency = settings.Currency,
|
|
||||||
Price = price,
|
|
||||||
BuyerEmail = email,
|
|
||||||
OrderId = orderId,
|
|
||||||
NotificationURL = notificationUrl,
|
|
||||||
RedirectURL = redirectUrl,
|
|
||||||
FullNotifications = true
|
|
||||||
}, store, HttpContext.Request.GetAbsoluteRoot());
|
|
||||||
return Redirect(invoice.Data.Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UpdateAppSettings(AppData app)
|
private async Task UpdateAppSettings(AppData app)
|
||||||
{
|
{
|
||||||
using (var ctx = _ContextFactory.CreateContext())
|
using (var ctx = _ContextFactory.CreateContext())
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
using BTCPayServer.Models.AppViewModels;
|
using BTCPayServer.Models.AppViewModels;
|
||||||
|
using BTCPayServer.Security;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Rates;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -19,28 +20,26 @@ namespace BTCPayServer.Controllers
|
|||||||
[Route("apps")]
|
[Route("apps")]
|
||||||
public partial class AppsController : Controller
|
public partial class AppsController : Controller
|
||||||
{
|
{
|
||||||
ApplicationDbContextFactory _ContextFactory;
|
public AppsController(
|
||||||
UserManager<ApplicationUser> _UserManager;
|
UserManager<ApplicationUser> userManager,
|
||||||
CurrencyNameTable _Currencies;
|
ApplicationDbContextFactory contextFactory,
|
||||||
InvoiceController _InvoiceController;
|
BTCPayNetworkProvider networkProvider,
|
||||||
BTCPayNetworkProvider _NetworkProvider;
|
AppsHelper appsHelper)
|
||||||
|
{
|
||||||
|
_UserManager = userManager;
|
||||||
|
_ContextFactory = contextFactory;
|
||||||
|
_NetworkProvider = networkProvider;
|
||||||
|
_AppsHelper = appsHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserManager<ApplicationUser> _UserManager;
|
||||||
|
private ApplicationDbContextFactory _ContextFactory;
|
||||||
|
private BTCPayNetworkProvider _NetworkProvider;
|
||||||
|
private AppsHelper _AppsHelper;
|
||||||
|
|
||||||
[TempData]
|
[TempData]
|
||||||
public string StatusMessage { get; set; }
|
public string StatusMessage { get; set; }
|
||||||
|
|
||||||
public AppsController(
|
|
||||||
UserManager<ApplicationUser> userManager,
|
|
||||||
ApplicationDbContextFactory contextFactory,
|
|
||||||
CurrencyNameTable currencies,
|
|
||||||
InvoiceController invoiceController,
|
|
||||||
BTCPayNetworkProvider networkProvider)
|
|
||||||
{
|
|
||||||
_InvoiceController = invoiceController;
|
|
||||||
_UserManager = userManager;
|
|
||||||
_ContextFactory = contextFactory;
|
|
||||||
_Currencies = currencies;
|
|
||||||
_NetworkProvider = networkProvider;
|
|
||||||
}
|
|
||||||
public async Task<IActionResult> ListApps()
|
public async Task<IActionResult> ListApps()
|
||||||
{
|
{
|
||||||
var apps = await GetAllApps();
|
var apps = await GetAllApps();
|
||||||
@@ -201,13 +200,5 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
return _UserManager.GetUserId(User);
|
return _UserManager.GetUserId(User);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<StoreData> GetStore(AppData app)
|
|
||||||
{
|
|
||||||
using (var ctx = _ContextFactory.CreateContext())
|
|
||||||
{
|
|
||||||
return await ctx.Stores.FirstOrDefaultAsync(s => s.Id == app.StoreDataId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
182
BTCPayServer/Controllers/AppsPublicController.cs
Normal file
182
BTCPayServer/Controllers/AppsPublicController.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Data;
|
||||||
|
using BTCPayServer.Models.AppViewModels;
|
||||||
|
using BTCPayServer.Services.Apps;
|
||||||
|
using BTCPayServer.Services.Rates;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using YamlDotNet.RepresentationModel;
|
||||||
|
using static BTCPayServer.Controllers.AppsController;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Controllers
|
||||||
|
{
|
||||||
|
public class AppsPublicController : Controller
|
||||||
|
{
|
||||||
|
public AppsPublicController(AppsHelper appsHelper, InvoiceController invoiceController)
|
||||||
|
{
|
||||||
|
_AppsHelper = appsHelper;
|
||||||
|
_InvoiceController = invoiceController;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppsHelper _AppsHelper;
|
||||||
|
private InvoiceController _InvoiceController;
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
[Route("/apps/{appId}/pos")]
|
||||||
|
public async Task<IActionResult> ViewPointOfSale(string appId)
|
||||||
|
{
|
||||||
|
var app = await _AppsHelper.GetApp(appId, AppType.PointOfSale);
|
||||||
|
if (app == null)
|
||||||
|
return NotFound();
|
||||||
|
var settings = app.GetSettings<PointOfSaleSettings>();
|
||||||
|
var currency = _AppsHelper.GetCurrencyData(settings.Currency, false);
|
||||||
|
double step = currency == null ? 1 : Math.Pow(10, -(currency.Divisibility));
|
||||||
|
|
||||||
|
return View(new ViewPointOfSaleViewModel()
|
||||||
|
{
|
||||||
|
Title = settings.Title,
|
||||||
|
Step = step.ToString(CultureInfo.InvariantCulture),
|
||||||
|
ShowCustomAmount = settings.ShowCustomAmount,
|
||||||
|
Items = _AppsHelper.Parse(settings.Template, settings.Currency)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("/apps/{appId}/pos")]
|
||||||
|
[IgnoreAntiforgeryToken]
|
||||||
|
[EnableCors(CorsPolicies.All)]
|
||||||
|
public async Task<IActionResult> ViewPointOfSale(string appId,
|
||||||
|
decimal amount,
|
||||||
|
string email,
|
||||||
|
string orderId,
|
||||||
|
string notificationUrl,
|
||||||
|
string redirectUrl,
|
||||||
|
string choiceKey)
|
||||||
|
{
|
||||||
|
var app = await _AppsHelper.GetApp(appId, AppType.PointOfSale);
|
||||||
|
if (string.IsNullOrEmpty(choiceKey) && amount <= 0)
|
||||||
|
{
|
||||||
|
return RedirectToAction(nameof(ViewPointOfSale), new { appId = appId });
|
||||||
|
}
|
||||||
|
if (app == null)
|
||||||
|
return NotFound();
|
||||||
|
var settings = app.GetSettings<PointOfSaleSettings>();
|
||||||
|
if (string.IsNullOrEmpty(choiceKey) && !settings.ShowCustomAmount)
|
||||||
|
{
|
||||||
|
return RedirectToAction(nameof(ViewPointOfSale), new { appId = appId });
|
||||||
|
}
|
||||||
|
string title = null;
|
||||||
|
var price = 0.0m;
|
||||||
|
if (!string.IsNullOrEmpty(choiceKey))
|
||||||
|
{
|
||||||
|
var choices = _AppsHelper.Parse(settings.Template, settings.Currency);
|
||||||
|
var choice = choices.FirstOrDefault(c => c.Id == choiceKey);
|
||||||
|
if (choice == null)
|
||||||
|
return NotFound();
|
||||||
|
title = choice.Title;
|
||||||
|
price = choice.Price.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!settings.ShowCustomAmount)
|
||||||
|
return NotFound();
|
||||||
|
price = amount;
|
||||||
|
title = settings.Title;
|
||||||
|
}
|
||||||
|
var store = await _AppsHelper.GetStore(app);
|
||||||
|
var invoice = await _InvoiceController.CreateInvoiceCore(new NBitpayClient.Invoice()
|
||||||
|
{
|
||||||
|
ItemDesc = title,
|
||||||
|
Currency = settings.Currency,
|
||||||
|
Price = price,
|
||||||
|
BuyerEmail = email,
|
||||||
|
OrderId = orderId,
|
||||||
|
NotificationURL = notificationUrl,
|
||||||
|
RedirectURL = redirectUrl,
|
||||||
|
FullNotifications = true
|
||||||
|
}, store, HttpContext.Request.GetAbsoluteRoot());
|
||||||
|
return Redirect(invoice.Data.Url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class AppsHelper
|
||||||
|
{
|
||||||
|
ApplicationDbContextFactory _ContextFactory;
|
||||||
|
CurrencyNameTable _Currencies;
|
||||||
|
|
||||||
|
public AppsHelper(ApplicationDbContextFactory contextFactory, CurrencyNameTable currencies)
|
||||||
|
{
|
||||||
|
_ContextFactory = contextFactory;
|
||||||
|
_Currencies = currencies;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<AppData> GetApp(string appId, AppType appType)
|
||||||
|
{
|
||||||
|
using (var ctx = _ContextFactory.CreateContext())
|
||||||
|
{
|
||||||
|
return await ctx.Apps
|
||||||
|
.Where(us => us.Id == appId &&
|
||||||
|
us.AppType == appType.ToString())
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<StoreData> GetStore(AppData app)
|
||||||
|
{
|
||||||
|
using (var ctx = _ContextFactory.CreateContext())
|
||||||
|
{
|
||||||
|
return await ctx.Stores.FirstOrDefaultAsync(s => s.Id == app.StoreDataId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewPointOfSaleViewModel.Item[] Parse(string template, string currency)
|
||||||
|
{
|
||||||
|
var input = new StringReader(template);
|
||||||
|
YamlStream stream = new YamlStream();
|
||||||
|
stream.Load(input);
|
||||||
|
var root = (YamlMappingNode)stream.Documents[0].RootNode;
|
||||||
|
return root
|
||||||
|
.Children
|
||||||
|
.Select(kv => new { Key = (kv.Key as YamlScalarNode)?.Value, Value = kv.Value as YamlMappingNode })
|
||||||
|
.Where(kv => kv.Value != null)
|
||||||
|
.Select(c => new ViewPointOfSaleViewModel.Item()
|
||||||
|
{
|
||||||
|
Id = c.Key,
|
||||||
|
Title = c.Value.Children
|
||||||
|
.Select(kv => new { Key = (kv.Key as YamlScalarNode)?.Value, Value = kv.Value as YamlScalarNode })
|
||||||
|
.Where(kv => kv.Value != null)
|
||||||
|
.Where(cc => cc.Key == "title")
|
||||||
|
.FirstOrDefault()?.Value?.Value ?? c.Key,
|
||||||
|
Price = c.Value.Children
|
||||||
|
.Select(kv => new { Key = (kv.Key as YamlScalarNode)?.Value, Value = kv.Value as YamlScalarNode })
|
||||||
|
.Where(kv => kv.Value != null)
|
||||||
|
.Where(cc => cc.Key == "price")
|
||||||
|
.Select(cc => new ViewPointOfSaleViewModel.Item.ItemPrice()
|
||||||
|
{
|
||||||
|
Value = decimal.Parse(cc.Value.Value, CultureInfo.InvariantCulture),
|
||||||
|
Formatted = FormatCurrency(cc.Value.Value, currency)
|
||||||
|
})
|
||||||
|
.Single()
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatCurrency(string price, string currency)
|
||||||
|
{
|
||||||
|
return decimal.Parse(price, CultureInfo.InvariantCulture).ToString("C", _Currencies.GetCurrencyProvider(currency));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CurrencyData GetCurrencyData(string currency, bool useFallback)
|
||||||
|
{
|
||||||
|
return _Currencies.GetCurrencyData(currency, useFallback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -95,6 +95,8 @@ namespace BTCPayServer.Hosting
|
|||||||
return opts.NetworkProvider;
|
return opts.NetworkProvider;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.TryAddSingleton<AppsHelper>();
|
||||||
|
|
||||||
services.TryAddSingleton<LightningConfigurationProvider>();
|
services.TryAddSingleton<LightningConfigurationProvider>();
|
||||||
services.TryAddSingleton<LanguageService>();
|
services.TryAddSingleton<LanguageService>();
|
||||||
services.TryAddSingleton<NBXplorerDashboard>();
|
services.TryAddSingleton<NBXplorerDashboard>();
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
{
|
{
|
||||||
<a asp-action="@app.UpdateAction" asp-controller="Apps" asp-route-appId="@app.Id">Settings</a><span> - </span>
|
<a asp-action="@app.UpdateAction" asp-controller="Apps" asp-route-appId="@app.Id">Settings</a><span> - </span>
|
||||||
}
|
}
|
||||||
<a asp-action="@app.ViewAction" asp-controller="Apps" asp-route-appId="@app.Id">View</a><span> - </span>
|
<a asp-action="@app.ViewAction" asp-controller="AppsPublic" asp-route-appId="@app.Id">View</a><span> - </span>
|
||||||
<a asp-action="DeleteApp" asp-route-appId="@app.Id">Remove</a>
|
<a asp-action="DeleteApp" asp-route-appId="@app.Id">Remove</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
||||||
|
|
||||||
@model ViewPointOfSaleViewModel
|
@model BTCPayServer.Models.AppViewModels.ViewPointOfSaleViewModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = Model.Title;
|
ViewData["Title"] = Model.Title;
|
||||||
Layout = null;
|
Layout = null;
|
||||||
Reference in New Issue
Block a user