From 64e34d0ef58d55f1b9f3aa5675f77dcbf1cbc931 Mon Sep 17 00:00:00 2001 From: Andrew Camilleri Date: Tue, 13 Apr 2021 13:19:48 +0200 Subject: [PATCH] Seaparate CoinSwitch as a plugin (#2390) * Separate coinswitch as a system plugin * Decouple Coinswitch from Checkout UI * remove dummy csproj * Remove CoinSwitchTests.cs per @NicolasDorier feedback Co-authored-by: rockstardev --- BTCPayServer.Tests/CoinSwitchTests.cs | 91 ------------------- BTCPayServer/BTCPayServer.csproj | 1 - .../Controllers/InvoiceController.UI.cs | 12 +-- BTCPayServer/Controllers/StoresController.cs | 9 -- BTCPayServer/Data/StoreBlob.cs | 4 +- .../Models/InvoicingModels/PaymentModel.cs | 5 - .../Models/StoreViewModels/StoreViewModel.cs | 3 - .../Payments/Lightning/LightningListener.cs | 2 +- .../CoinSwitch/CoinSwitchController.cs} | 37 +++++--- .../CoinSwitch/CoinSwitchExtensions.cs | 32 +++++++ .../Plugins/CoinSwitch/CoinSwitchPlugin.cs | 34 +++++++ .../Plugins/CoinSwitch/CoinSwitchService.cs | 36 ++++++++ .../CoinSwitch}/CoinswitchSettings.cs | 2 +- .../UpdateCoinSwitchSettingsViewModel.cs | 0 .../Services/Stores/StoreRepository.cs | 8 ++ .../UpdateCoinSwitchSettings.cshtml | 1 + BTCPayServer/Views/Invoice/Checkout.cshtml | 3 + .../Bitcoin/BitcoinLikeMethodCheckout.cshtml | 66 +------------- .../CheckoutContentExtension.cshtml | 41 +++++++++ .../Shared/CoinSwitch/CheckoutEnd.cshtml | 1 + .../CoinSwitch/CheckoutTabExtension.cshtml | 12 +++ .../StoreIntegrationCoinSwitchOption.cshtml | 40 ++++++++ .../EthereumLikeMethodCheckout.cshtml | 63 +------------ .../LightningLikeMethodCheckout.cshtml | 3 +- BTCPayServer/Views/Stores/UpdateStore.cshtml | 36 -------- BTCPayServer/wwwroot/checkout/css/default.css | 26 +----- .../wwwroot/checkout/css/themes/legacy.css | 30 +----- .../checkout/js/coinswitchComponent.js | 4 +- 28 files changed, 249 insertions(+), 353 deletions(-) delete mode 100644 BTCPayServer.Tests/CoinSwitchTests.cs rename BTCPayServer/{Controllers/StoresController.CoinSwitch.cs => Plugins/CoinSwitch/CoinSwitchController.cs} (66%) create mode 100644 BTCPayServer/Plugins/CoinSwitch/CoinSwitchExtensions.cs create mode 100644 BTCPayServer/Plugins/CoinSwitch/CoinSwitchPlugin.cs create mode 100644 BTCPayServer/Plugins/CoinSwitch/CoinSwitchService.cs rename BTCPayServer/{Payments/Coinswitch => Plugins/CoinSwitch}/CoinswitchSettings.cs (89%) rename BTCPayServer/{Models/StoreViewModels => Plugins/CoinSwitch}/UpdateCoinSwitchSettingsViewModel.cs (100%) rename BTCPayServer/Views/{Stores => CoinSwitch}/UpdateCoinSwitchSettings.cshtml (98%) create mode 100644 BTCPayServer/Views/Shared/CoinSwitch/CheckoutContentExtension.cshtml create mode 100644 BTCPayServer/Views/Shared/CoinSwitch/CheckoutEnd.cshtml create mode 100644 BTCPayServer/Views/Shared/CoinSwitch/CheckoutTabExtension.cshtml create mode 100644 BTCPayServer/Views/Shared/CoinSwitch/StoreIntegrationCoinSwitchOption.cshtml diff --git a/BTCPayServer.Tests/CoinSwitchTests.cs b/BTCPayServer.Tests/CoinSwitchTests.cs deleted file mode 100644 index 605fa02f4..000000000 --- a/BTCPayServer.Tests/CoinSwitchTests.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System.Threading.Tasks; -using BTCPayServer.Controllers; -using BTCPayServer.Data; -using BTCPayServer.Models.StoreViewModels; -using BTCPayServer.Payments.CoinSwitch; -using BTCPayServer.Tests.Logging; -using Microsoft.AspNetCore.Mvc; -using Xunit; -using Xunit.Abstractions; - -namespace BTCPayServer.Tests -{ - public class CoinSwitchTests - { - public CoinSwitchTests(ITestOutputHelper helper) - { - Logs.Tester = new XUnitLog(helper) { Name = "Tests" }; - Logs.LogProvider = new XUnitLogProvider(helper); - } - - [Fact] - [Trait("Integration", "Integration")] - public async Task CanSetCoinSwitchPaymentMethod() - { - using (var tester = ServerTester.Create()) - { - await tester.StartAsync(); - var user = tester.NewAccount(); - user.GrantAccess(); - var controller = tester.PayTester.GetController(user.UserId, user.StoreId); - - - var storeBlob = controller.CurrentStore.GetStoreBlob(); - Assert.Null(storeBlob.CoinSwitchSettings); - - var updateModel = new UpdateCoinSwitchSettingsViewModel() - { - MerchantId = "aaa", - }; - - Assert.Equal("UpdateStore", Assert.IsType( - await controller.UpdateCoinSwitchSettings(user.StoreId, updateModel, "save")).ActionName); - - var store = await tester.PayTester.StoreRepository.FindStore(user.StoreId); - storeBlob = controller.CurrentStore.GetStoreBlob(); - Assert.NotNull(storeBlob.CoinSwitchSettings); - Assert.NotNull(storeBlob.CoinSwitchSettings); - Assert.IsType(storeBlob.CoinSwitchSettings); - Assert.Equal(storeBlob.CoinSwitchSettings.MerchantId, - updateModel.MerchantId); - } - } - - - [Fact] - [Trait("Integration", "Integration")] - public async Task CanToggleCoinSwitchPaymentMethod() - { - using (var tester = ServerTester.Create()) - { - await tester.StartAsync(); - var user = tester.NewAccount(); - user.GrantAccess(); - var controller = tester.PayTester.GetController(user.UserId, user.StoreId); - - var updateModel = new UpdateCoinSwitchSettingsViewModel() - { - MerchantId = "aaa", - Enabled = true - }; - Assert.Equal("UpdateStore", Assert.IsType( - await controller.UpdateCoinSwitchSettings(user.StoreId, updateModel, "save")).ActionName); - - - var store = await tester.PayTester.StoreRepository.FindStore(user.StoreId); - - Assert.True(store.GetStoreBlob().CoinSwitchSettings.Enabled); - - updateModel.Enabled = false; - - Assert.Equal("UpdateStore", Assert.IsType( - await controller.UpdateCoinSwitchSettings(user.StoreId, updateModel, "save")).ActionName); - - store = await tester.PayTester.StoreRepository.FindStore(user.StoreId); - - Assert.False(store.GetStoreBlob().CoinSwitchSettings.Enabled); - } - } - - } -} diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index ecf7d5beb..8ee871776 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -134,7 +134,6 @@ - diff --git a/BTCPayServer/Controllers/InvoiceController.UI.cs b/BTCPayServer/Controllers/InvoiceController.UI.cs index c21a3cfc3..1fec3445b 100644 --- a/BTCPayServer/Controllers/InvoiceController.UI.cs +++ b/BTCPayServer/Controllers/InvoiceController.UI.cs @@ -19,8 +19,8 @@ using BTCPayServer.HostedServices; using BTCPayServer.Models; using BTCPayServer.Models.InvoicingModels; using BTCPayServer.Payments; -using BTCPayServer.Payments.CoinSwitch; using BTCPayServer.Payments.Lightning; +using BTCPayServer.Plugins.CoinSwitch; using BTCPayServer.Rating; using BTCPayServer.Security; using BTCPayServer.Services.Invoices; @@ -525,12 +525,6 @@ namespace BTCPayServer.Controllers var storeBlob = store.GetStoreBlob(); var accounting = paymentMethod.Calculate(); - CoinSwitchSettings coinswitch = (storeBlob.CoinSwitchSettings != null && storeBlob.CoinSwitchSettings.Enabled && - storeBlob.CoinSwitchSettings.IsConfigured()) - ? storeBlob.CoinSwitchSettings - : null; - - var paymentMethodHandler = _paymentMethodHandlerDictionary[paymentMethodId]; var divisibility = _CurrencyNameTable.GetNumberFormatInfo(paymentMethod.GetId().CryptoCode, false)?.CurrencyDecimalDigits; @@ -568,10 +562,6 @@ namespace BTCPayServer.Controllers #pragma warning restore CS0618 // Type or member is obsolete NetworkFee = paymentMethodDetails.GetNextNetworkFee(), IsMultiCurrency = invoice.GetPayments().Select(p => p.GetPaymentMethodId()).Concat(new[] { paymentMethod.GetId() }).Distinct().Count() > 1, - CoinSwitchEnabled = coinswitch != null, - CoinSwitchAmountMarkupPercentage = coinswitch?.AmountMarkupPercentage ?? 0, - CoinSwitchMerchantId = coinswitch?.MerchantId, - CoinSwitchMode = coinswitch?.Mode, StoreId = store.Id, AvailableCryptos = invoice.GetPaymentMethods() .Where(i => i.Network != null) diff --git a/BTCPayServer/Controllers/StoresController.cs b/BTCPayServer/Controllers/StoresController.cs index 822eba6ba..e2260ff94 100644 --- a/BTCPayServer/Controllers/StoresController.cs +++ b/BTCPayServer/Controllers/StoresController.cs @@ -553,15 +553,6 @@ namespace BTCPayServer.Controllers break; } } - - - var coinSwitchEnabled = storeBlob.CoinSwitchSettings != null && storeBlob.CoinSwitchSettings.Enabled; - vm.ThirdPartyPaymentMethods.Add(new StoreViewModel.AdditionalPaymentMethod() - { - Enabled = coinSwitchEnabled, - Action = nameof(UpdateCoinSwitchSettings), - Provider = "CoinSwitch" - }); } diff --git a/BTCPayServer/Data/StoreBlob.cs b/BTCPayServer/Data/StoreBlob.cs index d7b004aff..724032e4d 100644 --- a/BTCPayServer/Data/StoreBlob.cs +++ b/BTCPayServer/Data/StoreBlob.cs @@ -7,7 +7,7 @@ using BTCPayServer.Client.JsonConverters; using BTCPayServer.Client.Models; using BTCPayServer.JsonConverters; using BTCPayServer.Payments; -using BTCPayServer.Payments.CoinSwitch; +using BTCPayServer.Plugins.CoinSwitch; using BTCPayServer.Rating; using BTCPayServer.Services.Mails; using BTCPayServer.Services.Rates; @@ -90,8 +90,6 @@ namespace BTCPayServer.Data public bool AnyoneCanInvoice { get; set; } - public CoinSwitchSettings CoinSwitchSettings { get; set; } - string _LightningDescriptionTemplate; public string LightningDescriptionTemplate { diff --git a/BTCPayServer/Models/InvoicingModels/PaymentModel.cs b/BTCPayServer/Models/InvoicingModels/PaymentModel.cs index ebc21c9c7..bf9f1e2e1 100644 --- a/BTCPayServer/Models/InvoicingModels/PaymentModel.cs +++ b/BTCPayServer/Models/InvoicingModels/PaymentModel.cs @@ -62,12 +62,7 @@ namespace BTCPayServer.Models.InvoicingModels public string CryptoImage { get; set; } public string StoreId { get; set; } public string PeerInfo { get; set; } - - public bool CoinSwitchEnabled { get; set; } - public string CoinSwitchMode { get; set; } - public string CoinSwitchMerchantId { get; set; } public string RootPath { get; set; } - public decimal CoinSwitchAmountMarkupPercentage { get; set; } public bool RedirectAutomatically { get; set; } public bool Activated { get; set; } public string InvoiceCurrency { get; set; } diff --git a/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs b/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs index 93d2d1a5c..75fb019d8 100644 --- a/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs @@ -55,9 +55,6 @@ namespace BTCPayServer.Models.StoreViewModels public List DerivationSchemes { get; set; } = new List(); - public List ThirdPartyPaymentMethods { get; set; } = - new List(); - [Display(Name = "Invoice expires if the full amount has not been paid after …")] [Range(1, 60 * 24 * 24)] public int InvoiceExpiration diff --git a/BTCPayServer/Payments/Lightning/LightningListener.cs b/BTCPayServer/Payments/Lightning/LightningListener.cs index 9bbc74059..b1c0626e4 100644 --- a/BTCPayServer/Payments/Lightning/LightningListener.cs +++ b/BTCPayServer/Payments/Lightning/LightningListener.cs @@ -104,7 +104,7 @@ namespace BTCPayServer.Payments.Lightning } private Task> GetListenedInvoices(string invoiceId) { - return _memoryCache.GetOrCreateAsync(invoiceId, async (cacheEntry) => + return _memoryCache.GetOrCreateAsync($"{nameof(GetListenedInvoices)}-{invoiceId}", async (cacheEntry) => { var listenedInvoices = new List(); var invoice = await _InvoiceRepository.GetInvoice(invoiceId); diff --git a/BTCPayServer/Controllers/StoresController.CoinSwitch.cs b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchController.cs similarity index 66% rename from BTCPayServer/Controllers/StoresController.CoinSwitch.cs rename to BTCPayServer/Plugins/CoinSwitch/CoinSwitchController.cs index 9ba03b702..08fdb2ba4 100644 --- a/BTCPayServer/Controllers/StoresController.CoinSwitch.cs +++ b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchController.cs @@ -1,15 +1,27 @@ using System.Threading.Tasks; +using BTCPayServer.Abstractions.Constants; +using BTCPayServer.Client; using BTCPayServer.Data; using BTCPayServer.Models.StoreViewModels; -using BTCPayServer.Payments.CoinSwitch; +using BTCPayServer.Services.Stores; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -namespace BTCPayServer.Controllers +namespace BTCPayServer.Plugins.CoinSwitch { - public partial class StoresController + [Authorize(AuthenticationSchemes = AuthenticationSchemes.Cookie)] + [Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)] + [Route("plugins/{storeId}/coinswitch")] + public class CoinSwitchController : Controller { - [HttpGet] - [Route("{storeId}/coinswitch")] + private readonly StoreRepository _storeRepository; + + public CoinSwitchController(StoreRepository storeRepository) + { + _storeRepository = storeRepository; + } + + [HttpGet("")] public IActionResult UpdateCoinSwitchSettings(string storeId) { var store = HttpContext.GetStoreData(); @@ -22,8 +34,7 @@ namespace BTCPayServer.Controllers private void SetExistingValues(StoreData store, UpdateCoinSwitchSettingsViewModel vm) { - - var existing = store.GetStoreBlob().CoinSwitchSettings; + var existing = store.GetStoreBlob().GetCoinSwitchSettings(); if (existing == null) return; vm.MerchantId = existing.MerchantId; @@ -32,8 +43,7 @@ namespace BTCPayServer.Controllers vm.AmountMarkupPercentage = existing.AmountMarkupPercentage; } - [HttpPost] - [Route("{storeId}/coinswitch")] + [HttpPost("")] public async Task UpdateCoinSwitchSettings(string storeId, UpdateCoinSwitchSettingsViewModel vm, string command) { @@ -60,14 +70,11 @@ namespace BTCPayServer.Controllers { case "save": var storeBlob = store.GetStoreBlob(); - storeBlob.CoinSwitchSettings = coinSwitchSettings; + storeBlob.SetCoinSwitchSettings(coinSwitchSettings); store.SetStoreBlob(storeBlob); - await _Repo.UpdateStore(store); + await _storeRepository.UpdateStore(store); TempData[WellKnownTempData.SuccessMessage] = "CoinSwitch settings modified"; - return RedirectToAction(nameof(UpdateStore), new - { - storeId - }); + return RedirectToAction(nameof(UpdateCoinSwitchSettings), new {storeId}); default: return View(vm); diff --git a/BTCPayServer/Plugins/CoinSwitch/CoinSwitchExtensions.cs b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchExtensions.cs new file mode 100644 index 000000000..dd146f891 --- /dev/null +++ b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchExtensions.cs @@ -0,0 +1,32 @@ +using BTCPayServer.Data; +using NBitcoin; +using NBXplorer; +using Newtonsoft.Json.Linq; + +namespace BTCPayServer.Plugins.CoinSwitch +{ + public static class CoinSwitchExtensions + { + public const string StoreBlobKey = "coinSwitchSettings"; + public static CoinSwitchSettings GetCoinSwitchSettings(this StoreBlob storeBlob) + { + if (storeBlob.AdditionalData.TryGetValue(StoreBlobKey, out var rawS) && rawS is JObject rawObj) + { + return new Serializer(null).ToObject(rawObj); + } + + return null; + } + public static void SetCoinSwitchSettings(this StoreBlob storeBlob, CoinSwitchSettings settings) + { + if (settings is null) + { + storeBlob.AdditionalData.Remove(StoreBlobKey); + } + else + { + storeBlob.AdditionalData.AddOrReplace(StoreBlobKey, JObject.FromObject(settings)); + } + } + } +} diff --git a/BTCPayServer/Plugins/CoinSwitch/CoinSwitchPlugin.cs b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchPlugin.cs new file mode 100644 index 000000000..c60f284c5 --- /dev/null +++ b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchPlugin.cs @@ -0,0 +1,34 @@ +using BTCPayServer.Abstractions.Contracts; +using BTCPayServer.Abstractions.Models; +using BTCPayServer.Abstractions.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace BTCPayServer.Plugins.CoinSwitch +{ + public class CoinSwitchPlugin : BaseBTCPayServerPlugin + { + public override string Identifier => "BTCPayServer.Plugins.CoinSwitch"; + public override string Name => "CoinSwitch"; + + public override string Description => + "Allows you to embed a coinswitch conversion screen to allow customers to pay with altcoins."; + + public override void Execute(IServiceCollection applicationBuilder) + { + applicationBuilder.AddSingleton(); + applicationBuilder.AddSingleton(new UIExtension("CoinSwitch/StoreIntegrationCoinSwitchOption", + "store-integrations-list")); + applicationBuilder.AddSingleton(new UIExtension("CoinSwitch/CheckoutContentExtension", + "checkout-bitcoin-post-content")); + applicationBuilder.AddSingleton(new UIExtension("CoinSwitch/CheckoutContentExtension", + "checkout-ethereum-post-content")); + applicationBuilder.AddSingleton(new UIExtension("CoinSwitch/CheckoutTabExtension", + "checkout-bitcoin-post-tabs")); + applicationBuilder.AddSingleton(new UIExtension("CoinSwitch/CheckoutTabExtension", + "checkout-ethereum-post-tabs")); + applicationBuilder.AddSingleton(new UIExtension("CoinSwitch/CheckoutEnd", + "checkout-end")); + base.Execute(applicationBuilder); + } + } +} diff --git a/BTCPayServer/Plugins/CoinSwitch/CoinSwitchService.cs b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchService.cs new file mode 100644 index 000000000..96d09f775 --- /dev/null +++ b/BTCPayServer/Plugins/CoinSwitch/CoinSwitchService.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using BTCPayServer.Data; +using BTCPayServer.Services.Stores; +using Microsoft.Extensions.Caching.Memory; + +namespace BTCPayServer.Plugins.CoinSwitch +{ + public class CoinSwitchService: IDisposable + { + private readonly StoreRepository _storeRepository; + private readonly IMemoryCache _memoryCache; + + public CoinSwitchService(StoreRepository storeRepository, IMemoryCache memoryCache) + { + _storeRepository = storeRepository; + _memoryCache = memoryCache; + } + + public async Task GetCoinSwitchForInvoice(string id) + { + return await _memoryCache.GetOrCreateAsync($"{nameof(CoinSwitchService)}-{id}", async entry => + { + entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1); + var d = await _storeRepository.GetStoreByInvoiceId(id); + + return d?.GetStoreBlob()?.GetCoinSwitchSettings(); + }); + } + + public void Dispose() + { + _memoryCache?.Dispose(); + } + } +} diff --git a/BTCPayServer/Payments/Coinswitch/CoinswitchSettings.cs b/BTCPayServer/Plugins/CoinSwitch/CoinswitchSettings.cs similarity index 89% rename from BTCPayServer/Payments/Coinswitch/CoinswitchSettings.cs rename to BTCPayServer/Plugins/CoinSwitch/CoinswitchSettings.cs index 9af6d9aab..d797f1664 100644 --- a/BTCPayServer/Payments/Coinswitch/CoinswitchSettings.cs +++ b/BTCPayServer/Plugins/CoinSwitch/CoinswitchSettings.cs @@ -1,4 +1,4 @@ -namespace BTCPayServer.Payments.CoinSwitch +namespace BTCPayServer.Plugins.CoinSwitch { public class CoinSwitchSettings { diff --git a/BTCPayServer/Models/StoreViewModels/UpdateCoinSwitchSettingsViewModel.cs b/BTCPayServer/Plugins/CoinSwitch/UpdateCoinSwitchSettingsViewModel.cs similarity index 100% rename from BTCPayServer/Models/StoreViewModels/UpdateCoinSwitchSettingsViewModel.cs rename to BTCPayServer/Plugins/CoinSwitch/UpdateCoinSwitchSettingsViewModel.cs diff --git a/BTCPayServer/Services/Stores/StoreRepository.cs b/BTCPayServer/Services/Stores/StoreRepository.cs index 49a3b3129..7db402f40 100644 --- a/BTCPayServer/Services/Stores/StoreRepository.cs +++ b/BTCPayServer/Services/Stores/StoreRepository.cs @@ -95,6 +95,14 @@ namespace BTCPayServer.Services.Stores } } + public async Task GetStoreByInvoiceId(string invoiceId) + { + await using var context = _ContextFactory.CreateContext(); + var matched = await context.Invoices.Include(data => data.StoreData) + .SingleOrDefaultAsync(data => data.Id == invoiceId); + return matched?.StoreData; + } + public async Task AddStoreUser(string storeId, string userId, string role) { using (var ctx = _ContextFactory.CreateContext()) diff --git a/BTCPayServer/Views/Stores/UpdateCoinSwitchSettings.cshtml b/BTCPayServer/Views/CoinSwitch/UpdateCoinSwitchSettings.cshtml similarity index 98% rename from BTCPayServer/Views/Stores/UpdateCoinSwitchSettings.cshtml rename to BTCPayServer/Views/CoinSwitch/UpdateCoinSwitchSettings.cshtml index aca76b750..191491417 100644 --- a/BTCPayServer/Views/Stores/UpdateCoinSwitchSettings.cshtml +++ b/BTCPayServer/Views/CoinSwitch/UpdateCoinSwitchSettings.cshtml @@ -1,4 +1,5 @@ @using Microsoft.AspNetCore.Mvc.Rendering +@using BTCPayServer.Views.Stores @model UpdateCoinSwitchSettingsViewModel @{ Layout = "../Shared/_NavLayout.cshtml"; diff --git a/BTCPayServer/Views/Invoice/Checkout.cshtml b/BTCPayServer/Views/Invoice/Checkout.cshtml index b8c88cdbe..cb291b037 100644 --- a/BTCPayServer/Views/Invoice/Checkout.cshtml +++ b/BTCPayServer/Views/Invoice/Checkout.cshtml @@ -328,6 +328,8 @@ this.endDate = newEnd; // updating ui this.srvModel = jsonData; + + eventBus.$emit("data-fetched", this.srvModel); if (this.invoicePaid && jsonData.redirectAutomatically && jsonData.merchantRefLink) { this.loading = true; setTimeout(function () { @@ -371,5 +373,6 @@ { } +@await Component.InvokeAsync("UiExtensionPoint" , new { location="checkout-end"}) diff --git a/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml b/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml index 65dcc76f2..84484b41b 100644 --- a/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml +++ b/BTCPayServer/Views/Shared/Bitcoin/BitcoinLikeMethodCheckout.cshtml @@ -51,50 +51,7 @@ - @if (Model.CoinSwitchEnabled) - { -
- -
- } + @await Component.InvokeAsync("UiExtensionPoint" , new { location="checkout-bitcoin-post-content"}) @if (Model.ShowRecommendedFee) { @@ -132,12 +79,10 @@ props: ["srvModel"], template: "#bitcoin-method-checkout-template", components: { - qrcode: VueQrcode, - coinswitch: CoinSwitchComponent + qrcode: VueQrcode }, data: function() { return { - selectedThirdPartyProcessor: "", currentTab: "scan" } }, @@ -145,11 +90,6 @@ hasPayjoin: function(){ return this.srvModel.invoiceBitcoinUrl.indexOf('@PayjoinClient.BIP21EndpointKey=') === -1; }, - coinswitchAmountDue: function() { - return this.srvModel.coinSwitchAmountMarkupPercentage - ? this.srvModel.btcDue * (1 + (this.srvModel.coinSwitchAmountMarkupPercentage / 100)) - : this.srvModel.btcDue; - }, scanDisplayQr: function() { return this.srvModel.invoiceBitcoinUrlQR; } diff --git a/BTCPayServer/Views/Shared/CoinSwitch/CheckoutContentExtension.cshtml b/BTCPayServer/Views/Shared/CoinSwitch/CheckoutContentExtension.cshtml new file mode 100644 index 000000000..52acad9d0 --- /dev/null +++ b/BTCPayServer/Views/Shared/CoinSwitch/CheckoutContentExtension.cshtml @@ -0,0 +1,41 @@ +@using BTCPayServer.Plugins.CoinSwitch +@inject CoinSwitchService CoinSwitchService +@{ + var invoiceId = this.Context.GetRouteValue("invoiceId")?.ToString(); + var settings = await CoinSwitchService.GetCoinSwitchForInvoice(invoiceId); + if (settings?.IsConfigured() is true && settings.Enabled) + { +
+ +
+ } +} diff --git a/BTCPayServer/Views/Shared/CoinSwitch/CheckoutEnd.cshtml b/BTCPayServer/Views/Shared/CoinSwitch/CheckoutEnd.cshtml new file mode 100644 index 000000000..79a0b3a47 --- /dev/null +++ b/BTCPayServer/Views/Shared/CoinSwitch/CheckoutEnd.cshtml @@ -0,0 +1 @@ + diff --git a/BTCPayServer/Views/Shared/CoinSwitch/CheckoutTabExtension.cshtml b/BTCPayServer/Views/Shared/CoinSwitch/CheckoutTabExtension.cshtml new file mode 100644 index 000000000..740376ab2 --- /dev/null +++ b/BTCPayServer/Views/Shared/CoinSwitch/CheckoutTabExtension.cshtml @@ -0,0 +1,12 @@ +@using BTCPayServer.Plugins.CoinSwitch +@inject CoinSwitchService CoinSwitchService +@{ + var invoiceId = this.Context.GetRouteValue("invoiceId")?.ToString(); + var settings = await CoinSwitchService.GetCoinSwitchForInvoice(invoiceId); +} +@if (settings?.IsConfigured() is true) +{ +
+ {{$t("Conversion")}} +
+} diff --git a/BTCPayServer/Views/Shared/CoinSwitch/StoreIntegrationCoinSwitchOption.cshtml b/BTCPayServer/Views/Shared/CoinSwitch/StoreIntegrationCoinSwitchOption.cshtml new file mode 100644 index 000000000..e22bb1308 --- /dev/null +++ b/BTCPayServer/Views/Shared/CoinSwitch/StoreIntegrationCoinSwitchOption.cshtml @@ -0,0 +1,40 @@ +@using BTCPayServer.Plugins.CoinSwitch +@{ + var settings = Context.GetStoreData().GetStoreBlob().GetCoinSwitchSettings(); +} +
  • +
    + + + CoinSwitch + + + Allows your customers to pay with altcoins that are not supported by BTC Pay Server. + + + + @if (settings?.IsConfigured() is true) + { + + + Enabled + + + | + + Modify + + } + else + { + + + Disabled + + + Setup + + } + +
    +
  • diff --git a/BTCPayServer/Views/Shared/Ethereum/EthereumLikeMethodCheckout.cshtml b/BTCPayServer/Views/Shared/Ethereum/EthereumLikeMethodCheckout.cshtml index 7c0c12e76..e0ca0abe5 100644 --- a/BTCPayServer/Views/Shared/Ethereum/EthereumLikeMethodCheckout.cshtml +++ b/BTCPayServer/Views/Shared/Ethereum/EthereumLikeMethodCheckout.cshtml @@ -1,4 +1,3 @@ -@using BTCPayServer.Services @model BTCPayServer.Models.InvoicingModels.PaymentModel @inject BTCPayNetworkProvider BTCPayNetworkProvider @{ @@ -50,50 +49,7 @@ - @if (Model.CoinSwitchEnabled) - { -
    - -
    - } + @await Component.InvokeAsync("UiExtensionPoint" , new { location="checkout-ethereum-post-content"}) @@ -104,18 +60,8 @@
    {{$t("Copy")}} -
    - @if (Model.CoinSwitchEnabled) - { -
    - {{$t("Conversion")}} -
    -
    - } - else - { -
    - } + + @await Component.InvokeAsync("UiExtensionPoint" , new { location="checkout-ethereum-post-tabs"}) @@ -125,8 +71,7 @@ props: ["srvModel"], template: "#ethereum-method-checkout-template", components: { - qrcode: VueQrcode, - coinswitch: CoinSwitchComponent + qrcode: VueQrcode }, data: function() { return { diff --git a/BTCPayServer/Views/Shared/Lightning/LightningLikeMethodCheckout.cshtml b/BTCPayServer/Views/Shared/Lightning/LightningLikeMethodCheckout.cshtml index ac0f173b1..0c3c2ca19 100644 --- a/BTCPayServer/Views/Shared/Lightning/LightningLikeMethodCheckout.cshtml +++ b/BTCPayServer/Views/Shared/Lightning/LightningLikeMethodCheckout.cshtml @@ -58,6 +58,7 @@ + @await Component.InvokeAsync("UiExtensionPoint" , new { location="checkout-lightning-post-content"}) @@ -69,7 +70,7 @@
    {{$t("Copy")}}
    -
    + @await Component.InvokeAsync("UiExtensionPoint" , new { location="checkout-lightning-post-tabs"}) diff --git a/BTCPayServer/Views/Stores/UpdateStore.cshtml b/BTCPayServer/Views/Stores/UpdateStore.cshtml index 012887e64..2aacebbd7 100644 --- a/BTCPayServer/Views/Stores/UpdateStore.cshtml +++ b/BTCPayServer/Views/Stores/UpdateStore.cshtml @@ -266,42 +266,6 @@ -

    Additional payment methods

    -
    - - - - - - - - - - @foreach (var scheme in Model.ThirdPartyPaymentMethods) - { - - - - - - } - -
    ProviderEnabledActions
    @scheme.Provider - @if (scheme.Enabled) - { - - } - else - { - - } - - - @(scheme.Enabled ? "Modify" : "Setup") - -
    -
    -

    Services

    diff --git a/BTCPayServer/wwwroot/checkout/css/default.css b/BTCPayServer/wwwroot/checkout/css/default.css index f8e3c7d10..37671c9ae 100644 --- a/BTCPayServer/wwwroot/checkout/css/default.css +++ b/BTCPayServer/wwwroot/checkout/css/default.css @@ -8558,34 +8558,10 @@ strong { background: #f5f5f5; font-weight: 400; transition: all .2s ease; + border-bottom: #51b13e 3px solid } -.payment-tabs__slider { - position: absolute; - height: 3px; - width: 50%; - background: #51b13e; - bottom: 0; - right: 50%; - transition: all .2s ease; -} - .payment-tabs__slider.slide-copy { - right: 0; - } - - .payment-tabs__slider.three-tabs { - width: 33%; - right: 67%; - } - - .payment-tabs__slider.three-tabs.slide-copy { - right: 33%; - } - - .payment-tabs__slider.three-tabs.slide-altcoins { - right: 0; - } .manual__step-one__header { padding-top: 20px; diff --git a/BTCPayServer/wwwroot/checkout/css/themes/legacy.css b/BTCPayServer/wwwroot/checkout/css/themes/legacy.css index c6228349c..291f6406d 100644 --- a/BTCPayServer/wwwroot/checkout/css/themes/legacy.css +++ b/BTCPayServer/wwwroot/checkout/css/themes/legacy.css @@ -8558,34 +8558,10 @@ strong { .payment-tabs__tab.active { color: #214497; font-weight: 400; + + border-bottom: #329F80 5px solid; } - -.payment-tabs__slider { - position: absolute; - height: 5px; - width: 50%; - background: #329F80; - top: 0; - right: 50%; - transition: all .2s ease; -} - - .payment-tabs__slider.slide-copy { - right: 0; - } - - .payment-tabs__slider.three-tabs { - width: 33%; - right: 67%; - } - - .payment-tabs__slider.three-tabs.slide-copy { - right: 33%; - } - - .payment-tabs__slider.three-tabs.slide-altcoins { - right: 0; - } + .manual__step-one__header { padding-top: 20px; diff --git a/BTCPayServer/wwwroot/checkout/js/coinswitchComponent.js b/BTCPayServer/wwwroot/checkout/js/coinswitchComponent.js index 80d23583e..14f5e694d 100644 --- a/BTCPayServer/wwwroot/checkout/js/coinswitchComponent.js +++ b/BTCPayServer/wwwroot/checkout/js/coinswitchComponent.js @@ -1,4 +1,4 @@ -var CoinSwitchComponent = +Vue.component("coinswitch" , { props: ["toCurrency", "toCurrencyDue", "toCurrencyAddress", "merchantId", "autoload", "mode"], data: function () { @@ -63,4 +63,4 @@ this.openDialog(); } } - }; + });