diff --git a/BTCPayServer.Abstractions/Services/UIExtension.cs b/BTCPayServer.Abstractions/Services/UIExtension.cs index ba06187dd..601b83e50 100644 --- a/BTCPayServer.Abstractions/Services/UIExtension.cs +++ b/BTCPayServer.Abstractions/Services/UIExtension.cs @@ -1,9 +1,11 @@ +using System; using BTCPayServer.Abstractions.Contracts; namespace BTCPayServer.Abstractions.Services { public class UIExtension : IUIExtension { + [Obsolete("Use extension method BTCPayServer.Extensions.AddUIExtension(this IServiceCollection services, string location, string partialViewName) instead")] public UIExtension(string partial, string location) { Partial = partial; diff --git a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs index 382f5071a..5ec8f80e9 100644 --- a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs +++ b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs @@ -320,10 +320,10 @@ namespace BTCPayServer.Tests var controller = tester.PayTester.GetController(null); var checkout = - (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id) + (Models.InvoicingModels.CheckoutModel)((JsonResult)controller.GetStatus(invoice.Id) .GetAwaiter().GetResult()).Value; - Assert.Single(checkout.AvailableCryptos); - Assert.Equal("LTC", checkout.CryptoCode); + Assert.Single(checkout.AvailablePaymentMethods); + Assert.Equal("LTC", checkout.PaymentMethodCurrency); ////////////////////// @@ -337,7 +337,7 @@ namespace BTCPayServer.Tests { invoice = user.BitPay.GetInvoice(invoice.Id); Assert.Equal("paid", invoice.Status); - checkout = (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id) + checkout = (Models.InvoicingModels.CheckoutModel)((JsonResult)controller.GetStatus(invoice.Id) .GetAwaiter().GetResult()).Value; Assert.Equal("Processing", checkout.Status); }); @@ -475,10 +475,10 @@ namespace BTCPayServer.Tests var controller = tester.PayTester.GetController(null); var checkout = - (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id, null) + (Models.InvoicingModels.CheckoutModel)((JsonResult)controller.GetStatus(invoice.Id, null) .GetAwaiter().GetResult()).Value; - Assert.Single(checkout.AvailableCryptos); - Assert.Equal("BTC", checkout.CryptoCode); + Assert.Single(checkout.AvailablePaymentMethods); + Assert.Equal("BTC", checkout.PaymentMethodCurrency); Assert.Single(invoice.PaymentCodes); Assert.Single(invoice.SupportedTransactionCurrencies); @@ -536,10 +536,10 @@ namespace BTCPayServer.Tests }); controller = tester.PayTester.GetController(null); - checkout = (Models.InvoicingModels.PaymentModel)((JsonResult)controller.GetStatus(invoice.Id, "LTC") + checkout = (Models.InvoicingModels.CheckoutModel)((JsonResult)controller.GetStatus(invoice.Id, "LTC") .GetAwaiter().GetResult()).Value; - Assert.Equal(2, checkout.AvailableCryptos.Count); - Assert.Equal("LTC", checkout.CryptoCode); + Assert.Equal(2, checkout.AvailablePaymentMethods.Count); + Assert.Equal("LTC", checkout.PaymentMethodCurrency); Assert.Equal(2, invoice.PaymentCodes.Count()); Assert.Equal(2, invoice.SupportedTransactionCurrencies.Count()); diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index 7199e5859..b6e3e7744 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -2733,7 +2733,7 @@ namespace BTCPayServer.Tests Assert.EndsWith($"/i/{newInvoice.Id}", newInvoice.CheckoutLink); var controller = tester.PayTester.GetController(user.UserId, user.StoreId); - var model = (PaymentModel)((ViewResult)await controller.Checkout(newInvoice.Id)).Model; + var model = (CheckoutModel)((ViewResult)await controller.Checkout(newInvoice.Id)).Model; Assert.Equal("it-IT", model.DefaultLang); Assert.Equal("http://toto.com/lol", model.MerchantRefLink); diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index cdf579e9f..aae22c9b0 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -3264,6 +3264,7 @@ namespace BTCPayServer.Tests public async Task CanUseLNAddress() { using var s = CreateSeleniumTester(); + s.Server.DeleteStore = false; s.Server.ActivateLightning(); await s.StartAsync(); await s.Server.EnsureChannelsSetup(); @@ -3416,7 +3417,13 @@ namespace BTCPayServer.Tests var succ = JsonConvert.DeserializeObject(str); Assert.NotNull(succ.Pr); Assert.Equal(new LightMoney(2001), BOLT11PaymentRequest.Parse(succ.Pr, Network.RegTest).MinimumAmount); + await s.Server.CustomerLightningD.Pay(succ.Pr); } + + // Can we find our comment and address in the payment list? + s.GoToInvoices(); + var source = s.Driver.PageSource; + Assert.Contains(lnUsername, source); } [Fact] diff --git a/BTCPayServer.Tests/TestAccount.cs b/BTCPayServer.Tests/TestAccount.cs index 3a3b7e8a6..b143c441c 100644 --- a/BTCPayServer.Tests/TestAccount.cs +++ b/BTCPayServer.Tests/TestAccount.cs @@ -609,9 +609,7 @@ retry: var methods = await client.GetInvoicePaymentMethods(StoreId, invoiceId); var method = methods.First(m => m.PaymentMethodId == $"{cryptoCode}-LN"); var bolt11 = method.Destination; - TestLogs.LogInformation("PAYING"); await parent.CustomerLightningD.Pay(bolt11); - TestLogs.LogInformation("PAID"); await WaitInvoicePaid(invoiceId); } diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 69f713662..0c8731f9d 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -1587,14 +1587,14 @@ namespace BTCPayServer.Tests ItemDesc = "Some description", FullNotifications = true }, Facade.Merchant); - var checkout = (await user.GetController().Checkout(invoice.Id)).AssertViewModel(); + var checkout = (await user.GetController().Checkout(invoice.Id)).AssertViewModel(); Assert.Equal(lnMethod, checkout.PaymentMethodId); // If we change store's default, it should change the checkout's default vm.DefaultPaymentMethod = btcMethod; Assert.IsType(user.GetController().CheckoutAppearance(vm) .Result); - checkout = (await user.GetController().Checkout(invoice.Id)).AssertViewModel(); + checkout = (await user.GetController().Checkout(invoice.Id)).AssertViewModel(); Assert.Equal(btcMethod, checkout.PaymentMethodId); } @@ -1625,7 +1625,7 @@ namespace BTCPayServer.Tests // validate that invoice data model doesn't have lightning string initially var res = await user.GetController().Checkout(invoice.Id); - var paymentMethodFirst = Assert.IsType( + var paymentMethodFirst = Assert.IsType( Assert.IsType(res).Model ); Assert.DoesNotContain("&lightning=", paymentMethodFirst.InvoiceBitcoinUrlQR); @@ -1641,7 +1641,7 @@ namespace BTCPayServer.Tests // validate that QR code now has both onchain and offchain payment urls res = await user.GetController().Checkout(invoice.Id); - var paymentMethodUnified = Assert.IsType( + var paymentMethodUnified = Assert.IsType( Assert.IsType(res).Model ); Assert.StartsWith("bitcoin:bcrt", paymentMethodUnified.InvoiceBitcoinUrl); @@ -1655,8 +1655,8 @@ namespace BTCPayServer.Tests // Standard for all uppercase characters in QR codes is still not implemented in all wallets // But we're proceeding with BECH32 being uppercase - Assert.Equal($"bitcoin:{paymentMethodUnified.BtcAddress}", paymentMethodUnified.InvoiceBitcoinUrl.Split('?')[0]); - Assert.Equal($"bitcoin:{paymentMethodUnified.BtcAddress.ToUpperInvariant()}", paymentMethodUnified.InvoiceBitcoinUrlQR.Split('?')[0]); + Assert.Equal($"bitcoin:{paymentMethodUnified.Address}", paymentMethodUnified.InvoiceBitcoinUrl.Split('?')[0]); + Assert.Equal($"bitcoin:{paymentMethodUnified.Address.ToUpperInvariant()}", paymentMethodUnified.InvoiceBitcoinUrlQR.Split('?')[0]); // Fallback lightning invoice should be uppercase inside the QR code, lowercase in payment URI var lightningFallback = paymentMethodUnified.InvoiceBitcoinUrl.Split(new[] { "&lightning=" }, StringSplitOptions.None)[1]; diff --git a/BTCPayServer/Components/InvoiceStatus/Default.cshtml b/BTCPayServer/Components/InvoiceStatus/Default.cshtml index 27a6450a8..a66199c11 100644 --- a/BTCPayServer/Components/InvoiceStatus/Default.cshtml +++ b/BTCPayServer/Components/InvoiceStatus/Default.cshtml @@ -1,6 +1,6 @@ @using BTCPayServer.Payments @model BTCPayServer.Components.InvoiceStatus.InvoiceStatusViewModel -@inject Dictionary Extensions +@inject Dictionary Extensions @{ var state = Model.State.ToString(); diff --git a/BTCPayServer/Components/StoreRecentInvoices/StoreRecentInvoices.cs b/BTCPayServer/Components/StoreRecentInvoices/StoreRecentInvoices.cs index d8876ed4c..c90e4fa61 100644 --- a/BTCPayServer/Components/StoreRecentInvoices/StoreRecentInvoices.cs +++ b/BTCPayServer/Components/StoreRecentInvoices/StoreRecentInvoices.cs @@ -68,7 +68,7 @@ public class StoreRecentInvoices : ViewComponent Details = new InvoiceDetailsModel { Archived = invoice.Archived, - Payments = invoice.GetPayments(false) + Payments = invoice.GetPayments(false) } }).ToList(); diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index ae594d3cf..e795f3c1b 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -128,6 +128,7 @@ namespace BTCPayServer.Controllers StoreLink = Url.Action(nameof(UIStoresController.GeneralSettings), "UIStores", new { storeId = store.Id }), PaymentRequestLink = Url.Action(nameof(UIPaymentRequestController.ViewPaymentRequest), "UIPaymentRequest", new { payReqId = invoice.Metadata.PaymentRequestId }), Id = invoice.Id, + Entity = invoice, State = invoiceState, TransactionSpeed = invoice.SpeedPolicy == SpeedPolicy.HighSpeed ? "high" : invoice.SpeedPolicy == SpeedPolicy.MediumSpeed ? "medium" : @@ -554,6 +555,7 @@ namespace BTCPayServer.Controllers { Archived = invoice.Archived, Payments = invoice.GetPayments(false), + Entity = invoice, CryptoPayments = invoice.GetPaymentPrompts().Select( data => { @@ -692,7 +694,7 @@ namespace BTCPayServer.Controllers if (invoiceId is null) return NotFound(); - var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); + var model = await GetCheckoutModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); if (model == null) { // see if the invoice actually exists and is in a state for which we do not display the checkout @@ -711,22 +713,7 @@ namespace BTCPayServer.Controllers return View(model); } - [HttpGet("invoice-noscript")] - public async Task CheckoutNoScript(string? invoiceId, string? id = null, string? paymentMethodId = null, [FromQuery] string? lang = null) - { - //Keep compatibility with Bitpay - invoiceId = invoiceId ?? id; - // - if (invoiceId is null) - return NotFound(); - var model = await GetInvoiceModel(invoiceId, paymentMethodId is null ? null : PaymentMethodId.Parse(paymentMethodId), lang); - if (model == null) - return NotFound(); - - return View(model); - } - - private async Task GetInvoiceModel(string invoiceId, PaymentMethodId? paymentMethodId, string? lang) + private async Task GetCheckoutModel(string invoiceId, PaymentMethodId? paymentMethodId, string? lang) { var invoice = await _InvoiceRepository.GetInvoice(invoiceId); if (invoice == null) @@ -739,7 +726,7 @@ namespace BTCPayServer.Controllers bool isDefaultPaymentId = false; var storeBlob = store.GetStoreBlob(); - var displayedPaymentMethods = invoice.GetPaymentPrompts().Select(p => p.PaymentMethodId).ToList(); + var displayedPaymentMethods = invoice.GetPaymentPrompts().Select(p => p.PaymentMethodId).ToHashSet(); var btcId = PaymentTypes.CHAIN.GetPaymentMethodId("BTC"); @@ -835,7 +822,7 @@ namespace BTCPayServer.Controllers if (prompt is null) return null; if (activated) - return await GetInvoiceModel(invoiceId, paymentMethodId, lang); + return await GetCheckoutModel(invoiceId, paymentMethodId, lang); var accounting = prompt.Calculate(); @@ -876,11 +863,11 @@ namespace BTCPayServer.Controllers } string ShowMoney(decimal value) => MoneyExtensions.ShowMoney(value, prompt.RateDivisibility ?? prompt.Divisibility); - var model = new PaymentModel + var model = new CheckoutModel { Activated = prompt.Activated, PaymentMethodName = _prettyName.PrettyName(paymentMethodId), - CryptoCode = prompt.Currency, + PaymentMethodCurrency = prompt.Currency, RootPath = Request.PathBase.Value.WithTrailingSlash(), OrderId = orderId, InvoiceId = invoiceId, @@ -892,9 +879,9 @@ namespace BTCPayServer.Controllers CelebratePayment = storeBlob.CelebratePayment, OnChainWithLnInvoiceFallback = storeBlob.OnChainWithLnInvoiceFallback, CryptoImage = Request.GetRelativePathOrAbsolute(GetPaymentMethodImage(paymentMethodId)), - BtcAddress = prompt.Destination, - BtcDue = ShowMoney(accounting.Due), - BtcPaid = ShowMoney(accounting.Paid), + Address = prompt.Destination, + Due = ShowMoney(accounting.Due), + Paid = ShowMoney(accounting.Paid), InvoiceCurrency = invoice.Currency, // The Tweak is part of the PaymentMethodFee, but let's not show it in the UI as it's negligible. OrderAmount = ShowMoney(accounting.TotalDue - (prompt.PaymentMethodFee - prompt.TweakFee)), @@ -922,45 +909,31 @@ namespace BTCPayServer.Controllers Status = invoice.Status.ToString(), // The Tweak is part of the PaymentMethodFee, but let's not show it in the UI as it's negligible. NetworkFee = prompt.PaymentMethodFee - prompt.TweakFee, - IsMultiCurrency = invoice.GetPayments(false).Select(p => p.PaymentMethodId).Concat(new[] { prompt.PaymentMethodId }).Distinct().Count() > 1, StoreId = store.Id, - AvailableCryptos = invoice.GetPaymentPrompts() + AvailablePaymentMethods = invoice.GetPaymentPrompts() .Select(kv => { var handler = _handlers[kv.PaymentMethodId]; - return new PaymentModel.AvailableCrypto + return new CheckoutModel.AvailablePaymentMethod { Displayed = displayedPaymentMethods.Contains(kv.PaymentMethodId), - PaymentMethodId = kv.PaymentMethodId.ToString(), - CryptoCode = kv.Currency, + PaymentMethodId = kv.PaymentMethodId, PaymentMethodName = _prettyName.PrettyName(kv.PaymentMethodId), - IsLightning = handler is ILightningPaymentHandler, - CryptoImage = Request.GetRelativePathOrAbsolute(GetPaymentMethodImage(kv.PaymentMethodId)), - Link = Url.Action(nameof(Checkout), - new - { - invoiceId, - paymentMethodId = kv.PaymentMethodId.ToString() - }) + Order = kv.PaymentMethodId switch + { + _ when PaymentTypes.CHAIN.GetPaymentMethodId(_NetworkProvider.DefaultNetwork.CryptoCode) == kv.PaymentMethodId => 0, + _ when PaymentTypes.LN.GetPaymentMethodId(_NetworkProvider.DefaultNetwork.CryptoCode) == kv.PaymentMethodId => 1, + _ when handler is ILightningPaymentHandler => 2, + _ => 3 + } }; - }).Where(c => c.CryptoImage != "/") - .OrderByDescending(a => a.CryptoCode == _NetworkProvider.DefaultNetwork.CryptoCode).ThenBy(a => a.PaymentMethodName).ThenBy(a => a.IsLightning ? 1 : 0) + }) + .OrderBy(a => a.Order) .ToList() }; - if (_paymentModelExtensions.TryGetValue(paymentMethodId, out var extension)) - extension.ModifyPaymentModel(new PaymentModelContext(model, store, storeBlob, invoice, Url, prompt, handler)); - model.UISettings = _viewProvider.TryGetViewViewModel(prompt, "CheckoutUI")?.View as CheckoutUIPaymentMethodSettings; - model.PaymentMethodId = paymentMethodId.ToString(); - model.OrderAmountFiat = OrderAmountFromInvoice(model.CryptoCode, invoice, DisplayFormatter.CurrencyFormat.Symbol); - foreach (var paymentPrompt in invoice.GetPaymentPrompts()) - { - var vvm = _viewProvider.TryGetViewViewModel(paymentPrompt, "CheckoutUI"); - if (vvm?.View is CheckoutUIPaymentMethodSettings { ExtensionPartial: { } partial }) - { - model.ExtensionPartials.Add(partial); - } - } + model.PaymentMethodId = paymentMethodId.ToString(); + model.OrderAmountFiat = OrderAmountFromInvoice(model.PaymentMethodCurrency, invoice, DisplayFormatter.CurrencyFormat.Symbol); if (storeBlob.PlaySoundOnPayment) { @@ -973,6 +946,12 @@ namespace BTCPayServer.Controllers var expiration = TimeSpan.FromSeconds(model.ExpirationSeconds); model.TimeLeft = expiration.PrettyPrint(); + + if (_paymentModelExtensions.TryGetValue(paymentMethodId, out var extension) && + _handlers.TryGetValue(paymentMethodId, out var h)) + { + extension.ModifyCheckoutModel(new CheckoutModelContext(model, store, storeBlob, invoice, Url, prompt, h)); + } return model; } @@ -1008,7 +987,7 @@ namespace BTCPayServer.Controllers { if (string.IsNullOrEmpty(paymentMethodId)) paymentMethodId = implicitPaymentMethodId; - var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); + var model = await GetCheckoutModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); if (model == null) return NotFound(); return Json(model); diff --git a/BTCPayServer/Controllers/UIInvoiceController.cs b/BTCPayServer/Controllers/UIInvoiceController.cs index 3793800d8..12e930a8d 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.cs @@ -62,8 +62,7 @@ namespace BTCPayServer.Controllers private readonly LinkGenerator _linkGenerator; private readonly IAuthorizationService _authorizationService; private readonly TransactionLinkProviders _transactionLinkProviders; - private readonly Dictionary _paymentModelExtensions; - private readonly PaymentMethodViewProvider _viewProvider; + private readonly Dictionary _paymentModelExtensions; private readonly PrettyNameProvider _prettyName; private readonly AppService _appService; private readonly IFileService _fileService; @@ -98,8 +97,7 @@ namespace BTCPayServer.Controllers DefaultRulesCollection defaultRules, IAuthorizationService authorizationService, TransactionLinkProviders transactionLinkProviders, - Dictionary paymentModelExtensions, - PaymentMethodViewProvider viewProvider, + Dictionary paymentModelExtensions, PrettyNameProvider prettyName) { _displayFormatter = displayFormatter; @@ -124,7 +122,6 @@ namespace BTCPayServer.Controllers _authorizationService = authorizationService; _transactionLinkProviders = transactionLinkProviders; _paymentModelExtensions = paymentModelExtensions; - _viewProvider = viewProvider; _prettyName = prettyName; _fileService = fileService; _uriResolver = uriResolver; diff --git a/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs b/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs index 07483e2a6..140462d67 100644 --- a/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs +++ b/BTCPayServer/Controllers/UIPublicLightningNodeInfoController.cs @@ -21,13 +21,13 @@ namespace BTCPayServer.Controllers public class UIPublicLightningNodeInfoController : Controller { private readonly BTCPayNetworkProvider _BtcPayNetworkProvider; - private readonly Dictionary _paymentModelExtensions; + private readonly Dictionary _paymentModelExtensions; private readonly UriResolver _uriResolver; private readonly PaymentMethodHandlerDictionary _handlers; private readonly StoreRepository _StoreRepository; public UIPublicLightningNodeInfoController(BTCPayNetworkProvider btcPayNetworkProvider, - Dictionary paymentModelExtensions, + Dictionary paymentModelExtensions, UriResolver uriResolver, PaymentMethodHandlerDictionary handlers, StoreRepository storeRepository) diff --git a/BTCPayServer/Controllers/UIWalletsController.cs b/BTCPayServer/Controllers/UIWalletsController.cs index 65f83028b..ae3f1e6c1 100644 --- a/BTCPayServer/Controllers/UIWalletsController.cs +++ b/BTCPayServer/Controllers/UIWalletsController.cs @@ -70,7 +70,7 @@ namespace BTCPayServer.Controllers private readonly LabelService _labelService; private readonly PaymentMethodHandlerDictionary _handlers; private readonly DefaultRulesCollection _defaultRules; - private readonly Dictionary _paymentModelExtensions; + private readonly Dictionary _paymentModelExtensions; private readonly TransactionLinkProviders _transactionLinkProviders; private readonly PullPaymentHostedService _pullPaymentHostedService; private readonly WalletHistogramService _walletHistogramService; @@ -98,7 +98,7 @@ namespace BTCPayServer.Controllers LabelService labelService, DefaultRulesCollection defaultRules, PaymentMethodHandlerDictionary handlers, - Dictionary paymentModelExtensions, + Dictionary paymentModelExtensions, TransactionLinkProviders transactionLinkProviders) { _currencyTable = currencyTable; diff --git a/BTCPayServer/Extensions.cs b/BTCPayServer/Extensions.cs index 3e8721b80..ab6ace52d 100644 --- a/BTCPayServer/Extensions.cs +++ b/BTCPayServer/Extensions.cs @@ -14,6 +14,8 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using BTCPayServer.Abstractions.Contracts; +using BTCPayServer.Abstractions.Services; using BTCPayServer.BIP78.Sender; using BTCPayServer.Configuration; using BTCPayServer.Data; @@ -289,6 +291,14 @@ namespace BTCPayServer } } + + public static IServiceCollection AddUIExtension(this IServiceCollection services, string location, string partialViewName) + { +#pragma warning disable CS0618 // Type or member is obsolete + services.AddSingleton(new UIExtension(partialViewName, location)); +#pragma warning restore CS0618 // Type or member is obsolete + return services; + } public static IServiceCollection AddReportProvider(this IServiceCollection services) where T : ReportProvider { diff --git a/BTCPayServer/Hosting/BTCPayServerServices.cs b/BTCPayServer/Hosting/BTCPayServerServices.cs index 80c045533..2103eeb50 100644 --- a/BTCPayServer/Hosting/BTCPayServerServices.cs +++ b/BTCPayServer/Hosting/BTCPayServerServices.cs @@ -158,8 +158,7 @@ namespace BTCPayServer.Hosting // AddOnchainWalletParsers(services); - services.AddSingleton(new UIExtension("Bitcoin/ViewBitcoinLikePaymentData", "store-invoices-payments")); - services.AddSingleton(new UIExtension("Lightning/ViewLightningLikePaymentData", "store-invoices-payments")); + services.AddStartupTask(); services.AddStartupTask(); @@ -365,6 +364,11 @@ namespace BTCPayServer.Hosting o.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(DerivationStrategyBase))); }); + services.AddUIExtension("checkout-end", "Bitcoin/BitcoinLikeMethodCheckout"); + services.AddUIExtension("checkout-end", "Lightning/LightningLikeMethodCheckout"); + services.AddUIExtension("store-invoices-payments", "Bitcoin/ViewBitcoinLikePaymentData"); + services.AddUIExtension("store-invoices-payments", "Lightning/ViewLightningLikePaymentData"); + services.AddSingleton(); services.AddSingleton(o => o.GetRequiredService()); services.AddSingleton(); @@ -386,8 +390,8 @@ namespace BTCPayServer.Hosting o.GetRequiredService>().ToDictionary(o => o.PaymentMethodId, o => o)); services.AddSingleton>(o => o.GetRequiredService>().ToDictionary(o => o.PaymentMethodId, o => o)); - services.AddSingleton>(o => - o.GetRequiredService>().ToDictionary(o => o.PaymentMethodId, o => o)); + services.AddSingleton>(o => + o.GetRequiredService>().ToDictionary(o => o.PaymentMethodId, o => o)); services.AddHttpClient(LightningLikePayoutHandler.LightningLikePayoutHandlerOnionNamedClient) .ConfigurePrimaryHttpMessageHandler(); @@ -398,13 +402,11 @@ o.GetRequiredService>().ToDictionary(o => o.P services.AddSingleton(); - services.AddSingleton(new UIExtension("LNURL/LightningAddressNav", - "store-integrations-nav")); + services.AddUIExtension("store-integrations-nav", "LNURL/LightningAddressNav"); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); @@ -627,12 +629,10 @@ o.GetRequiredService>().ToDictionary(o => o.P (BitcoinLikePaymentHandler)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinLikePaymentHandler), new object[] { network, pmi })); services.AddSingleton(provider => (IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentLinkExtension), new object[] { network, pmi })); - services.AddSingleton(provider => - (BitcoinPaymentModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentModelExtension), new object[] { network, pmi })); + services.AddSingleton(provider => + (BitcoinCheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinCheckoutModelExtension), new object[] { network, pmi })); services.AddSingleton(provider => (IPaymentMethodBitpayAPIExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentMethodBitpayAPIExtension), new object[] { pmi })); - services.AddSingleton(provider => -(IPaymentMethodViewExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentMethodViewExtension), new object[] { pmi })); if (!network.ReadonlyWallet && network.WalletSupported) { @@ -650,10 +650,8 @@ o.GetRequiredService>().ToDictionary(o => o.P (LightningLikePaymentHandler)ActivatorUtilities.CreateInstance(provider, typeof(LightningLikePaymentHandler), new object[] { network, pmi })); services.AddSingleton(provider => (IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(LightningPaymentLinkExtension), new object[] { network, pmi })); - services.AddSingleton(provider => - (IPaymentModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(LightningPaymentModelExtension), new object[] { network, pmi })); - services.AddSingleton(provider => -(IPaymentMethodViewExtension)ActivatorUtilities.CreateInstance(provider, typeof(LightningPaymentMethodViewExtension), new object[] { pmi })); + services.AddSingleton(provider => + (ICheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNCheckoutModelExtension), new object[] { network, pmi })); services.AddSingleton(provider => (IPaymentMethodBitpayAPIExtension)ActivatorUtilities.CreateInstance(provider, typeof(LightningPaymentMethodBitpayAPIExtension), new object[] { pmi })); var payoutMethodId = PayoutTypes.LN.GetPayoutMethodId(network.CryptoCode); @@ -667,10 +665,8 @@ o.GetRequiredService>().ToDictionary(o => o.P (LNURLPayPaymentHandler)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentHandler), new object[] { network, pmi })); services.AddSingleton(provider => (IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentLinkExtension), new object[] { network, pmi })); - services.AddSingleton(provider => -(IPaymentModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentModelExtension), new object[] { network, pmi })); - services.AddSingleton(provider => -(IPaymentMethodViewExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPaymentMethodViewExtension), new object[] { pmi })); + services.AddSingleton(provider => +(ICheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLCheckoutModelExtension), new object[] { network, pmi })); services.AddSingleton(provider => (IPaymentMethodBitpayAPIExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentMethodBitpayAPIExtension), new object[] { pmi })); } diff --git a/BTCPayServer/Models/InvoicingModels/PaymentModel.cs b/BTCPayServer/Models/InvoicingModels/CheckoutModel.cs similarity index 73% rename from BTCPayServer/Models/InvoicingModels/PaymentModel.cs rename to BTCPayServer/Models/InvoicingModels/CheckoutModel.cs index 5518ffd67..bd60cb635 100644 --- a/BTCPayServer/Models/InvoicingModels/PaymentModel.cs +++ b/BTCPayServer/Models/InvoicingModels/CheckoutModel.cs @@ -1,21 +1,24 @@ using System.Collections.Generic; using BTCPayServer.Client.Models; +using BTCPayServer.JsonConverters; using BTCPayServer.Payments; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace BTCPayServer.Models.InvoicingModels { - public class PaymentModel + public class CheckoutModel { - public CheckoutUIPaymentMethodSettings UISettings; - public class AvailableCrypto + public string CheckoutBodyComponentName { get; set; } + public class AvailablePaymentMethod { - public string PaymentMethodId { get; set; } - public string CryptoImage { get; set; } - public string Link { get; set; } - public string PaymentMethodName { get; set; } - public bool IsLightning { get; set; } - public string CryptoCode { get; set; } + [JsonConverter(typeof(PaymentMethodIdJsonConverter))] + public PaymentMethodId PaymentMethodId { get; set; } public bool Displayed { get; set; } + public string PaymentMethodName { get; set; } + public int Order { get; set; } + [JsonExtensionData] + public Dictionary AdditionalData { get; set; } = new(); } public StoreBrandingViewModel StoreBranding { get; set; } public string PaymentSoundUrl { get; set; } @@ -26,15 +29,15 @@ namespace BTCPayServer.Models.InvoicingModels public string DefaultLang { get; set; } public bool ShowPayInWalletButton { get; set; } public bool ShowStoreHeader { get; set; } - public List AvailableCryptos { get; set; } = new(); + public List AvailablePaymentMethods { get; set; } = new(); public bool IsModal { get; set; } public bool IsUnsetTopUp { get; set; } public bool OnChainWithLnInvoiceFallback { get; set; } public bool CelebratePayment { get; set; } - public string CryptoCode { get; set; } + public string PaymentMethodCurrency { get; set; } public string InvoiceId { get; set; } - public string BtcAddress { get; set; } - public string BtcDue { get; set; } + public string Address { get; set; } + public string Due { get; set; } public string CustomerEmail { get; set; } public bool ShowRecommendedFee { get; set; } public decimal FeeRate { get; set; } @@ -53,12 +56,11 @@ namespace BTCPayServer.Models.InvoicingModels public string InvoiceBitcoinUrlQR { get; set; } public int TxCount { get; set; } public int TxCountForFee { get; set; } - public string BtcPaid { get; set; } + public string Paid { get; set; } public string StoreSupportUrl { get; set; } public string OrderId { get; set; } public decimal NetworkFee { get; set; } - public bool IsMultiCurrency { get; set; } public int MaxTimeMinutes { get; set; } public string PaymentMethodId { get; set; } public string PaymentMethodName { get; set; } @@ -72,7 +74,7 @@ namespace BTCPayServer.Models.InvoicingModels public string ReceiptLink { get; set; } public int? RequiredConfirmations { get; set; } public long? ReceivedConfirmations { get; set; } - - public HashSet ExtensionPartials { get; } = new HashSet(); + [JsonExtensionData] + public Dictionary AdditionalData { get; set; } = new(); } } diff --git a/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs b/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs index 401456411..d62d6f6fd 100644 --- a/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs +++ b/BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs @@ -136,5 +136,6 @@ namespace BTCPayServer.Models.InvoicingModels public bool HasRefund { get; set; } public bool StillDue { get; set; } public bool HasRates { get; set; } + public InvoiceEntity Entity { get; internal set; } } } diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinPaymentModelExtension.cs b/BTCPayServer/Payments/Bitcoin/BitcoinCheckoutModelExtension.cs similarity index 87% rename from BTCPayServer/Payments/Bitcoin/BitcoinPaymentModelExtension.cs rename to BTCPayServer/Payments/Bitcoin/BitcoinCheckoutModelExtension.cs index 1b22e46e3..06cf0133b 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinPaymentModelExtension.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinCheckoutModelExtension.cs @@ -12,8 +12,9 @@ using NBitcoin.DataEncoders; namespace BTCPayServer.Payments.Bitcoin { - public class BitcoinPaymentModelExtension : IPaymentModelExtension + public class BitcoinCheckoutModelExtension : ICheckoutModelExtension { + public const string CheckoutBodyComponentName = "BitcoinCheckoutBody"; private readonly PaymentMethodHandlerDictionary _handlers; private readonly BTCPayNetwork _Network; private readonly DisplayFormatter _displayFormatter; @@ -22,7 +23,7 @@ namespace BTCPayServer.Payments.Bitcoin private readonly IPaymentLinkExtension? lnurlPaymentLinkExtension; private readonly string? _bech32Prefix; - public BitcoinPaymentModelExtension( + public BitcoinCheckoutModelExtension( PaymentMethodId paymentMethodId, BTCPayNetwork network, IEnumerable paymentLinkExtensions, @@ -44,18 +45,19 @@ namespace BTCPayServer.Payments.Bitcoin public string Image => _Network.CryptoImagePath; public string Badge => ""; public PaymentMethodId PaymentMethodId { get; } - public void ModifyPaymentModel(PaymentModelContext context) + public void ModifyCheckoutModel(CheckoutModelContext context) { - var prompt = context.Prompt; - if (!_handlers.TryGetValue(PaymentMethodId, out var o) || o is not BitcoinLikePaymentHandler handler) + if (context is not { Handler: BitcoinLikePaymentHandler handler}) return; + var prompt = context.Prompt; var details = handler.ParsePaymentPromptDetails(prompt.Details); + context.Model.CheckoutBodyComponentName = CheckoutBodyComponentName; context.Model.ShowRecommendedFee = context.StoreBlob.ShowRecommendedFee; context.Model.FeeRate = details.RecommendedFeeRate.SatoshiPerByte; var bip21Case = _Network.SupportLightning && context.StoreBlob.OnChainWithLnInvoiceFallback; - var amountInSats = bip21Case && context.StoreBlob.LightningAmountInSatoshi && context.Model.CryptoCode == "BTC"; + var amountInSats = bip21Case && context.StoreBlob.LightningAmountInSatoshi && context.Model.PaymentMethodCurrency == "BTC"; string? lightningFallback = null; if (context.Model.Activated && bip21Case) { @@ -117,10 +119,10 @@ namespace BTCPayServer.Payments.Bitcoin // model.InvoiceBitcoinUrlQR: bitcoin:bcrt1qxp2qa5dhn7?amount=0.00044007&lightning=LNBCRT4400... } - if (_Network.CryptoCode.Equals("BTC", StringComparison.InvariantCultureIgnoreCase) && _bech32Prefix is not null && context.Model.BtcAddress.StartsWith(_bech32Prefix, StringComparison.OrdinalIgnoreCase)) + if (_Network.CryptoCode.Equals("BTC", StringComparison.InvariantCultureIgnoreCase) && _bech32Prefix is not null && context.Model.Address.StartsWith(_bech32Prefix, StringComparison.OrdinalIgnoreCase)) { context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrlQR.Replace( - $"{_Network.NBitcoinNetwork.UriScheme}:{context.Model.BtcAddress}", $"{_Network.NBitcoinNetwork.UriScheme}:{context.Model.BtcAddress.ToUpperInvariant()}", + $"{_Network.NBitcoinNetwork.UriScheme}:{context.Model.Address}", $"{_Network.NBitcoinNetwork.UriScheme}:{context.Model.Address.ToUpperInvariant()}", StringComparison.OrdinalIgnoreCase); // model.InvoiceBitcoinUrlQR: bitcoin:BCRT1QXP2QA5DHN...?amount=0.00044007&lightning=LNBCRT4400... } @@ -136,15 +138,15 @@ namespace BTCPayServer.Payments.Bitcoin } } - public static void PreparePaymentModelForAmountInSats(PaymentModel model, decimal rate, DisplayFormatter displayFormatter) + public static void PreparePaymentModelForAmountInSats(CheckoutModel model, decimal rate, DisplayFormatter displayFormatter) { var satoshiCulture = new CultureInfo(CultureInfo.InvariantCulture.Name) { NumberFormat = { NumberGroupSeparator = " " } }; - model.CryptoCode = "sats"; - model.BtcDue = Money.Parse(model.BtcDue).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture); - model.BtcPaid = Money.Parse(model.BtcPaid).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture); + model.PaymentMethodCurrency = "sats"; + model.Due = Money.Parse(model.Due).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture); + model.Paid = Money.Parse(model.Paid).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture); model.OrderAmount = Money.Parse(model.OrderAmount).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture); model.NetworkFee = new Money(model.NetworkFee, MoneyUnit.BTC).ToUnit(MoneyUnit.Satoshi); model.Rate = model.InvoiceCurrency is "BTC" or "SATS" diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinPaymentMethodViewExtension.cs b/BTCPayServer/Payments/Bitcoin/BitcoinPaymentMethodViewExtension.cs deleted file mode 100644 index bfcb6e07a..000000000 --- a/BTCPayServer/Payments/Bitcoin/BitcoinPaymentMethodViewExtension.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace BTCPayServer.Payments.Bitcoin -{ - public class BitcoinPaymentMethodViewExtension : IPaymentMethodViewExtension - { - public BitcoinPaymentMethodViewExtension(PaymentMethodId paymentMethodId) - { - PaymentMethodId = paymentMethodId; - } - public PaymentMethodId PaymentMethodId { get; } - - public void RegisterViews(PaymentMethodViewContext context) - { - context.RegisterCheckoutUI(new CheckoutUIPaymentMethodSettings - { - ExtensionPartial = "Bitcoin/BitcoinLikeMethodCheckout", - CheckoutBodyVueComponentName = "BitcoinLikeMethodCheckout", - CheckoutHeaderVueComponentName = "BitcoinLikeMethodCheckoutHeader", - NoScriptPartialName = "Bitcoin/BitcoinLikeMethodCheckoutNoScript" - }); - } - } -} diff --git a/BTCPayServer/Payments/IPaymentModelExtension.cs b/BTCPayServer/Payments/ICheckoutModelExtension.cs similarity index 74% rename from BTCPayServer/Payments/IPaymentModelExtension.cs rename to BTCPayServer/Payments/ICheckoutModelExtension.cs index 3881396e7..8567c2f8a 100644 --- a/BTCPayServer/Payments/IPaymentModelExtension.cs +++ b/BTCPayServer/Payments/ICheckoutModelExtension.cs @@ -4,20 +4,20 @@ using Microsoft.AspNetCore.Mvc; namespace BTCPayServer.Payments { - public record PaymentModelContext( - PaymentModel Model, + public record CheckoutModelContext( + CheckoutModel Model, Data.StoreData Store, Data.StoreBlob StoreBlob, InvoiceEntity InvoiceEntity, IUrlHelper UrlHelper, PaymentPrompt Prompt, IPaymentMethodHandler Handler); - public interface IPaymentModelExtension + public interface ICheckoutModelExtension { public PaymentMethodId PaymentMethodId { get; } string DisplayName { get; } string Image { get; } string Badge { get; } - void ModifyPaymentModel(PaymentModelContext context); + void ModifyCheckoutModel(CheckoutModelContext context); } } diff --git a/BTCPayServer/Payments/IPaymentMethodViewExtension.cs b/BTCPayServer/Payments/IPaymentMethodViewExtension.cs deleted file mode 100644 index 00641483d..000000000 --- a/BTCPayServer/Payments/IPaymentMethodViewExtension.cs +++ /dev/null @@ -1,70 +0,0 @@ -#nullable enable -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using BTCPayServer.Services.Invoices; - -namespace BTCPayServer.Payments -{ - public interface IPaymentMethodViewExtension - { - PaymentMethodId PaymentMethodId { get; } - void RegisterViews(PaymentMethodViewContext context); - } - public record ViewViewModel(object View, object ViewModel); - public class PaymentMethodViewProvider - { - private readonly Dictionary _extensions; - private readonly PaymentMethodHandlerDictionary _handlers; - - public PaymentMethodViewProvider( - IEnumerable extensions, - PaymentMethodHandlerDictionary handlers) - { - _extensions = extensions.ToDictionary(o => o.PaymentMethodId, o => o); - _handlers = handlers; - } - public ViewViewModel? TryGetViewViewModel(PaymentPrompt paymentPrompt, string key) - { - if (!_extensions.TryGetValue(paymentPrompt.PaymentMethodId, out var extension)) - return null; - if (!_handlers.TryGetValue(paymentPrompt.PaymentMethodId, out var handler) || paymentPrompt.Details is null) - return null; - var ctx = new PaymentMethodViewContext() - { - Details = handler.ParsePaymentPromptDetails(paymentPrompt.Details) - }; - extension.RegisterViews(ctx); - object? view = null; - if (!ctx._Views.TryGetValue(key, out view)) - return null; - return new ViewViewModel(view, handler.ParsePaymentPromptDetails(paymentPrompt.Details)); - } - } - public class PaymentMethodViewContext - { - internal Dictionary _Views = new Dictionary(); - - public object? Details { get; internal set; } - - public void RegisterPaymentMethodDetails(string partialName) - { - _Views.Add("AdditionalPaymentMethodDetails", partialName); - } - public void RegisterCheckoutUI(CheckoutUIPaymentMethodSettings settings) - { - _Views.Add("CheckoutUI", settings); - } - public void Register(string key, object value) - { - _Views.Add(key, value); - } - } - public class CheckoutUIPaymentMethodSettings - { - public string? ExtensionPartial { get; set; } - public string? CheckoutBodyVueComponentName { get; set; } - public string? CheckoutHeaderVueComponentName { get; set; } - public string? NoScriptPartialName { get; set; } - } -} diff --git a/BTCPayServer/Payments/LNURLPay/LNURLPayPaymentModelExtension.cs b/BTCPayServer/Payments/LNURLPay/LNURLCheckoutModelExtension.cs similarity index 76% rename from BTCPayServer/Payments/LNURLPay/LNURLPayPaymentModelExtension.cs rename to BTCPayServer/Payments/LNURLPay/LNURLCheckoutModelExtension.cs index b9abe91f3..27ab08065 100644 --- a/BTCPayServer/Payments/LNURLPay/LNURLPayPaymentModelExtension.cs +++ b/BTCPayServer/Payments/LNURLPay/LNURLCheckoutModelExtension.cs @@ -8,9 +8,9 @@ using NBitcoin; namespace BTCPayServer.Payments.LNURLPay { - public class LNURLPayPaymentModelExtension : IPaymentModelExtension + public class LNURLCheckoutModelExtension : ICheckoutModelExtension { - public LNURLPayPaymentModelExtension( + public LNURLCheckoutModelExtension( PaymentMethodId paymentMethodId, BTCPayNetwork network, DisplayFormatter displayFormatter, @@ -37,19 +37,22 @@ namespace BTCPayServer.Payments.LNURLPay public string Badge => "⚡"; private const string UriScheme = "lightning:"; - public void ModifyPaymentModel(PaymentModelContext context) + public void ModifyCheckoutModel(CheckoutModelContext context) { + if (context is not { Handler: LNURLPayPaymentHandler handler }) + return; var lnurl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper); if (lnurl is not null) { - context.Model.BtcAddress = lnurl.Replace(UriScheme, ""); + context.Model.Address = lnurl.Replace(UriScheme, ""); context.Model.InvoiceBitcoinUrl = lnurl; context.Model.InvoiceBitcoinUrlQR = lnurl.ToUpperInvariant().Replace(UriScheme.ToUpperInvariant(), UriScheme); } + context.Model.CheckoutBodyComponentName = LNCheckoutModelExtension.CheckoutBodyComponentName; context.Model.PeerInfo = handler.ParsePaymentPromptDetails(context.Prompt.Details).NodeInfo; - if (context.StoreBlob.LightningAmountInSatoshi && context.Model.CryptoCode == "BTC") + if (context.StoreBlob.LightningAmountInSatoshi && context.Model.PaymentMethodCurrency == "BTC") { - BitcoinPaymentModelExtension.PreparePaymentModelForAmountInSats(context.Model, context.Prompt.Rate, _displayFormatter); + BitcoinCheckoutModelExtension.PreparePaymentModelForAmountInSats(context.Model, context.Prompt.Rate, _displayFormatter); } } } diff --git a/BTCPayServer/Payments/LNURLPay/LNURLPaymentMethodViewExtension.cs b/BTCPayServer/Payments/LNURLPay/LNURLPaymentMethodViewExtension.cs deleted file mode 100644 index bc09fc254..000000000 --- a/BTCPayServer/Payments/LNURLPay/LNURLPaymentMethodViewExtension.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace BTCPayServer.Payments.LNURLPay -{ - public class LNURLPaymentMethodViewExtension : IPaymentMethodViewExtension - { - public LNURLPaymentMethodViewExtension(PaymentMethodId paymentMethodId) - { - PaymentMethodId = paymentMethodId; - } - public PaymentMethodId PaymentMethodId { get; } - - public void RegisterViews(PaymentMethodViewContext context) - { - var details = context.Details; - if (details is not LNURLPayPaymentMethodDetails d) - return; - context.RegisterPaymentMethodDetails("LNURL/AdditionalPaymentMethodDetails"); - context.RegisterCheckoutUI(new CheckoutUIPaymentMethodSettings() - { - ExtensionPartial = "Lightning/LightningLikeMethodCheckout", - CheckoutBodyVueComponentName = "LightningLikeMethodCheckout", - CheckoutHeaderVueComponentName = "LightningLikeMethodCheckoutHeader", - NoScriptPartialName = "Lightning/LightningLikeMethodCheckoutNoScript" - }); - } - } -} diff --git a/BTCPayServer/Payments/Lightning/LightningPaymentModelExtension.cs b/BTCPayServer/Payments/Lightning/LNCheckoutModelExtension.cs similarity index 78% rename from BTCPayServer/Payments/Lightning/LightningPaymentModelExtension.cs rename to BTCPayServer/Payments/Lightning/LNCheckoutModelExtension.cs index 7a47ae7c1..5a3c52c42 100644 --- a/BTCPayServer/Payments/Lightning/LightningPaymentModelExtension.cs +++ b/BTCPayServer/Payments/Lightning/LNCheckoutModelExtension.cs @@ -9,11 +9,12 @@ using System.Linq; namespace BTCPayServer.Payments.Lightning { - public class LightningPaymentModelExtension : IPaymentModelExtension + public class LNCheckoutModelExtension : ICheckoutModelExtension { + public const string CheckoutBodyComponentName = "LightningCheckoutBody"; private readonly DisplayFormatter _displayFormatter; IPaymentLinkExtension _PaymentLinkExtension; - public LightningPaymentModelExtension( + public LNCheckoutModelExtension( PaymentMethodId paymentMethodId, BTCPayNetwork network, DisplayFormatter displayFormatter, @@ -37,20 +38,21 @@ namespace BTCPayServer.Payments.Lightning public string Image => Network.LightningImagePath; public string Badge => "⚡"; - public void ModifyPaymentModel(PaymentModelContext context) + public void ModifyCheckoutModel(CheckoutModelContext context) { - if (!Handlers.TryGetValue(PaymentMethodId, out var o) || o is not LightningLikePaymentHandler handler) + if (context is not { Handler: LightningLikePaymentHandler handler }) return; var paymentPrompt = context.InvoiceEntity.GetPaymentPrompt(PaymentMethodId); if (paymentPrompt is null) return; + context.Model.CheckoutBodyComponentName = CheckoutBodyComponentName; context.Model.InvoiceBitcoinUrl = _PaymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper); if (context.Model.InvoiceBitcoinUrl is not null) context.Model.InvoiceBitcoinUrlQR = $"lightning:{context.Model.InvoiceBitcoinUrl.ToUpperInvariant()?.Substring("LIGHTNING:".Length)}"; context.Model.PeerInfo = handler.ParsePaymentPromptDetails(paymentPrompt.Details).NodeInfo; - if (context.StoreBlob.LightningAmountInSatoshi && context.Model.CryptoCode == "BTC") + if (context.StoreBlob.LightningAmountInSatoshi && context.Model.PaymentMethodCurrency == "BTC") { - BitcoinPaymentModelExtension.PreparePaymentModelForAmountInSats(context.Model, paymentPrompt.Rate, _displayFormatter); + BitcoinCheckoutModelExtension.PreparePaymentModelForAmountInSats(context.Model, paymentPrompt.Rate, _displayFormatter); } } } diff --git a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs index 3bca13009..520e0e0b7 100644 --- a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs @@ -21,9 +21,9 @@ using Newtonsoft.Json.Linq; namespace BTCPayServer.Payments.Lightning { - public interface ILightningPaymentHandler : IHasNetwork + public interface ILightningPaymentHandler : IHasNetwork, IPaymentMethodHandler { - LightningPaymentData ParsePaymentDetails(JToken details); + new LightningPaymentData ParsePaymentDetails(JToken details); } public class LightningLikePaymentHandler : IPaymentMethodHandler, ILightningPaymentHandler { diff --git a/BTCPayServer/Payments/Lightning/LightningPaymentMethodViewExtension.cs b/BTCPayServer/Payments/Lightning/LightningPaymentMethodViewExtension.cs deleted file mode 100644 index 41eb3ff4d..000000000 --- a/BTCPayServer/Payments/Lightning/LightningPaymentMethodViewExtension.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace BTCPayServer.Payments.Lightning -{ - public class LightningPaymentMethodViewExtension : IPaymentMethodViewExtension - { - public LightningPaymentMethodViewExtension(PaymentMethodId paymentMethodId) - { - PaymentMethodId = paymentMethodId; - } - public PaymentMethodId PaymentMethodId { get; } - - public void RegisterViews(PaymentMethodViewContext context) - { - context.RegisterCheckoutUI(new CheckoutUIPaymentMethodSettings() - { - ExtensionPartial = "Lightning/LightningLikeMethodCheckout", - CheckoutBodyVueComponentName = "LightningLikeMethodCheckout", - CheckoutHeaderVueComponentName = "LightningLikeMethodCheckoutHeader", - NoScriptPartialName = "Lightning/LightningLikeMethodCheckoutNoScript" - }); - } - } -} diff --git a/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs b/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs index e51e16dcd..af0ce5568 100644 --- a/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs +++ b/BTCPayServer/Plugins/Altcoins/Monero/AltcoinsPlugin.Monero.cs @@ -42,8 +42,6 @@ public partial class AltcoinsPlugin var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("XMR"); services.AddBTCPayNetwork(network) .AddTransactionLinkProvider(pmi, new SimpleTransactionLinkProvider(blockExplorerLink)); - services.AddSingleton(provider => -(IPaymentMethodViewExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentMethodViewExtension), new object[] { pmi })); services.AddSingleton(provider => @@ -69,12 +67,12 @@ public partial class AltcoinsPlugin (IPaymentMethodHandler)ActivatorUtilities.CreateInstance(provider, typeof(MoneroLikePaymentMethodHandler), new object[] { network })); services.AddSingleton(provider => (IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(MoneroPaymentLinkExtension), new object[] { network, pmi })); - services.AddSingleton(provider => -(IPaymentModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(MoneroPaymentModelExtension), new object[] { network, pmi })); + services.AddSingleton(provider => +(ICheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(MoneroCheckoutModelExtension), new object[] { network, pmi })); - services.AddSingleton(new UIExtension("Monero/StoreNavMoneroExtension", "store-nav")); - services.AddSingleton(new UIExtension("Monero/StoreWalletsNavMoneroExtension", "store-wallets-nav")); - services.AddSingleton(new UIExtension("Monero/ViewMoneroLikePaymentData", "store-invoices-payments")); + services.AddUIExtension("store-nav", "Monero/StoreNavMoneroExtension"); + services.AddUIExtension("store-wallets-nav", "Monero/StoreWalletsNavMoneroExtension"); + services.AddUIExtension("store-invoices-payments", "Monero/ViewMoneroLikePaymentData"); services.AddSingleton(); } private static MoneroLikeConfiguration ConfigureMoneroLikeConfiguration(IServiceProvider serviceProvider) diff --git a/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs b/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs index a6ffd2610..34ddaf263 100644 --- a/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs +++ b/BTCPayServer/Plugins/Altcoins/Zcash/AltcoinsPlugin.Zcash.cs @@ -43,8 +43,6 @@ public partial class AltcoinsPlugin var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("ZEC"); services.AddBTCPayNetwork(network) .AddTransactionLinkProvider(pmi, new SimpleTransactionLinkProvider(blockExplorerLink)); - services.AddSingleton(provider => -(IPaymentMethodViewExtension)ActivatorUtilities.CreateInstance(provider, typeof(BitcoinPaymentMethodViewExtension), new object[] { pmi })); services.AddSingleton(provider => @@ -58,13 +56,13 @@ public partial class AltcoinsPlugin (IPaymentMethodHandler)ActivatorUtilities.CreateInstance(provider, typeof(ZcashLikePaymentMethodHandler), new object[] { network })); services.AddSingleton(provider => (IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(ZcashPaymentLinkExtension), new object[] { network, pmi })); - services.AddSingleton(provider => -(IPaymentModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(ZcashPaymentModelExtension), new object[] { network, pmi })); + services.AddSingleton(provider => +(ICheckoutModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(ZcashCheckoutModelExtension), new object[] { network, pmi })); services.AddSingleton(); services.AddSingleton(provider => provider.GetRequiredService()); - services.AddSingleton(new UIExtension("Zcash/StoreNavZcashExtension", "store-nav")); - services.AddSingleton(new UIExtension("Zcash/ViewZcashLikePaymentData", "store-invoices-payments")); + services.AddUIExtension("store-nav", "Zcash/StoreNavZcashExtension"); + services.AddUIExtension("store-invoices-payments", "Zcash/ViewZcashLikePaymentData"); services.AddSingleton(); } diff --git a/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs b/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs index c41893585..9dd42b491 100644 --- a/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs +++ b/BTCPayServer/Plugins/Crowdfund/CrowdfundPlugin.cs @@ -36,7 +36,7 @@ namespace BTCPayServer.Plugins.Crowdfund public override void Execute(IServiceCollection services) { - services.AddSingleton(new UIExtension("Crowdfund/NavExtension", "header-nav")); + services.AddUIExtension("header-nav", "Crowdfund/NavExtension"); services.AddSingleton(); services.AddSingleton(); diff --git a/BTCPayServer/Plugins/NFC/NFCPlugin.cs b/BTCPayServer/Plugins/NFC/NFCPlugin.cs index cdbcaa0cc..37d3a8c31 100644 --- a/BTCPayServer/Plugins/NFC/NFCPlugin.cs +++ b/BTCPayServer/Plugins/NFC/NFCPlugin.cs @@ -15,12 +15,9 @@ namespace BTCPayServer.Plugins.NFC public override void Execute(IServiceCollection applicationBuilder) { - applicationBuilder.AddSingleton(new UIExtension("NFC/CheckoutEnd", - "checkout-end")); - applicationBuilder.AddSingleton(new UIExtension("NFC/LNURLNFCPostContent", - "checkout-lightning-post-content")); - applicationBuilder.AddSingleton(new UIExtension("NFC/LNURLNFCPostContent", - "checkout-bitcoin-post-content")); + applicationBuilder.AddUIExtension("checkout-end", "NFC/CheckoutEnd"); + applicationBuilder.AddUIExtension("checkout-lightning-post-content", "NFC/LNURLNFCPostContent"); + applicationBuilder.AddUIExtension("checkout-bitcoin-post-content", "NFC/LNURLNFCPostContent"); base.Execute(applicationBuilder); } } diff --git a/BTCPayServer/Plugins/PayButton/PayButtonPlugin.cs b/BTCPayServer/Plugins/PayButton/PayButtonPlugin.cs index bb7a2db4c..2b9c50022 100644 --- a/BTCPayServer/Plugins/PayButton/PayButtonPlugin.cs +++ b/BTCPayServer/Plugins/PayButton/PayButtonPlugin.cs @@ -13,7 +13,7 @@ namespace BTCPayServer.Plugins.PayButton public override void Execute(IServiceCollection services) { - services.AddSingleton(new UIExtension("PayButton/NavExtension", "header-nav")); + services.AddUIExtension("header-nav", "PayButton/NavExtension"); base.Execute(services); } } diff --git a/BTCPayServer/Plugins/PointOfSale/PointOfSalePlugin.cs b/BTCPayServer/Plugins/PointOfSale/PointOfSalePlugin.cs index deb8a6b72..ccd9da1e5 100644 --- a/BTCPayServer/Plugins/PointOfSale/PointOfSalePlugin.cs +++ b/BTCPayServer/Plugins/PointOfSale/PointOfSalePlugin.cs @@ -28,7 +28,7 @@ namespace BTCPayServer.Plugins.PointOfSale public override void Execute(IServiceCollection services) { - services.AddSingleton(new UIExtension("PointOfSale/NavExtension", "header-nav")); + services.AddUIExtension("header-nav", "PointOfSale/NavExtension"); services.AddSingleton(); base.Execute(services); } diff --git a/BTCPayServer/Plugins/Shopify/ShopifyPlugin.cs b/BTCPayServer/Plugins/Shopify/ShopifyPlugin.cs index a2cb98d51..6745d81d3 100644 --- a/BTCPayServer/Plugins/Shopify/ShopifyPlugin.cs +++ b/BTCPayServer/Plugins/Shopify/ShopifyPlugin.cs @@ -16,7 +16,7 @@ namespace BTCPayServer.Plugins.Shopify { applicationBuilder.AddSingleton(); applicationBuilder.AddSingleton(provider => provider.GetRequiredService()); - applicationBuilder.AddSingleton(new UIExtension("Shopify/NavExtension", "header-nav")); + applicationBuilder.AddUIExtension("header-nav", "Shopify/NavExtension"); base.Execute(applicationBuilder); } } diff --git a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentModelExtension.cs b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroCheckoutModelExtension.cs similarity index 62% rename from BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentModelExtension.cs rename to BTCPayServer/Services/Altcoins/Monero/Payments/MoneroCheckoutModelExtension.cs index 6af2fbdcc..1b51dcd03 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroPaymentModelExtension.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroCheckoutModelExtension.cs @@ -2,18 +2,19 @@ using System.Collections.Generic; using System.Linq; using BTCPayServer.Payments; using BTCPayServer.Payments.Bitcoin; +using BTCPayServer.Payments.Lightning; using BTCPayServer.Services.Altcoins.Monero.Services; using BTCPayServer.Services.Invoices; namespace BTCPayServer.Services.Altcoins.Monero.Payments { - public class MoneroPaymentModelExtension : IPaymentModelExtension + public class MoneroCheckoutModelExtension : ICheckoutModelExtension { private readonly BTCPayNetworkBase _network; private readonly PaymentMethodHandlerDictionary _handlers; private readonly IPaymentLinkExtension paymentLinkExtension; - public MoneroPaymentModelExtension( + public MoneroCheckoutModelExtension( PaymentMethodId paymentMethodId, IEnumerable paymentLinkExtensions, BTCPayNetworkBase network, @@ -31,22 +32,23 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments public string Image => _network.CryptoImagePath; public string Badge => ""; - public void ModifyPaymentModel(PaymentModelContext context) + public void ModifyCheckoutModel(CheckoutModelContext context) { + if (context is not { Handler: MoneroLikePaymentMethodHandler handler }) + return; + context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName; if (context.Model.Activated) { - if (_handlers.TryGetValue(PaymentMethodId, out var handler)) + var details = context.InvoiceEntity.GetPayments(true) + .Select(p => p.GetDetails(handler)) + .Where(p => p is not null) + .FirstOrDefault(); + if (details is not null) { - var details = context.InvoiceEntity.GetPayments(true) - .Select(p => p.GetDetails(handler)) - .Where(p => p is not null) - .FirstOrDefault(); - if (details is not null) - { - context.Model.ReceivedConfirmations = details.ConfirmationCount; - context.Model.RequiredConfirmations = (int)MoneroListener.ConfirmationsRequired(details, context.InvoiceEntity.SpeedPolicy); - } + context.Model.ReceivedConfirmations = details.ConfirmationCount; + context.Model.RequiredConfirmations = (int)MoneroListener.ConfirmationsRequired(details, context.InvoiceEntity.SpeedPolicy); } + context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper); context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrl; } diff --git a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs index 1e216c3cc..04f01016b 100644 --- a/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs +++ b/BTCPayServer/Services/Altcoins/Monero/Payments/MoneroLikePaymentMethodHandler.cs @@ -108,17 +108,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments return details.ToObject(Serializer); } - public CheckoutUIPaymentMethodSettings GetCheckoutUISettings() - { - return new CheckoutUIPaymentMethodSettings - { - ExtensionPartial = "Bitcoin/BitcoinLikeMethodCheckout", - CheckoutBodyVueComponentName = "BitcoinLikeMethodCheckout", - CheckoutHeaderVueComponentName = "BitcoinLikeMethodCheckoutHeader", - NoScriptPartialName = "Bitcoin/BitcoinLikeMethodCheckoutNoScript" - }; - } - public MoneroLikePaymentData ParsePaymentDetails(JToken details) { return details.ToObject(Serializer) ?? throw new FormatException($"Invalid {nameof(MoneroLikePaymentMethodHandler)}"); diff --git a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentModelExtension.cs b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashCheckoutModelExtension.cs similarity index 60% rename from BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentModelExtension.cs rename to BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashCheckoutModelExtension.cs index f0fb35265..234aba63f 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashPaymentModelExtension.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashCheckoutModelExtension.cs @@ -1,18 +1,20 @@ using System.Collections.Generic; using System.Linq; using BTCPayServer.Payments; +using BTCPayServer.Payments.Bitcoin; +using BTCPayServer.Services.Altcoins.Monero.Payments; using BTCPayServer.Services.Altcoins.Zcash.Services; using BTCPayServer.Services.Invoices; namespace BTCPayServer.Services.Altcoins.Zcash.Payments { - public class ZcashPaymentModelExtension : IPaymentModelExtension + public class ZcashCheckoutModelExtension : ICheckoutModelExtension { private readonly BTCPayNetworkBase _network; private readonly PaymentMethodHandlerDictionary _handlers; private readonly IPaymentLinkExtension paymentLinkExtension; - public ZcashPaymentModelExtension( + public ZcashCheckoutModelExtension( PaymentMethodId paymentMethodId, IEnumerable paymentLinkExtensions, BTCPayNetworkBase network, @@ -30,21 +32,21 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Payments public string Image => _network.CryptoImagePath; public string Badge => ""; - public void ModifyPaymentModel(PaymentModelContext context) + public void ModifyCheckoutModel(CheckoutModelContext context) { - if (context.Model.Activated) + if (context is not { Handler: ZcashLikePaymentMethodHandler handler }) + return; + context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName; + if (context.Model.Activated) { - if (_handlers.TryGetValue(PaymentMethodId, out var handler)) + var details = context.InvoiceEntity.GetPayments(true) + .Select(p => p.GetDetails(handler)) + .Where(p => p is not null) + .FirstOrDefault(); + if (details is not null) { - var details = context.InvoiceEntity.GetPayments(true) - .Select(p => p.GetDetails(handler)) - .Where(p => p is not null) - .FirstOrDefault(); - if (details is not null) - { - context.Model.ReceivedConfirmations = details.ConfirmationCount; - context.Model.RequiredConfirmations = (int)ZcashListener.ConfirmationsRequired(context.InvoiceEntity.SpeedPolicy); - } + context.Model.ReceivedConfirmations = details.ConfirmationCount; + context.Model.RequiredConfirmations = (int)ZcashListener.ConfirmationsRequired(context.InvoiceEntity.SpeedPolicy); } context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper); context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrl; diff --git a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs index 76714b2f3..7db54a244 100644 --- a/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs +++ b/BTCPayServer/Services/Altcoins/Zcash/Payments/ZcashLikePaymentMethodHandler.cs @@ -102,17 +102,6 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Payments public long AccountIndex { get; internal set; } } - public CheckoutUIPaymentMethodSettings GetCheckoutUISettings() - { - return new CheckoutUIPaymentMethodSettings - { - ExtensionPartial = "Bitcoin/BitcoinLikeMethodCheckout", - CheckoutBodyVueComponentName = "BitcoinLikeMethodCheckout", - CheckoutHeaderVueComponentName = "BitcoinLikeMethodCheckoutHeader", - NoScriptPartialName = "Bitcoin/BitcoinLikeMethodCheckoutNoScript" - }; - } - public ZcashLikePaymentData ParsePaymentDetails(JToken details) { return details.ToObject(Serializer) ?? throw new FormatException($"Invalid {nameof(ZcashLikePaymentData)}"); diff --git a/BTCPayServer/Services/PrettyNameProvider.cs b/BTCPayServer/Services/PrettyNameProvider.cs index 639d986fe..71b65140e 100644 --- a/BTCPayServer/Services/PrettyNameProvider.cs +++ b/BTCPayServer/Services/PrettyNameProvider.cs @@ -6,9 +6,9 @@ namespace BTCPayServer.Services { public class PrettyNameProvider { - private readonly Dictionary _extensions; + private readonly Dictionary _extensions; - public PrettyNameProvider(Dictionary extensions) + public PrettyNameProvider(Dictionary extensions) { _extensions = extensions; } diff --git a/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml b/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml index ad2e89e2f..ad869b63e 100644 --- a/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml +++ b/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml @@ -1,9 +1,10 @@ @using BTCPayServer.BIP78.Sender @using BTCPayServer.Components.TruncateCenter @using BTCPayServer.Abstractions.TagHelpers -@model BTCPayServer.Models.InvoicingModels.PaymentModel +@using BTCPayServer.Payments.Bitcoin +@model BTCPayServer.Models.InvoicingModels.CheckoutModel -