btcpayserver/BTCPayServer/Controllers/UIPaymentRequestController.cs

381 lines
15 KiB
C#
Raw Normal View History

2019-01-14 22:43:29 +01:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
2019-01-14 22:43:29 +01:00
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Client;
2020-07-24 09:40:37 +02:00
using BTCPayServer.Client.Models;
2019-01-14 22:43:29 +01:00
using BTCPayServer.Data;
using BTCPayServer.Filters;
Form Builder (#4137) * wip * Cleanups * UI updates * Update UIFormsController.cs * Make predefined forms usable statically * Add support for pos app + forms * pay request form rough support * invoice form through receipt page * Display form name in inherit from store setting * Do not request additional forms on invoice from pay request * fix up code * move checkoutform id in checkout appearance outside of checkotu v2 toggle * general fixes for form system * fix pav bug * UI updates * Fix warnings in Form builder (#4331) * Fix build warnings about string? Enable nullable on UIFormsController.cs Fixes CS8632 The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. * Clean up lack of space in injected services in Submit() of UIFormsController.cs * Remove unused variables (CS0219) and assignment of nullable value to nullable type (CS8600) * Cleanup double semicolons while we're at tit * Fix: If reverse proxy wasn't well configured, and error message should have been displayed (#4322) * fix monero issue * Server Settings: Update Policies page (#4326) Handles the multiple submit buttons on that page and closes #4319. Contains some UI unifications with other pages and also shows the block explorers without needing to toggle the section via JS. * Change confirmed to settled. (#4328) * POS: Fix null pointer Introduced in #4307, the referenced object needs to be `itemChoice` instead of `choice`. * Add documentation link to plugins (#4329) * Add documentation link to plugins * Minor UI updates Co-authored-by: Dennis Reimann <mail@dennisreimann.de> * Fix flaky test (#4330) * Fix flaky test * Update BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs Co-authored-by: d11n <mail@dennisreimann.de> Co-authored-by: d11n <mail@dennisreimann.de> * Remove invoice and store level form * add form test * fix migration for forms * fix * make pay request form submission redirect to invoice * Refactor FormQuery to only be able to query single store and single form * Put the Authorize at controller level on UIForms * Fix warnings * Fix ef request * Fix query to forms, ensure no permission bypass * Fix modify * Remove storeId from step form * Remove useless storeId parameter * Hide custom form feature in UI * Minor cleanups * Remove custom form options from select for now * More minor syntax cleanups * Update test * Add index - needs migration * Refactoring: Use PostRedirect instead of TempData for data transfer * Remove untested and unfinished code * formResponse should be a JObject, not a string * Fix case for Form type Co-authored-by: Dennis Reimann <mail@dennisreimann.de> Co-authored-by: JesterHodl <103882255+jesterhodl@users.noreply.github.com> Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com> Co-authored-by: Andreas Tasch <andy.tasch@gmail.com>
2022-11-25 02:42:55 +01:00
using BTCPayServer.Models;
2019-01-14 22:43:29 +01:00
using BTCPayServer.Models.PaymentRequestViewModels;
using BTCPayServer.PaymentRequest;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.PaymentRequests;
using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Stores;
using Microsoft.AspNetCore.Authorization;
Form Builder (#4137) * wip * Cleanups * UI updates * Update UIFormsController.cs * Make predefined forms usable statically * Add support for pos app + forms * pay request form rough support * invoice form through receipt page * Display form name in inherit from store setting * Do not request additional forms on invoice from pay request * fix up code * move checkoutform id in checkout appearance outside of checkotu v2 toggle * general fixes for form system * fix pav bug * UI updates * Fix warnings in Form builder (#4331) * Fix build warnings about string? Enable nullable on UIFormsController.cs Fixes CS8632 The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. * Clean up lack of space in injected services in Submit() of UIFormsController.cs * Remove unused variables (CS0219) and assignment of nullable value to nullable type (CS8600) * Cleanup double semicolons while we're at tit * Fix: If reverse proxy wasn't well configured, and error message should have been displayed (#4322) * fix monero issue * Server Settings: Update Policies page (#4326) Handles the multiple submit buttons on that page and closes #4319. Contains some UI unifications with other pages and also shows the block explorers without needing to toggle the section via JS. * Change confirmed to settled. (#4328) * POS: Fix null pointer Introduced in #4307, the referenced object needs to be `itemChoice` instead of `choice`. * Add documentation link to plugins (#4329) * Add documentation link to plugins * Minor UI updates Co-authored-by: Dennis Reimann <mail@dennisreimann.de> * Fix flaky test (#4330) * Fix flaky test * Update BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs Co-authored-by: d11n <mail@dennisreimann.de> Co-authored-by: d11n <mail@dennisreimann.de> * Remove invoice and store level form * add form test * fix migration for forms * fix * make pay request form submission redirect to invoice * Refactor FormQuery to only be able to query single store and single form * Put the Authorize at controller level on UIForms * Fix warnings * Fix ef request * Fix query to forms, ensure no permission bypass * Fix modify * Remove storeId from step form * Remove useless storeId parameter * Hide custom form feature in UI * Minor cleanups * Remove custom form options from select for now * More minor syntax cleanups * Update test * Add index - needs migration * Refactoring: Use PostRedirect instead of TempData for data transfer * Remove untested and unfinished code * formResponse should be a JObject, not a string * Fix case for Form type Co-authored-by: Dennis Reimann <mail@dennisreimann.de> Co-authored-by: JesterHodl <103882255+jesterhodl@users.noreply.github.com> Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com> Co-authored-by: Andreas Tasch <andy.tasch@gmail.com>
2022-11-25 02:42:55 +01:00
using Microsoft.AspNetCore.Http.Extensions;
2019-01-14 22:43:29 +01:00
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
Form Builder (#4137) * wip * Cleanups * UI updates * Update UIFormsController.cs * Make predefined forms usable statically * Add support for pos app + forms * pay request form rough support * invoice form through receipt page * Display form name in inherit from store setting * Do not request additional forms on invoice from pay request * fix up code * move checkoutform id in checkout appearance outside of checkotu v2 toggle * general fixes for form system * fix pav bug * UI updates * Fix warnings in Form builder (#4331) * Fix build warnings about string? Enable nullable on UIFormsController.cs Fixes CS8632 The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. * Clean up lack of space in injected services in Submit() of UIFormsController.cs * Remove unused variables (CS0219) and assignment of nullable value to nullable type (CS8600) * Cleanup double semicolons while we're at tit * Fix: If reverse proxy wasn't well configured, and error message should have been displayed (#4322) * fix monero issue * Server Settings: Update Policies page (#4326) Handles the multiple submit buttons on that page and closes #4319. Contains some UI unifications with other pages and also shows the block explorers without needing to toggle the section via JS. * Change confirmed to settled. (#4328) * POS: Fix null pointer Introduced in #4307, the referenced object needs to be `itemChoice` instead of `choice`. * Add documentation link to plugins (#4329) * Add documentation link to plugins * Minor UI updates Co-authored-by: Dennis Reimann <mail@dennisreimann.de> * Fix flaky test (#4330) * Fix flaky test * Update BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs Co-authored-by: d11n <mail@dennisreimann.de> Co-authored-by: d11n <mail@dennisreimann.de> * Remove invoice and store level form * add form test * fix migration for forms * fix * make pay request form submission redirect to invoice * Refactor FormQuery to only be able to query single store and single form * Put the Authorize at controller level on UIForms * Fix warnings * Fix ef request * Fix query to forms, ensure no permission bypass * Fix modify * Remove storeId from step form * Remove useless storeId parameter * Hide custom form feature in UI * Minor cleanups * Remove custom form options from select for now * More minor syntax cleanups * Update test * Add index - needs migration * Refactoring: Use PostRedirect instead of TempData for data transfer * Remove untested and unfinished code * formResponse should be a JObject, not a string * Fix case for Form type Co-authored-by: Dennis Reimann <mail@dennisreimann.de> Co-authored-by: JesterHodl <103882255+jesterhodl@users.noreply.github.com> Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com> Co-authored-by: Andreas Tasch <andy.tasch@gmail.com>
2022-11-25 02:42:55 +01:00
using Newtonsoft.Json.Linq;
2020-07-24 09:40:37 +02:00
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
using StoreData = BTCPayServer.Data.StoreData;
2019-01-14 22:43:29 +01:00
namespace BTCPayServer.Controllers
{
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
2019-01-14 22:43:29 +01:00
[Route("payment-requests")]
2022-01-07 04:32:00 +01:00
public class UIPaymentRequestController : Controller
2019-01-14 22:43:29 +01:00
{
2022-01-07 04:32:00 +01:00
private readonly UIInvoiceController _InvoiceController;
2019-01-14 22:43:29 +01:00
private readonly UserManager<ApplicationUser> _UserManager;
private readonly PaymentRequestRepository _PaymentRequestRepository;
private readonly PaymentRequestService _PaymentRequestService;
private readonly EventAggregator _EventAggregator;
private readonly CurrencyNameTable _Currencies;
private readonly InvoiceRepository _InvoiceRepository;
private readonly StoreRepository _storeRepository;
2019-01-14 22:43:29 +01:00
2022-01-07 04:32:00 +01:00
public UIPaymentRequestController(
UIInvoiceController invoiceController,
2019-01-14 22:43:29 +01:00
UserManager<ApplicationUser> userManager,
PaymentRequestRepository paymentRequestRepository,
PaymentRequestService paymentRequestService,
EventAggregator eventAggregator,
CurrencyNameTable currencies,
StoreRepository storeRepository,
InvoiceRepository invoiceRepository)
2019-01-14 22:43:29 +01:00
{
_InvoiceController = invoiceController;
_UserManager = userManager;
_PaymentRequestRepository = paymentRequestRepository;
_PaymentRequestService = paymentRequestService;
_EventAggregator = eventAggregator;
_Currencies = currencies;
_storeRepository = storeRepository;
_InvoiceRepository = invoiceRepository;
2019-01-14 22:43:29 +01:00
}
[BitpayAPIConstraint(false)]
[HttpGet("/stores/{storeId}/payment-requests")]
public async Task<IActionResult> GetPaymentRequests(string storeId, ListPaymentRequestsViewModel model = null)
2019-01-14 22:43:29 +01:00
{
model = this.ParseListQuery(model ?? new ListPaymentRequestsViewModel());
var store = GetCurrentStore();
var includeArchived = new SearchString(model.SearchTerm).GetFilterBool("includearchived") == true;
var result = await _PaymentRequestRepository.FindPaymentRequests(new PaymentRequestQuery
2019-01-14 22:43:29 +01:00
{
2020-06-28 10:55:27 +02:00
UserId = GetUserId(),
StoreId = store.Id,
Skip = model.Skip,
Count = model.Count,
2020-06-28 10:55:27 +02:00
IncludeArchived = includeArchived
2019-01-14 22:43:29 +01:00
});
model.Items = result.Select(data =>
{
var blob = data.GetBlob();
return new ViewPaymentRequestViewModel(data)
{
AmountFormatted = _Currencies.FormatCurrency(blob.Amount, blob.Currency)
};
}).ToList();
return View(model);
2019-01-14 22:43:29 +01:00
}
[HttpGet("/stores/{storeId}/payment-requests/edit/{payReqId?}")]
public IActionResult EditPaymentRequest(string storeId, string payReqId)
2019-01-14 22:43:29 +01:00
{
var store = GetCurrentStore();
var paymentRequest = GetCurrentPaymentRequest();
if (paymentRequest == null && !string.IsNullOrEmpty(payReqId))
2019-01-14 22:43:29 +01:00
{
return NotFound();
}
var vm = new UpdatePaymentRequestViewModel(paymentRequest)
2019-01-14 22:43:29 +01:00
{
StoreId = store.Id
};
vm.Currency ??= store.GetStoreBlob().DefaultCurrency;
return View(nameof(EditPaymentRequest), vm);
2019-01-14 22:43:29 +01:00
}
[HttpPost("/stores/{storeId}/payment-requests/edit/{payReqId?}")]
public async Task<IActionResult> EditPaymentRequest(string payReqId, UpdatePaymentRequestViewModel viewModel)
2019-01-14 22:43:29 +01:00
{
if (!string.IsNullOrEmpty(viewModel.Currency) &&
2019-01-14 22:43:29 +01:00
_Currencies.GetCurrencyData(viewModel.Currency, false) == null)
ModelState.AddModelError(nameof(viewModel.Currency), "Invalid currency");
if (string.IsNullOrEmpty(viewModel.Currency))
viewModel.Currency = null;
var store = GetCurrentStore();
var paymentRequest = GetCurrentPaymentRequest();
if (paymentRequest == null && !string.IsNullOrEmpty(payReqId))
2019-01-14 22:43:29 +01:00
{
return NotFound();
}
if (paymentRequest?.Archived is true && viewModel.Archived)
2020-05-08 12:33:47 +02:00
{
ModelState.AddModelError(string.Empty, "You cannot edit an archived payment request.");
}
2019-01-14 22:43:29 +01:00
if (!ModelState.IsValid)
{
2020-06-28 10:55:27 +02:00
return View(nameof(EditPaymentRequest), viewModel);
2019-01-14 22:43:29 +01:00
}
var data = paymentRequest ?? new PaymentRequestData();
2019-01-14 22:43:29 +01:00
data.StoreDataId = viewModel.StoreId;
2020-05-08 12:33:47 +02:00
data.Archived = viewModel.Archived;
2021-12-31 08:59:02 +01:00
2019-01-14 22:43:29 +01:00
var blob = data.GetBlob();
blob.Title = viewModel.Title;
blob.Email = viewModel.Email;
blob.Description = viewModel.Description;
2019-01-14 22:43:29 +01:00
blob.Amount = viewModel.Amount;
blob.ExpiryDate = viewModel.ExpiryDate?.ToUniversalTime();
blob.Currency = viewModel.Currency ?? store.GetStoreBlob().DefaultCurrency;
2019-01-14 22:43:29 +01:00
blob.EmbeddedCSS = viewModel.EmbeddedCSS;
blob.CustomCSSLink = viewModel.CustomCSSLink;
blob.AllowCustomPaymentAmounts = viewModel.AllowCustomPaymentAmounts;
Form Builder (#4137) * wip * Cleanups * UI updates * Update UIFormsController.cs * Make predefined forms usable statically * Add support for pos app + forms * pay request form rough support * invoice form through receipt page * Display form name in inherit from store setting * Do not request additional forms on invoice from pay request * fix up code * move checkoutform id in checkout appearance outside of checkotu v2 toggle * general fixes for form system * fix pav bug * UI updates * Fix warnings in Form builder (#4331) * Fix build warnings about string? Enable nullable on UIFormsController.cs Fixes CS8632 The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. * Clean up lack of space in injected services in Submit() of UIFormsController.cs * Remove unused variables (CS0219) and assignment of nullable value to nullable type (CS8600) * Cleanup double semicolons while we're at tit * Fix: If reverse proxy wasn't well configured, and error message should have been displayed (#4322) * fix monero issue * Server Settings: Update Policies page (#4326) Handles the multiple submit buttons on that page and closes #4319. Contains some UI unifications with other pages and also shows the block explorers without needing to toggle the section via JS. * Change confirmed to settled. (#4328) * POS: Fix null pointer Introduced in #4307, the referenced object needs to be `itemChoice` instead of `choice`. * Add documentation link to plugins (#4329) * Add documentation link to plugins * Minor UI updates Co-authored-by: Dennis Reimann <mail@dennisreimann.de> * Fix flaky test (#4330) * Fix flaky test * Update BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs Co-authored-by: d11n <mail@dennisreimann.de> Co-authored-by: d11n <mail@dennisreimann.de> * Remove invoice and store level form * add form test * fix migration for forms * fix * make pay request form submission redirect to invoice * Refactor FormQuery to only be able to query single store and single form * Put the Authorize at controller level on UIForms * Fix warnings * Fix ef request * Fix query to forms, ensure no permission bypass * Fix modify * Remove storeId from step form * Remove useless storeId parameter * Hide custom form feature in UI * Minor cleanups * Remove custom form options from select for now * More minor syntax cleanups * Update test * Add index - needs migration * Refactoring: Use PostRedirect instead of TempData for data transfer * Remove untested and unfinished code * formResponse should be a JObject, not a string * Fix case for Form type Co-authored-by: Dennis Reimann <mail@dennisreimann.de> Co-authored-by: JesterHodl <103882255+jesterhodl@users.noreply.github.com> Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com> Co-authored-by: Andreas Tasch <andy.tasch@gmail.com>
2022-11-25 02:42:55 +01:00
blob.FormId = viewModel.FormId;
2019-01-14 22:43:29 +01:00
data.SetBlob(blob);
var isNewPaymentRequest = string.IsNullOrEmpty(payReqId);
if (isNewPaymentRequest)
{
data.Created = DateTimeOffset.UtcNow;
}
2020-05-08 12:33:47 +02:00
2019-01-14 22:43:29 +01:00
data = await _PaymentRequestRepository.CreateOrUpdatePaymentRequest(data);
_EventAggregator.Publish(new PaymentRequestUpdated { Data = data, PaymentRequestId = data.Id, });
2019-02-22 11:37:45 +01:00
TempData[WellKnownTempData.SuccessMessage] = $"Payment request \"{viewModel.Title}\" {(isNewPaymentRequest ? "created" : "updated")} successfully";
return RedirectToAction(nameof(GetPaymentRequests), new { storeId = store.Id, payReqId = data.Id });
2019-01-14 22:43:29 +01:00
}
[HttpGet("{payReqId}")]
2019-01-14 22:43:29 +01:00
[AllowAnonymous]
public async Task<IActionResult> ViewPaymentRequest(string payReqId)
2019-01-14 22:43:29 +01:00
{
var result = await _PaymentRequestService.GetPaymentRequest(payReqId, GetUserId());
2019-01-14 22:43:29 +01:00
if (result == null)
{
return NotFound();
}
2020-05-08 12:33:47 +02:00
result.HubPath = PaymentRequestHub.GetHubPath(Request);
2019-01-14 22:43:29 +01:00
return View(result);
}
Form Builder (#4137) * wip * Cleanups * UI updates * Update UIFormsController.cs * Make predefined forms usable statically * Add support for pos app + forms * pay request form rough support * invoice form through receipt page * Display form name in inherit from store setting * Do not request additional forms on invoice from pay request * fix up code * move checkoutform id in checkout appearance outside of checkotu v2 toggle * general fixes for form system * fix pav bug * UI updates * Fix warnings in Form builder (#4331) * Fix build warnings about string? Enable nullable on UIFormsController.cs Fixes CS8632 The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. * Clean up lack of space in injected services in Submit() of UIFormsController.cs * Remove unused variables (CS0219) and assignment of nullable value to nullable type (CS8600) * Cleanup double semicolons while we're at tit * Fix: If reverse proxy wasn't well configured, and error message should have been displayed (#4322) * fix monero issue * Server Settings: Update Policies page (#4326) Handles the multiple submit buttons on that page and closes #4319. Contains some UI unifications with other pages and also shows the block explorers without needing to toggle the section via JS. * Change confirmed to settled. (#4328) * POS: Fix null pointer Introduced in #4307, the referenced object needs to be `itemChoice` instead of `choice`. * Add documentation link to plugins (#4329) * Add documentation link to plugins * Minor UI updates Co-authored-by: Dennis Reimann <mail@dennisreimann.de> * Fix flaky test (#4330) * Fix flaky test * Update BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs Co-authored-by: d11n <mail@dennisreimann.de> Co-authored-by: d11n <mail@dennisreimann.de> * Remove invoice and store level form * add form test * fix migration for forms * fix * make pay request form submission redirect to invoice * Refactor FormQuery to only be able to query single store and single form * Put the Authorize at controller level on UIForms * Fix warnings * Fix ef request * Fix query to forms, ensure no permission bypass * Fix modify * Remove storeId from step form * Remove useless storeId parameter * Hide custom form feature in UI * Minor cleanups * Remove custom form options from select for now * More minor syntax cleanups * Update test * Add index - needs migration * Refactoring: Use PostRedirect instead of TempData for data transfer * Remove untested and unfinished code * formResponse should be a JObject, not a string * Fix case for Form type Co-authored-by: Dennis Reimann <mail@dennisreimann.de> Co-authored-by: JesterHodl <103882255+jesterhodl@users.noreply.github.com> Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com> Co-authored-by: Andreas Tasch <andy.tasch@gmail.com>
2022-11-25 02:42:55 +01:00
[HttpGet("{payReqId}/form")]
[HttpPost("{payReqId}/form")]
[AllowAnonymous]
public async Task<IActionResult> ViewPaymentRequestForm(string payReqId, [FromForm] string formId, [FromForm] string formData)
{
var result = await _PaymentRequestRepository.FindPaymentRequest(payReqId, GetUserId());
if (result == null)
{
return NotFound();
}
var prBlob = result.GetBlob();
var prFormId = prBlob.FormId;
switch (prFormId)
{
case null:
case { } when string.IsNullOrEmpty(prFormId):
break;
default:
// POST case: Handle form submit
if (!string.IsNullOrEmpty(formData) && formId == prFormId)
{
prBlob.FormResponse = JObject.Parse(formData);
result.SetBlob(prBlob);
await _PaymentRequestRepository.CreateOrUpdatePaymentRequest(result);
return RedirectToAction("PayPaymentRequest", new { payReqId });
}
// GET or empty form data case: Redirect to form
return View("PostRedirect", new PostRedirectViewModel
{
AspController = "UIForms",
AspAction = "ViewPublicForm",
FormParameters =
{
{ "formId", prFormId },
{ "redirectUrl", Request.GetCurrentUrl() }
}
});
}
return RedirectToAction("ViewPaymentRequest", new { payReqId });
}
[HttpGet("{payReqId}/pay")]
2019-01-14 22:43:29 +01:00
[AllowAnonymous]
public async Task<IActionResult> PayPaymentRequest(string payReqId, bool redirectToInvoice = true,
decimal? amount = null, CancellationToken cancellationToken = default)
2019-01-14 22:43:29 +01:00
{
if (amount.HasValue && amount.Value <= 0)
{
return BadRequest("Please provide an amount greater than 0");
}
2020-05-08 12:33:47 +02:00
var result = await _PaymentRequestService.GetPaymentRequest(payReqId, GetUserId());
2019-01-14 22:43:29 +01:00
if (result == null)
{
return NotFound();
}
2020-05-08 12:33:47 +02:00
if (result.Archived)
{
if (redirectToInvoice)
{
2022-04-22 15:52:57 +02:00
return RedirectToAction("ViewPaymentRequest", new { payReqId });
2020-05-08 12:33:47 +02:00
}
return BadRequest("Payment Request cannot be paid as it has been archived");
}
result.HubPath = PaymentRequestHub.GetHubPath(Request);
2019-01-14 22:43:29 +01:00
if (result.AmountDue <= 0)
{
if (redirectToInvoice)
{
2022-04-22 15:52:57 +02:00
return RedirectToAction("ViewPaymentRequest", new { payReqId });
2019-01-14 22:43:29 +01:00
}
return BadRequest("Payment Request has already been settled.");
}
if (result.ExpiryDate.HasValue && DateTime.UtcNow >= result.ExpiryDate)
2019-01-14 22:43:29 +01:00
{
if (redirectToInvoice)
{
2022-04-22 15:52:57 +02:00
return RedirectToAction("ViewPaymentRequest", new { payReqId });
2019-01-14 22:43:29 +01:00
}
return BadRequest("Payment Request has expired");
}
var currentInvoice = result.Invoices.GetReusableInvoice(amount);
if (currentInvoice != null)
2019-01-14 22:43:29 +01:00
{
if (redirectToInvoice)
{
2022-01-07 04:32:00 +01:00
return RedirectToAction("Checkout", "UIInvoice", new { currentInvoice.Id });
2019-01-14 22:43:29 +01:00
}
return Ok(currentInvoice.Id);
2019-01-14 22:43:29 +01:00
}
2019-01-14 22:43:29 +01:00
try
{
var store = await _storeRepository.FindStore(result.StoreId);
var newInvoice = await _InvoiceController.CreatePaymentRequestInvoice(result, amount, store, Request, cancellationToken);
2019-01-14 22:43:29 +01:00
if (redirectToInvoice)
{
2022-04-22 15:52:57 +02:00
return RedirectToAction("Checkout", "UIInvoice", new { invoiceId = newInvoice.Id });
2019-01-14 22:43:29 +01:00
}
return Ok(newInvoice.Id);
2019-01-14 22:43:29 +01:00
}
catch (BitpayHttpException e)
{
return BadRequest(e.Message);
}
}
[HttpGet("{payReqId}/cancel")]
public async Task<IActionResult> CancelUnpaidPendingInvoice(string payReqId, bool redirect = true)
{
var result = await _PaymentRequestService.GetPaymentRequest(payReqId, GetUserId());
2020-05-08 12:33:47 +02:00
if (result == null)
{
return NotFound();
}
2019-03-05 09:13:34 +01:00
2021-12-31 08:59:02 +01:00
if (!result.AllowCustomPaymentAmounts)
{
return BadRequest("Not allowed to cancel this invoice");
}
var invoices = result.Invoices.Where(requestInvoice =>
requestInvoice.State.Status == InvoiceStatusLegacy.New && !requestInvoice.Payments.Any());
if (!invoices.Any())
{
return BadRequest("No unpaid pending invoice to cancel");
}
2020-05-08 12:33:47 +02:00
foreach (var invoice in invoices)
{
2020-07-24 09:40:37 +02:00
await _InvoiceRepository.MarkInvoiceStatus(invoice.Id, InvoiceStatus.Invalid);
}
if (redirect)
{
TempData[WellKnownTempData.SuccessMessage] = "Payment cancelled";
2022-04-22 15:52:57 +02:00
return RedirectToAction(nameof(ViewPaymentRequest), new { payReqId });
}
return Ok("Payment cancelled");
}
2020-05-08 12:33:47 +02:00
[HttpGet("{payReqId}/clone")]
public IActionResult ClonePaymentRequest(string payReqId)
{
var store = GetCurrentStore();
var result = EditPaymentRequest(store.Id, payReqId);
if (result is ViewResult viewResult)
{
var model = (UpdatePaymentRequestViewModel)viewResult.Model;
model.Id = null;
2020-05-08 12:33:47 +02:00
model.Archived = false;
model.ExpiryDate = null;
model.Title = $"Clone of {model.Title}";
return View("EditPaymentRequest", model);
2020-05-08 12:33:47 +02:00
}
return NotFound();
}
[HttpGet("{payReqId}/archive")]
public async Task<IActionResult> TogglePaymentRequestArchival(string payReqId)
2020-05-08 12:33:47 +02:00
{
var store = GetCurrentStore();
var result = EditPaymentRequest(store.Id, payReqId);
2020-05-08 12:33:47 +02:00
if (result is ViewResult viewResult)
{
var model = (UpdatePaymentRequestViewModel)viewResult.Model;
model.Archived = !model.Archived;
await EditPaymentRequest(payReqId, model);
2020-05-08 12:33:47 +02:00
TempData[WellKnownTempData.SuccessMessage] = model.Archived
? "The payment request has been archived and will no longer appear in the payment request list by default again."
: "The payment request has been unarchived and will appear in the payment request list by default.";
return RedirectToAction("GetPaymentRequests", new { storeId = store.Id });
}
return NotFound();
}
private string GetUserId() => _UserManager.GetUserId(User);
2021-12-31 08:59:02 +01:00
private StoreData GetCurrentStore() => HttpContext.GetStoreData();
2021-12-31 08:59:02 +01:00
private PaymentRequestData GetCurrentPaymentRequest() => HttpContext.GetPaymentRequestData();
2019-01-14 22:43:29 +01:00
}
}