Make LNURL enabled when only method (#3930)

* Make LNURL enabled when only method

This fixes the scenario where LNURL for standard invoices are disabled, but the POS Print view only shows LNURL, so the QR code would always error out. The fix is to bypass the setting when lnurl is the only enabled payment method on the invoice

* Make sure not to affect other flows

* fix
This commit is contained in:
Andrew Camilleri 2022-07-06 15:09:05 +02:00 committed by GitHub
parent 3576ebd14f
commit 612a0397a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 39 additions and 24 deletions

View File

@ -281,18 +281,20 @@ namespace BTCPayServer.Controllers
// This loop ends with .ToList so we are querying all payment methods at once
// instead of sequentially to improve response time
foreach (var o in store.GetSupportedPaymentMethods(_NetworkProvider)
var x1 = store.GetSupportedPaymentMethods(_NetworkProvider)
.Where(s => !excludeFilter.Match(s.PaymentId) &&
_paymentMethodHandlerDictionary.Support(s.PaymentId))
.Select(c =>
(Handler: _paymentMethodHandlerDictionary[c.PaymentId],
SupportedPaymentMethod: c,
Network: _NetworkProvider.GetNetwork<BTCPayNetworkBase>(c.PaymentId.CryptoCode)))
.Where(c => c.Network != null)
.Where(c => c.Network != null).ToList();
var pmis = x1.Select(tuple => tuple.SupportedPaymentMethod.PaymentId).ToHashSet();
foreach (var o in x1
.Select(o =>
(SupportedPaymentMethod: o.SupportedPaymentMethod,
PaymentMethod: CreatePaymentMethodAsync(fetchingByCurrencyPair, o.Handler,
o.SupportedPaymentMethod, o.Network, entity, store, logs)))
o.SupportedPaymentMethod, o.Network, entity, store, logs, pmis)))
.ToList())
{
var paymentMethod = await o.PaymentMethod;
@ -362,9 +364,12 @@ namespace BTCPayServer.Controllers
}).ToArray());
}
private async Task<PaymentMethod?> CreatePaymentMethodAsync(Dictionary<CurrencyPair, Task<RateResult>> fetchingByCurrencyPair,
IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetworkBase network, InvoiceEntity entity,
StoreData store, InvoiceLogs logs)
private async Task<PaymentMethod?> CreatePaymentMethodAsync(
Dictionary<CurrencyPair, Task<RateResult>> fetchingByCurrencyPair,
IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetworkBase network,
InvoiceEntity entity,
StoreData store, InvoiceLogs logs,
HashSet<PaymentMethodId> invoicePaymentMethods)
{
try
{
@ -396,7 +401,7 @@ namespace BTCPayServer.Controllers
using (logs.Measure($"{logPrefix} Payment method details creation"))
{
var paymentDetails = await handler.CreatePaymentMethodDetails(logs, supportedPaymentMethod, paymentMethod, store, network, preparePayment);
var paymentDetails = await handler.CreatePaymentMethodDetails(logs, supportedPaymentMethod, paymentMethod, store, network, preparePayment, invoicePaymentMethods);
paymentMethod.SetPaymentMethodDetails(paymentDetails);
}

View File

@ -474,8 +474,7 @@ namespace BTCPayServer
var isTopup = i.IsUnsetTopUp();
var lnurlSupportedPaymentMethod =
i.GetSupportedPaymentMethod<LNURLPaySupportedPaymentMethod>(pmi).FirstOrDefault();
if (lnurlSupportedPaymentMethod is null ||
(!isTopup && !lnurlSupportedPaymentMethod.EnableForStandardInvoices))
if (lnurlSupportedPaymentMethod is null)
{
return NotFound();
}

View File

@ -153,7 +153,7 @@ namespace BTCPayServer.Payments.Bitcoin
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
InvoiceLogs logs,
DerivationSchemeSettings supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store,
BTCPayNetwork network, object preparePaymentObject)
BTCPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods)
{
if (preparePaymentObject is null)
{

View File

@ -20,14 +20,18 @@ namespace BTCPayServer.Payments
/// <summary>
/// Create needed to track payments of this invoice
/// </summary>
/// <param name="logs"></param>
/// <param name="supportedPaymentMethod"></param>
/// <param name="paymentMethod"></param>
/// <param name="store"></param>
/// <param name="network"></param>
/// <param name="preparePaymentObject"></param>
/// <param name="invoicePaymentMethods"></param>
/// <returns></returns>
Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs, ISupportedPaymentMethod supportedPaymentMethod,
PaymentMethod paymentMethod, StoreData store, BTCPayNetworkBase network, object preparePaymentObject);
Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs,
ISupportedPaymentMethod supportedPaymentMethod,
PaymentMethod paymentMethod, StoreData store, BTCPayNetworkBase network, object preparePaymentObject,
IEnumerable<PaymentMethodId> invoicePaymentMethods);
/// <summary>
/// This method called before the rate have been fetched
@ -52,7 +56,7 @@ namespace BTCPayServer.Payments
where TBTCPayNetwork : BTCPayNetworkBase
{
Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs, TSupportedPaymentMethod supportedPaymentMethod,
PaymentMethod paymentMethod, StoreData store, TBTCPayNetwork network, object preparePaymentObject);
PaymentMethod paymentMethod, StoreData store, TBTCPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods);
}
public abstract class PaymentMethodHandlerBase<TSupportedPaymentMethod, TBTCPayNetwork> : IPaymentMethodHandler<
@ -65,7 +69,7 @@ namespace BTCPayServer.Payments
public abstract Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
InvoiceLogs logs,
TSupportedPaymentMethod supportedPaymentMethod,
PaymentMethod paymentMethod, StoreData store, TBTCPayNetwork network, object preparePaymentObject);
PaymentMethod paymentMethod, StoreData store, TBTCPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods);
public abstract void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse,
StoreBlob storeBlob, IPaymentMethod paymentMethod);
@ -95,12 +99,14 @@ namespace BTCPayServer.Payments
return null;
}
public Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs, ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod,
StoreData store, BTCPayNetworkBase network, object preparePaymentObject)
public Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs,
ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod,
StoreData store, BTCPayNetworkBase network, object preparePaymentObject,
IEnumerable<PaymentMethodId> invoicePaymentMethods)
{
if (supportedPaymentMethod is TSupportedPaymentMethod method && network is TBTCPayNetwork correctNetwork)
{
return CreatePaymentMethodDetails(logs, method, paymentMethod, store, correctNetwork, preparePaymentObject);
return CreatePaymentMethodDetails(logs, method, paymentMethod, store, correctNetwork, preparePaymentObject, invoicePaymentMethods);
}
throw new NotSupportedException("Invalid supportedPaymentMethod");

View File

@ -46,10 +46,12 @@ namespace BTCPayServer.Payments.Lightning
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
InvoiceLogs logs,
LNURLPaySupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, Data.StoreData store,
BTCPayNetwork network, object preparePaymentObject)
BTCPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods)
{
var lnPmi = new PaymentMethodId(supportedPaymentMethod.CryptoCode, PaymentTypes.LightningLike);
if (!supportedPaymentMethod.EnableForStandardInvoices &&
paymentMethod.ParentEntity.Type == InvoiceType.Standard)
paymentMethod.ParentEntity.Type == InvoiceType.Standard &&
invoicePaymentMethods.Contains(lnPmi))
{
throw new PaymentMethodUnavailableException("LNURL is not enabled for standard invoices");
}

View File

@ -53,7 +53,7 @@ namespace BTCPayServer.Payments.Lightning
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
InvoiceLogs logs,
LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, Data.StoreData store,
BTCPayNetwork network, object preparePaymentObject)
BTCPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods)
{
if (supportedPaymentMethod.DisableBOLT11PaymentOption)
{

View File

@ -298,10 +298,12 @@ namespace BTCPayServer.Payments.Lightning
var prepObj =
_lightningLikePaymentHandler.PreparePayment(supportedMethod, store, paymentMethod.Network);
var pmis = invoice.GetPaymentMethods().Select(method => method.GetId()).ToHashSet();
var newPaymentMethodDetails =
(LightningLikePaymentMethodDetails)(await _lightningLikePaymentHandler
.CreatePaymentMethodDetails(logs, supportedMethod, paymentMethod, store,
paymentMethod.Network, prepObj));
paymentMethod.Network, prepObj, pmis));
var instanceListenerKey = (paymentMethod.Network.CryptoCode,
GetLightningUrl(supportedMethod).ToString());

View File

@ -32,7 +32,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments
public override PaymentType PaymentType => MoneroPaymentType.Instance;
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs, MoneroSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod,
StoreData store, MoneroLikeSpecificBtcPayNetwork network, object preparePaymentObject)
StoreData store, MoneroLikeSpecificBtcPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods)
{
if (preparePaymentObject is null)

View File

@ -32,7 +32,7 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Payments
public override PaymentType PaymentType => ZcashPaymentType.Instance;
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs, ZcashSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod,
StoreData store, ZcashLikeSpecificBtcPayNetwork network, object preparePaymentObject)
StoreData store, ZcashLikeSpecificBtcPayNetwork network, object preparePaymentObject, IEnumerable<PaymentMethodId> invoicePaymentMethods)
{
if (preparePaymentObject is null)

View File

@ -30,10 +30,11 @@ namespace BTCPayServer.Services.Invoices
InvoiceLogs logs = new InvoiceLogs();
try
{
var pmis = invoice.GetPaymentMethods().Select(method => method.GetId()).ToHashSet();
logs.Write($"{paymentMethodId}: Activating", InvoiceEventData.EventSeverity.Info);
var newDetails = await
payHandler.CreatePaymentMethodDetails(logs, supportPayMethod, paymentMethod, store, network,
prepare);
prepare, pmis);
eligibleMethodToActivate.SetPaymentMethodDetails(newDetails);
await invoiceRepository.UpdateInvoicePaymentMethod(invoice.Id, eligibleMethodToActivate);
eventAggregator.Publish(new InvoicePaymentMethodActivated(paymentMethodId, invoice));