mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-03 17:36:59 +01:00
add status and refactor
This commit is contained in:
parent
cb5601c68b
commit
d96bd15b3b
23 changed files with 167 additions and 62 deletions
|
@ -9,6 +9,10 @@ namespace BTCPayServer.Client.Models
|
||||||
public class InvoiceData : CreateInvoiceRequest
|
public class InvoiceData : CreateInvoiceRequest
|
||||||
{
|
{
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public InvoiceStatus Status { get; set; }
|
||||||
|
[JsonConverter(typeof(StringEnumConverter))]
|
||||||
|
public InvoiceExceptionStatus ExceptionStatus { get; set; }
|
||||||
public Dictionary<string, PaymentMethodDataModel> PaymentMethodData { get; set; }
|
public Dictionary<string, PaymentMethodDataModel> PaymentMethodData { get; set; }
|
||||||
|
|
||||||
public class PaymentMethodDataModel
|
public class PaymentMethodDataModel
|
||||||
|
|
12
BTCPayServer.Client/Models/InvoiceExceptionStatus.cs
Normal file
12
BTCPayServer.Client/Models/InvoiceExceptionStatus.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace BTCPayServer.Client.Models
|
||||||
|
{
|
||||||
|
public enum InvoiceExceptionStatus
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
PaidLate,
|
||||||
|
PaidPartial,
|
||||||
|
Marked,
|
||||||
|
Invalid,
|
||||||
|
PaidOver
|
||||||
|
}
|
||||||
|
}
|
12
BTCPayServer.Client/Models/InvoiceStatus.cs
Normal file
12
BTCPayServer.Client/Models/InvoiceStatus.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace BTCPayServer.Client.Models
|
||||||
|
{
|
||||||
|
public enum InvoiceStatus
|
||||||
|
{
|
||||||
|
New,
|
||||||
|
Paid,
|
||||||
|
Expired,
|
||||||
|
Invalid,
|
||||||
|
Complete,
|
||||||
|
Confirmed
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ namespace BTCPayServer.Client.Models
|
||||||
{
|
{
|
||||||
public class UpdateInvoiceRequest
|
public class UpdateInvoiceRequest
|
||||||
{
|
{
|
||||||
public bool Archived { get; set; }
|
public bool? Archived { get; set; }
|
||||||
|
public InvoiceStatus? Status { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Controllers;
|
using BTCPayServer.Controllers;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Controllers;
|
using BTCPayServer.Controllers;
|
||||||
using BTCPayServer.Models.PaymentRequestViewModels;
|
using BTCPayServer.Models.PaymentRequestViewModels;
|
||||||
using BTCPayServer.PaymentRequest;
|
using BTCPayServer.PaymentRequest;
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
|
using BTCPayServer.Models.InvoicingModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Security;
|
using BTCPayServer.Security;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
|
@ -154,16 +155,64 @@ namespace BTCPayServer.Controllers.GreenField
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
await _invoiceRepository.ToggleInvoiceArchival(invoiceId, request.Archived, storeId);
|
var invoice = await _invoiceRepository.GetInvoice(invoiceId, true);
|
||||||
|
if (invoice.StoreId != store.Id)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Archived.HasValue)
|
||||||
|
{
|
||||||
|
if (request.Archived.Value && !invoice.Archived)
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(request.Archived),
|
||||||
|
"You can only archive an invoice via HTTP DELETE.");
|
||||||
|
}
|
||||||
|
else if (!request.Archived.Value && invoice.Archived)
|
||||||
|
{
|
||||||
|
await _invoiceRepository.ToggleInvoiceArchival(invoiceId, false, storeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Status != null)
|
||||||
|
{
|
||||||
|
if (!await _invoiceRepository.MarkInvoiceStatus(invoice.Id, request.Status.Value))
|
||||||
|
{
|
||||||
|
ModelState.AddModelError(nameof(request.Status),
|
||||||
|
"Status can only be marked to invalid or complete within certain conditions.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Email != null)
|
||||||
|
{
|
||||||
|
if (!EmailValidator.IsEmail(request.Email))
|
||||||
|
{
|
||||||
|
request.AddModelError(invoiceRequest => invoiceRequest.Email, "Invalid email address",
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(invoice.BuyerInformation.BuyerEmail))
|
||||||
|
{
|
||||||
|
request.AddModelError(invoiceRequest => invoiceRequest.Email, "Email address already set",
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _invoiceRepository.UpdateInvoice(invoice.Id, new UpdateCustomerModel() {Email = request.Email});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
return this.CreateValidationError(ModelState);
|
||||||
|
|
||||||
return await GetInvoice(storeId, invoiceId);
|
return await GetInvoice(storeId, invoiceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public InvoiceData ToModel(InvoiceEntity entity)
|
private InvoiceData ToModel(InvoiceEntity entity)
|
||||||
{
|
{
|
||||||
return new InvoiceData()
|
return new InvoiceData()
|
||||||
{
|
{
|
||||||
Amount = entity.ProductInformation.Price,
|
Amount = entity.ProductInformation.Price,
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
|
Status = entity.Status,
|
||||||
|
ExceptionStatus = entity.ExceptionStatus,
|
||||||
Currency = entity.ProductInformation.Currency,
|
Currency = entity.ProductInformation.Currency,
|
||||||
Metadata =
|
Metadata =
|
||||||
new CreateInvoiceRequest.ProductInformation()
|
new CreateInvoiceRequest.ProductInformation()
|
||||||
|
@ -244,7 +293,7 @@ namespace BTCPayServer.Controllers.GreenField
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Models.CreateInvoiceRequest FromModel(CreateInvoiceRequest entity)
|
private Models.CreateInvoiceRequest FromModel(CreateInvoiceRequest entity)
|
||||||
{
|
{
|
||||||
return new Models.CreateInvoiceRequest()
|
return new Models.CreateInvoiceRequest()
|
||||||
{
|
{
|
||||||
|
|
|
@ -778,14 +778,12 @@ namespace BTCPayServer.Controllers
|
||||||
}
|
}
|
||||||
if (newState == "invalid")
|
if (newState == "invalid")
|
||||||
{
|
{
|
||||||
await _InvoiceRepository.UpdatePaidInvoiceToInvalid(invoiceId);
|
await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Invalid);
|
||||||
_EventAggregator.Publish(new InvoiceEvent(invoice, 1008, InvoiceEvent.MarkedInvalid));
|
|
||||||
model.StatusString = new InvoiceState("invalid", "marked").ToString();
|
model.StatusString = new InvoiceState("invalid", "marked").ToString();
|
||||||
}
|
}
|
||||||
else if (newState == "complete")
|
else if (newState == "complete")
|
||||||
{
|
{
|
||||||
await _InvoiceRepository.UpdatePaidInvoiceToComplete(invoiceId);
|
await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Complete);
|
||||||
_EventAggregator.Publish(new InvoiceEvent(invoice, 2008, InvoiceEvent.MarkedCompleted));
|
|
||||||
model.StatusString = new InvoiceState("complete", "marked").ToString();
|
model.StatusString = new InvoiceState("complete", "marked").ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ namespace BTCPayServer.Controllers
|
||||||
}
|
}
|
||||||
await _InvoiceRepository.AddInvoiceLogs(entity.Id, logs);
|
await _InvoiceRepository.AddInvoiceLogs(entity.Id, logs);
|
||||||
});
|
});
|
||||||
_EventAggregator.Publish(new Events.InvoiceEvent(entity, 1001, InvoiceEvent.Created));
|
_EventAggregator.Publish(new Events.InvoiceEvent(entity, InvoiceEvent.Created));
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Filters;
|
using BTCPayServer.Filters;
|
||||||
|
@ -19,6 +20,9 @@ using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using CreateInvoiceRequest = BTCPayServer.Models.CreateInvoiceRequest;
|
||||||
|
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
|
||||||
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
|
|
||||||
namespace BTCPayServer.Controllers
|
namespace BTCPayServer.Controllers
|
||||||
{
|
{
|
||||||
|
@ -303,9 +307,7 @@ namespace BTCPayServer.Controllers
|
||||||
|
|
||||||
foreach (var invoice in invoices)
|
foreach (var invoice in invoices)
|
||||||
{
|
{
|
||||||
await _InvoiceRepository.UpdatePaidInvoiceToInvalid(invoice.Id);
|
await _InvoiceRepository.MarkInvoiceStatus(invoice.Id, InvoiceStatus.Invalid);
|
||||||
_EventAggregator.Publish(new InvoiceEvent(await _InvoiceRepository.GetInvoice(invoice.Id), 1008,
|
|
||||||
InvoiceEvent.MarkedInvalid));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redirect)
|
if (redirect)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
|
|
||||||
namespace BTCPayServer.Events
|
namespace BTCPayServer.Events
|
||||||
|
@ -16,10 +17,25 @@ namespace BTCPayServer.Events
|
||||||
public const string Confirmed = "invoice_confirmed";
|
public const string Confirmed = "invoice_confirmed";
|
||||||
public const string Completed = "invoice_completed";
|
public const string Completed = "invoice_completed";
|
||||||
|
|
||||||
public InvoiceEvent(InvoiceEntity invoice, int code, string name)
|
public static Dictionary<string, int> EventCodes = new Dictionary<string, int>()
|
||||||
|
{
|
||||||
|
{Created, 1001},
|
||||||
|
{ReceivedPayment, 1002},
|
||||||
|
{PaidInFull, 1003},
|
||||||
|
{Expired, 1004},
|
||||||
|
{Confirmed, 1005},
|
||||||
|
{Completed, 1006},
|
||||||
|
{MarkedInvalid, 1008},
|
||||||
|
{FailedToConfirm, 1013},
|
||||||
|
{PaidAfterExpiration, 1009},
|
||||||
|
{ExpiredPaidPartial, 2000},
|
||||||
|
{MarkedCompleted, 2008},
|
||||||
|
};
|
||||||
|
|
||||||
|
public InvoiceEvent(InvoiceEntity invoice, string name)
|
||||||
{
|
{
|
||||||
Invoice = invoice;
|
Invoice = invoice;
|
||||||
EventCode = code;
|
EventCode = EventCodes[name];
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
|
@ -65,9 +66,9 @@ namespace BTCPayServer.HostedServices
|
||||||
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
||||||
|
|
||||||
invoice.Status = InvoiceStatus.Expired;
|
invoice.Status = InvoiceStatus.Expired;
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 1004, InvoiceEvent.Expired));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Expired));
|
||||||
if (invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
|
if (invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial)
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 2000, InvoiceEvent.ExpiredPaidPartial));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.ExpiredPaidPartial));
|
||||||
}
|
}
|
||||||
|
|
||||||
var payments = invoice.GetPayments().Where(p => p.Accounted).ToArray();
|
var payments = invoice.GetPayments().Where(p => p.Accounted).ToArray();
|
||||||
|
@ -81,7 +82,7 @@ namespace BTCPayServer.HostedServices
|
||||||
{
|
{
|
||||||
if (invoice.Status == InvoiceStatus.New)
|
if (invoice.Status == InvoiceStatus.New)
|
||||||
{
|
{
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 1003, InvoiceEvent.PaidInFull));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidInFull));
|
||||||
invoice.Status = InvoiceStatus.Paid;
|
invoice.Status = InvoiceStatus.Paid;
|
||||||
invoice.ExceptionStatus = accounting.Paid > accounting.TotalDue ? InvoiceExceptionStatus.PaidOver : InvoiceExceptionStatus.None;
|
invoice.ExceptionStatus = accounting.Paid > accounting.TotalDue ? InvoiceExceptionStatus.PaidOver : InvoiceExceptionStatus.None;
|
||||||
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
||||||
|
@ -90,7 +91,7 @@ namespace BTCPayServer.HostedServices
|
||||||
else if (invoice.Status == InvoiceStatus.Expired && invoice.ExceptionStatus != InvoiceExceptionStatus.PaidLate)
|
else if (invoice.Status == InvoiceStatus.Expired && invoice.ExceptionStatus != InvoiceExceptionStatus.PaidLate)
|
||||||
{
|
{
|
||||||
invoice.ExceptionStatus = InvoiceExceptionStatus.PaidLate;
|
invoice.ExceptionStatus = InvoiceExceptionStatus.PaidLate;
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 1009, InvoiceEvent.PaidAfterExpiration));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.PaidAfterExpiration));
|
||||||
context.MarkDirty();
|
context.MarkDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +137,7 @@ namespace BTCPayServer.HostedServices
|
||||||
(confirmedAccounting.Paid < accounting.MinimumTotalDue))
|
(confirmedAccounting.Paid < accounting.MinimumTotalDue))
|
||||||
{
|
{
|
||||||
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 1013, InvoiceEvent.FailedToConfirm));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.FailedToConfirm));
|
||||||
invoice.Status = InvoiceStatus.Invalid;
|
invoice.Status = InvoiceStatus.Invalid;
|
||||||
context.MarkDirty();
|
context.MarkDirty();
|
||||||
}
|
}
|
||||||
|
@ -144,7 +145,7 @@ namespace BTCPayServer.HostedServices
|
||||||
{
|
{
|
||||||
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
await _InvoiceRepository.UnaffectAddress(invoice.Id);
|
||||||
invoice.Status = InvoiceStatus.Confirmed;
|
invoice.Status = InvoiceStatus.Confirmed;
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 1005, InvoiceEvent.Confirmed));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Confirmed));
|
||||||
context.MarkDirty();
|
context.MarkDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +155,7 @@ namespace BTCPayServer.HostedServices
|
||||||
var completedAccounting = paymentMethod.Calculate(p => p.GetCryptoPaymentData().PaymentCompleted(p));
|
var completedAccounting = paymentMethod.Calculate(p => p.GetCryptoPaymentData().PaymentCompleted(p));
|
||||||
if (completedAccounting.Paid >= accounting.MinimumTotalDue)
|
if (completedAccounting.Paid >= accounting.MinimumTotalDue)
|
||||||
{
|
{
|
||||||
context.Events.Add(new InvoiceEvent(invoice, 1006, InvoiceEvent.Completed));
|
context.Events.Add(new InvoiceEvent(invoice, InvoiceEvent.Completed));
|
||||||
invoice.Status = InvoiceStatus.Complete;
|
invoice.Status = InvoiceStatus.Complete;
|
||||||
context.MarkDirty();
|
context.MarkDirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace BTCPayServer.Hosting
|
||||||
var dbpath = Path.Combine(opts.DataDir, "InvoiceDB");
|
var dbpath = Path.Combine(opts.DataDir, "InvoiceDB");
|
||||||
if (!Directory.Exists(dbpath))
|
if (!Directory.Exists(dbpath))
|
||||||
Directory.CreateDirectory(dbpath);
|
Directory.CreateDirectory(dbpath);
|
||||||
return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService<BTCPayNetworkProvider>());
|
return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService<BTCPayNetworkProvider>(), o.GetService<EventAggregator>());
|
||||||
});
|
});
|
||||||
services.AddSingleton<BTCPayServerEnvironment>();
|
services.AddSingleton<BTCPayServerEnvironment>();
|
||||||
services.TryAddSingleton<TokenRepository>();
|
services.TryAddSingleton<TokenRepository>();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
|
|
||||||
namespace BTCPayServer.Models.InvoicingModels
|
namespace BTCPayServer.Models.InvoicingModels
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Models.PaymentRequestViewModels;
|
using BTCPayServer.Models.PaymentRequestViewModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
@ -9,6 +10,7 @@ using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.PaymentRequests;
|
using BTCPayServer.Services.PaymentRequests;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
|
||||||
|
|
||||||
namespace BTCPayServer.PaymentRequest
|
namespace BTCPayServer.PaymentRequest
|
||||||
{
|
{
|
||||||
|
|
|
@ -406,7 +406,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||||
invoice.SetPaymentMethod(paymentMethod);
|
invoice.SetPaymentMethod(paymentMethod);
|
||||||
}
|
}
|
||||||
wallet.InvalidateCache(strategy);
|
wallet.InvalidateCache(strategy);
|
||||||
_Aggregator.Publish(new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
_Aggregator.Publish(new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
||||||
return invoice;
|
return invoice;
|
||||||
}
|
}
|
||||||
public async Task StopAsync(CancellationToken cancellationToken)
|
public async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
|
|
@ -329,7 +329,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||||
{
|
{
|
||||||
var invoice = await invoiceRepository.GetInvoice(invoiceId);
|
var invoice = await invoiceRepository.GetInvoice(invoiceId);
|
||||||
if (invoice != null)
|
if (invoice != null)
|
||||||
_eventAggregator.Publish(new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
_eventAggregator.Publish(new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
||||||
}
|
}
|
||||||
return payment != null;
|
return payment != null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,7 +454,7 @@ namespace BTCPayServer.Payments.PayJoin
|
||||||
$"The original transaction has already been accounted"));
|
$"The original transaction has already been accounted"));
|
||||||
}
|
}
|
||||||
await _btcPayWalletProvider.GetWallet(network).SaveOffchainTransactionAsync(ctx.OriginalTransaction);
|
await _btcPayWalletProvider.GetWallet(network).SaveOffchainTransactionAsync(ctx.OriginalTransaction);
|
||||||
_eventAggregator.Publish(new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
_eventAggregator.Publish(new InvoiceEvent(invoice,InvoiceEvent.ReceivedPayment) { Payment = payment });
|
||||||
_eventAggregator.Publish(new UpdateTransactionLabel()
|
_eventAggregator.Publish(new UpdateTransactionLabel()
|
||||||
{
|
{
|
||||||
WalletId = new WalletId(invoice.StoreId, network.CryptoCode),
|
WalletId = new WalletId(invoice.StoreId, network.CryptoCode),
|
||||||
|
|
|
@ -143,7 +143,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
|
||||||
}
|
}
|
||||||
|
|
||||||
_eventAggregator.Publish(
|
_eventAggregator.Publish(
|
||||||
new InvoiceEvent(invoice, 1002, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
new InvoiceEvent(invoice, InvoiceEvent.ReceivedPayment) { Payment = payment });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdatePaymentStates(string cryptoCode, InvoiceEntity[] invoices)
|
private async Task UpdatePaymentStates(string cryptoCode, InvoiceEntity[] invoices)
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Models.AppViewModels;
|
using BTCPayServer.Models.AppViewModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
@ -20,6 +21,7 @@ using NUglify.Helpers;
|
||||||
using YamlDotNet.RepresentationModel;
|
using YamlDotNet.RepresentationModel;
|
||||||
using YamlDotNet.Serialization;
|
using YamlDotNet.Serialization;
|
||||||
using static BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel;
|
using static BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel;
|
||||||
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
|
|
||||||
namespace BTCPayServer.Services.Apps
|
namespace BTCPayServer.Services.Apps
|
||||||
{
|
{
|
||||||
|
|
|
@ -604,24 +604,7 @@ namespace BTCPayServer.Services.Invoices
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InvoiceStatus
|
|
||||||
{
|
|
||||||
New,
|
|
||||||
Paid,
|
|
||||||
Expired,
|
|
||||||
Invalid,
|
|
||||||
Complete,
|
|
||||||
Confirmed
|
|
||||||
}
|
|
||||||
public enum InvoiceExceptionStatus
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
PaidLate,
|
|
||||||
PaidPartial,
|
|
||||||
Marked,
|
|
||||||
Invalid,
|
|
||||||
PaidOver
|
|
||||||
}
|
|
||||||
public class InvoiceState
|
public class InvoiceState
|
||||||
{
|
{
|
||||||
static readonly Dictionary<string, InvoiceStatus> _StringToInvoiceStatus;
|
static readonly Dictionary<string, InvoiceStatus> _StringToInvoiceStatus;
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.Models.InvoicingModels;
|
using BTCPayServer.Models.InvoicingModels;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
@ -37,11 +38,12 @@ namespace BTCPayServer.Services.Invoices
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ApplicationDbContextFactory _ContextFactory;
|
private readonly ApplicationDbContextFactory _ContextFactory;
|
||||||
|
private readonly EventAggregator _eventAggregator;
|
||||||
private readonly BTCPayNetworkProvider _Networks;
|
private readonly BTCPayNetworkProvider _Networks;
|
||||||
private readonly CustomThreadPool _IndexerThread;
|
private readonly CustomThreadPool _IndexerThread;
|
||||||
|
|
||||||
public InvoiceRepository(ApplicationDbContextFactory contextFactory, string dbreezePath,
|
public InvoiceRepository(ApplicationDbContextFactory contextFactory, string dbreezePath,
|
||||||
BTCPayNetworkProvider networks)
|
BTCPayNetworkProvider networks, EventAggregator eventAggregator)
|
||||||
{
|
{
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
retry:
|
retry:
|
||||||
|
@ -53,6 +55,7 @@ retry:
|
||||||
_IndexerThread = new CustomThreadPool(1, "Invoice Indexer");
|
_IndexerThread = new CustomThreadPool(1, "Invoice Indexer");
|
||||||
_ContextFactory = contextFactory;
|
_ContextFactory = contextFactory;
|
||||||
_Networks = networks;
|
_Networks = networks;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InvoiceEntity CreateNewInvoice()
|
public InvoiceEntity CreateNewInvoice()
|
||||||
|
@ -441,29 +444,44 @@ retry:
|
||||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task UpdatePaidInvoiceToInvalid(string invoiceId)
|
public async Task<bool> MarkInvoiceStatus(string invoiceId, InvoiceStatus status)
|
||||||
{
|
{
|
||||||
using (var context = _ContextFactory.CreateContext())
|
using (var context = _ContextFactory.CreateContext())
|
||||||
{
|
{
|
||||||
var invoiceData = await context.FindAsync<Data.InvoiceData>(invoiceId).ConfigureAwait(false);
|
var invoiceData = await context.FindAsync<Data.InvoiceData>(invoiceId).ConfigureAwait(false);
|
||||||
if (invoiceData == null || !invoiceData.GetInvoiceState().CanMarkInvalid())
|
if (invoiceData == null)
|
||||||
return;
|
{
|
||||||
invoiceData.Status = "invalid";
|
return false;
|
||||||
invoiceData.ExceptionStatus = "marked";
|
}
|
||||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
|
||||||
}
|
string eventName;
|
||||||
}
|
switch (status)
|
||||||
public async Task UpdatePaidInvoiceToComplete(string invoiceId)
|
{
|
||||||
{
|
case InvoiceStatus.Complete:
|
||||||
using (var context = _ContextFactory.CreateContext())
|
if (!invoiceData.GetInvoiceState().CanMarkComplete())
|
||||||
{
|
{
|
||||||
var invoiceData = await context.FindAsync<Data.InvoiceData>(invoiceId).ConfigureAwait(false);
|
return false;
|
||||||
if (invoiceData == null || !invoiceData.GetInvoiceState().CanMarkComplete())
|
}
|
||||||
return;
|
|
||||||
invoiceData.Status = "complete";
|
eventName = InvoiceEvent.MarkedCompleted;
|
||||||
invoiceData.ExceptionStatus = "marked";
|
break;
|
||||||
|
case InvoiceStatus.Invalid:
|
||||||
|
if (!invoiceData.GetInvoiceState().CanMarkInvalid())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
eventName = InvoiceEvent.MarkedInvalid;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
invoiceData.Status =status.ToString().ToLowerInvariant();
|
||||||
|
invoiceData.ExceptionStatus = InvoiceExceptionStatus.Marked.ToString().ToLowerInvariant();
|
||||||
|
_eventAggregator.Publish(new InvoiceEvent(ToEntity(invoiceData), eventName));
|
||||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
public async Task<InvoiceEntity> GetInvoice(string id, bool inludeAddressData = false)
|
public async Task<InvoiceEntity> GetInvoice(string id, bool inludeAddressData = false)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue