mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Checkout v2: Option to display amount in Sats in BIP21 case (#4730)
This commit is contained in:
@@ -1305,7 +1305,7 @@
|
|||||||
"name":"Satoshis",
|
"name":"Satoshis",
|
||||||
"code":"SATS",
|
"code":"SATS",
|
||||||
"divisibility":0,
|
"divisibility":0,
|
||||||
"symbol":"Sats",
|
"symbol":"sats",
|
||||||
"crypto":true
|
"crypto":true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
var invoiceId = s.CreateInvoice(10, "USD", "a@g.com");
|
var invoiceId = s.CreateInvoice(10, "USD", "a@g.com");
|
||||||
s.GoToInvoiceCheckout(invoiceId);
|
s.GoToInvoiceCheckout(invoiceId);
|
||||||
Assert.Contains("Sats", s.Driver.FindElement(By.ClassName("payment__currencies_noborder")).Text);
|
Assert.Contains("sats", s.Driver.FindElement(By.ClassName("payment__currencies_noborder")).Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = TestTimeout)]
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ namespace BTCPayServer.Tests
|
|||||||
s.Driver.ElementDoesNotExist(By.Id("Address_BTC"));
|
s.Driver.ElementDoesNotExist(By.Id("Address_BTC"));
|
||||||
s.Driver.FindElement(By.Id("PayByLNURL"));
|
s.Driver.FindElement(By.Id("PayByLNURL"));
|
||||||
|
|
||||||
// Lightning amount in Sats
|
// Lightning amount in sats
|
||||||
Assert.Contains("BTC", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
||||||
s.GoToHome();
|
s.GoToHome();
|
||||||
s.GoToLightningSettings();
|
s.GoToLightningSettings();
|
||||||
@@ -111,7 +111,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Contains("BTC Lightning settings successfully updated", s.FindAlertMessage().Text);
|
Assert.Contains("BTC Lightning settings successfully updated", s.FindAlertMessage().Text);
|
||||||
s.GoToInvoiceCheckout(invoiceId);
|
s.GoToInvoiceCheckout(invoiceId);
|
||||||
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
||||||
Assert.Contains("Sats", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
||||||
|
|
||||||
// Expire
|
// Expire
|
||||||
var expirySeconds = s.Driver.FindElement(By.Id("ExpirySeconds"));
|
var expirySeconds = s.Driver.FindElement(By.Id("ExpirySeconds"));
|
||||||
@@ -193,6 +193,7 @@ namespace BTCPayServer.Tests
|
|||||||
s.GoToHome();
|
s.GoToHome();
|
||||||
s.GoToStore(StoreNavPages.CheckoutAppearance);
|
s.GoToStore(StoreNavPages.CheckoutAppearance);
|
||||||
s.Driver.SetCheckbox(By.Id("OnChainWithLnInvoiceFallback"), true);
|
s.Driver.SetCheckbox(By.Id("OnChainWithLnInvoiceFallback"), true);
|
||||||
|
s.Driver.SetCheckbox(By.Id("LightningAmountInSatoshi"), false);
|
||||||
s.Driver.FindElement(By.Id("Save")).Click();
|
s.Driver.FindElement(By.Id("Save")).Click();
|
||||||
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
||||||
|
|
||||||
@@ -200,6 +201,7 @@ namespace BTCPayServer.Tests
|
|||||||
s.GoToInvoiceCheckout(invoiceId);
|
s.GoToInvoiceCheckout(invoiceId);
|
||||||
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
||||||
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
Assert.Empty(s.Driver.FindElements(By.CssSelector(".payment-method")));
|
||||||
|
Assert.Contains("BTC", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
||||||
qrValue = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-qr-value");
|
qrValue = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-qr-value");
|
||||||
address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
address = s.Driver.FindElement(By.CssSelector(".qr-container")).GetAttribute("data-clipboard");
|
||||||
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
payUrl = s.Driver.FindElement(By.Id("PayInWallet")).GetAttribute("href");
|
||||||
@@ -215,6 +217,16 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Contains("&lightning=LNBCRT", qrValue);
|
Assert.Contains("&lightning=LNBCRT", qrValue);
|
||||||
s.Driver.FindElement(By.Id("PayByLNURL"));
|
s.Driver.FindElement(By.Id("PayByLNURL"));
|
||||||
|
|
||||||
|
// Switch to amount displayed in sats
|
||||||
|
s.GoToHome();
|
||||||
|
s.GoToStore(StoreNavPages.CheckoutAppearance);
|
||||||
|
s.Driver.SetCheckbox(By.Id("LightningAmountInSatoshi"), true);
|
||||||
|
s.Driver.FindElement(By.Id("Save")).Click();
|
||||||
|
Assert.Contains("Store successfully updated", s.FindAlertMessage().Text);
|
||||||
|
s.GoToInvoiceCheckout(invoiceId);
|
||||||
|
s.Driver.WaitUntilAvailable(By.Id("Checkout-v2"));
|
||||||
|
Assert.Contains("sats", s.Driver.FindElement(By.Id("AmountDue")).Text);
|
||||||
|
|
||||||
// BIP21 with LN as default payment method
|
// BIP21 with LN as default payment method
|
||||||
s.GoToHome();
|
s.GoToHome();
|
||||||
invoiceId = s.CreateInvoice(defaultPaymentMethod: "BTC_LightningLike");
|
invoiceId = s.CreateInvoice(defaultPaymentMethod: "BTC_LightningLike");
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ namespace BTCPayServer.Tests
|
|||||||
var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest);
|
var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest);
|
||||||
var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[]
|
var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[]
|
||||||
{
|
{
|
||||||
new BitcoinLikePaymentHandler(null, networkProvider, null, null, null),
|
new BitcoinLikePaymentHandler(null, networkProvider, null, null, null, null),
|
||||||
new LightningLikePaymentHandler(null, null, networkProvider, null, null, null),
|
new LightningLikePaymentHandler(null, null, networkProvider, null, null, null),
|
||||||
});
|
});
|
||||||
var entity = new InvoiceEntity();
|
var entity = new InvoiceEntity();
|
||||||
@@ -512,7 +512,7 @@ namespace BTCPayServer.Tests
|
|||||||
var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest);
|
var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest);
|
||||||
var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[]
|
var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[]
|
||||||
{
|
{
|
||||||
new BitcoinLikePaymentHandler(null, networkProvider, null, null, null),
|
new BitcoinLikePaymentHandler(null, networkProvider, null, null, null, null),
|
||||||
new LightningLikePaymentHandler(null, null, networkProvider, null, null, null),
|
new LightningLikePaymentHandler(null, null, networkProvider, null, null, null),
|
||||||
});
|
});
|
||||||
var entity = new InvoiceEntity();
|
var entity = new InvoiceEntity();
|
||||||
@@ -1466,14 +1466,14 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(1m / 0.000061m, rule2.BidAsk.Bid);
|
Assert.Equal(1m / 0.000061m, rule2.BidAsk.Bid);
|
||||||
|
|
||||||
// testing rounding
|
// testing rounding
|
||||||
rule2 = rules.GetRuleFor(CurrencyPair.Parse("Sats_EUR"));
|
rule2 = rules.GetRuleFor(CurrencyPair.Parse("SATS_EUR"));
|
||||||
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_EUR"), new BidAsk(1.23m, 2.34m));
|
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_EUR"), new BidAsk(1.23m, 2.34m));
|
||||||
Assert.True(rule2.Reevaluate());
|
Assert.True(rule2.Reevaluate());
|
||||||
Assert.Equal("0.00000001 * (1.23, 2.34)", rule2.ToString(true));
|
Assert.Equal("0.00000001 * (1.23, 2.34)", rule2.ToString(true));
|
||||||
Assert.Equal(0.0000000234m, rule2.BidAsk.Ask);
|
Assert.Equal(0.0000000234m, rule2.BidAsk.Ask);
|
||||||
Assert.Equal(0.0000000123m, rule2.BidAsk.Bid);
|
Assert.Equal(0.0000000123m, rule2.BidAsk.Bid);
|
||||||
|
|
||||||
rule2 = rules.GetRuleFor(CurrencyPair.Parse("EUR_Sats"));
|
rule2 = rules.GetRuleFor(CurrencyPair.Parse("EUR_SATS"));
|
||||||
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_EUR"), new BidAsk(1.23m, 2.34m));
|
rule2.ExchangeRates.SetRate("coinbase", CurrencyPair.Parse("BTC_EUR"), new BidAsk(1.23m, 2.34m));
|
||||||
Assert.True(rule2.Reevaluate());
|
Assert.True(rule2.Reevaluate());
|
||||||
Assert.Equal("1 / (0.00000001 * (1.23, 2.34))", rule2.ToString(true));
|
Assert.Equal("1 / (0.00000001 * (1.23, 2.34))", rule2.ToString(true));
|
||||||
@@ -1715,7 +1715,7 @@ namespace BTCPayServer.Tests
|
|||||||
var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest);
|
var networkProvider = new BTCPayNetworkProvider(ChainName.Regtest);
|
||||||
var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[]
|
var paymentMethodHandlerDictionary = new PaymentMethodHandlerDictionary(new IPaymentMethodHandler[]
|
||||||
{
|
{
|
||||||
new BitcoinLikePaymentHandler(null, networkProvider, null, null, null),
|
new BitcoinLikePaymentHandler(null, networkProvider, null, null, null, null),
|
||||||
new LightningLikePaymentHandler(null, null, networkProvider, null, null, null),
|
new LightningLikePaymentHandler(null, null, networkProvider, null, null, null),
|
||||||
});
|
});
|
||||||
var networkBTC = networkProvider.GetNetwork("BTC");
|
var networkBTC = networkProvider.GetNetwork("BTC");
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ namespace BTCPayServer.Tests
|
|||||||
var receiverCoin = await receiverUser.ReceiveUTXO(Money.Satoshis(810), network);
|
var receiverCoin = await receiverUser.ReceiveUTXO(Money.Satoshis(810), network);
|
||||||
|
|
||||||
string errorCode = receiverAddressType == senderAddressType ? null : "unavailable|any UTXO available";
|
string errorCode = receiverAddressType == senderAddressType ? null : "unavailable|any UTXO available";
|
||||||
var invoice = receiverUser.BitPay.CreateInvoice(new Invoice() { Price = 50000, Currency = "sats", FullNotifications = true });
|
var invoice = receiverUser.BitPay.CreateInvoice(new Invoice() { Price = 50000, Currency = "SATS", FullNotifications = true });
|
||||||
if (unsupportedFormats.Contains(receiverAddressType))
|
if (unsupportedFormats.Contains(receiverAddressType))
|
||||||
{
|
{
|
||||||
Assert.Null(TestAccount.GetPayjoinBitcoinUrl(invoice, cashCow.Network));
|
Assert.Null(TestAccount.GetPayjoinBitcoinUrl(invoice, cashCow.Network));
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ using BTCPayServer.Services.Stores;
|
|||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
@@ -388,6 +387,7 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
vm.UseNewCheckout = storeBlob.CheckoutType == Client.Models.CheckoutType.V2;
|
vm.UseNewCheckout = storeBlob.CheckoutType == Client.Models.CheckoutType.V2;
|
||||||
vm.OnChainWithLnInvoiceFallback = storeBlob.OnChainWithLnInvoiceFallback;
|
vm.OnChainWithLnInvoiceFallback = storeBlob.OnChainWithLnInvoiceFallback;
|
||||||
|
vm.LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi;
|
||||||
vm.RequiresRefundEmail = storeBlob.RequiresRefundEmail;
|
vm.RequiresRefundEmail = storeBlob.RequiresRefundEmail;
|
||||||
vm.LazyPaymentMethods = storeBlob.LazyPaymentMethods;
|
vm.LazyPaymentMethods = storeBlob.LazyPaymentMethods;
|
||||||
vm.RedirectAutomatically = storeBlob.RedirectAutomatically;
|
vm.RedirectAutomatically = storeBlob.RedirectAutomatically;
|
||||||
@@ -507,6 +507,7 @@ namespace BTCPayServer.Controllers
|
|||||||
blob.CheckoutType = model.UseNewCheckout ? Client.Models.CheckoutType.V2 : Client.Models.CheckoutType.V1;
|
blob.CheckoutType = model.UseNewCheckout ? Client.Models.CheckoutType.V2 : Client.Models.CheckoutType.V1;
|
||||||
|
|
||||||
blob.OnChainWithLnInvoiceFallback = model.OnChainWithLnInvoiceFallback;
|
blob.OnChainWithLnInvoiceFallback = model.OnChainWithLnInvoiceFallback;
|
||||||
|
blob.LightningAmountInSatoshi = model.LightningAmountInSatoshi;
|
||||||
blob.RequiresRefundEmail = model.RequiresRefundEmail;
|
blob.RequiresRefundEmail = model.RequiresRefundEmail;
|
||||||
blob.LazyPaymentMethods = model.LazyPaymentMethods;
|
blob.LazyPaymentMethods = model.LazyPaymentMethods;
|
||||||
blob.RedirectAutomatically = model.RedirectAutomatically;
|
blob.RedirectAutomatically = model.RedirectAutomatically;
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace BTCPayServer.Models.StoreViewModels
|
|||||||
[Display(Name = "Unify on-chain and lightning payment URL/QR code")]
|
[Display(Name = "Unify on-chain and lightning payment URL/QR code")]
|
||||||
public bool OnChainWithLnInvoiceFallback { get; set; }
|
public bool OnChainWithLnInvoiceFallback { get; set; }
|
||||||
|
|
||||||
|
[Display(Name = "Display Lightning payment amounts in Satoshis")]
|
||||||
|
public bool LightningAmountInSatoshi { get; set; }
|
||||||
|
|
||||||
[Display(Name = "Default payment method on checkout")]
|
[Display(Name = "Default payment method on checkout")]
|
||||||
public string DefaultPaymentMethod { get; set; }
|
public string DefaultPaymentMethod { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using BTCPayServer.Models;
|
|||||||
using BTCPayServer.Models.InvoicingModels;
|
using BTCPayServer.Models.InvoicingModels;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
|
using BTCPayServer.Services.Rates;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.DataEncoders;
|
using NBitcoin.DataEncoders;
|
||||||
using NBXplorer.Models;
|
using NBXplorer.Models;
|
||||||
@@ -23,12 +24,14 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
private readonly BTCPayNetworkProvider _networkProvider;
|
private readonly BTCPayNetworkProvider _networkProvider;
|
||||||
private readonly IFeeProviderFactory _FeeRateProviderFactory;
|
private readonly IFeeProviderFactory _FeeRateProviderFactory;
|
||||||
private readonly NBXplorerDashboard _dashboard;
|
private readonly NBXplorerDashboard _dashboard;
|
||||||
|
private readonly CurrencyNameTable _currencyNameTable;
|
||||||
private readonly Services.Wallets.BTCPayWalletProvider _WalletProvider;
|
private readonly Services.Wallets.BTCPayWalletProvider _WalletProvider;
|
||||||
private readonly Dictionary<string, string> _bech32Prefix;
|
private readonly Dictionary<string, string> _bech32Prefix;
|
||||||
|
|
||||||
public BitcoinLikePaymentHandler(ExplorerClientProvider provider,
|
public BitcoinLikePaymentHandler(ExplorerClientProvider provider,
|
||||||
BTCPayNetworkProvider networkProvider,
|
BTCPayNetworkProvider networkProvider,
|
||||||
IFeeProviderFactory feeRateProviderFactory,
|
IFeeProviderFactory feeRateProviderFactory,
|
||||||
|
CurrencyNameTable currencyNameTable,
|
||||||
NBXplorerDashboard dashboard,
|
NBXplorerDashboard dashboard,
|
||||||
Services.Wallets.BTCPayWalletProvider walletProvider)
|
Services.Wallets.BTCPayWalletProvider walletProvider)
|
||||||
{
|
{
|
||||||
@@ -37,6 +40,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
_FeeRateProviderFactory = feeRateProviderFactory;
|
_FeeRateProviderFactory = feeRateProviderFactory;
|
||||||
_dashboard = dashboard;
|
_dashboard = dashboard;
|
||||||
_WalletProvider = walletProvider;
|
_WalletProvider = walletProvider;
|
||||||
|
_currencyNameTable = currencyNameTable;
|
||||||
|
|
||||||
_bech32Prefix = networkProvider.GetAll().OfType<BTCPayNetwork>()
|
_bech32Prefix = networkProvider.GetAll().OfType<BTCPayNetwork>()
|
||||||
.Where(network => network.NBitcoinNetwork?.Consensus?.SupportSegwit is true).ToDictionary(network => network.CryptoCode,
|
.Where(network => network.NBitcoinNetwork?.Consensus?.SupportSegwit is true).ToDictionary(network => network.CryptoCode,
|
||||||
@@ -63,8 +67,10 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
model.FeeRate = paymentMethodDetails.GetFeeRate();
|
model.FeeRate = paymentMethodDetails.GetFeeRate();
|
||||||
model.PaymentMethodName = GetPaymentMethodName(network);
|
model.PaymentMethodName = GetPaymentMethodName(network);
|
||||||
|
|
||||||
|
var bip21Case = network.SupportLightning && storeBlob.OnChainWithLnInvoiceFallback;
|
||||||
|
var amountInSats = bip21Case && storeBlob.LightningAmountInSatoshi && model.CryptoCode == "BTC";
|
||||||
string lightningFallback = null;
|
string lightningFallback = null;
|
||||||
if (model.Activated && network.SupportLightning && storeBlob.OnChainWithLnInvoiceFallback)
|
if (model.Activated && bip21Case)
|
||||||
{
|
{
|
||||||
var lightningInfo = invoiceResponse.CryptoInfo.FirstOrDefault(a =>
|
var lightningInfo = invoiceResponse.CryptoInfo.FirstOrDefault(a =>
|
||||||
a.GetpaymentMethodId() == new PaymentMethodId(model.CryptoCode, PaymentTypes.LightningLike));
|
a.GetpaymentMethodId() == new PaymentMethodId(model.CryptoCode, PaymentTypes.LightningLike));
|
||||||
@@ -135,6 +141,11 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
{
|
{
|
||||||
model.InvoiceBitcoinUrl = model.InvoiceBitcoinUrlQR = string.Empty;
|
model.InvoiceBitcoinUrl = model.InvoiceBitcoinUrlQR = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model.Activated && amountInSats)
|
||||||
|
{
|
||||||
|
base.PreparePaymentModelForAmountInSats(model, paymentMethod, _currencyNameTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetCryptoImage(PaymentMethodId paymentMethodId)
|
public override string GetCryptoImage(PaymentMethodId paymentMethodId)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
@@ -99,6 +100,20 @@ namespace BTCPayServer.Payments
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void PreparePaymentModelForAmountInSats(PaymentModel model, IPaymentMethod paymentMethod, CurrencyNameTable currencyNameTable)
|
||||||
|
{
|
||||||
|
var satoshiCulture = new CultureInfo(CultureInfo.InvariantCulture.Name)
|
||||||
|
{
|
||||||
|
NumberFormat = { NumberGroupSeparator = " " }
|
||||||
|
};
|
||||||
|
model.CryptoCode = "sats";
|
||||||
|
model.BtcDue = Money.Parse(model.BtcDue).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
||||||
|
model.BtcPaid = Money.Parse(model.BtcPaid).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
||||||
|
model.OrderAmount = Money.Parse(model.OrderAmount).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
||||||
|
model.NetworkFee = new Money(model.NetworkFee, MoneyUnit.BTC).ToUnit(MoneyUnit.Satoshi);
|
||||||
|
model.Rate = currencyNameTable.DisplayFormatCurrency(paymentMethod.Rate / 100_000_000, model.InvoiceCurrency);
|
||||||
|
}
|
||||||
|
|
||||||
public Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs,
|
public Task<IPaymentMethodDetails> CreatePaymentMethodDetails(InvoiceLogs logs,
|
||||||
ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod,
|
ISupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod,
|
||||||
StoreData store, BTCPayNetworkBase network, object preparePaymentObject,
|
StoreData store, BTCPayNetworkBase network, object preparePaymentObject,
|
||||||
|
|||||||
@@ -1,23 +1,17 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
using BTCPayServer.Models.InvoicingModels;
|
using BTCPayServer.Models.InvoicingModels;
|
||||||
using BTCPayServer.Services;
|
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Rates;
|
using BTCPayServer.Services.Rates;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using NBitcoin;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Payments.Lightning
|
namespace BTCPayServer.Payments.Lightning
|
||||||
{
|
{
|
||||||
@@ -112,23 +106,16 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>(model.CryptoCode);
|
var network = _networkProvider.GetNetwork<BTCPayNetwork>(model.CryptoCode);
|
||||||
var cryptoInfo = invoiceResponse.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId);
|
var cryptoInfo = invoiceResponse.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId);
|
||||||
var lnurl = cryptoInfo.PaymentUrls?.AdditionalData["LNURLP"].ToObject<string>();
|
var lnurl = cryptoInfo.PaymentUrls?.AdditionalData["LNURLP"].ToObject<string>();
|
||||||
|
|
||||||
model.PaymentMethodName = GetPaymentMethodName(network);
|
model.PaymentMethodName = GetPaymentMethodName(network);
|
||||||
model.BtcAddress = lnurl?.Replace(UriScheme, "");
|
model.BtcAddress = lnurl?.Replace(UriScheme, "");
|
||||||
model.InvoiceBitcoinUrl = lnurl;
|
model.InvoiceBitcoinUrl = lnurl;
|
||||||
model.InvoiceBitcoinUrlQR = lnurl?.ToUpperInvariant().Replace(UriScheme.ToUpperInvariant(), UriScheme);
|
model.InvoiceBitcoinUrlQR = lnurl?.ToUpperInvariant().Replace(UriScheme.ToUpperInvariant(), UriScheme);
|
||||||
model.PeerInfo = ((LNURLPayPaymentMethodDetails)paymentMethod.GetPaymentMethodDetails()).NodeInfo;
|
model.PeerInfo = ((LNURLPayPaymentMethodDetails)paymentMethod.GetPaymentMethodDetails()).NodeInfo;
|
||||||
|
|
||||||
if (storeBlob.LightningAmountInSatoshi && model.CryptoCode == "BTC")
|
if (storeBlob.LightningAmountInSatoshi && model.CryptoCode == "BTC")
|
||||||
{
|
{
|
||||||
var satoshiCulture = new CultureInfo(CultureInfo.InvariantCulture.Name);
|
base.PreparePaymentModelForAmountInSats(model, paymentMethod, _currencyNameTable);
|
||||||
satoshiCulture.NumberFormat.NumberGroupSeparator = " ";
|
|
||||||
model.CryptoCode = "Sats";
|
|
||||||
model.BtcDue = Money.Parse(model.BtcDue).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
|
||||||
model.BtcPaid = Money.Parse(model.BtcPaid).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
|
||||||
model.OrderAmount = Money.Parse(model.OrderAmount).ToUnit(MoneyUnit.Satoshi)
|
|
||||||
.ToString("N0", satoshiCulture);
|
|
||||||
model.NetworkFee = new Money(model.NetworkFee, MoneyUnit.BTC).ToUnit(MoneyUnit.Satoshi);
|
|
||||||
model.Rate =
|
|
||||||
_currencyNameTable.DisplayFormatCurrency(paymentMethod.Rate / 100_000_000, model.InvoiceCurrency);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -212,24 +211,17 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
StoreBlob storeBlob, IPaymentMethod paymentMethod)
|
StoreBlob storeBlob, IPaymentMethod paymentMethod)
|
||||||
{
|
{
|
||||||
var paymentMethodId = paymentMethod.GetId();
|
var paymentMethodId = paymentMethod.GetId();
|
||||||
|
|
||||||
var cryptoInfo = invoiceResponse.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId);
|
var cryptoInfo = invoiceResponse.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId);
|
||||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>(model.CryptoCode);
|
var network = _networkProvider.GetNetwork<BTCPayNetwork>(model.CryptoCode);
|
||||||
|
|
||||||
model.PaymentMethodName = GetPaymentMethodName(network);
|
model.PaymentMethodName = GetPaymentMethodName(network);
|
||||||
model.InvoiceBitcoinUrl = cryptoInfo.PaymentUrls?.BOLT11;
|
model.InvoiceBitcoinUrl = cryptoInfo.PaymentUrls?.BOLT11;
|
||||||
model.InvoiceBitcoinUrlQR = $"lightning:{cryptoInfo.PaymentUrls?.BOLT11?.ToUpperInvariant()?.Substring("LIGHTNING:".Length)}";
|
model.InvoiceBitcoinUrlQR = $"lightning:{cryptoInfo.PaymentUrls?.BOLT11?.ToUpperInvariant()?.Substring("LIGHTNING:".Length)}";
|
||||||
|
|
||||||
model.PeerInfo = ((LightningLikePaymentMethodDetails)paymentMethod.GetPaymentMethodDetails()).NodeInfo;
|
model.PeerInfo = ((LightningLikePaymentMethodDetails)paymentMethod.GetPaymentMethodDetails()).NodeInfo;
|
||||||
|
|
||||||
if (storeBlob.LightningAmountInSatoshi && model.CryptoCode == "BTC")
|
if (storeBlob.LightningAmountInSatoshi && model.CryptoCode == "BTC")
|
||||||
{
|
{
|
||||||
var satoshiCulture = new CultureInfo(CultureInfo.InvariantCulture.Name);
|
base.PreparePaymentModelForAmountInSats(model, paymentMethod, _currencyNameTable);
|
||||||
satoshiCulture.NumberFormat.NumberGroupSeparator = " ";
|
|
||||||
model.CryptoCode = "Sats";
|
|
||||||
model.BtcDue = Money.Parse(model.BtcDue).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
|
||||||
model.BtcPaid = Money.Parse(model.BtcPaid).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
|
||||||
model.OrderAmount = Money.Parse(model.OrderAmount).ToUnit(MoneyUnit.Satoshi).ToString("N0", satoshiCulture);
|
|
||||||
model.NetworkFee = new Money(model.NetworkFee, MoneyUnit.BTC).ToUnit(MoneyUnit.Satoshi);
|
|
||||||
model.Rate = _currencyNameTable.DisplayFormatCurrency(paymentMethod.Rate / 100_000_000, model.InvoiceCurrency);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public override string GetCryptoImage(PaymentMethodId paymentMethodId)
|
public override string GetCryptoImage(PaymentMethodId paymentMethodId)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<div class="paywithRowRight cursorPointer" v-on:click="openPaymentMethodDialog">
|
<div class="paywithRowRight cursorPointer" v-on:click="openPaymentMethodDialog">
|
||||||
<span class="payment__currencies " v-show="!changingCurrencies">
|
<span class="payment__currencies " v-show="!changingCurrencies">
|
||||||
<img v-bind:src="srvModel.cryptoImage" />
|
<img v-bind:src="srvModel.cryptoImage" />
|
||||||
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCodeSrv}})</span>
|
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span>
|
||||||
<span v-show="srvModel.isLightning">⚡</span>
|
<span v-show="srvModel.isLightning">⚡</span>
|
||||||
<span class="clickable_indicator fa fa-angle-right"></span>
|
<span class="clickable_indicator fa fa-angle-right"></span>
|
||||||
</span>
|
</span>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
{
|
{
|
||||||
<div class="payment__currencies_noborder">
|
<div class="payment__currencies_noborder">
|
||||||
<img v-bind:src="srvModel.cryptoImage" />
|
<img v-bind:src="srvModel.cryptoImage" />
|
||||||
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCodeSrv}})</span>
|
<span>{{srvModel.paymentMethodName}} ({{srvModel.cryptoCode}})</span>
|
||||||
<span v-show="srvModel.isLightning">⚡</span>
|
<span v-show="srvModel.isLightning">⚡</span>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -102,8 +102,8 @@
|
|||||||
<span>{{ srvModel.btcDue }} {{ srvModel.cryptoCode }}</span>
|
<span>{{ srvModel.btcDue }} {{ srvModel.cryptoCode }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="single-item-order__right__ex-rate" v-if="srvModel.orderAmountFiat && srvModel.cryptoCode">
|
<div class="single-item-order__right__ex-rate" v-if="srvModel.orderAmountFiat && srvModel.cryptoCode">
|
||||||
<span v-if="srvModel.cryptoCodeSrv === 'Sats'">1 Sat = {{ srvModel.rate }}</span>
|
<span v-if="srvModel.cryptoCode === 'sats'">1 sat = {{ srvModel.rate }}</span>
|
||||||
<span v-else>1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}</span>
|
<span v-else>1 {{ srvModel.cryptoCode }} = {{ srvModel.rate }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="fa fa-angle-double-down" v-if="!srvModel.isUnsetTopUp"></span>
|
<span class="fa fa-angle-double-down" v-if="!srvModel.isUnsetTopUp"></span>
|
||||||
|
|||||||
@@ -358,8 +358,6 @@
|
|||||||
if (jsonData.paymentMethodId === this.srvModel.paymentMethodId) {
|
if (jsonData.paymentMethodId === this.srvModel.paymentMethodId) {
|
||||||
this.changingCurrencies = false;
|
this.changingCurrencies = false;
|
||||||
}
|
}
|
||||||
// displaying satoshis for lightning payments
|
|
||||||
jsonData.cryptoCodeSrv = jsonData.cryptoCode;
|
|
||||||
// expand line items to show details on amount due for multi-transaction payment
|
// expand line items to show details on amount due for multi-transaction payment
|
||||||
if (this.srvModel.txCount === 1 && jsonData.txCount > 1) {
|
if (this.srvModel.txCount === 1 && jsonData.txCount > 1) {
|
||||||
this.onlyExpandLineItems();
|
this.onlyExpandLineItems();
|
||||||
|
|||||||
@@ -193,8 +193,8 @@
|
|||||||
<div v-if="srvModel.rate && srvModel.cryptoCode">
|
<div v-if="srvModel.rate && srvModel.cryptoCode">
|
||||||
<dt v-t="'exchange_rate'"></dt>
|
<dt v-t="'exchange_rate'"></dt>
|
||||||
<dd :data-clipboard="srvModel.rate" :data-clipboard-confirm="$t('copy_confirm')">
|
<dd :data-clipboard="srvModel.rate" :data-clipboard-confirm="$t('copy_confirm')">
|
||||||
<template v-if="srvModel.cryptoCodeSrv === 'Sats'">1 Sat = {{ srvModel.rate }}</template>
|
<template v-if="srvModel.cryptoCode === 'sats'">1 sat = {{ srvModel.rate }}</template>
|
||||||
<template v-else>1 {{ srvModel.cryptoCodeSrv }} = {{ srvModel.rate }}</template>
|
<template v-else>1 {{ srvModel.cryptoCode }} = {{ srvModel.rate }}</template>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="srvModel.networkFee">
|
<div v-if="srvModel.networkFee">
|
||||||
|
|||||||
@@ -94,6 +94,10 @@
|
|||||||
<vc:icon symbol="info" />
|
<vc:icon symbol="info" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input asp-for="LightningAmountInSatoshi" type="checkbox" class="form-check-input" />
|
||||||
|
<label asp-for="LightningAmountInSatoshi" class="form-check-label"></label>
|
||||||
|
</div>
|
||||||
<div class="checkout-settings collapse @(Model.UseNewCheckout ? "" : "show")" id="OldCheckoutSettings">
|
<div class="checkout-settings collapse @(Model.UseNewCheckout ? "" : "show")" id="OldCheckoutSettings">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input asp-for="RequiresRefundEmail" type="checkbox" class="form-check-input" />
|
<input asp-for="RequiresRefundEmail" type="checkbox" class="form-check-input" />
|
||||||
|
|||||||
@@ -261,9 +261,6 @@ function initApp() {
|
|||||||
window.parent.postMessage({ invoiceId, status }, '*');
|
window.parent.postMessage({ invoiceId, status }, '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
// displaying satoshis for lightning payments
|
|
||||||
data.cryptoCodeSrv = data.cryptoCode;
|
|
||||||
|
|
||||||
const newEnd = new Date();
|
const newEnd = new Date();
|
||||||
newEnd.setSeconds(newEnd.getSeconds() + data.expirationSeconds);
|
newEnd.setSeconds(newEnd.getSeconds() + data.expirationSeconds);
|
||||||
this.endDate = newEnd;
|
this.endDate = newEnd;
|
||||||
|
|||||||
Reference in New Issue
Block a user