mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-18 21:32:27 +01:00
Simplify extension of payments extensions
This commit is contained in:
parent
e1bfc04451
commit
34b2cca492
@ -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<LNURLPayRequest.LNURLPayRequestCallbackResponse>(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]
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class StoreRecentInvoices : ViewComponent
|
||||
Details = new InvoiceDetailsModel
|
||||
{
|
||||
Archived = invoice.Archived,
|
||||
Payments = invoice.GetPayments(false)
|
||||
Payments = invoice.GetPayments(false)
|
||||
}
|
||||
}).ToList();
|
||||
|
||||
|
@ -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 =>
|
||||
{
|
||||
|
@ -63,7 +63,6 @@ namespace BTCPayServer.Controllers
|
||||
private readonly IAuthorizationService _authorizationService;
|
||||
private readonly TransactionLinkProviders _transactionLinkProviders;
|
||||
private readonly Dictionary<PaymentMethodId, IPaymentModelExtension> _paymentModelExtensions;
|
||||
private readonly PaymentMethodViewProvider _viewProvider;
|
||||
private readonly PrettyNameProvider _prettyName;
|
||||
private readonly AppService _appService;
|
||||
private readonly IFileService _fileService;
|
||||
@ -99,7 +98,6 @@ namespace BTCPayServer.Controllers
|
||||
IAuthorizationService authorizationService,
|
||||
TransactionLinkProviders transactionLinkProviders,
|
||||
Dictionary<PaymentMethodId, IPaymentModelExtension> paymentModelExtensions,
|
||||
PaymentMethodViewProvider viewProvider,
|
||||
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;
|
||||
|
@ -292,10 +292,9 @@ namespace BTCPayServer
|
||||
}
|
||||
|
||||
|
||||
public static IServiceCollection AddUIExtension(this IServiceCollection services, string key, string partialView)
|
||||
public static IServiceCollection AddUIExtension(this IServiceCollection services, string location, string partialViewName)
|
||||
{
|
||||
services.AddSingleton<IUIExtension>(new UIExtension(partialView,
|
||||
key));
|
||||
services.AddSingleton<IUIExtension>(new UIExtension(partialViewName, location));
|
||||
return services;
|
||||
}
|
||||
public static IServiceCollection AddReportProvider<T>(this IServiceCollection services)
|
||||
|
@ -158,8 +158,7 @@ namespace BTCPayServer.Hosting
|
||||
//
|
||||
|
||||
AddOnchainWalletParsers(services);
|
||||
services.AddSingleton<IUIExtension>(new UIExtension("Bitcoin/ViewBitcoinLikePaymentData", "store-invoices-payments"));
|
||||
services.AddSingleton<IUIExtension>(new UIExtension("Lightning/ViewLightningLikePaymentData", "store-invoices-payments"));
|
||||
|
||||
|
||||
services.AddStartupTask<BlockExplorerLinkStartupTask>();
|
||||
services.AddStartupTask<LoadCurrencyNameTableStartupTask>();
|
||||
@ -367,6 +366,8 @@ namespace BTCPayServer.Hosting
|
||||
|
||||
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.NBXplorerConnectionFactory>();
|
||||
services.AddSingleton<IHostedService, Services.NBXplorerConnectionFactory>(o => o.GetRequiredService<Services.NBXplorerConnectionFactory>());
|
||||
@ -407,7 +408,6 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
|
||||
services.AddSingleton<IHostedService, LightningPendingPayoutListener>();
|
||||
|
||||
services.AddSingleton<PaymentMethodHandlerDictionary>();
|
||||
services.AddSingleton<PaymentMethodViewProvider>();
|
||||
|
||||
services.AddSingleton<PayoutMethodHandlerDictionary>();
|
||||
|
||||
@ -668,8 +668,6 @@ o.GetRequiredService<IEnumerable<IPaymentLinkExtension>>().ToDictionary(o => o.P
|
||||
(IPaymentLinkExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentLinkExtension), new object[] { network, pmi }));
|
||||
services.AddSingleton<IPaymentModelExtension>(provider =>
|
||||
(IPaymentModelExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentModelExtension), new object[] { network, pmi }));
|
||||
services.AddSingleton<IPaymentMethodViewExtension>(provider =>
|
||||
(IPaymentMethodViewExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPaymentMethodViewExtension), new object[] { pmi }));
|
||||
services.AddSingleton<IPaymentMethodBitpayAPIExtension>(provider =>
|
||||
(IPaymentMethodBitpayAPIExtension)ActivatorUtilities.CreateInstance(provider, typeof(LNURLPayPaymentMethodBitpayAPIExtension), new object[] { pmi }));
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +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<PaymentMethodId, IPaymentMethodViewExtension> _extensions;
|
||||
private readonly PaymentMethodHandlerDictionary _handlers;
|
||||
|
||||
public PaymentMethodViewProvider(
|
||||
IEnumerable<IPaymentMethodViewExtension> 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<string, object> _Views = new Dictionary<string, object>();
|
||||
|
||||
public object? Details { get; internal set; }
|
||||
|
||||
public void RegisterPaymentMethodDetails(string partialName)
|
||||
{
|
||||
_Views.Add("AdditionalPaymentMethodDetails", partialName);
|
||||
}
|
||||
public void Register(string key, object value)
|
||||
{
|
||||
_Views.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -7,10 +7,10 @@
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
@inject TransactionLinkProviders TransactionLinkProviders
|
||||
@inject PaymentMethodHandlerDictionary handlers
|
||||
@model IEnumerable<BTCPayServer.Services.Invoices.PaymentEntity>
|
||||
@model InvoiceDetailsModel
|
||||
@{
|
||||
PayjoinInformation payjoinInformation = null;
|
||||
var payments = Model
|
||||
var payments = Model.Payments
|
||||
.Select(payment =>
|
||||
{
|
||||
if (!handlers.TryGetValue(payment.PaymentMethodId, out var h) || h is not BitcoinLikePaymentHandler handler)
|
||||
|
@ -1,18 +0,0 @@
|
||||
@model BTCPayServer.Payments.LNURLPayPaymentMethodDetails
|
||||
|
||||
@if (!string.IsNullOrEmpty(Model.ProvidedComment))
|
||||
{
|
||||
<tr>
|
||||
<td colspan="100% bg-tile">
|
||||
LNURL Comment: @Model.ProvidedComment
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.ConsumedLightningAddress))
|
||||
{
|
||||
<tr>
|
||||
<td colspan="100% bg-tile">
|
||||
Lightning address used: @Model.ConsumedLightningAddress
|
||||
</td>
|
||||
</tr>
|
||||
}
|
@ -7,16 +7,31 @@
|
||||
@inject DisplayFormatter DisplayFormatter
|
||||
@inject PaymentMethodHandlerDictionary handlers
|
||||
@inject PrettyNameProvider prettyName
|
||||
@model IEnumerable<BTCPayServer.Services.Invoices.PaymentEntity>
|
||||
@model InvoiceDetailsModel
|
||||
|
||||
@{
|
||||
string providedComment = null;
|
||||
string consumedLightningAddress = null;
|
||||
var payments = Model
|
||||
.Payments
|
||||
.Select(payment =>
|
||||
{
|
||||
|
||||
|
||||
if (handlers.TryGet(payment.PaymentMethodId) is not ILightningPaymentHandler handler)
|
||||
return null;
|
||||
var offChainPaymentData = handler.ParsePaymentDetails(payment.Details);
|
||||
|
||||
if (handler.ParsePaymentPromptDetails(Model.Entity.GetPaymentPrompt(payment.PaymentMethodId)?.Details) is LNURLPayPaymentMethodDetails lnurlPrompt)
|
||||
{
|
||||
if (lnurlPrompt.ConsumedLightningAddress is string consumed)
|
||||
{
|
||||
consumedLightningAddress = consumed;
|
||||
}
|
||||
if (lnurlPrompt.ProvidedComment is string comment)
|
||||
{
|
||||
providedComment = comment;
|
||||
}
|
||||
}
|
||||
return new OffChainPaymentViewModel
|
||||
{
|
||||
Type = prettyName.PrettyName(payment.PaymentMethodId),
|
||||
@ -25,8 +40,8 @@
|
||||
Amount = DisplayFormatter.Currency(payment.Value, handler.Network.CryptoCode, divisibility: payment.Divisibility)
|
||||
};
|
||||
})
|
||||
.Where(model => model != null)
|
||||
.ToList();
|
||||
.Where(model => model != null)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@if (payments.Any())
|
||||
@ -37,7 +52,7 @@
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-75px">Type</th>
|
||||
<th class="w-175px">Type</th>
|
||||
<th class="w-175px">Destination</th>
|
||||
<th class="text-nowrap">Payment Proof</th>
|
||||
<th class="w-150px text-end">Paid</th>
|
||||
@ -61,6 +76,19 @@
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@if (!string.IsNullOrEmpty(providedComment))
|
||||
{
|
||||
<div>
|
||||
<b>LNURL Comment</b>: @providedComment
|
||||
</div>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(consumedLightningAddress))
|
||||
{
|
||||
<div>
|
||||
<b>Lightning address used</b>: @consumedLightningAddress
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
@using BTCPayServer.Payments
|
||||
@inject PaymentMethodViewProvider paymentMethodViewProvider
|
||||
@model (InvoiceDetailsModel Invoice, bool ShowAddress)
|
||||
@{
|
||||
var invoice = Model.Invoice;
|
||||
@ -87,14 +86,10 @@
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
var vvm = paymentMethodViewProvider.TryGetViewViewModel(payment.PaymentMethodRaw, "AdditionalPaymentMethodDetails");;
|
||||
if (vvm != null)
|
||||
{
|
||||
<partial name="@((string)vvm.View)" model="@vvm.ViewModel" />
|
||||
}
|
||||
<vc:ui-extension-point location="invoice-payments-list" />
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<vc:ui-extension-point location="store-invoices-payments" model="@invoice.Payments" />
|
||||
<vc:ui-extension-point location="store-invoices-payments" model="@invoice" />
|
||||
|
Loading…
Reference in New Issue
Block a user