mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2026-01-18 13:34:25 +01:00
* mark items to abstract wip wip wip wip wip wip wip cleanup parse other types compile and fix tests fix bug fix warnings fix rebase error reduce payment method handler passings more cleanup switch tests to Fast mode fix obsolete warning remove argument requirement rebase fixes remove overcomplicated code better parsing remove dependency on environement remove async * fixes and simplification * simplify * clean up even more * replace nuglify dependency * remove extra space * Fix tests * fix booboo * missing setter * change url resolver * reduce payment method handlers * wrap payment method handlers in a custom type * fix tests * make invoice controller UI selectlist population cleaner * make store controller use payment handler dictionary * fix ln flag * fix store controller test * remove null checks on payment handlers * remove unused imports * BitcoinSpecificBtcPayNetwork - abstract BTCPayNetwork * some type fixes * fix tests * simplify fetching handler in invoice controller * rename network base and bitcoin classes * abstract serializer to network level * fix serializer when network not provided * fix serializer when network not provided * fix serializer when network not provided * Abstract more payment type specific logic to handlers * fix merge issue * small fixes * make use of repository instead of direct context usage * reduce redundant code * sanity check * test fixes
265 lines
9.0 KiB
C#
265 lines
9.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BTCPayServer.Data;
|
|
using BTCPayServer.Services.Invoices;
|
|
using BTCPayServer.Services.Stores;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Internal;
|
|
using NBitcoin;
|
|
using NBXplorer;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace BTCPayServer.Services.PaymentRequests
|
|
{
|
|
public class PaymentRequestRepository
|
|
{
|
|
private readonly ApplicationDbContextFactory _ContextFactory;
|
|
private readonly InvoiceRepository _InvoiceRepository;
|
|
private readonly StoreRepository _storeRepository;
|
|
|
|
public PaymentRequestRepository(ApplicationDbContextFactory contextFactory, InvoiceRepository invoiceRepository,
|
|
StoreRepository storeRepository)
|
|
{
|
|
_ContextFactory = contextFactory;
|
|
_InvoiceRepository = invoiceRepository;
|
|
_storeRepository = storeRepository;
|
|
}
|
|
|
|
|
|
public async Task<PaymentRequestData> CreateOrUpdatePaymentRequest(PaymentRequestData entity)
|
|
{
|
|
using (var context = _ContextFactory.CreateContext())
|
|
{
|
|
if (string.IsNullOrEmpty(entity.Id))
|
|
{
|
|
await context.PaymentRequests.AddAsync(entity);
|
|
}
|
|
else
|
|
{
|
|
context.PaymentRequests.Update(entity);
|
|
}
|
|
|
|
await context.SaveChangesAsync();
|
|
return entity;
|
|
}
|
|
}
|
|
|
|
public async Task<PaymentRequestData> FindPaymentRequest(string id, string userId, CancellationToken cancellationToken = default)
|
|
{
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
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);
|
|
if (result != null)
|
|
{
|
|
result.StoreData = _storeRepository.PrepareEntity(result.StoreData);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public async Task<bool> IsPaymentRequestAdmin(string paymentRequestId, string userId)
|
|
{
|
|
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(paymentRequestId))
|
|
{
|
|
return false;
|
|
}
|
|
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)));
|
|
}
|
|
}
|
|
|
|
public async Task UpdatePaymentRequestStatus(string paymentRequestId, PaymentRequestData.PaymentRequestStatus status, CancellationToken cancellationToken = default)
|
|
{
|
|
using (var context = _ContextFactory.CreateContext())
|
|
{
|
|
var invoiceData = await context.FindAsync<PaymentRequestData>(paymentRequestId);
|
|
if (invoiceData == null)
|
|
return;
|
|
invoiceData.Status = status;
|
|
await context.SaveChangesAsync(cancellationToken);
|
|
}
|
|
}
|
|
|
|
public async Task<(int Total, PaymentRequestData[] Items)> FindPaymentRequests(PaymentRequestQuery query, CancellationToken cancellationToken = default)
|
|
{
|
|
using (var context = _ContextFactory.CreateContext())
|
|
{
|
|
var queryable = context.PaymentRequests.Include(data => data.StoreData).AsQueryable();
|
|
if (!string.IsNullOrEmpty(query.StoreId))
|
|
{
|
|
queryable = queryable.Where(data =>
|
|
data.StoreDataId.Equals(query.StoreId, StringComparison.InvariantCulture));
|
|
}
|
|
|
|
if (query.Status != null && query.Status.Any())
|
|
{
|
|
queryable = queryable.Where(data =>
|
|
query.Status.Contains(data.Status));
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(query.UserId))
|
|
{
|
|
queryable = queryable.Where(i =>
|
|
i.StoreData != null && i.StoreData.UserStores.Any(u => u.ApplicationUserId == query.UserId));
|
|
}
|
|
|
|
var total = await queryable.CountAsync(cancellationToken);
|
|
|
|
if (query.Skip.HasValue)
|
|
{
|
|
queryable = queryable.Skip(query.Skip.Value);
|
|
}
|
|
|
|
if (query.Count.HasValue)
|
|
{
|
|
queryable = queryable.Take(query.Count.Value);
|
|
}
|
|
|
|
return (total, await queryable.ToArrayAsync(cancellationToken));
|
|
}
|
|
}
|
|
|
|
public async Task<bool> RemovePaymentRequest(string id, string userId)
|
|
{
|
|
using (var context = _ContextFactory.CreateContext())
|
|
{
|
|
var canDelete = !EnumerableExtensions.Any((await GetInvoicesForPaymentRequest(id)));
|
|
if (!canDelete) return false;
|
|
var pr = await FindPaymentRequest(id, userId);
|
|
if (pr == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
context.PaymentRequests.Remove(pr);
|
|
await context.SaveChangesAsync();
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public async Task<InvoiceEntity[]> GetInvoicesForPaymentRequest(string paymentRequestId,
|
|
InvoiceQuery invoiceQuery = null)
|
|
{
|
|
if (invoiceQuery == null)
|
|
{
|
|
invoiceQuery = new InvoiceQuery();
|
|
}
|
|
|
|
invoiceQuery.OrderId = new[] {GetOrderIdForPaymentRequest(paymentRequestId)};
|
|
return await _InvoiceRepository.GetInvoices(invoiceQuery);
|
|
}
|
|
|
|
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#");
|
|
}
|
|
}
|
|
|
|
public class PaymentRequestUpdated
|
|
{
|
|
public string PaymentRequestId { get; set; }
|
|
public PaymentRequestData Data { get; set; }
|
|
}
|
|
|
|
public class PaymentRequestQuery
|
|
{
|
|
public string StoreId { get; set; }
|
|
|
|
public PaymentRequestData.PaymentRequestStatus[] Status{ get; set; }
|
|
public string UserId { get; set; }
|
|
public int? Skip { get; set; }
|
|
public int? Count { get; set; }
|
|
}
|
|
|
|
public class PaymentRequestData
|
|
{
|
|
public string Id { get; set; }
|
|
public string StoreDataId { get; set; }
|
|
|
|
public StoreData StoreData { get; set; }
|
|
|
|
public PaymentRequestStatus Status { get; set; }
|
|
|
|
public byte[] Blob { get; set; }
|
|
|
|
public PaymentRequestBlob GetBlob()
|
|
{
|
|
var result = Blob == null
|
|
? new PaymentRequestBlob()
|
|
: JObject.Parse(ZipUtils.Unzip(Blob)).ToObject<PaymentRequestBlob>();
|
|
return result;
|
|
}
|
|
|
|
public bool SetBlob(PaymentRequestBlob blob)
|
|
{
|
|
var original = new Serializer(Network.Main).ToString(GetBlob());
|
|
var newBlob = new Serializer(Network.Main).ToString(blob);
|
|
if (original == newBlob)
|
|
return false;
|
|
Blob = ZipUtils.Zip(newBlob);
|
|
return true;
|
|
}
|
|
|
|
public class PaymentRequestBlob
|
|
{
|
|
public decimal Amount { get; set; }
|
|
public string Currency { get; set; }
|
|
|
|
public DateTime? ExpiryDate { get; set; }
|
|
|
|
public string Title { get; set; }
|
|
public string Description { get; set; }
|
|
public string Email { get; set; }
|
|
|
|
public string EmbeddedCSS { get; set; }
|
|
public string CustomCSSLink { get; set; }
|
|
public bool AllowCustomPaymentAmounts { get; set; }
|
|
}
|
|
|
|
public enum PaymentRequestStatus
|
|
{
|
|
Pending = 0,
|
|
Completed = 1,
|
|
Expired = 2
|
|
}
|
|
}
|
|
}
|