mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
start work on payment tolerance feature
This commit is contained in:
@@ -98,6 +98,7 @@ namespace BTCPayServer.Controllers
|
|||||||
entity.ExtendedNotifications = invoice.ExtendedNotifications;
|
entity.ExtendedNotifications = invoice.ExtendedNotifications;
|
||||||
entity.NotificationURL = notificationUri?.AbsoluteUri;
|
entity.NotificationURL = notificationUri?.AbsoluteUri;
|
||||||
entity.BuyerInformation = Map<Invoice, BuyerInformation>(invoice);
|
entity.BuyerInformation = Map<Invoice, BuyerInformation>(invoice);
|
||||||
|
entity.PaymentTolerance = storeBlob.PaymentTolerance;
|
||||||
//Another way of passing buyer info to support
|
//Another way of passing buyer info to support
|
||||||
FillBuyerInfo(invoice.Buyer, entity.BuyerInformation);
|
FillBuyerInfo(invoice.Buyer, entity.BuyerInformation);
|
||||||
if (entity?.BuyerInformation?.BuyerEmail != null)
|
if (entity?.BuyerInformation?.BuyerEmail != null)
|
||||||
|
|||||||
@@ -431,6 +431,7 @@ namespace BTCPayServer.Controllers
|
|||||||
vm.MonitoringExpiration = storeBlob.MonitoringExpiration;
|
vm.MonitoringExpiration = storeBlob.MonitoringExpiration;
|
||||||
vm.InvoiceExpiration = storeBlob.InvoiceExpiration;
|
vm.InvoiceExpiration = storeBlob.InvoiceExpiration;
|
||||||
vm.LightningDescriptionTemplate = storeBlob.LightningDescriptionTemplate;
|
vm.LightningDescriptionTemplate = storeBlob.LightningDescriptionTemplate;
|
||||||
|
vm.PaymentTolerance = storeBlob.PaymentTolerance;
|
||||||
return View(vm);
|
return View(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,6 +497,7 @@ namespace BTCPayServer.Controllers
|
|||||||
blob.MonitoringExpiration = model.MonitoringExpiration;
|
blob.MonitoringExpiration = model.MonitoringExpiration;
|
||||||
blob.InvoiceExpiration = model.InvoiceExpiration;
|
blob.InvoiceExpiration = model.InvoiceExpiration;
|
||||||
blob.LightningDescriptionTemplate = model.LightningDescriptionTemplate ?? string.Empty;
|
blob.LightningDescriptionTemplate = model.LightningDescriptionTemplate ?? string.Empty;
|
||||||
|
blob.PaymentTolerance = model.PaymentTolerance;
|
||||||
|
|
||||||
if (StoreData.SetStoreBlob(blob))
|
if (StoreData.SetStoreBlob(blob))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ namespace BTCPayServer.Data
|
|||||||
{
|
{
|
||||||
InvoiceExpiration = 15;
|
InvoiceExpiration = 15;
|
||||||
MonitoringExpiration = 60;
|
MonitoringExpiration = 60;
|
||||||
|
PaymentTolerance = 0;
|
||||||
RequiresRefundEmail = true;
|
RequiresRefundEmail = true;
|
||||||
}
|
}
|
||||||
public bool NetworkFeeDisabled
|
public bool NetworkFeeDisabled
|
||||||
@@ -326,6 +327,10 @@ namespace BTCPayServer.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DefaultValue(0)]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||||
|
public double PaymentTolerance { get; set; }
|
||||||
|
|
||||||
public BTCPayServer.Rating.RateRules GetRateRules(BTCPayNetworkProvider networkProvider)
|
public BTCPayServer.Rating.RateRules GetRateRules(BTCPayNetworkProvider networkProvider)
|
||||||
{
|
{
|
||||||
if (!RateScripting ||
|
if (!RateScripting ||
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ namespace BTCPayServer.HostedServices
|
|||||||
{
|
{
|
||||||
if (e.Name == "invoice_expired" ||
|
if (e.Name == "invoice_expired" ||
|
||||||
e.Name == "invoice_paidInFull" ||
|
e.Name == "invoice_paidInFull" ||
|
||||||
|
e.Name == "invoice_paidWithinTolerance" ||
|
||||||
e.Name == "invoice_failedToConfirm" ||
|
e.Name == "invoice_failedToConfirm" ||
|
||||||
e.Name == "invoice_markedInvalid" ||
|
e.Name == "invoice_markedInvalid" ||
|
||||||
e.Name == "invoice_failedToConfirm" ||
|
e.Name == "invoice_failedToConfirm" ||
|
||||||
|
|||||||
@@ -96,11 +96,28 @@ namespace BTCPayServer.HostedServices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accounting.Paid < accounting.TotalDue && invoice.GetPayments().Count != 0 && invoice.ExceptionStatus != "paidPartial")
|
if (accounting.Paid < accounting.TotalDue && invoice.GetPayments().Count != 0)
|
||||||
{
|
{
|
||||||
invoice.ExceptionStatus = "paidPartial";
|
if (invoice.PaymentTolerance > 0)
|
||||||
context.MarkDirty();
|
{
|
||||||
|
var tolerantAmount = (accounting.TotalDue.Satoshi * (invoice.PaymentTolerance / 100));
|
||||||
|
var minimumTotalDue = accounting.TotalDue.Satoshi - tolerantAmount;
|
||||||
|
if (accounting.Paid.Satoshi >= minimumTotalDue)
|
||||||
|
{
|
||||||
|
context.Events.Add(new InvoiceEvent(invoice, 1003, "invoide_paidWithinTolerance"));
|
||||||
|
invoice.ExceptionStatus = "paidWithinTolerance";
|
||||||
|
invoice.Status = "paid";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invoice.ExceptionStatus != "paidPartial")
|
||||||
|
{
|
||||||
|
invoice.ExceptionStatus = "paidPartial";
|
||||||
|
context.MarkDirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just make sure RBF did not cancelled a payment
|
// Just make sure RBF did not cancelled a payment
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ namespace BTCPayServer.Models
|
|||||||
}
|
}
|
||||||
|
|
||||||
//"exceptionStatus":false
|
//"exceptionStatus":false
|
||||||
//Can be `paidPartial`, `paidOver`, or false
|
//Can be `paidPartial`, `paidOver`, `paidWithinTolerance` or false
|
||||||
[JsonProperty("exceptionStatus")]
|
[JsonProperty("exceptionStatus")]
|
||||||
public JToken ExceptionStatus
|
public JToken ExceptionStatus
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -85,5 +85,13 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
} = new List<LightningNode>();
|
} = new List<LightningNode>();
|
||||||
|
|
||||||
|
[Display(Name = "Consider the invoice paid even if the paid amount is ... % less than expected")]
|
||||||
|
[Range(0, 100)]
|
||||||
|
public double PaymentTolerance
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
}
|
}
|
||||||
public bool ExtendedNotifications { get; set; }
|
public bool ExtendedNotifications { get; set; }
|
||||||
public List<InvoiceEventData> Events { get; internal set; }
|
public List<InvoiceEventData> Events { get; internal set; }
|
||||||
|
public double PaymentTolerance { get; set; }
|
||||||
|
|
||||||
public bool IsExpired()
|
public bool IsExpired()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,6 +44,11 @@
|
|||||||
<input asp-for="MonitoringExpiration" class="form-control" />
|
<input asp-for="MonitoringExpiration" class="form-control" />
|
||||||
<span asp-validation-for="MonitoringExpiration" class="text-danger"></span>
|
<span asp-validation-for="MonitoringExpiration" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="PaymentTolerance"></label>
|
||||||
|
<input asp-for="PaymentTolerance" class="form-control" />
|
||||||
|
<span asp-validation-for="PaymentTolerance" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="SpeedPolicy"></label>
|
<label asp-for="SpeedPolicy"></label>
|
||||||
<select asp-for="SpeedPolicy" class="form-control">
|
<select asp-for="SpeedPolicy" class="form-control">
|
||||||
|
|||||||
Reference in New Issue
Block a user