mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-20 02:28:31 +01:00
022285806b
* 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>
171 lines
7.7 KiB
C#
171 lines
7.7 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using BTCPayServer.Client.Models;
|
|
using BTCPayServer.Data;
|
|
using BTCPayServer.Models.PaymentRequestViewModels;
|
|
using BTCPayServer.Payments;
|
|
using BTCPayServer.Services.Apps;
|
|
using BTCPayServer.Services.Invoices;
|
|
using BTCPayServer.Services.PaymentRequests;
|
|
using BTCPayServer.Services.Rates;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
|
|
|
|
namespace BTCPayServer.PaymentRequest
|
|
{
|
|
public class PaymentRequestService
|
|
{
|
|
private readonly PaymentRequestRepository _PaymentRequestRepository;
|
|
private readonly BTCPayNetworkProvider _BtcPayNetworkProvider;
|
|
private readonly AppService _AppService;
|
|
private readonly CurrencyNameTable _currencies;
|
|
|
|
public PaymentRequestService(
|
|
PaymentRequestRepository paymentRequestRepository,
|
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
|
AppService appService,
|
|
CurrencyNameTable currencies)
|
|
{
|
|
_PaymentRequestRepository = paymentRequestRepository;
|
|
_BtcPayNetworkProvider = btcPayNetworkProvider;
|
|
_AppService = appService;
|
|
_currencies = currencies;
|
|
}
|
|
|
|
public async Task UpdatePaymentRequestStateIfNeeded(string id)
|
|
{
|
|
var pr = await _PaymentRequestRepository.FindPaymentRequest(id, null);
|
|
await UpdatePaymentRequestStateIfNeeded(pr);
|
|
}
|
|
|
|
public async Task UpdatePaymentRequestStateIfNeeded(PaymentRequestData pr)
|
|
{
|
|
var blob = pr.GetBlob();
|
|
var currentStatus = pr.Status;
|
|
if (blob.ExpiryDate.HasValue)
|
|
{
|
|
if (blob.ExpiryDate.Value <= DateTimeOffset.UtcNow)
|
|
currentStatus = Client.Models.PaymentRequestData.PaymentRequestStatus.Expired;
|
|
}
|
|
else if (currentStatus != Client.Models.PaymentRequestData.PaymentRequestStatus.Completed)
|
|
{
|
|
currentStatus = Client.Models.PaymentRequestData.PaymentRequestStatus.Pending;
|
|
}
|
|
|
|
if (currentStatus != Client.Models.PaymentRequestData.PaymentRequestStatus.Expired)
|
|
{
|
|
var invoices = await _PaymentRequestRepository.GetInvoicesForPaymentRequest(pr.Id);
|
|
var contributions = _AppService.GetContributionsByPaymentMethodId(blob.Currency, invoices, true);
|
|
|
|
currentStatus = contributions.TotalCurrency >= blob.Amount
|
|
? Client.Models.PaymentRequestData.PaymentRequestStatus.Completed
|
|
: Client.Models.PaymentRequestData.PaymentRequestStatus.Pending;
|
|
}
|
|
|
|
if (currentStatus != pr.Status)
|
|
{
|
|
pr.Status = currentStatus;
|
|
await _PaymentRequestRepository.UpdatePaymentRequestStatus(pr.Id, currentStatus);
|
|
}
|
|
}
|
|
|
|
public async Task<ViewPaymentRequestViewModel> GetPaymentRequest(string id, string userId = null)
|
|
{
|
|
var pr = await _PaymentRequestRepository.FindPaymentRequest(id, null);
|
|
if (pr == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var blob = pr.GetBlob();
|
|
|
|
var invoices = await _PaymentRequestRepository.GetInvoicesForPaymentRequest(id);
|
|
|
|
var paymentStats = _AppService.GetContributionsByPaymentMethodId(blob.Currency, invoices, true);
|
|
var amountDue = blob.Amount - paymentStats.TotalCurrency;
|
|
var pendingInvoice = invoices.OrderByDescending(entity => entity.InvoiceTime)
|
|
.FirstOrDefault(entity => entity.Status == InvoiceStatusLegacy.New);
|
|
|
|
return new ViewPaymentRequestViewModel(pr)
|
|
{
|
|
Archived = pr.Archived,
|
|
AmountFormatted = _currencies.FormatCurrency(blob.Amount, blob.Currency),
|
|
AmountCollected = paymentStats.TotalCurrency,
|
|
AmountCollectedFormatted = _currencies.FormatCurrency(paymentStats.TotalCurrency, blob.Currency),
|
|
AmountDue = amountDue,
|
|
AmountDueFormatted = _currencies.FormatCurrency(amountDue, blob.Currency),
|
|
CurrencyData = _currencies.GetCurrencyData(blob.Currency, true),
|
|
LastUpdated = DateTime.UtcNow,
|
|
FormId = blob.FormId,
|
|
FormSubmitted = blob.FormResponse is not null,
|
|
AnyPendingInvoice = pendingInvoice != null,
|
|
PendingInvoiceHasPayments = pendingInvoice != null &&
|
|
pendingInvoice.ExceptionStatus != InvoiceExceptionStatus.None,
|
|
Invoices = new ViewPaymentRequestViewModel.InvoiceList(invoices.Select(entity =>
|
|
{
|
|
var state = entity.GetInvoiceState();
|
|
var payments = entity
|
|
.GetPayments(true)
|
|
.Select(paymentEntity =>
|
|
{
|
|
var paymentData = paymentEntity.GetCryptoPaymentData();
|
|
var paymentMethodId = paymentEntity.GetPaymentMethodId();
|
|
if (paymentData is null || paymentMethodId is null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string txId = paymentData.GetPaymentId();
|
|
string link = GetTransactionLink(paymentMethodId, txId);
|
|
var paymentMethod = entity.GetPaymentMethod(paymentMethodId);
|
|
var amount = paymentData.GetValue();
|
|
var rate = paymentMethod.Rate;
|
|
var paid = (amount - paymentEntity.NetworkFee) * rate;
|
|
|
|
return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment
|
|
{
|
|
Amount = amount,
|
|
Paid = paid,
|
|
ReceivedDate = paymentEntity.ReceivedTime.DateTime,
|
|
PaidFormatted = _currencies.FormatCurrency(paid, blob.Currency),
|
|
RateFormatted = _currencies.FormatCurrency(rate, blob.Currency),
|
|
PaymentMethod = paymentMethodId.ToPrettyString(),
|
|
Link = link,
|
|
Id = txId,
|
|
Destination = paymentData.GetDestination()
|
|
};
|
|
})
|
|
.Where(payment => payment != null)
|
|
.ToList();
|
|
|
|
if (state.Status == InvoiceStatusLegacy.Invalid ||
|
|
state.Status == InvoiceStatusLegacy.Expired && !payments.Any())
|
|
return null;
|
|
|
|
return new ViewPaymentRequestViewModel.PaymentRequestInvoice
|
|
{
|
|
Id = entity.Id,
|
|
Amount = entity.Price,
|
|
AmountFormatted = _currencies.FormatCurrency(entity.Price, blob.Currency),
|
|
Currency = entity.Currency,
|
|
ExpiryDate = entity.ExpirationTime.DateTime,
|
|
State = state,
|
|
StateFormatted = state.ToString(),
|
|
Payments = payments
|
|
};
|
|
})
|
|
.Where(invoice => invoice != null))
|
|
};
|
|
}
|
|
|
|
private string GetTransactionLink(PaymentMethodId paymentMethodId, string txId)
|
|
{
|
|
var network = _BtcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode);
|
|
if (network == null)
|
|
return null;
|
|
return paymentMethodId.PaymentType.GetTransactionLink(network, txId);
|
|
}
|
|
}
|
|
}
|