diff --git a/BTCPayServer/BTCPayServer.csproj b/BTCPayServer/BTCPayServer.csproj index 4d5c8f99c..679d45668 100644 --- a/BTCPayServer/BTCPayServer.csproj +++ b/BTCPayServer/BTCPayServer.csproj @@ -2,7 +2,7 @@ Exe netcoreapp2.0 - 1.0.1.76 + 1.0.1.77 NU1701,CA1816,CA1308,CA1810,CA2208 diff --git a/BTCPayServer/Controllers/InvoiceController.cs b/BTCPayServer/Controllers/InvoiceController.cs index c590f16f8..8c4e67790 100644 --- a/BTCPayServer/Controllers/InvoiceController.cs +++ b/BTCPayServer/Controllers/InvoiceController.cs @@ -119,7 +119,7 @@ namespace BTCPayServer.Controllers .Where(c => c.Network != null) .Select(o => (SupportedPaymentMethod: o.SupportedPaymentMethod, - PaymentMethod: CreatePaymentMethodAsync(o.Handler, o.SupportedPaymentMethod, o.Network, entity, storeBlob))) + PaymentMethod: CreatePaymentMethodAsync(o.Handler, o.SupportedPaymentMethod, o.Network, entity, store))) .ToList(); List paymentMethodErrors = new List(); @@ -183,15 +183,16 @@ namespace BTCPayServer.Controllers return new DataWrapper(resp) { Facade = "pos/invoice" }; } - private async Task CreatePaymentMethodAsync(IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, InvoiceEntity entity, StoreBlob storeBlob) + private async Task CreatePaymentMethodAsync(IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, InvoiceEntity entity, StoreData store) { + var storeBlob = store.GetStoreBlob(); var rate = await storeBlob.ApplyRateRules(network, _RateProviders.GetRateProvider(network, false)).GetRateAsync(entity.ProductInformation.Currency); PaymentMethod paymentMethod = new PaymentMethod(); paymentMethod.ParentEntity = entity; paymentMethod.Network = network; paymentMethod.SetId(supportedPaymentMethod.PaymentId); paymentMethod.Rate = rate; - var paymentDetails = await handler.CreatePaymentMethodDetails(supportedPaymentMethod, paymentMethod, network); + var paymentDetails = await handler.CreatePaymentMethodDetails(supportedPaymentMethod, paymentMethod, store, network); if (storeBlob.NetworkFeeDisabled) paymentDetails.SetNoTxFee(); paymentMethod.SetPaymentMethodDetails(paymentDetails); diff --git a/BTCPayServer/Controllers/StoresController.cs b/BTCPayServer/Controllers/StoresController.cs index ea26acb86..1c1ae5e90 100644 --- a/BTCPayServer/Controllers/StoresController.cs +++ b/BTCPayServer/Controllers/StoresController.cs @@ -282,6 +282,7 @@ namespace BTCPayServer.Controllers vm.MonitoringExpiration = storeBlob.MonitoringExpiration; vm.InvoiceExpiration = storeBlob.InvoiceExpiration; vm.RateMultiplier = (double)storeBlob.GetRateMultiplier(); + vm.LightningDescriptionTemplate = storeBlob.LightningDescriptionTemplate; vm.PreferredExchange = storeBlob.PreferredExchange.IsCoinAverage() ? "coinaverage" : storeBlob.PreferredExchange; return View(vm); } @@ -356,6 +357,7 @@ namespace BTCPayServer.Controllers blob.NetworkFeeDisabled = !model.NetworkFee; blob.MonitoringExpiration = model.MonitoringExpiration; blob.InvoiceExpiration = model.InvoiceExpiration; + blob.LightningDescriptionTemplate = model.LightningDescriptionTemplate ?? string.Empty; bool newExchange = blob.PreferredExchange != model.PreferredExchange; blob.PreferredExchange = model.PreferredExchange; diff --git a/BTCPayServer/Data/StoreData.cs b/BTCPayServer/Data/StoreData.cs index e94887fda..d953fabf1 100644 --- a/BTCPayServer/Data/StoreData.cs +++ b/BTCPayServer/Data/StoreData.cs @@ -270,6 +270,20 @@ namespace BTCPayServer.Data [JsonConverter(typeof(UriJsonConverter))] public Uri CustomCSS { get; set; } + + string _LightningDescriptionTemplate; + public string LightningDescriptionTemplate + { + get + { + return _LightningDescriptionTemplate ?? "Paid to {StoreName} (Order ID: {OrderId})"; + } + set + { + _LightningDescriptionTemplate = value; + } + } + public IRateProvider ApplyRateRules(BTCPayNetwork network, IRateProvider rateProvider) { if (!PreferredExchange.IsCoinAverage()) diff --git a/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs b/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs index 9eaf51317..dc4a71e80 100644 --- a/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs +++ b/BTCPayServer/Models/StoreViewModels/StoreViewModel.cs @@ -91,6 +91,9 @@ namespace BTCPayServer.Models.StoreViewModels get; set; } + [Display(Name = "Description template of the lightning invoice")] + public string LightningDescriptionTemplate { get; set; } + public class LightningNode { public string CryptoCode { get; set; } @@ -100,6 +103,5 @@ namespace BTCPayServer.Models.StoreViewModels { get; set; } = new List(); - } } diff --git a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs index 27f5bd219..4ddb426aa 100644 --- a/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Bitcoin/BitcoinLikePaymentHandler.cs @@ -27,7 +27,7 @@ namespace BTCPayServer.Payments.Bitcoin _WalletProvider = walletProvider; } - public override async Task CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network) + public override async Task CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network) { if (!_ExplorerProvider.IsAvailable(network)) throw new PaymentMethodUnavailableException($"Full node not available"); diff --git a/BTCPayServer/Payments/IPaymentMethodHandler.cs b/BTCPayServer/Payments/IPaymentMethodHandler.cs index f2e138cf6..9ec09fa45 100644 --- a/BTCPayServer/Payments/IPaymentMethodHandler.cs +++ b/BTCPayServer/Payments/IPaymentMethodHandler.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using BTCPayServer.Data; using BTCPayServer.Services.Invoices; namespace BTCPayServer.Payments @@ -16,25 +17,26 @@ namespace BTCPayServer.Payments /// /// /// + /// /// /// - Task CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network); + Task CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network); } public interface IPaymentMethodHandler : IPaymentMethodHandler where T : ISupportedPaymentMethod { - Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network); + Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network); } public abstract class PaymentMethodHandlerBase : IPaymentMethodHandler where T : ISupportedPaymentMethod { - public abstract Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network); + public abstract Task CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network); - Task IPaymentMethodHandler.CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network) + Task IPaymentMethodHandler.CreatePaymentMethodDetails(ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network) { if (supportedPaymentMethod is T method) { - return CreatePaymentMethodDetails(method, paymentMethod, network); + return CreatePaymentMethodDetails(method, paymentMethod, store, network); } throw new NotSupportedException("Invalid supportedPaymentMethod"); } diff --git a/BTCPayServer/Payments/Lightning/Charge/ChargeClient.cs b/BTCPayServer/Payments/Lightning/Charge/ChargeClient.cs index f143d90e8..062f01bdc 100644 --- a/BTCPayServer/Payments/Lightning/Charge/ChargeClient.cs +++ b/BTCPayServer/Payments/Lightning/Charge/ChargeClient.cs @@ -48,8 +48,10 @@ namespace BTCPayServer.Payments.Lightning.Charge { var message = CreateMessage(HttpMethod.Post, "invoice"); Dictionary parameters = new Dictionary(); - parameters.Add("msatoshi", request.Amont.MilliSatoshi.ToString(CultureInfo.InvariantCulture)); + parameters.Add("msatoshi", request.Amount.MilliSatoshi.ToString(CultureInfo.InvariantCulture)); parameters.Add("expiry", ((int)request.Expiry.TotalSeconds).ToString(CultureInfo.InvariantCulture)); + if(request.Description != null) + parameters.Add("description", request.Description); message.Content = new FormUrlEncodedContent(parameters); var result = await _Client.SendAsync(message, cancellation); result.EnsureSuccessStatusCode(); @@ -154,7 +156,7 @@ namespace BTCPayServer.Payments.Lightning.Charge async Task ILightningInvoiceClient.CreateInvoice(LightMoney amount, string description, TimeSpan expiry, CancellationToken cancellation) { - var invoice = await CreateInvoiceAsync(new CreateInvoiceRequest() { Amont = amount, Expiry = expiry, Description = description ?? "" }); + var invoice = await CreateInvoiceAsync(new CreateInvoiceRequest() { Amount = amount, Expiry = expiry, Description = description ?? "" }); return new LightningInvoice() { Id = invoice.Id, Amount = amount, BOLT11 = invoice.PayReq, Status = "unpaid" }; } diff --git a/BTCPayServer/Payments/Lightning/Charge/CreateInvoiceRequest.cs b/BTCPayServer/Payments/Lightning/Charge/CreateInvoiceRequest.cs index 0d7e010d7..9a425fc8a 100644 --- a/BTCPayServer/Payments/Lightning/Charge/CreateInvoiceRequest.cs +++ b/BTCPayServer/Payments/Lightning/Charge/CreateInvoiceRequest.cs @@ -7,7 +7,7 @@ namespace BTCPayServer.Payments.Lightning.Charge { public class CreateInvoiceRequest { - public LightMoney Amont { get; set; } + public LightMoney Amount { get; set; } public TimeSpan Expiry { get; set; } public string Description { get; set; } } diff --git a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs index b3c4b928d..fd5baa805 100644 --- a/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs +++ b/BTCPayServer/Payments/Lightning/LightningLikePaymentHandler.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using BTCPayServer.Data; using BTCPayServer.HostedServices; using BTCPayServer.Payments.Lightning.Charge; using BTCPayServer.Payments.Lightning.CLightning; @@ -23,8 +24,9 @@ namespace BTCPayServer.Payments.Lightning _LightningClientFactory = lightningClientFactory; _Dashboard = dashboard; } - public override async Task CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network) + public override async Task CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network) { + var storeBlob = store.GetStoreBlob(); var test = Test(supportedPaymentMethod, network); var invoice = paymentMethod.ParentEntity; var due = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, 8); @@ -36,7 +38,11 @@ namespace BTCPayServer.Payments.Lightning LightningInvoice lightningInvoice = null; try { - lightningInvoice = await client.CreateInvoice(new LightMoney(due, LightMoneyUnit.BTC), invoice.ProductInformation.ItemDesc, expiry); + string description = storeBlob.LightningDescriptionTemplate; + description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase) + .Replace("{ItemDescription}", invoice.ProductInformation.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase) + .Replace("{OrderId}", invoice.OrderId ?? "", StringComparison.OrdinalIgnoreCase); + lightningInvoice = await client.CreateInvoice(new LightMoney(due, LightMoneyUnit.BTC), description, expiry); } catch(Exception ex) { diff --git a/BTCPayServer/Views/Stores/UpdateStore.cshtml b/BTCPayServer/Views/Stores/UpdateStore.cshtml index 2a18fa082..5d83a8f31 100644 --- a/BTCPayServer/Views/Stores/UpdateStore.cshtml +++ b/BTCPayServer/Views/Stores/UpdateStore.cshtml @@ -129,6 +129,14 @@ +
+ + + +

+ Placeholder available are: {StoreName}, {ItemDescription} and {OrderId} +

+