From 4c57405945229194b992dffe1f4cfeed153a8663 Mon Sep 17 00:00:00 2001 From: Nicolas Dorier Date: Fri, 30 Jul 2021 18:46:49 +0900 Subject: [PATCH] Properly clip taxIncluded and invoice's amount (#2724) --- BTCPayServer.Tests/UnitTest1.cs | 16 ++++++++++ BTCPayServer/Controllers/InvoiceController.cs | 31 ++++++++++++------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs index 6c6a4fe01..eac4c83e3 100644 --- a/BTCPayServer.Tests/UnitTest1.cs +++ b/BTCPayServer.Tests/UnitTest1.cs @@ -2803,6 +2803,22 @@ namespace BTCPayServer.Tests var invoice = user.BitPay.CreateInvoice( new Invoice() { Price = -0.1m, Currency = "BTC", FullNotifications = true }, Facade.Merchant); Assert.Equal(0.0m, invoice.Price); + + // Should round down to 50.51, taxIncluded should be also clipped to this value because taxIncluded can't be higher than the price. + var invoice5 = user.BitPay.CreateInvoice( + new Invoice() { Price = 50.513m, Currency = "USD", FullNotifications = true, TaxIncluded = 50.516m }, Facade.Merchant); + Assert.Equal(50.51m, invoice5.Price); + Assert.Equal(50.51m, invoice5.TaxIncluded); + + var greenfield = await user.CreateClient(); + var invoice5g = await greenfield.CreateInvoice(user.StoreId, new CreateInvoiceRequest() + { + Amount = 50.513m, + Currency = "USD", + Metadata = new JObject() { new JProperty("taxIncluded", 50.516m) } + }); + Assert.Equal(50.51m, invoice5g.Amount); + Assert.Equal(50.51m, (decimal)invoice5g.Metadata["taxIncluded"]); } } diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index d5c971ef3..21f01e3ff 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -112,24 +112,14 @@ namespace BTCPayServer.Controllers FillBuyerInfo(invoice, entity); var taxIncluded = invoice.TaxIncluded.HasValue ? invoice.TaxIncluded.Value : 0m; + var price = invoice.Price; - var currencyInfo = _CurrencyNameTable.GetNumberFormatInfo(invoice.Currency, false); - if (currencyInfo != null) - { - int divisibility = currencyInfo.CurrencyDecimalDigits; - invoice.Price = invoice.Price.RoundToSignificant(ref divisibility); - divisibility = currencyInfo.CurrencyDecimalDigits; - invoice.TaxIncluded = taxIncluded.RoundToSignificant(ref divisibility); - } - invoice.Price = Math.Max(0.0m, invoice.Price); - invoice.TaxIncluded = Math.Max(0.0m, taxIncluded); - invoice.TaxIncluded = Math.Min(taxIncluded, invoice.Price); entity.Metadata.ItemCode = invoice.ItemCode; entity.Metadata.ItemDesc = invoice.ItemDesc; entity.Metadata.Physical = invoice.Physical; entity.Metadata.TaxIncluded = invoice.TaxIncluded; entity.Currency = invoice.Currency; - entity.Price = invoice.Price; + entity.Price = price; entity.RedirectURLTemplate = invoice.RedirectURL ?? store.StoreWebsite; entity.RedirectAutomatically = @@ -195,6 +185,23 @@ namespace BTCPayServer.Controllers InvoiceLogs logs = new InvoiceLogs(); logs.Write("Creation of invoice starting", InvoiceEventData.EventSeverity.Info); + entity.Price = Math.Max(0.0m, entity.Price); + var currencyInfo = _CurrencyNameTable.GetNumberFormatInfo(entity.Currency, false); + if (currencyInfo != null) + { + entity.Price = entity.Price.RoundToSignificant(currencyInfo.CurrencyDecimalDigits); + } + if (entity.Metadata.TaxIncluded is decimal taxIncluded) + { + if (currencyInfo != null) + { + taxIncluded = taxIncluded.RoundToSignificant(currencyInfo.CurrencyDecimalDigits); + } + taxIncluded = Math.Max(0.0m, taxIncluded); + taxIncluded = Math.Min(taxIncluded, entity.Price); + entity.Metadata.TaxIncluded = taxIncluded; + } + var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id); var storeBlob = store.GetStoreBlob();