Refactoring: Invoice UI Controller cleanups

Simple and IDE proposed changes and cleanups I came across while working on #3092.
This commit is contained in:
Dennis Reimann
2021-11-15 09:35:03 +01:00
committed by Andrew Camilleri
parent 4cd18a1b28
commit 6813a6ea63

View File

@@ -15,7 +15,6 @@ using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Filters; using BTCPayServer.Filters;
using BTCPayServer.HostedServices; using BTCPayServer.HostedServices;
using BTCPayServer.Logging;
using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Models.InvoicingModels;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Rating; using BTCPayServer.Rating;
@@ -26,9 +25,7 @@ using BTCPayServer.Services.Rates;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NBitcoin; using NBitcoin;
using NBitpayClient; using NBitpayClient;
using NBXplorer; using NBXplorer;
@@ -40,9 +37,7 @@ namespace BTCPayServer.Controllers
{ {
public partial class InvoiceController public partial class InvoiceController
{ {
[HttpGet("invoices/{invoiceId}/deliveries/{deliveryId}/request")]
[HttpGet]
[Route("invoices/{invoiceId}/deliveries/{deliveryId}/request")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> WebhookDelivery(string invoiceId, string deliveryId) public async Task<IActionResult> WebhookDelivery(string invoiceId, string deliveryId)
{ {
@@ -56,10 +51,10 @@ namespace BTCPayServer.Controllers
var delivery = await _InvoiceRepository.GetWebhookDelivery(invoiceId, deliveryId); var delivery = await _InvoiceRepository.GetWebhookDelivery(invoiceId, deliveryId);
if (delivery is null) if (delivery is null)
return NotFound(); return NotFound();
return this.File(delivery.GetBlob().Request, "application/json"); return File(delivery.GetBlob().Request, "application/json");
} }
[HttpPost]
[Route("invoices/{invoiceId}/deliveries/{deliveryId}/redeliver")] [HttpPost("invoices/{invoiceId}/deliveries/{deliveryId}/redeliver")]
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> RedeliverWebhook(string storeId, string invoiceId, string deliveryId) public async Task<IActionResult> RedeliverWebhook(string storeId, string invoiceId, string deliveryId)
{ {
@@ -85,8 +80,7 @@ namespace BTCPayServer.Controllers
}); });
} }
[HttpGet] [HttpGet("invoices/{invoiceId}")]
[Route("invoices/{invoiceId}")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> Invoice(string invoiceId) public async Task<IActionResult> Invoice(string invoiceId)
{ {
@@ -162,13 +156,12 @@ namespace BTCPayServer.Controllers
invoiceState.Status == InvoiceStatusLegacy.Invalid; invoiceState.Status == InvoiceStatusLegacy.Invalid;
} }
[HttpGet] [HttpGet("invoices/{invoiceId}/refund")]
[Route("invoices/{invoiceId}/refund")]
[AllowAnonymous] [AllowAnonymous]
public async Task<IActionResult> Refund([FromServices]IEnumerable<IPayoutHandler> payoutHandlers, string invoiceId, CancellationToken cancellationToken) public async Task<IActionResult> Refund([FromServices]IEnumerable<IPayoutHandler> payoutHandlers, string invoiceId, CancellationToken cancellationToken)
{ {
await using var ctx = _dbContextFactory.CreateContext(); await using var ctx = _dbContextFactory.CreateContext();
ctx.ChangeTracker.QueryTrackingBehavior = Microsoft.EntityFrameworkCore.QueryTrackingBehavior.NoTracking; ctx.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var invoice = await ctx.Invoices.Include(i => i.Payments) var invoice = await ctx.Invoices.Include(i => i.Payments)
.Include(i => i.CurrentRefund) .Include(i => i.CurrentRefund)
.Include(i => i.StoreData) .Include(i => i.StoreData)
@@ -189,42 +182,40 @@ namespace BTCPayServer.Controllers
"PullPayment", "PullPayment",
new { pullPaymentId = ppId }); new { pullPaymentId = ppId });
} }
else
var paymentMethods = invoice.GetBlob(_NetworkProvider).GetPaymentMethods();
var pmis = paymentMethods.Select(method => method.GetId()).ToList();
var options = (await payoutHandlers.GetSupportedPaymentMethods(invoice.StoreData)).Where(id => pmis.Contains(id)).ToList();
if (!options.Any())
{ {
var paymentMethods = invoice.GetBlob(_NetworkProvider).GetPaymentMethods(); TempData.SetStatusMessageModel(new StatusMessageModel()
var pmis = paymentMethods.Select(method => method.GetId()).ToList();
var options = (await payoutHandlers.GetSupportedPaymentMethods(invoice.StoreData)).Where(id => pmis.Contains(id)).ToList();
if (!options.Any())
{ {
TempData.SetStatusMessageModel(new StatusMessageModel() Severity = StatusMessageModel.StatusSeverity.Error,
{ Message = "There were no payment methods available to provide refunds with for this invoice."
Severity = StatusMessageModel.StatusSeverity.Error, });
Message = "There were no payment methods available to provide refunds with for this invoice." return RedirectToAction(nameof(Invoice), new { invoiceId });
});
return RedirectToAction(nameof(Invoice), new { invoiceId });
}
var defaultRefund = invoice.Payments
.Select(p => p.GetBlob(_NetworkProvider))
.Select(p => p?.GetPaymentMethodId())
.FirstOrDefault(p => p != null && options.Contains(p));
// TODO: What if no option?
var refund = new RefundModel();
refund.Title = "Select a payment method";
refund.AvailablePaymentMethods =
new SelectList(options.Select(id => new SelectListItem(id.ToPrettyString(), id.ToString())), "Value", "Text");
refund.SelectedPaymentMethod = defaultRefund?.ToString() ?? options.First().ToString();
// Nothing to select, skip to next
if (refund.AvailablePaymentMethods.Count() == 1)
{
return await Refund(invoiceId, refund, cancellationToken);
}
return View(refund);
} }
var defaultRefund = invoice.Payments
.Select(p => p.GetBlob(_NetworkProvider))
.Select(p => p?.GetPaymentMethodId())
.FirstOrDefault(p => p != null && options.Contains(p));
// TODO: What if no option?
var refund = new RefundModel();
refund.Title = "Select a payment method";
refund.AvailablePaymentMethods =
new SelectList(options.Select(id => new SelectListItem(id.ToPrettyString(), id.ToString())), "Value", "Text");
refund.SelectedPaymentMethod = defaultRefund?.ToString() ?? options.First().ToString();
// Nothing to select, skip to next
if (refund.AvailablePaymentMethods.Count() == 1)
{
return await Refund(invoiceId, refund, cancellationToken);
}
return View(refund);
} }
[HttpPost]
[Route("invoices/{invoiceId}/refund")] [HttpPost("invoices/{invoiceId}/refund")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
public async Task<IActionResult> Refund(string invoiceId, RefundModel model, CancellationToken cancellationToken) public async Task<IActionResult> Refund(string invoiceId, RefundModel model, CancellationToken cancellationToken)
{ {
@@ -256,29 +247,34 @@ namespace BTCPayServer.Controllers
{ {
paymentMethod = pms[new PaymentMethodId(paymentMethodId.CryptoCode, PaymentTypes.LNURLPay)]; paymentMethod = pms[new PaymentMethodId(paymentMethodId.CryptoCode, PaymentTypes.LNURLPay)];
} }
var cryptoPaid = paymentMethod.Calculate().Paid.ToDecimal(MoneyUnit.BTC);
var paidCurrency = if (paymentMethod != null)
Math.Round(cryptoPaid * paymentMethod.Rate,
cdCurrency.Divisibility);
model.CryptoAmountThen = cryptoPaid.RoundToSignificant(paymentMethodDivisibility);
model.RateThenText =
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountThen, paymentMethodId.CryptoCode);
rules = store.GetStoreBlob().GetRateRules(_NetworkProvider);
rateResult = await _RateProvider.FetchRate(
new Rating.CurrencyPair(paymentMethodId.CryptoCode, invoice.Currency), rules,
cancellationToken);
//TODO: What if fetching rate failed?
if (rateResult.BidAsk is null)
{ {
ModelState.AddModelError(nameof(model.SelectedRefundOption), var cryptoPaid = paymentMethod.Calculate().Paid.ToDecimal(MoneyUnit.BTC);
$"Impossible to fetch rate: {rateResult.EvaluatedRule}"); var paidCurrency =
return View(model); Math.Round(cryptoPaid * paymentMethod.Rate,
cdCurrency.Divisibility);
model.CryptoAmountThen = cryptoPaid.RoundToSignificant(paymentMethodDivisibility);
model.RateThenText =
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountThen, paymentMethodId.CryptoCode);
rules = store.GetStoreBlob().GetRateRules(_NetworkProvider);
rateResult = await _RateProvider.FetchRate(
new Rating.CurrencyPair(paymentMethodId.CryptoCode, invoice.Currency), rules,
cancellationToken);
//TODO: What if fetching rate failed?
if (rateResult.BidAsk is null)
{
ModelState.AddModelError(nameof(model.SelectedRefundOption),
$"Impossible to fetch rate: {rateResult.EvaluatedRule}");
return View(model);
}
model.CryptoAmountNow = Math.Round(paidCurrency / rateResult.BidAsk.Bid, paymentMethodDivisibility);
model.CurrentRateText =
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountNow, paymentMethodId.CryptoCode);
model.FiatAmount = paidCurrency;
} }
model.CryptoAmountNow = Math.Round(paidCurrency / rateResult.BidAsk.Bid, paymentMethodDivisibility);
model.CurrentRateText =
_CurrencyNameTable.DisplayFormatCurrency(model.CryptoAmountNow, paymentMethodId.CryptoCode);
model.FiatAmount = paidCurrency;
model.FiatText = _CurrencyNameTable.DisplayFormatCurrency(model.FiatAmount, invoice.Currency); model.FiatText = _CurrencyNameTable.DisplayFormatCurrency(model.FiatAmount, invoice.Currency);
return View(model); return View(model);
case RefundSteps.SelectRate: case RefundSteps.SelectRate:
@@ -330,7 +326,7 @@ namespace BTCPayServer.Controllers
} }
rules = store.GetStoreBlob().GetRateRules(_NetworkProvider); rules = store.GetStoreBlob().GetRateRules(_NetworkProvider);
rateResult = await _RateProvider.FetchRate( rateResult = await _RateProvider.FetchRate(
new Rating.CurrencyPair(paymentMethodId.CryptoCode, model.CustomCurrency), rules, new CurrencyPair(paymentMethodId.CryptoCode, model.CustomCurrency), rules,
cancellationToken); cancellationToken);
//TODO: What if fetching rate failed? //TODO: What if fetching rate failed?
if (rateResult.BidAsk is null) if (rateResult.BidAsk is null)
@@ -340,7 +336,7 @@ namespace BTCPayServer.Controllers
return View(model); return View(model);
} }
createPullPayment = new HostedServices.CreatePullPayment(); createPullPayment = new CreatePullPayment();
createPullPayment.Name = $"Refund {invoice.Id}"; createPullPayment.Name = $"Refund {invoice.Id}";
createPullPayment.PaymentMethodIds = new[] { paymentMethodId }; createPullPayment.PaymentMethodIds = new[] { paymentMethodId };
createPullPayment.StoreId = invoice.StoreId; createPullPayment.StoreId = invoice.StoreId;
@@ -352,12 +348,12 @@ namespace BTCPayServer.Controllers
} }
var ppId = await _paymentHostedService.CreatePullPayment(createPullPayment); var ppId = await _paymentHostedService.CreatePullPayment(createPullPayment);
this.TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Html = "Refund successfully created!<br />Share the link to this page with a customer.<br />The customer needs to enter their address and claim the refund.<br />Once a customer claims the refund, you will get a notification and would need to approve and initiate it from your Store > Payouts.", Html = "Refund successfully created!<br />Share the link to this page with a customer.<br />The customer needs to enter their address and claim the refund.<br />Once a customer claims the refund, you will get a notification and would need to approve and initiate it from your Store > Payouts.",
Severity = StatusMessageModel.StatusSeverity.Success Severity = StatusMessageModel.StatusSeverity.Success
}); });
(await ctx.Invoices.FindAsync(new[] { invoice.Id }, cancellationToken: cancellationToken)).CurrentRefundId = ppId; (await ctx.Invoices.FindAsync(new[] { invoice.Id }, cancellationToken)).CurrentRefundId = ppId;
ctx.Refunds.Add(new RefundData() ctx.Refunds.Add(new RefundData()
{ {
InvoiceDataId = invoice.Id, InvoiceDataId = invoice.Id,
@@ -442,10 +438,9 @@ namespace BTCPayServer.Controllers
return RedirectToAction(nameof(ListInvoices)); return RedirectToAction(nameof(ListInvoices));
} }
[HttpGet] [HttpGet("i/{invoiceId}")]
[Route("i/{invoiceId}")] [HttpGet("i/{invoiceId}/{paymentMethodId}")]
[Route("i/{invoiceId}/{paymentMethodId}")] [HttpGet("invoice")]
[Route("invoice")]
[AcceptMediaTypeConstraint("application/bitcoin-paymentrequest", false)] [AcceptMediaTypeConstraint("application/bitcoin-paymentrequest", false)]
[XFrameOptionsAttribute(null)] [XFrameOptionsAttribute(null)]
[ReferrerPolicyAttribute("origin")] [ReferrerPolicyAttribute("origin")]
@@ -466,8 +461,7 @@ namespace BTCPayServer.Controllers
return View(nameof(Checkout), model); return View(nameof(Checkout), model);
} }
[HttpGet] [HttpGet("invoice-noscript")]
[Route("invoice-noscript")]
public async Task<IActionResult> CheckoutNoScript(string? invoiceId, string? id = null, string? paymentMethodId = null, [FromQuery] string? lang = null) public async Task<IActionResult> CheckoutNoScript(string? invoiceId, string? id = null, string? paymentMethodId = null, [FromQuery] string? lang = null)
{ {
//Keep compatibility with Bitpay //Keep compatibility with Bitpay
@@ -491,7 +485,7 @@ namespace BTCPayServer.Controllers
bool isDefaultPaymentId = false; bool isDefaultPaymentId = false;
if (paymentMethodId is null) if (paymentMethodId is null)
{ {
var enabledPaymentIds = store.GetEnabledPaymentIds(_NetworkProvider) ?? Array.Empty<PaymentMethodId>(); var enabledPaymentIds = store.GetEnabledPaymentIds(_NetworkProvider);
PaymentMethodId? invoicePaymentId = invoice.GetDefaultPaymentMethod(); PaymentMethodId? invoicePaymentId = invoice.GetDefaultPaymentMethod();
PaymentMethodId? storePaymentId = store.GetDefaultPaymentId(); PaymentMethodId? storePaymentId = store.GetDefaultPaymentId();
if (invoicePaymentId is PaymentMethodId) if (invoicePaymentId is PaymentMethodId)
@@ -570,11 +564,11 @@ namespace BTCPayServer.Controllers
} }
lang ??= storeBlob.DefaultLang; lang ??= storeBlob.DefaultLang;
var model = new PaymentModel() var model = new PaymentModel
{ {
Activated = paymentMethodDetails.Activated, Activated = paymentMethodDetails.Activated,
CryptoCode = network.CryptoCode, CryptoCode = network.CryptoCode,
RootPath = this.Request.PathBase.Value.WithTrailingSlash(), RootPath = Request.PathBase.Value.WithTrailingSlash(),
OrderId = invoice.Metadata.OrderId, OrderId = invoice.Metadata.OrderId,
InvoiceId = invoice.Id, InvoiceId = invoice.Id,
DefaultLang = lang ?? invoice.DefaultLanguage ?? storeBlob.DefaultLang ?? "en", DefaultLang = lang ?? invoice.DefaultLanguage ?? storeBlob.DefaultLang ?? "en",
@@ -630,7 +624,7 @@ namespace BTCPayServer.Controllers
Link = Url.Action(nameof(Checkout), Link = Url.Action(nameof(Checkout),
new new
{ {
invoiceId = invoiceId, invoiceId,
paymentMethodId = kv.GetId().ToString() paymentMethodId = kv.GetId().ToString()
}) })
}; };
@@ -660,12 +654,11 @@ namespace BTCPayServer.Controllers
return _CurrencyNameTable.DisplayFormatCurrency(paymentMethod.Rate, currency); return _CurrencyNameTable.DisplayFormatCurrency(paymentMethod.Rate, currency);
} }
[HttpGet] [HttpGet("i/{invoiceId}/status")]
[Route("i/{invoiceId}/status")] [HttpGet("i/{invoiceId}/{implicitPaymentMethodId}/status")]
[Route("i/{invoiceId}/{implicitPaymentMethodId}/status")] [HttpGet("invoice/{invoiceId}/status")]
[Route("invoice/{invoiceId}/status")] [HttpGet("invoice/{invoiceId}/{implicitPaymentMethodId}/status")]
[Route("invoice/{invoiceId}/{implicitPaymentMethodId}/status")] [HttpGet("invoice/status")]
[Route("invoice/status")]
public async Task<IActionResult> GetStatus(string invoiceId, string? paymentMethodId = null, string? implicitPaymentMethodId = null, [FromQuery] string? lang = null) public async Task<IActionResult> GetStatus(string invoiceId, string? paymentMethodId = null, string? implicitPaymentMethodId = null, [FromQuery] string? lang = null)
{ {
if (string.IsNullOrEmpty(paymentMethodId)) if (string.IsNullOrEmpty(paymentMethodId))
@@ -676,12 +669,11 @@ namespace BTCPayServer.Controllers
return Json(model); return Json(model);
} }
[HttpGet] [HttpGet("i/{invoiceId}/status/ws")]
[Route("i/{invoiceId}/status/ws")] [HttpGet("i/{invoiceId}/{paymentMethodId}/status/ws")]
[Route("i/{invoiceId}/{paymentMethodId}/status/ws")] [HttpGet("invoice/{invoiceId}/status/ws")]
[Route("invoice/{invoiceId}/status/ws")] [HttpGet("invoice/{invoiceId}/{paymentMethodId}/status")]
[Route("invoice/{invoiceId}/{paymentMethodId}/status")] [HttpGet("invoice/status/ws")]
[Route("invoice/status/ws")]
public async Task<IActionResult> GetStatusWebSocket(string invoiceId, CancellationToken cancellationToken) public async Task<IActionResult> GetStatusWebSocket(string invoiceId, CancellationToken cancellationToken)
{ {
if (!HttpContext.WebSockets.IsWebSocketRequest) if (!HttpContext.WebSockets.IsWebSocketRequest)
@@ -698,7 +690,7 @@ namespace BTCPayServer.Controllers
leases.Add(_EventAggregator.SubscribeAsync<Events.InvoiceEvent>(async o => await NotifySocket(webSocket, o.Invoice.Id, invoiceId))); leases.Add(_EventAggregator.SubscribeAsync<Events.InvoiceEvent>(async o => await NotifySocket(webSocket, o.Invoice.Id, invoiceId)));
while (true) while (true)
{ {
var message = await webSocket.ReceiveAndPingAsync(DummyBuffer, default(CancellationToken)); var message = await webSocket.ReceiveAndPingAsync(DummyBuffer);
if (message.MessageType == WebSocketMessageType.Close) if (message.MessageType == WebSocketMessageType.Close)
break; break;
} }
@@ -728,9 +720,8 @@ namespace BTCPayServer.Controllers
catch { try { webSocket.Dispose(); } catch { } } catch { try { webSocket.Dispose(); } catch { } }
} }
[HttpPost] [HttpPost("i/{invoiceId}/UpdateCustomer")]
[Route("i/{invoiceId}/UpdateCustomer")] [HttpPost("invoice/UpdateCustomer")]
[Route("invoice/UpdateCustomer")]
public async Task<IActionResult> UpdateCustomer(string invoiceId, [FromBody] UpdateCustomerModel data) public async Task<IActionResult> UpdateCustomer(string invoiceId, [FromBody] UpdateCustomerModel data)
{ {
if (!ModelState.IsValid) if (!ModelState.IsValid)
@@ -741,8 +732,7 @@ namespace BTCPayServer.Controllers
return Ok("{}"); return Ok("{}");
} }
[HttpGet] [HttpGet("invoices")]
[Route("invoices")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[BitpayAPIConstraint(false)] [BitpayAPIConstraint(false)]
public async Task<IActionResult> ListInvoices(InvoicesModel? model = null) public async Task<IActionResult> ListInvoices(InvoicesModel? model = null)
@@ -823,8 +813,7 @@ namespace BTCPayServer.Controllers
Response.Headers.Add("X-Content-Type-Options", "nosniff"); Response.Headers.Add("X-Content-Type-Options", "nosniff");
return Content(res, "application/" + format); return Content(res, "application/" + format);
} }
private SelectList GetPaymentMethodsSelectList() private SelectList GetPaymentMethodsSelectList()
{ {
return new SelectList(_paymentMethodHandlerDictionary.Distinct().SelectMany(handler => return new SelectList(_paymentMethodHandlerDictionary.Distinct().SelectMany(handler =>
@@ -834,8 +823,7 @@ namespace BTCPayServer.Controllers
nameof(SelectListItem.Text)); nameof(SelectListItem.Text));
} }
[HttpGet] [HttpGet("invoices/create")]
[Route("invoices/create")]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[BitpayAPIConstraint(false)] [BitpayAPIConstraint(false)]
public async Task<IActionResult> CreateInvoice(InvoicesModel? model = null) public async Task<IActionResult> CreateInvoice(InvoicesModel? model = null)
@@ -852,11 +840,16 @@ namespace BTCPayServer.Controllers
return RedirectToAction(nameof(UserStoresController.ListStores), "UserStores"); return RedirectToAction(nameof(UserStoresController.ListStores), "UserStores");
} }
return View(new CreateInvoiceModel() { Stores = stores, AvailablePaymentMethods = GetPaymentMethodsSelectList() }); var vm = new CreateInvoiceModel
{
Stores = stores,
AvailablePaymentMethods = GetPaymentMethodsSelectList()
};
return View(vm);
} }
[HttpPost] [HttpPost("invoices/create")]
[Route("invoices/create")]
[Authorize(Policy = Policies.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Cookie)] [Authorize(Policy = Policies.CanCreateInvoice, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
[BitpayAPIConstraint(false)] [BitpayAPIConstraint(false)]
public async Task<IActionResult> CreateInvoice(CreateInvoiceModel model, CancellationToken cancellationToken) public async Task<IActionResult> CreateInvoice(CreateInvoiceModel model, CancellationToken cancellationToken)
@@ -912,7 +905,7 @@ namespace BTCPayServer.Controllers
} }
catch (BitpayHttpException ex) catch (BitpayHttpException ex)
{ {
this.TempData.SetStatusMessageModel(new StatusMessageModel() TempData.SetStatusMessageModel(new StatusMessageModel()
{ {
Severity = StatusMessageModel.StatusSeverity.Error, Severity = StatusMessageModel.StatusSeverity.Error,
Message = ex.Message Message = ex.Message