mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
Fix: An unactivated payment method failing to activate would crash the checkout
This commit is contained in:
@@ -698,6 +698,7 @@ namespace BTCPayServer.Controllers
|
|||||||
if (model == null)
|
if (model == null)
|
||||||
{
|
{
|
||||||
// see if the invoice actually exists and is in a state for which we do not display the checkout
|
// see if the invoice actually exists and is in a state for which we do not display the checkout
|
||||||
|
// TODO: Can happen if the invoice has lazy activation which failed for all payment methods. We should display error instead...
|
||||||
var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
|
var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
|
||||||
var store = invoice != null ? await _StoreRepository.GetStoreByInvoiceId(invoice.Id) : null;
|
var store = invoice != null ? await _StoreRepository.GetStoreByInvoiceId(invoice.Id) : null;
|
||||||
var receipt = invoice != null && store != null ? InvoiceDataBase.ReceiptOptions.Merge(store.GetStoreBlob().ReceiptOptions, invoice.ReceiptOptions) : null;
|
var receipt = invoice != null && store != null ? InvoiceDataBase.ReceiptOptions.Merge(store.GetStoreBlob().ReceiptOptions, invoice.ReceiptOptions) : null;
|
||||||
@@ -713,8 +714,9 @@ namespace BTCPayServer.Controllers
|
|||||||
return View(model);
|
return View(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CheckoutModel?> GetCheckoutModel(string invoiceId, PaymentMethodId? paymentMethodId, string? lang)
|
private async Task<CheckoutModel?> GetCheckoutModel(string invoiceId, PaymentMethodId? paymentMethodId, string? lang, HashSet<PaymentMethodId>? excludedPaymentMethodIds = null)
|
||||||
{
|
{
|
||||||
|
var originalPaymentMethodId = paymentMethodId;
|
||||||
var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
|
var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
|
||||||
if (invoice == null)
|
if (invoice == null)
|
||||||
return null;
|
return null;
|
||||||
@@ -722,11 +724,13 @@ namespace BTCPayServer.Controllers
|
|||||||
var store = await _StoreRepository.FindStore(invoice.StoreId);
|
var store = await _StoreRepository.FindStore(invoice.StoreId);
|
||||||
if (store == null)
|
if (store == null)
|
||||||
return null;
|
return null;
|
||||||
|
excludedPaymentMethodIds ??= new HashSet<PaymentMethodId>();
|
||||||
bool isDefaultPaymentId = false;
|
bool isDefaultPaymentId = false;
|
||||||
var storeBlob = store.GetStoreBlob();
|
var storeBlob = store.GetStoreBlob();
|
||||||
|
|
||||||
var displayedPaymentMethods = invoice.GetPaymentPrompts().Select(p => p.PaymentMethodId).ToHashSet();
|
var displayedPaymentMethods = invoice.GetPaymentPrompts()
|
||||||
|
.Where(p => !excludedPaymentMethodIds.Contains(p.PaymentMethodId))
|
||||||
|
.Select(p => p.PaymentMethodId).ToHashSet();
|
||||||
|
|
||||||
|
|
||||||
var btcId = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
|
var btcId = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
|
||||||
@@ -822,7 +826,14 @@ namespace BTCPayServer.Controllers
|
|||||||
if (prompt is null)
|
if (prompt is null)
|
||||||
return null;
|
return null;
|
||||||
if (activated)
|
if (activated)
|
||||||
return await GetCheckoutModel(invoiceId, paymentMethodId, lang);
|
return await GetCheckoutModel(invoiceId, paymentMethodId, lang, excludedPaymentMethodIds);
|
||||||
|
|
||||||
|
if (!prompt.Activated)
|
||||||
|
{
|
||||||
|
// It failed to activate. Let's try to exclude it and retry
|
||||||
|
excludedPaymentMethodIds.Add(prompt.PaymentMethodId);
|
||||||
|
return await GetCheckoutModel(invoiceId, originalPaymentMethodId, lang, excludedPaymentMethodIds);
|
||||||
|
}
|
||||||
|
|
||||||
var accounting = prompt.Calculate();
|
var accounting = prompt.Calculate();
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
{
|
{
|
||||||
if (context is not { Handler: BitcoinLikePaymentHandler handler })
|
if (context is not { Handler: BitcoinLikePaymentHandler handler })
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var prompt = context.Prompt;
|
var prompt = context.Prompt;
|
||||||
var details = handler.ParsePaymentPromptDetails(prompt.Details);
|
var details = handler.ParsePaymentPromptDetails(prompt.Details);
|
||||||
context.Model.CheckoutBodyComponentName = CheckoutBodyComponentName;
|
context.Model.CheckoutBodyComponentName = CheckoutBodyComponentName;
|
||||||
@@ -59,7 +60,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
var bip21Case = _Network.SupportLightning && context.StoreBlob.OnChainWithLnInvoiceFallback;
|
var bip21Case = _Network.SupportLightning && context.StoreBlob.OnChainWithLnInvoiceFallback;
|
||||||
var amountInSats = bip21Case && context.StoreBlob.LightningAmountInSatoshi && context.Model.PaymentMethodCurrency == "BTC";
|
var amountInSats = bip21Case && context.StoreBlob.LightningAmountInSatoshi && context.Model.PaymentMethodCurrency == "BTC";
|
||||||
string? lightningFallback = null;
|
string? lightningFallback = null;
|
||||||
if (context.Model.Activated && bip21Case)
|
if (bip21Case)
|
||||||
{
|
{
|
||||||
var lnPmi = PaymentTypes.LN.GetPaymentMethodId(handler.Network.CryptoCode);
|
var lnPmi = PaymentTypes.LN.GetPaymentMethodId(handler.Network.CryptoCode);
|
||||||
var lnPrompt = context.InvoiceEntity.GetPaymentPrompt(lnPmi);
|
var lnPrompt = context.InvoiceEntity.GetPaymentPrompt(lnPmi);
|
||||||
@@ -85,8 +86,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.Model.Activated)
|
|
||||||
{
|
|
||||||
var paymentData = context.InvoiceEntity.GetAllBitcoinPaymentData(handler, true)?.MinBy(o => o.ConfirmationCount);
|
var paymentData = context.InvoiceEntity.GetAllBitcoinPaymentData(handler, true)?.MinBy(o => o.ConfirmationCount);
|
||||||
if (paymentData is not null)
|
if (paymentData is not null)
|
||||||
{
|
{
|
||||||
@@ -126,13 +126,9 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
StringComparison.OrdinalIgnoreCase);
|
StringComparison.OrdinalIgnoreCase);
|
||||||
// model.InvoiceBitcoinUrlQR: bitcoin:BCRT1QXP2QA5DHN...?amount=0.00044007&lightning=LNBCRT4400...
|
// model.InvoiceBitcoinUrlQR: bitcoin:BCRT1QXP2QA5DHN...?amount=0.00044007&lightning=LNBCRT4400...
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Model.InvoiceBitcoinUrl = context.Model.InvoiceBitcoinUrlQR = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.Model.Activated && amountInSats)
|
|
||||||
|
if (amountInSats)
|
||||||
{
|
{
|
||||||
PreparePaymentModelForAmountInSats(context.Model, context.Prompt.Rate, _displayFormatter);
|
PreparePaymentModelForAmountInSats(context.Model, context.Prompt.Rate, _displayFormatter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments
|
|||||||
if (context is not { Handler: MoneroLikePaymentMethodHandler handler })
|
if (context is not { Handler: MoneroLikePaymentMethodHandler handler })
|
||||||
return;
|
return;
|
||||||
context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName;
|
context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName;
|
||||||
if (context.Model.Activated)
|
|
||||||
{
|
|
||||||
var details = context.InvoiceEntity.GetPayments(true)
|
var details = context.InvoiceEntity.GetPayments(true)
|
||||||
.Select(p => p.GetDetails<MoneroLikePaymentData>(handler))
|
.Select(p => p.GetDetails<MoneroLikePaymentData>(handler))
|
||||||
.Where(p => p is not null)
|
.Where(p => p is not null)
|
||||||
@@ -52,11 +50,5 @@ namespace BTCPayServer.Services.Altcoins.Monero.Payments
|
|||||||
context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper);
|
context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper);
|
||||||
context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrl;
|
context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrl;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Model.InvoiceBitcoinUrl = "";
|
|
||||||
context.Model.InvoiceBitcoinUrlQR = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Payments
|
|||||||
if (context is not { Handler: ZcashLikePaymentMethodHandler handler })
|
if (context is not { Handler: ZcashLikePaymentMethodHandler handler })
|
||||||
return;
|
return;
|
||||||
context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName;
|
context.Model.CheckoutBodyComponentName = BitcoinCheckoutModelExtension.CheckoutBodyComponentName;
|
||||||
if (context.Model.Activated)
|
|
||||||
{
|
|
||||||
var details = context.InvoiceEntity.GetPayments(true)
|
var details = context.InvoiceEntity.GetPayments(true)
|
||||||
.Select(p => p.GetDetails<ZcashLikePaymentData>(handler))
|
.Select(p => p.GetDetails<ZcashLikePaymentData>(handler))
|
||||||
.Where(p => p is not null)
|
.Where(p => p is not null)
|
||||||
@@ -51,11 +49,5 @@ namespace BTCPayServer.Services.Altcoins.Zcash.Payments
|
|||||||
context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper);
|
context.Model.InvoiceBitcoinUrl = paymentLinkExtension.GetPaymentLink(context.Prompt, context.UrlHelper);
|
||||||
context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrl;
|
context.Model.InvoiceBitcoinUrlQR = context.Model.InvoiceBitcoinUrl;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
context.Model.InvoiceBitcoinUrl = "";
|
|
||||||
context.Model.InvoiceBitcoinUrlQR = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user