diff --git a/BTCPayServer.Tests/CheckoutUITests.cs b/BTCPayServer.Tests/CheckoutUITests.cs index b48711e2b..294d1eae6 100644 --- a/BTCPayServer.Tests/CheckoutUITests.cs +++ b/BTCPayServer.Tests/CheckoutUITests.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Payments; using BTCPayServer.Tests.Logging; using BTCPayServer.Views.Stores; @@ -27,6 +28,7 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.AddDerivationScheme(); s.GoToStore(StoreNavPages.CheckoutAppearance); s.Driver.FindElement(By.Id("RequiresRefundEmail")).Click(); @@ -72,6 +74,7 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.AddDerivationScheme(); // Now create an invoice that requires a refund email @@ -124,6 +127,7 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.AddDerivationScheme(); var invoiceId = s.CreateInvoice(); @@ -154,12 +158,12 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(true); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.AddLightningNode(); s.AddDerivationScheme(); var invoiceId = s.CreateInvoice(defaultPaymentMethod: "BTC_LightningLike"); s.GoToInvoiceCheckout(invoiceId); - Assert.Equal("Bitcoin (Lightning) (BTC)", s.Driver.FindElement(By.ClassName("payment__currencies")).Text); s.Driver.Quit(); } @@ -174,6 +178,7 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(true); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.AddLightningNode(); s.GoToLightningSettings(); s.Driver.SetCheckbox(By.Id("LightningAmountInSatoshi"), true); @@ -193,6 +198,7 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.GoToStore(); s.AddDerivationScheme(); var invoiceId = s.CreateInvoice(0.001m, "BTC", "a@x.com"); diff --git a/BTCPayServer.Tests/Checkoutv2Tests.cs b/BTCPayServer.Tests/Checkoutv2Tests.cs index d2123c75f..4836c1123 100644 --- a/BTCPayServer.Tests/Checkoutv2Tests.cs +++ b/BTCPayServer.Tests/Checkoutv2Tests.cs @@ -1,11 +1,13 @@ using System; using System.Threading; using System.Threading.Tasks; +using BTCPayServer.Client.Models; using BTCPayServer.Payments; using BTCPayServer.Tests.Logging; using BTCPayServer.Views.Stores; using NBitcoin; using OpenQA.Selenium; +using OpenQA.Selenium.Support.Extensions; using OpenQA.Selenium.Support.UI; using Xunit; using Xunit.Abstractions; @@ -32,7 +34,6 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(true); s.CreateNewStore(); - s.EnableCheckoutV2(); s.AddLightningNode(); // Use non-legacy derivation scheme s.AddDerivationScheme("BTC", "tpubDD79XF4pzhmPSJ9AyUay9YbXAeD1c6nkUqC32pnKARJH6Ja5hGUfGc76V82ahXpsKqN6UcSGXMkzR34aZq4W23C6DAdZFaVrzWqzj24F8BC"); @@ -148,7 +149,7 @@ namespace BTCPayServer.Tests Assert.True(expiredSection.Displayed); Assert.Contains("Invoice Expired", expiredSection.Text); }); - Assert.True(s.Driver.ElementDoesNotExist(By.Id("ReceiptLink"))); + Assert.True(s.Driver.ElementDoesNotExist(By.Id("receipt-btn"))); Assert.Equal(storeUrl, s.Driver.FindElement(By.Id("StoreLink")).GetAttribute("href")); // Test payment @@ -179,23 +180,16 @@ namespace BTCPayServer.Tests await s.Server.ExplorerNode.GenerateAsync(1); // Fake Pay - s.Driver.FindElement(By.Id("FakePayAmount")).FillIn(amountFraction); - s.Driver.FindElement(By.Id("FakePay")).Click(); TestUtils.Eventually(() => { - Assert.Contains("Created transaction", - s.Driver.WaitForElement(By.Id("CheatSuccessMessage")).Text); - s.Server.ExplorerNode.Generate(2); paymentInfo = s.Driver.WaitForElement(By.Id("PaymentInfo")); Assert.Contains("The invoice hasn't been paid in full", paymentInfo.Text); Assert.Contains("Please send", paymentInfo.Text); }); + s.Driver.Navigate().Refresh(); // Pay full amount - var amountDue = s.Driver.FindElement(By.Id("AmountDue")).GetAttribute("data-amount-due"); - s.Driver.FindElement(By.Id("FakePayAmount")).FillIn(amountDue); - s.Driver.FindElement(By.Id("FakePay")).Click(); - + s.PayInvoice(); // Processing TestUtils.Eventually(() => { @@ -205,9 +199,8 @@ namespace BTCPayServer.Tests Assert.Contains("Your payment has been received and is now processing", processingSection.Text); Assert.True(s.Driver.ElementDoesNotExist(By.Id("confetti"))); }); - // Mine - s.Driver.FindElement(By.Id("Mine")).Click(); + s.MineBlockOnInvoiceCheckout(); TestUtils.Eventually(() => { Assert.Contains("Mined 1 block", @@ -222,7 +215,7 @@ namespace BTCPayServer.Tests Assert.Contains("Invoice Paid", settledSection.Text); }); s.Driver.FindElement(By.Id("confetti")); - s.Driver.FindElement(By.Id("ReceiptLink")); + s.Driver.FindElement(By.Id("receipt-btn")); Assert.Equal(storeUrl, s.Driver.FindElement(By.Id("StoreLink")).GetAttribute("href")); // BIP21 @@ -412,7 +405,6 @@ namespace BTCPayServer.Tests s.GoToRegister(); s.RegisterNewUser(); s.CreateNewStore(); - s.EnableCheckoutV2(); s.GoToStore(); s.AddDerivationScheme(); var invoiceId = s.CreateInvoice(0.001m, "BTC", "a@x.com"); diff --git a/BTCPayServer.Tests/PayJoinTests.cs b/BTCPayServer.Tests/PayJoinTests.cs index 481d9b918..9b889ea03 100644 --- a/BTCPayServer.Tests/PayJoinTests.cs +++ b/BTCPayServer.Tests/PayJoinTests.cs @@ -249,6 +249,7 @@ namespace BTCPayServer.Tests await s.StartAsync(); s.RegisterNewUser(true); var receiver = s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); var receiverSeed = s.GenerateWallet("BTC", "", true, true, ScriptPubKeyType.Segwit); var receiverWalletId = new WalletId(receiver.storeId, "BTC"); @@ -303,6 +304,7 @@ namespace BTCPayServer.Tests { var cryptoCode = "BTC"; var receiver = s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); var receiverSeed = s.GenerateWallet(cryptoCode, "", true, true, format); var receiverWalletId = new WalletId(receiver.storeId, cryptoCode); diff --git a/BTCPayServer.Tests/SeleniumTester.cs b/BTCPayServer.Tests/SeleniumTester.cs index cd21324f0..f9f4b1c57 100644 --- a/BTCPayServer.Tests/SeleniumTester.cs +++ b/BTCPayServer.Tests/SeleniumTester.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using BTCPayServer.Abstractions.Extensions; using BTCPayServer.Abstractions.Models; +using BTCPayServer.Client.Models; using BTCPayServer.Lightning; using BTCPayServer.Lightning.CLightning; using BTCPayServer.Views.Manage; @@ -94,6 +95,7 @@ namespace BTCPayServer.Tests Driver.FindElement(By.Id("test-payment-amount")).Clear(); Driver.FindElement(By.Id("test-payment-amount")).SendKeys(amount.ToString()); } + Driver.WaitUntilAvailable(By.Id("FakePayment")); Driver.FindElement(By.Id("FakePayment")).Click(); if (mine) { @@ -193,16 +195,22 @@ namespace BTCPayServer.Tests StoreId = storeId; return (name, storeId); } - - public void EnableCheckoutV2(bool bip21 = false) + public void EnableCheckout(CheckoutType checkoutType, bool bip21 = false) { GoToStore(StoreNavPages.CheckoutAppearance); - Driver.SetCheckbox(By.Id("UseNewCheckout"), true); - Driver.WaitForElement(By.Id("OnChainWithLnInvoiceFallback")); - Driver.SetCheckbox(By.Id("OnChainWithLnInvoiceFallback"), bip21); + if (checkoutType == CheckoutType.V2) + { + Driver.SetCheckbox(By.Id("UseClassicCheckout"), false); + Driver.WaitForElement(By.Id("OnChainWithLnInvoiceFallback")); + Driver.SetCheckbox(By.Id("OnChainWithLnInvoiceFallback"), bip21); + } + else + { + Driver.SetCheckbox(By.Id("UseClassicCheckout"), true); + } Driver.FindElement(By.Id("Save")).SendKeys(Keys.Enter); Assert.Contains("Store successfully updated", FindAlertMessage().Text); - Assert.True(Driver.FindElement(By.Id("UseNewCheckout")).Selected); + Assert.True(Driver.FindElement(By.Id("UseClassicCheckout")).Selected); } public Mnemonic GenerateWallet(string cryptoCode = "BTC", string seed = "", bool? importkeys = null, bool isHotWallet = false, ScriptPubKeyType format = ScriptPubKeyType.Segwit) diff --git a/BTCPayServer.Tests/SeleniumTests.cs b/BTCPayServer.Tests/SeleniumTests.cs index 386735920..024446183 100644 --- a/BTCPayServer.Tests/SeleniumTests.cs +++ b/BTCPayServer.Tests/SeleniumTests.cs @@ -592,7 +592,7 @@ namespace BTCPayServer.Tests s.GoToInvoices(s.StoreId); s.GoToInvoiceCheckout(i); var checkouturi = s.Driver.Url; - s.PayInvoice(); + s.PayInvoice(mine: true); TestUtils.Eventually(() => { s.Driver.Navigate().Refresh(); @@ -602,7 +602,7 @@ namespace BTCPayServer.Tests { s.Driver.Navigate().Refresh(); Assert.DoesNotContain("invoice-unsettled", s.Driver.PageSource); - Assert.Contains("invoice-processing", s.Driver.PageSource); + Assert.Contains("\"PaymentDetails\"", s.Driver.PageSource); }); s.GoToUrl(checkouturi); @@ -1067,6 +1067,7 @@ namespace BTCPayServer.Tests await s.StartAsync(); s.RegisterNewUser(); s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); s.AddDerivationScheme(); s.Driver.FindElement(By.Id("StoreNav-PaymentRequests")).Click(); @@ -2038,6 +2039,7 @@ namespace BTCPayServer.Tests new[] { s.Server.MerchantLnd.Client }); s.RegisterNewUser(true); (_, string storeId) = s.CreateNewStore(); + s.EnableCheckout(CheckoutType.V1); var network = s.Server.NetworkProvider.GetNetwork(cryptoCode).NBitcoinNetwork; s.AddLightningNode(LightningConnectionType.CLightning, false); s.GoToLightningSettings(); @@ -2168,6 +2170,7 @@ namespace BTCPayServer.Tests s.GoToHome(); s.CreateNewStore(false); + s.EnableCheckout(CheckoutType.V1); s.AddLightningNode(LightningConnectionType.LndREST, false); s.GoToLightningSettings(); s.Driver.SetCheckbox(By.Id("LNURLEnabled"), true); diff --git a/BTCPayServer.Tests/TestUtils.cs b/BTCPayServer.Tests/TestUtils.cs index 1a233a838..f08b259ba 100644 --- a/BTCPayServer.Tests/TestUtils.cs +++ b/BTCPayServer.Tests/TestUtils.cs @@ -17,7 +17,7 @@ namespace BTCPayServer.Tests #if DEBUG && !SHORT_TIMEOUT public const int TestTimeout = 600_000; #else - public const int TestTimeout = 60_000; + public const int TestTimeout = 90_000; #endif public static DirectoryInfo TryGetSolutionDirectoryInfo(string currentPath = null) { diff --git a/BTCPayServer/Controllers/UIInvoiceController.UI.cs b/BTCPayServer/Controllers/UIInvoiceController.UI.cs index 3d3d990a5..368e66236 100644 --- a/BTCPayServer/Controllers/UIInvoiceController.UI.cs +++ b/BTCPayServer/Controllers/UIInvoiceController.UI.cs @@ -1157,7 +1157,7 @@ namespace BTCPayServer.Controllers { StoreId = model.StoreId, Currency = storeBlob?.DefaultCurrency, - UseNewCheckout = storeBlob?.CheckoutType is CheckoutType.V2, + CheckoutType = storeBlob?.CheckoutType ?? CheckoutType.V2, AvailablePaymentMethods = GetPaymentMethodsSelectList() }; @@ -1172,7 +1172,7 @@ namespace BTCPayServer.Controllers { var store = HttpContext.GetStoreData(); var storeBlob = store.GetStoreBlob(); - model.UseNewCheckout = storeBlob.CheckoutType == CheckoutType.V2; + model.CheckoutType = storeBlob.CheckoutType; model.AvailablePaymentMethods = GetPaymentMethodsSelectList(); if (!ModelState.IsValid) diff --git a/BTCPayServer/Controllers/UIStoresController.cs b/BTCPayServer/Controllers/UIStoresController.cs index 07c8b7512..49e3b6589 100644 --- a/BTCPayServer/Controllers/UIStoresController.cs +++ b/BTCPayServer/Controllers/UIStoresController.cs @@ -385,7 +385,7 @@ namespace BTCPayServer.Controllers }; }).ToList(); - vm.UseNewCheckout = storeBlob.CheckoutType == Client.Models.CheckoutType.V2; + vm.UseClassicCheckout = storeBlob.CheckoutType == Client.Models.CheckoutType.V1; vm.CelebratePayment = storeBlob.CelebratePayment; vm.OnChainWithLnInvoiceFallback = storeBlob.OnChainWithLnInvoiceFallback; vm.ShowPayInWalletButton = storeBlob.ShowPayInWalletButton; @@ -509,7 +509,7 @@ namespace BTCPayServer.Controllers blob.ShowPayInWalletButton = model.ShowPayInWalletButton; blob.ShowStoreHeader = model.ShowStoreHeader; - blob.CheckoutType = model.UseNewCheckout ? Client.Models.CheckoutType.V2 : Client.Models.CheckoutType.V1; + blob.CheckoutType = model.UseClassicCheckout ? Client.Models.CheckoutType.V1 : Client.Models.CheckoutType.V2; blob.CelebratePayment = model.CelebratePayment; blob.OnChainWithLnInvoiceFallback = model.OnChainWithLnInvoiceFallback; blob.LightningAmountInSatoshi = model.LightningAmountInSatoshi; diff --git a/BTCPayServer/Data/StoreBlob.cs b/BTCPayServer/Data/StoreBlob.cs index b2f35ed1d..62d115503 100644 --- a/BTCPayServer/Data/StoreBlob.cs +++ b/BTCPayServer/Data/StoreBlob.cs @@ -33,12 +33,15 @@ namespace BTCPayServer.Data RecommendedFeeBlockTarget = 1; PaymentMethodCriteria = new List(); ReceiptOptions = InvoiceDataBase.ReceiptOptions.CreateDefault(); + CheckoutType = CheckoutType.V2; } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public NetworkFeeMode NetworkFeeMode { get; set; } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] + [DefaultValue(CheckoutType.V1)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public CheckoutType CheckoutType { get; set; } public bool RequiresRefundEmail { get; set; } public bool LightningAmountInSatoshi { get; set; } diff --git a/BTCPayServer/Models/InvoicingModels/CreateInvoiceModel.cs b/BTCPayServer/Models/InvoicingModels/CreateInvoiceModel.cs index 6e28effac..105e0b663 100644 --- a/BTCPayServer/Models/InvoicingModels/CreateInvoiceModel.cs +++ b/BTCPayServer/Models/InvoicingModels/CreateInvoiceModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; +using BTCPayServer.Client.Models; using BTCPayServer.Services.Apps; using BTCPayServer.Validation; using Microsoft.AspNetCore.Mvc.Rendering; @@ -89,6 +90,6 @@ namespace BTCPayServer.Models.InvoicingModels get; set; } - public bool UseNewCheckout { get; set; } + public CheckoutType CheckoutType { get; set; } } } diff --git a/BTCPayServer/Models/StoreViewModels/CheckoutAppearanceViewModel.cs b/BTCPayServer/Models/StoreViewModels/CheckoutAppearanceViewModel.cs index 59ddbb610..9d2beb094 100644 --- a/BTCPayServer/Models/StoreViewModels/CheckoutAppearanceViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/CheckoutAppearanceViewModel.cs @@ -38,8 +38,8 @@ namespace BTCPayServer.Models.StoreViewModels [Display(Name = "Default payment method on checkout")] public string DefaultPaymentMethod { get; set; } - [Display(Name = "Use the new checkout")] - public bool UseNewCheckout { get; set; } + [Display(Name = "Use the classic checkout")] + public bool UseClassicCheckout { get; set; } [Display(Name = "Celebrate payment with confetti")] public bool CelebratePayment { get; set; } diff --git a/BTCPayServer/Views/UIInvoice/Checkout-Cheating.cshtml b/BTCPayServer/Views/UIInvoice/Checkout-Cheating.cshtml index caae3dff9..3b1482f2c 100644 --- a/BTCPayServer/Views/UIInvoice/Checkout-Cheating.cshtml +++ b/BTCPayServer/Views/UIInvoice/Checkout-Cheating.cshtml @@ -10,13 +10,13 @@
- +
- +
- +
@@ -26,7 +26,7 @@
blocks
- +
diff --git a/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml b/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml index a34189858..c7a4c3b4f 100644 --- a/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml +++ b/BTCPayServer/Views/UIInvoice/CheckoutV2.cshtml @@ -172,7 +172,7 @@
- +
diff --git a/BTCPayServer/Views/UIStores/CheckoutAppearance.cshtml b/BTCPayServer/Views/UIStores/CheckoutAppearance.cshtml index 618f3ec3e..ca8316acb 100644 --- a/BTCPayServer/Views/UIStores/CheckoutAppearance.cshtml +++ b/BTCPayServer/Views/UIStores/CheckoutAppearance.cshtml @@ -19,14 +19,16 @@ : '' }); delegate('click', '#Presets_InStore', e => { - $("#UseNewCheckout").prop('checked', true); - $("#NewCheckoutSettings").addClass('show'); + $("#UseClassicCheckout").prop('checked', false); + $("#CheckoutV2Settings").addClass('show'); + $("#ClassicCheckoutSettings").removeClass('show'); $("#ShowPayInWalletButton").prop('checked', false); $("#ShowStoreHeader").prop('checked', false); }); delegate('click', '#Presets_Online', e => { - $("#UseNewCheckout").prop('checked', false); - $("#NewCheckoutSettings").removeClass('show'); + $("#UseClassicCheckout").prop('checked', false); + $("#CheckoutV2Settings").addClass('show'); + $("#ClassicCheckoutSettings").removeClass('show'); $("#ShowPayInWalletButton").prop('checked', true); $("#ShowStoreHeader").prop('checked', true); }); @@ -93,22 +95,13 @@ -
- -
- - -
- Since v1.7.0 a new version of the checkout is available. Note: For now, the new version is English-only.
- We are still collecting feedback and offer this as an opt-in feature. -
-
+
+ + +
-
+
@@ -141,7 +134,7 @@
-
+