Fix: PaymentRequest get expired even if paid on time

This commit is contained in:
nicolas.dorier
2025-04-09 18:47:10 +09:00
parent 5df2ffe689
commit ba9646f486
4 changed files with 22 additions and 17 deletions

View File

@@ -1,4 +1,6 @@
using System;
using System.ComponentModel.DataAnnotations.Schema;
using BTCPayServer.Client.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -18,6 +20,9 @@ namespace BTCPayServer.Data
public Client.Models.PaymentRequestStatus Status { get; set; }
[NotMapped]
public bool Expirable => Status is PaymentRequestStatus.Pending or PaymentRequestStatus.Processing && Expiry is not null;
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
public string Blob2 { get; set; }

View File

@@ -199,7 +199,7 @@ namespace BTCPayServer.PaymentRequest
{
if (data is
{
Status: PaymentRequestStatus.Pending or PaymentRequestStatus.Processing,
Expirable: true,
Expiry: { } e
})
{

View File

@@ -10,6 +10,7 @@ using BTCPayServer.Services.Apps;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.PaymentRequests;
using BTCPayServer.Services.Rates;
using static System.Runtime.InteropServices.JavaScript.JSType;
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
namespace BTCPayServer.PaymentRequest
@@ -50,24 +51,21 @@ namespace BTCPayServer.PaymentRequest
public async Task UpdatePaymentRequestStateIfNeeded(PaymentRequestData pr)
{
var blob = pr.GetBlob();
var currentStatus = pr.Status;
if (pr.Expiry.HasValue)
var newStatus = pr.Status;
newStatus = pr switch
{
if (pr.Expiry.Value <= DateTimeOffset.UtcNow)
currentStatus = Client.Models.PaymentRequestStatus.Expired;
}
else if (currentStatus != Client.Models.PaymentRequestStatus.Completed)
{
currentStatus = Client.Models.PaymentRequestStatus.Pending;
}
{ Expirable: true, Expiry: { } e }
when e <= DateTimeOffset.UtcNow => PaymentRequestStatus.Expired,
{ Status: PaymentRequestStatus.Expired, Expiry: null } => PaymentRequestStatus.Pending,
_ => pr.Status
};
if (currentStatus != Client.Models.PaymentRequestStatus.Expired)
if (newStatus is not (PaymentRequestStatus.Expired or PaymentRequestStatus.Completed))
{
var invoices = await _paymentRequestRepository.GetInvoicesForPaymentRequest(pr.Id);
var contributions = _invoiceRepository.GetContributionsByPaymentMethodId(pr.Currency, invoices, true);
currentStatus =
newStatus =
(PaidEnough: contributions.Total >= pr.Amount,
SettledEnough: contributions.TotalSettled >= pr.Amount) switch
{
@@ -77,10 +75,10 @@ namespace BTCPayServer.PaymentRequest
};
}
if (currentStatus != pr.Status)
if (newStatus != pr.Status)
{
pr.Status = currentStatus;
await _paymentRequestRepository.UpdatePaymentRequestStatus(pr.Id, currentStatus);
pr.Status = newStatus;
await _paymentRequestRepository.UpdatePaymentRequestStatus(pr.Id, newStatus);
}
}

View File

@@ -22,6 +22,8 @@ namespace BTCPayServer.Services
var due = ExecuteAt - DateTimeOffset.UtcNow;
if (due < TimeSpan.Zero)
due = TimeSpan.Zero;
else
due += TimeSpan.FromSeconds(1.0); // Better to be a bit late than too early
// Max timer needed, else dotnet crash
if (due > MaxTimer)
due = MaxTimer;
@@ -61,7 +63,7 @@ namespace BTCPayServer.Services
var s = (TimerState)state!;
Task.Run(async () =>
{
bool run = s.NextWait() == TimeSpan.Zero;
bool run = s.NextWait() < TimeSpan.FromSeconds(5.0);
try
{
if (run)