mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Better handle transition from paid to invalid
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
<Version>1.0.0.21</Version>
|
<Version>1.0.0.22</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Build\dockerfiles\**" />
|
<Compile Remove="Build\dockerfiles\**" />
|
||||||
|
|||||||
@@ -75,8 +75,9 @@ namespace BTCPayServer.Controllers
|
|||||||
_FeeProvider = feeProvider ?? throw new ArgumentNullException(nameof(feeProvider));
|
_FeeProvider = feeProvider ?? throw new ArgumentNullException(nameof(feeProvider));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<DataWrapper<InvoiceResponse>> CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl, double expiryMinutes = 15)
|
internal async Task<DataWrapper<InvoiceResponse>> CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl, double expiryMinutes = 15, double monitoringMinutes = 60)
|
||||||
{
|
{
|
||||||
|
//TODO: expiryMinutes (time before a new invoice can become paid) and monitoringMinutes (time before a paid invoice becomes invalid) should be configurable at store level
|
||||||
var derivationStrategy = store.DerivationStrategy;
|
var derivationStrategy = store.DerivationStrategy;
|
||||||
var entity = new InvoiceEntity
|
var entity = new InvoiceEntity
|
||||||
{
|
{
|
||||||
@@ -88,6 +89,7 @@ namespace BTCPayServer.Controllers
|
|||||||
notificationUri = null;
|
notificationUri = null;
|
||||||
EmailAddressAttribute emailValidator = new EmailAddressAttribute();
|
EmailAddressAttribute emailValidator = new EmailAddressAttribute();
|
||||||
entity.ExpirationTime = entity.InvoiceTime.AddMinutes(expiryMinutes);
|
entity.ExpirationTime = entity.InvoiceTime.AddMinutes(expiryMinutes);
|
||||||
|
entity.MonitoringExpiration = entity.InvoiceTime.AddMinutes(monitoringMinutes);
|
||||||
entity.OrderId = invoice.OrderId;
|
entity.OrderId = invoice.OrderId;
|
||||||
entity.ServerUrl = serverUrl;
|
entity.ServerUrl = serverUrl;
|
||||||
entity.FullNotifications = invoice.FullNotifications;
|
entity.FullNotifications = invoice.FullNotifications;
|
||||||
|
|||||||
@@ -248,6 +248,11 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
public DateTimeOffset? MonitoringExpiration
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsExpired()
|
public bool IsExpired()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -80,7 +80,9 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
Logs.PayServer.LogInformation($"Invoice {invoice.Id}: {stateBefore} => {invoice.Status}");
|
Logs.PayServer.LogInformation($"Invoice {invoice.Id}: {stateBefore} => {invoice.Status}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(invoice.Status == "complete" || invoice.Status == "invalid")
|
var expirationMonitoring = invoice.MonitoringExpiration.HasValue ? invoice.MonitoringExpiration.Value : invoice.InvoiceTime + TimeSpan.FromMinutes(60);
|
||||||
|
if(invoice.Status == "complete" ||
|
||||||
|
((invoice.Status == "invalid" || invoice.Status == "expired") && expirationMonitoring < DateTimeOffset.UtcNow))
|
||||||
{
|
{
|
||||||
if(await _InvoiceRepository.RemovePendingInvoice(invoice.Id).ConfigureAwait(false))
|
if(await _InvoiceRepository.RemovePendingInvoice(invoice.Id).ConfigureAwait(false))
|
||||||
Logs.PayServer.LogInformation("Stopped watching invoice " + invoiceId);
|
Logs.PayServer.LogInformation("Stopped watching invoice " + invoiceId);
|
||||||
@@ -106,15 +108,7 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
private async Task<(bool NeedSave, UTXOChanges Changes)> UpdateInvoice(UTXOChanges changes, InvoiceEntity invoice)
|
private async Task<(bool NeedSave, UTXOChanges Changes)> UpdateInvoice(UTXOChanges changes, InvoiceEntity invoice)
|
||||||
{
|
{
|
||||||
bool needSave = false;
|
bool needSave = false;
|
||||||
|
//Fetch unknown payments
|
||||||
if(invoice.Status == "new" && invoice.ExpirationTime < DateTimeOffset.UtcNow)
|
|
||||||
{
|
|
||||||
needSave = true;
|
|
||||||
invoice.Status = "expired";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(invoice.Status == "expired" || invoice.Status == "new" || invoice.Status == "invalid")
|
|
||||||
{
|
|
||||||
var strategy = _DerivationFactory.Parse(invoice.DerivationStrategy);
|
var strategy = _DerivationFactory.Parse(invoice.DerivationStrategy);
|
||||||
changes = await _ExplorerClient.SyncAsync(strategy, changes, !LongPollingMode, _Cts.Token).ConfigureAwait(false);
|
changes = await _ExplorerClient.SyncAsync(strategy, changes, !LongPollingMode, _Cts.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
@@ -135,19 +129,21 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
{
|
{
|
||||||
var payment = await _InvoiceRepository.AddPayment(invoice.Id, coin).ConfigureAwait(false);
|
var payment = await _InvoiceRepository.AddPayment(invoice.Id, coin).ConfigureAwait(false);
|
||||||
invoice.Payments.Add(payment);
|
invoice.Payments.Add(payment);
|
||||||
if(invoice.Status == "expired")
|
}
|
||||||
|
//////
|
||||||
|
|
||||||
|
if(invoice.Status == "new" && invoice.ExpirationTime < DateTimeOffset.UtcNow)
|
||||||
{
|
{
|
||||||
if(invoice.ExceptionStatus == null)
|
|
||||||
invoice.ExceptionStatus = "paidLate";
|
|
||||||
needSave = true;
|
needSave = true;
|
||||||
}
|
invoice.Status = "expired";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(invoice.Status == "new")
|
if(invoice.Status == "new" || invoice.Status == "expired")
|
||||||
{
|
{
|
||||||
var totalPaid = invoice.Payments.Select(p => p.Output.Value).Sum();
|
var totalPaid = invoice.Payments.Select(p => p.Output.Value).Sum();
|
||||||
if(totalPaid >= invoice.GetTotalCryptoDue())
|
if(totalPaid >= invoice.GetTotalCryptoDue())
|
||||||
|
{
|
||||||
|
if(invoice.Status == "new")
|
||||||
{
|
{
|
||||||
invoice.Status = "paid";
|
invoice.Status = "paid";
|
||||||
if(invoice.FullNotifications)
|
if(invoice.FullNotifications)
|
||||||
@@ -157,6 +153,12 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
invoice.ExceptionStatus = null;
|
invoice.ExceptionStatus = null;
|
||||||
needSave = true;
|
needSave = true;
|
||||||
}
|
}
|
||||||
|
else if(invoice.Status == "expired")
|
||||||
|
{
|
||||||
|
invoice.ExceptionStatus = "paidLate";
|
||||||
|
needSave = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(totalPaid > invoice.GetTotalCryptoDue() && invoice.ExceptionStatus != "paidOver")
|
if(totalPaid > invoice.GetTotalCryptoDue() && invoice.ExceptionStatus != "paidOver")
|
||||||
{
|
{
|
||||||
@@ -172,6 +174,8 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(invoice.Status == "paid")
|
if(invoice.Status == "paid")
|
||||||
|
{
|
||||||
|
if(!invoice.MonitoringExpiration.HasValue || invoice.MonitoringExpiration > DateTimeOffset.UtcNow)
|
||||||
{
|
{
|
||||||
var transactions = await GetPaymentsWithTransaction(invoice);
|
var transactions = await GetPaymentsWithTransaction(invoice);
|
||||||
if(invoice.SpeedPolicy == SpeedPolicy.HighSpeed)
|
if(invoice.SpeedPolicy == SpeedPolicy.HighSpeed)
|
||||||
@@ -195,6 +199,12 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
needSave = true;
|
needSave = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
invoice.Status = "invalid";
|
||||||
|
needSave = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(invoice.Status == "confirmed")
|
if(invoice.Status == "confirmed")
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user