From 42892e24f478080c49a4c6f011cd12d7caa4a8ae Mon Sep 17 00:00:00 2001 From: "nicolas.dorier" Date: Sun, 6 Jan 2019 17:58:11 +0900 Subject: [PATCH 1/3] Remove uneeded database call during derivation scheme registration --- BTCPayServer.Tests/TestAccount.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/BTCPayServer.Tests/TestAccount.cs b/BTCPayServer.Tests/TestAccount.cs index bfe337b52..5ef6b0b08 100644 --- a/BTCPayServer.Tests/TestAccount.cs +++ b/BTCPayServer.Tests/TestAccount.cs @@ -99,10 +99,6 @@ namespace BTCPayServer.Tests var store = parent.PayTester.GetController(UserId, StoreId); ExtKey = new ExtKey().GetWif(SupportedNetwork.NBitcoinNetwork); DerivationScheme = new DerivationStrategyFactory(SupportedNetwork.NBitcoinNetwork).Parse(ExtKey.Neuter().ToString() + (segwit ? "" : "-[legacy]")); - var vm = (StoreViewModel)((ViewResult)store.UpdateStore()).Model; - vm.SpeedPolicy = SpeedPolicy.MediumSpeed; - await store.UpdateStore(vm); - await store.AddDerivationScheme(StoreId, new DerivationSchemeViewModel() { DerivationScheme = DerivationScheme.ToString(), From 40c85d6104b12f35de331edf8f2a8119ee008879 Mon Sep 17 00:00:00 2001 From: Kukks Date: Sun, 6 Jan 2019 10:00:55 +0100 Subject: [PATCH 2/3] Expand Invoice Searching --- .../Controllers/InvoiceController.API.cs | 4 ++-- .../Services/Invoices/InvoiceRepository.cs | 19 ++++++++++++------- .../Views/Invoice/ListInvoices.cshtml | 2 ++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/BTCPayServer/Controllers/InvoiceController.API.cs b/BTCPayServer/Controllers/InvoiceController.API.cs index 58c637a9d..b5b706fa5 100644 --- a/BTCPayServer/Controllers/InvoiceController.API.cs +++ b/BTCPayServer/Controllers/InvoiceController.API.cs @@ -73,8 +73,8 @@ namespace BTCPayServer.Controllers Skip = offset, EndDate = dateEnd, StartDate = dateStart, - OrderId = orderId, - ItemCode = itemCode, + OrderId = orderId == null ? null : new[] { orderId }, + ItemCode = itemCode == null ? null : new[] { itemCode }, Status = status == null ? null : new[] { status }, StoreId = new[] { this.HttpContext.GetStoreData().Id } }; diff --git a/BTCPayServer/Services/Invoices/InvoiceRepository.cs b/BTCPayServer/Services/Invoices/InvoiceRepository.cs index 1ae4befc7..ba9f5bd19 100644 --- a/BTCPayServer/Services/Invoices/InvoiceRepository.cs +++ b/BTCPayServer/Services/Invoices/InvoiceRepository.cs @@ -463,11 +463,16 @@ retry: if (queryObject.EndDate != null) query = query.Where(i => i.Created <= queryObject.EndDate.Value); - if (queryObject.ItemCode != null) - query = query.Where(i => i.ItemCode == queryObject.ItemCode); - - if (queryObject.OrderId != null) - query = query.Where(i => i.OrderId == queryObject.OrderId); + if (queryObject.OrderId != null && queryObject.OrderId.Length > 0) + { + var statusSet = queryObject.OrderId.ToHashSet(); + query = query.Where(i => statusSet.Contains(i.OrderId)); + } + if (queryObject.ItemCode != null && queryObject.ItemCode.Length > 0) + { + var statusSet = queryObject.ItemCode.ToHashSet(); + query = query.Where(i => statusSet.Contains(i.ItemCode)); + } if (queryObject.Status != null && queryObject.Status.Length > 0) { @@ -694,12 +699,12 @@ retry: get; set; } - public string OrderId + public string[] OrderId { get; set; } - public string ItemCode + public string[] ItemCode { get; set; } diff --git a/BTCPayServer/Views/Invoice/ListInvoices.cshtml b/BTCPayServer/Views/Invoice/ListInvoices.cshtml index a415e5706..c3a877d1b 100644 --- a/BTCPayServer/Views/Invoice/ListInvoices.cshtml +++ b/BTCPayServer/Views/Invoice/ListInvoices.cshtml @@ -29,6 +29,8 @@

  • storeid:id for filtering a specific store
  • +
  • orderid:id for filtering a specific order
  • +
  • itemcode:code for filtering a specific type of item purchased through the pos or crowdfund apps
  • status:(expired|invalid|complete|confirmed|paid|new) for filtering a specific status
  • exceptionstatus:(paidover|paidlate|paidpartial) for filtering a specific exception state
  • unusual:(true|false) for filtering invoices which might requires merchant attention (those invalid or with an exceptionstatus)
  • From 5076d7369556743c43b60dfc881755bb419691a4 Mon Sep 17 00:00:00 2001 From: Kukks Date: Sun, 6 Jan 2019 10:12:45 +0100 Subject: [PATCH 3/3] Enhance Invoice Events --- BTCPayServer.Tests/UnitTest1.cs | 11 ++++++----- .../Controllers/InvoiceController.UI.cs | 4 ++-- BTCPayServer/Controllers/InvoiceController.cs | 3 ++- BTCPayServer/Events/InvoiceEvent.cs | 14 ++++++++++++++ .../InvoiceNotificationManager.cs | 16 ++++++++-------- BTCPayServer/HostedServices/InvoiceWatcher.cs | 18 +++++++++--------- BTCPayServer/Models/InvoiceResponse.cs | 6 ++++++ .../Payments/Bitcoin/NBXplorerListener.cs | 2 +- .../Payments/Lightning/LightningListener.cs | 4 ++-- 9 files changed, 50 insertions(+), 28 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 6c94c1115..5734380de 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -51,6 +51,7 @@ using RatesViewModel = BTCPayServer.Models.StoreViewModels.RatesViewModel; using NBitpayClient.Extensions; using BTCPayServer.Services; using System.Text.RegularExpressions; +using BTCPayServer.Events; namespace BTCPayServer.Tests { @@ -521,22 +522,22 @@ namespace BTCPayServer.Tests var evtName = request["event"]["name"].Value(); switch (evtName) { - case "invoice_created": + case InvoiceEvent.Created: tester.ExplorerNode.SendToAddress(url.Address, url.Amount); break; - case "invoice_receivedPayment": + case InvoiceEvent.ReceivedPayment: receivedPayment = true; break; - case "invoice_paidInFull": + case InvoiceEvent.PaidInFull: Assert.True(receivedPayment); tester.ExplorerNode.Generate(6); paid = true; break; - case "invoice_confirmed": + case InvoiceEvent.Confirmed: Assert.True(paid); confirmed = true; break; - case "invoice_completed": + case InvoiceEvent.Completed: Assert.True(paid); //TODO: Fix, out of order event mean we can receive invoice_confirmed after invoice_complete completed = true; break; diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index 74086aba6..4e9803d2d 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -638,13 +638,13 @@ namespace BTCPayServer.Controllers if (newState == "invalid") { await _InvoiceRepository.UpdatePaidInvoiceToInvalid(invoiceId); - _EventAggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1008, "invoice_markedInvalid")); + _EventAggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1008, InvoiceEvent.MarkedInvalid)); StatusMessage = "Invoice marked invalid"; } else if(newState == "complete") { await _InvoiceRepository.UpdatePaidInvoiceToComplete(invoiceId); - _EventAggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 2008, "invoice_markedComplete")); + _EventAggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 2008, InvoiceEvent.MarkedCompleted)); StatusMessage = "Invoice marked complete"; } return RedirectToAction(nameof(ListInvoices)); diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index de58dc171..47c46a615 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using BTCPayServer.Data; +using BTCPayServer.Events; using BTCPayServer.Logging; using BTCPayServer.Models; using BTCPayServer.Payments; @@ -159,7 +160,7 @@ namespace BTCPayServer.Controllers entity.PosData = invoice.PosData; entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, logs, _NetworkProvider); await fetchingAll; - _EventAggregator.Publish(new Events.InvoiceEvent(entity.EntityToDTO(_NetworkProvider), 1001, "invoice_created")); + _EventAggregator.Publish(new Events.InvoiceEvent(entity.EntityToDTO(_NetworkProvider), 1001, InvoiceEvent.Created)); var resp = entity.EntityToDTO(_NetworkProvider); return new DataWrapper(resp) { Facade = "pos/invoice" }; } diff --git a/BTCPayServer/Events/InvoiceEvent.cs b/BTCPayServer/Events/InvoiceEvent.cs index c3d0f60a3..88b3c26b5 100644 --- a/BTCPayServer/Events/InvoiceEvent.cs +++ b/BTCPayServer/Events/InvoiceEvent.cs @@ -8,6 +8,18 @@ namespace BTCPayServer.Events { public class InvoiceEvent { + public const string Created = "invoice_created"; + public const string ReceivedPayment = "invoice_receivedPayment"; + public const string MarkedCompleted = "invoice_markedComplete"; + public const string MarkedInvalid= "invoice_markedInvalid"; + public const string Expired= "invoice_expired"; + public const string ExpiredPaidPartial= "invoice_expiredPaidPartial"; + public const string PaidInFull= "invoice_paidInFull"; + public const string PaidAfterExpiration= "invoice_paidAfterExpiration"; + public const string FailedToConfirm= "invoice_failedToConfirm"; + public const string Confirmed= "invoice_confirmed"; + public const string Completed= "invoice_completed"; + public InvoiceEvent(Models.InvoiceResponse invoice, int code, string name) { Invoice = invoice; @@ -19,6 +31,8 @@ namespace BTCPayServer.Events public int EventCode { get; set; } public string Name { get; set; } + public PaymentEntity Payment { get; set; } + public override string ToString() { return $"Invoice {Invoice.Id} new event: {Name} ({EventCode})"; diff --git a/BTCPayServer/HostedServices/InvoiceNotificationManager.cs b/BTCPayServer/HostedServices/InvoiceNotificationManager.cs index 455050373..b63d5d5d8 100644 --- a/BTCPayServer/HostedServices/InvoiceNotificationManager.cs +++ b/BTCPayServer/HostedServices/InvoiceNotificationManager.cs @@ -341,14 +341,14 @@ namespace BTCPayServer.HostedServices // we need to use the status in the event and not in the invoice. The invoice might now be in another status. if (invoice.FullNotifications) { - if (e.Name == "invoice_expired" || - e.Name == "invoice_paidInFull" || - e.Name == "invoice_failedToConfirm" || - e.Name == "invoice_markedInvalid" || - e.Name == "invoice_markedComplete" || - e.Name == "invoice_failedToConfirm" || - e.Name == "invoice_completed" || - e.Name == "invoice_expiredPaidPartial" + if (e.Name == InvoiceEvent.Expired || + e.Name == InvoiceEvent.PaidInFull || + e.Name == InvoiceEvent.FailedToConfirm || + e.Name == InvoiceEvent.MarkedInvalid || + e.Name == InvoiceEvent.MarkedCompleted || + e.Name == InvoiceEvent.FailedToConfirm || + e.Name == InvoiceEvent.Completed || + e.Name == InvoiceEvent.ExpiredPaidPartial ) tasks.Add(Notify(invoice)); } diff --git a/BTCPayServer/HostedServices/InvoiceWatcher.cs b/BTCPayServer/HostedServices/InvoiceWatcher.cs index c037a9724..7c9687bfc 100644 --- a/BTCPayServer/HostedServices/InvoiceWatcher.cs +++ b/BTCPayServer/HostedServices/InvoiceWatcher.cs @@ -66,10 +66,10 @@ namespace BTCPayServer.HostedServices context.MarkDirty(); await _InvoiceRepository.UnaffectAddress(invoice.Id); - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1004, "invoice_expired")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1004, InvoiceEvent.Expired)); invoice.Status = InvoiceStatus.Expired; if(invoice.ExceptionStatus == InvoiceExceptionStatus.PaidPartial) - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 2000, "invoice_expiredPaidPartial")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 2000, InvoiceEvent.ExpiredPaidPartial)); } var payments = invoice.GetPayments().Where(p => p.Accounted).ToArray(); @@ -84,7 +84,7 @@ namespace BTCPayServer.HostedServices { if (invoice.Status == InvoiceStatus.New) { - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1003, "invoice_paidInFull")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1003, InvoiceEvent.PaidInFull)); invoice.Status = InvoiceStatus.Paid; invoice.ExceptionStatus = accounting.Paid > accounting.TotalDue ? InvoiceExceptionStatus.PaidOver : InvoiceExceptionStatus.None; await _InvoiceRepository.UnaffectAddress(invoice.Id); @@ -93,7 +93,7 @@ namespace BTCPayServer.HostedServices else if (invoice.Status == InvoiceStatus.Expired && invoice.ExceptionStatus != InvoiceExceptionStatus.PaidLate) { invoice.ExceptionStatus = InvoiceExceptionStatus.PaidLate; - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1009, "invoice_paidAfterExpiration")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1009, InvoiceEvent.PaidAfterExpiration)); context.MarkDirty(); } } @@ -139,14 +139,14 @@ namespace BTCPayServer.HostedServices (confirmedAccounting.Paid < accounting.MinimumTotalDue)) { await _InvoiceRepository.UnaffectAddress(invoice.Id); - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1013, "invoice_failedToConfirm")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1013, InvoiceEvent.FailedToConfirm)); invoice.Status = InvoiceStatus.Invalid; context.MarkDirty(); } else if (confirmedAccounting.Paid >= accounting.MinimumTotalDue) { await _InvoiceRepository.UnaffectAddress(invoice.Id); - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1005, "invoice_confirmed")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1005, InvoiceEvent.Confirmed)); invoice.Status = InvoiceStatus.Confirmed; context.MarkDirty(); } @@ -157,7 +157,7 @@ namespace BTCPayServer.HostedServices var completedAccounting = paymentMethod.Calculate(p => p.GetCryptoPaymentData().PaymentCompleted(p, network)); if (completedAccounting.Paid >= accounting.MinimumTotalDue) { - context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1006, "invoice_completed")); + context.Events.Add(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1006, InvoiceEvent.Completed)); invoice.Status = InvoiceStatus.Complete; context.MarkDirty(); } @@ -247,13 +247,13 @@ namespace BTCPayServer.HostedServices })); leases.Add(_EventAggregator.Subscribe(async b => { - if (b.Name == "invoice_created") + if (b.Name == InvoiceEvent.Created) { Watch(b.Invoice.Id); await Wait(b.Invoice.Id); } - if (b.Name == "invoice_receivedPayment") + if (b.Name == InvoiceEvent.ReceivedPayment) { Watch(b.Invoice.Id); } diff --git a/BTCPayServer/Models/InvoiceResponse.cs b/BTCPayServer/Models/InvoiceResponse.cs index df47d65a9..486a3b906 100644 --- a/BTCPayServer/Models/InvoiceResponse.cs +++ b/BTCPayServer/Models/InvoiceResponse.cs @@ -40,6 +40,12 @@ namespace BTCPayServer.Models //{"facade":"pos/invoice","data":{,}} public class InvoiceResponse { + [JsonIgnore] + public string StoreId + { + get; set; + } + //"url":"https://test.bitpay.com/invoice?id=9saCHtp1zyPcNoi3rDdBu8" [JsonProperty("url")] public string Url diff --git a/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs b/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs index ad8acabc4..77b31d4f5 100644 --- a/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs +++ b/BTCPayServer/Payments/Bitcoin/NBXplorerListener.cs @@ -373,7 +373,7 @@ namespace BTCPayServer.Payments.Bitcoin invoice.SetPaymentMethod(paymentMethod); } wallet.InvalidateCache(strategy); - _Aggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1002, "invoice_receivedPayment")); + _Aggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1002, InvoiceEvent.ReceivedPayment){Payment = payment}); return invoice; } public Task StopAsync(CancellationToken cancellationToken) diff --git a/BTCPayServer/Payments/Lightning/LightningListener.cs b/BTCPayServer/Payments/Lightning/LightningListener.cs index e81e14400..6ec855458 100644 --- a/BTCPayServer/Payments/Lightning/LightningListener.cs +++ b/BTCPayServer/Payments/Lightning/LightningListener.cs @@ -42,7 +42,7 @@ namespace BTCPayServer.Payments.Lightning { leases.Add(_Aggregator.Subscribe(async inv => { - if (inv.Name == "invoice_created") + if (inv.Name == InvoiceEvent.Created) { await EnsureListening(inv.Invoice.Id, false); } @@ -197,7 +197,7 @@ namespace BTCPayServer.Payments.Lightning { var invoice = await _InvoiceRepository.GetInvoice(listenedInvoice.InvoiceId); if (invoice != null) - _Aggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1002, "invoice_receivedPayment")); + _Aggregator.Publish(new InvoiceEvent(invoice.EntityToDTO(_NetworkProvider), 1002, InvoiceEvent.ReceivedPayment){Payment = payment}); } }