btcpayserver/BTCPayServer/Services/PaymentRequests/PaymentRequestRepository.cs

184 lines
6.6 KiB
C#
Raw Normal View History

2019-01-14 22:43:29 +01:00
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Stores;
2019-01-14 22:43:29 +01:00
using Microsoft.EntityFrameworkCore;
namespace BTCPayServer.Services.PaymentRequests
{
public class PaymentRequestRepository
{
private readonly ApplicationDbContextFactory _ContextFactory;
private readonly InvoiceRepository _InvoiceRepository;
public PaymentRequestRepository(ApplicationDbContextFactory contextFactory, InvoiceRepository invoiceRepository)
2019-01-14 22:43:29 +01:00
{
_ContextFactory = contextFactory;
_InvoiceRepository = invoiceRepository;
}
public async Task<PaymentRequestData> CreateOrUpdatePaymentRequest(PaymentRequestData entity)
{
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
await using var context = _ContextFactory.CreateContext();
2022-01-14 17:50:29 +09:00
if (string.IsNullOrEmpty(entity.Id))
2019-01-14 22:43:29 +01:00
{
2022-01-14 17:50:29 +09:00
entity.Id = Guid.NewGuid().ToString();
await context.PaymentRequests.AddAsync(entity);
2019-01-14 22:43:29 +01:00
}
2022-01-14 17:50:29 +09:00
else
{
context.PaymentRequests.Update(entity);
}
await context.SaveChangesAsync();
return entity;
2019-01-14 22:43:29 +01:00
}
public async Task<PaymentRequestData> FindPaymentRequest(string id, string userId, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(id))
{
return null;
}
2022-01-14 17:50:29 +09:00
using var context = _ContextFactory.CreateContext();
var result = await context.PaymentRequests.Include(x => x.StoreData)
.Where(data =>
string.IsNullOrEmpty(userId) ||
(data.StoreData != null && data.StoreData.UserStores.Any(u => u.ApplicationUserId == userId)))
.SingleOrDefaultAsync(x => x.Id == id, cancellationToken);
return result;
2019-01-14 22:43:29 +01:00
}
public async Task<bool> IsPaymentRequestAdmin(string paymentRequestId, string userId)
{
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(paymentRequestId))
{
return false;
}
2022-01-14 17:50:29 +09:00
using var context = _ContextFactory.CreateContext();
return await context.PaymentRequests.Include(x => x.StoreData)
.AnyAsync(data =>
data.Id == paymentRequestId &&
(data.StoreData != null && data.StoreData.UserStores.Any(u => u.ApplicationUserId == userId)));
2019-01-14 22:43:29 +01:00
}
2020-06-28 17:55:27 +09:00
public async Task UpdatePaymentRequestStatus(string paymentRequestId, Client.Models.PaymentRequestData.PaymentRequestStatus status, CancellationToken cancellationToken = default)
2019-01-14 22:43:29 +01:00
{
2022-01-14 17:50:29 +09:00
using var context = _ContextFactory.CreateContext();
var invoiceData = await context.FindAsync<PaymentRequestData>(paymentRequestId);
if (invoiceData == null)
return;
invoiceData.Status = status;
await context.SaveChangesAsync(cancellationToken);
2019-01-14 22:43:29 +01:00
}
public async Task<PaymentRequestData[]> FindPaymentRequests(PaymentRequestQuery query, CancellationToken cancellationToken = default)
2019-01-14 22:43:29 +01:00
{
2022-01-14 17:50:29 +09:00
using var context = _ContextFactory.CreateContext();
var queryable = context.PaymentRequests.Include(data => data.StoreData).AsQueryable();
if (!query.IncludeArchived)
{
queryable = queryable.Where(data => !data.Archived);
}
if (!string.IsNullOrEmpty(query.StoreId))
{
queryable = queryable.Where(data =>
data.StoreDataId == query.StoreId);
}
if (query.Status != null && query.Status.Any())
{
queryable = queryable.Where(data =>
query.Status.Contains(data.Status));
}
if (query.Ids != null && query.Ids.Any())
{
queryable = queryable.Where(data =>
query.Ids.Contains(data.Id));
}
if (!string.IsNullOrEmpty(query.UserId))
{
queryable = queryable.Where(i =>
i.StoreData != null && i.StoreData.UserStores.Any(u => u.ApplicationUserId == query.UserId));
}
queryable = queryable.OrderByDescending(u => u.Created);
if (query.Skip.HasValue)
{
queryable = queryable.Skip(query.Skip.Value);
}
if (query.Count.HasValue)
2019-01-14 22:43:29 +01:00
{
2022-01-14 17:50:29 +09:00
queryable = queryable.Take(query.Count.Value);
2019-01-14 22:43:29 +01:00
}
var items = await queryable.ToArrayAsync(cancellationToken);
return items;
2019-01-14 22:43:29 +01:00
}
public async Task<InvoiceEntity[]> GetInvoicesForPaymentRequest(string paymentRequestId,
InvoiceQuery invoiceQuery = null)
{
if (invoiceQuery == null)
{
invoiceQuery = new InvoiceQuery();
}
2020-06-28 17:55:27 +09:00
invoiceQuery.OrderId = new[] { GetOrderIdForPaymentRequest(paymentRequestId) };
return (await _InvoiceRepository.GetInvoices(invoiceQuery))
.Where(i => i.InternalTags.Contains(GetInternalTag(paymentRequestId)))
.ToArray();
2019-01-14 22:43:29 +01:00
}
public static string GetOrderIdForPaymentRequest(string paymentRequestId)
{
return $"PAY_REQUEST_{paymentRequestId}";
}
public static string GetPaymentRequestIdFromOrderId(string invoiceOrderId)
{
if (string.IsNullOrEmpty(invoiceOrderId) ||
!invoiceOrderId.StartsWith("PAY_REQUEST_", StringComparison.InvariantCulture))
{
return null;
}
return invoiceOrderId.Replace("PAY_REQUEST_", "", StringComparison.InvariantCulture);
}
public static string GetInternalTag(string id)
{
return $"PAYREQ#{id}";
}
public static string[] GetPaymentIdsFromInternalTags(InvoiceEntity invoiceEntity)
{
return invoiceEntity.GetInternalTags("PAYREQ#");
2019-01-14 22:43:29 +01:00
}
}
public class PaymentRequestUpdated
{
public string PaymentRequestId { get; set; }
public PaymentRequestData Data { get; set; }
}
public class PaymentRequestQuery
{
public string StoreId { get; set; }
2020-06-28 17:55:27 +09:00
public bool IncludeArchived { get; set; } = true;
public Client.Models.PaymentRequestData.PaymentRequestStatus[] Status { get; set; }
2019-01-14 22:43:29 +01:00
public string UserId { get; set; }
public int? Skip { get; set; }
public int? Count { get; set; }
public string[] Ids { get; set; }
2019-01-14 22:43:29 +01:00
}
}