Compare commits
37 Commits
v1.0.3.106
...
v1.0.3.114
Author | SHA1 | Date | |
---|---|---|---|
410be51951 | |||
eefe8289b3 | |||
a53a5944f8 | |||
cd009466b6 | |||
f0c106de75 | |||
03ba57cd46 | |||
bea08e5cfd | |||
01787e2662 | |||
ac76220349 | |||
796954c6e3 | |||
292c188182 | |||
1f7097ef89 | |||
b97e083017 | |||
8ffd182b98 | |||
1e77546251 | |||
8711960e74 | |||
8e2bcef824 | |||
d418cf7b07 | |||
864bcbb675 | |||
0b257b98f5 | |||
daab68d0b8 | |||
ab0511aa1d | |||
12494c3ac6 | |||
621533e050 | |||
dc334d230a | |||
b848595378 | |||
ae4b2ab1fd | |||
2ca8cc6ca3 | |||
3b57e2684e | |||
898c672193 | |||
18a7bc9278 | |||
bb29ee10c5 | |||
5441ae537a | |||
0a0ddafd67 | |||
a3b914d8b4 | |||
39f75d3742 | |||
3dd77a4f2c |
.circleci
BTCPayServer.Common
BTCPayServer.Tests
BTCPayServer
Configuration
Controllers
Data
Extensions.csHosting
PaymentRequest
Payments
Bitcoin
IPaymentMethodDetails.csIPaymentMethodHandler.csLightning
PaymentMethodId.csPaymentTypes.Bitcoin.csPaymentTypes.Lightning.csPaymentTypes.csServices
Invoices
Export
InvoiceEntity.csInvoiceRepository.csPaymentMethodDictionary.csPaymentMethodHandlerDictionary.csPaymentRequests
Stores
Views
Account
Apps
Invoice
Manage
ChangePassword.cshtmlEnableAuthenticator.cshtmlGenerateRecoveryCodes.cshtmlIndex.cshtmlResetAuthenticator.cshtmlTwoFactorAuthentication.cshtml
PaymentRequest
Server
CreateTemporaryFileUrl.cshtmlEditAmazonS3StorageProvider.cshtmlEditAzureBlobStorageStorageProvider.cshtmlEditFilesystemStorageProvider.cshtmlEditGoogleCloudStorageStorageProvider.cshtmlFiles.cshtmlListUsers.cshtmlLogs.cshtmlMaintenance.cshtmlPolicies.cshtmlRates.cshtmlServices.cshtmlStorage.cshtmlTheme.cshtml
Shared
Stores
AddDerivationScheme.cshtmlAddLightningNode.cshtmlCheckoutExperience.cshtmlCreateToken.cshtmlPayButtonEnable.cshtmlRates.cshtmlStoreUsers.cshtmlUpdateChangellySettings.cshtmlUpdateCoinSwitchSettings.cshtmlUpdateStore.cshtml
UserStores
Wallets
wwwroot/locales
am-ET.jsonbs-BA.jsonca-ES.jsoncs-CZ.jsonda-DK.jsonde-DE.jsonel-GR.jsonen.jsones-ES.jsonfi-FI.jsonfr-FR.jsonhi.jsonhr-HR.jsonhu-HU.jsonis-IS.jsonit-IT.jsonja-JP.jsonkk-KZ.jsonlv.jsonnl-NL.jsonnp-NP.jsonpl.jsonpt-BR.jsonpt-PT.jsonru-RU.jsonsk-SK.jsonsl-SI.jsonsr.jsonsv.jsontr.jsonuk-UA.jsonvi-VN.jsonzh-SP.json
@ -1,30 +1,41 @@
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
test:
|
||||
fast_tests:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd BTCPayServer.Tests
|
||||
docker-compose -v
|
||||
docker-compose down --v
|
||||
docker-compose build
|
||||
TESTS_RUN_EXTERNAL_INTEGRATION="false"
|
||||
if [ "$CIRCLE_PROJECT_USERNAME" == "btcpayserver" ] && [ "$CIRCLE_PROJECT_REPONAME" == "btcpayserver" ]; then
|
||||
TESTS_RUN_EXTERNAL_INTEGRATION="true"
|
||||
fi
|
||||
docker-compose run -e TESTS_RUN_EXTERNAL_INTEGRATION=$TESTS_RUN_EXTERNAL_INTEGRATION tests
|
||||
cd .circleci && ./run-tests.sh "Fast=Fast"
|
||||
selenium_tests:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Selenium=Selenium"
|
||||
integration_tests:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "Integration=Integration"
|
||||
external_tests:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci && ./run-tests.sh "ExternalIntegration=ExternalIntegration"
|
||||
|
||||
|
||||
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
|
||||
publish_docker_linuxamd64:
|
||||
amd64:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
@ -33,11 +44,11 @@ jobs:
|
||||
command: |
|
||||
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
|
||||
#
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-amd64 -f Dockerfile.linuxamd64 .
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-amd64 -f amd64.Dockerfile .
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-amd64
|
||||
|
||||
publish_docker_linuxarm:
|
||||
arm32v7:
|
||||
machine:
|
||||
docker_layer_caching: true
|
||||
steps:
|
||||
@ -47,11 +58,11 @@ jobs:
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
|
||||
#
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 -f Dockerfile.linuxarm32v7 .
|
||||
sudo docker build --pull -t $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 -f arm32v7.Dockerfile .
|
||||
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
|
||||
sudo docker push $DOCKERHUB_REPO:$LATEST_TAG-arm32v7
|
||||
|
||||
publish_docker_multiarch:
|
||||
multiarch:
|
||||
machine:
|
||||
enabled: true
|
||||
image: circleci/classic:201808-01
|
||||
@ -74,11 +85,17 @@ workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
- test
|
||||
- fast_tests
|
||||
- selenium_tests
|
||||
- integration_tests
|
||||
- external_tests:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
|
||||
publish:
|
||||
jobs:
|
||||
- publish_docker_linuxamd64:
|
||||
- amd64:
|
||||
filters:
|
||||
# ignore any commit on any branch by default
|
||||
branches:
|
||||
@ -86,16 +103,16 @@ workflows:
|
||||
# only act on version tags
|
||||
tags:
|
||||
only: /v[1-9]+(\.[0-9]+)*/
|
||||
- publish_docker_linuxarm:
|
||||
- arm32v7:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /v[1-9]+(\.[0-9]+)*/
|
||||
- publish_docker_multiarch:
|
||||
- multiarch:
|
||||
requires:
|
||||
- publish_docker_linuxamd64
|
||||
- publish_docker_linuxarm
|
||||
- amd64
|
||||
- arm32v7
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
8
.circleci/run-tests.sh
Executable file
8
.circleci/run-tests.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
cd ../BTCPayServer.Tests
|
||||
docker-compose -v
|
||||
docker-compose down --v
|
||||
docker-compose build
|
||||
docker-compose run -e "TEST_FILTERS=$1" tests
|
@ -22,13 +22,14 @@ namespace BTCPayServer
|
||||
}
|
||||
}
|
||||
|
||||
BTCPayNetworkProvider(BTCPayNetworkProvider filtered, string[] cryptoCodes)
|
||||
BTCPayNetworkProvider(BTCPayNetworkProvider unfiltered, string[] cryptoCodes)
|
||||
{
|
||||
NetworkType = filtered.NetworkType;
|
||||
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(filtered.NetworkType);
|
||||
UnfilteredNetworks = unfiltered.UnfilteredNetworks ?? unfiltered;
|
||||
NetworkType = unfiltered.NetworkType;
|
||||
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(unfiltered.NetworkType);
|
||||
_Networks = new Dictionary<string, BTCPayNetworkBase>();
|
||||
cryptoCodes = cryptoCodes.Select(c => c.ToUpperInvariant()).ToArray();
|
||||
foreach (var network in filtered._Networks)
|
||||
foreach (var network in unfiltered._Networks)
|
||||
{
|
||||
if(cryptoCodes.Contains(network.Key))
|
||||
{
|
||||
@ -37,9 +38,12 @@ namespace BTCPayServer
|
||||
}
|
||||
}
|
||||
|
||||
public BTCPayNetworkProvider UnfilteredNetworks { get; }
|
||||
|
||||
public NetworkType NetworkType { get; private set; }
|
||||
public BTCPayNetworkProvider(NetworkType networkType)
|
||||
{
|
||||
UnfilteredNetworks = this;
|
||||
_NBXplorerNetworkProvider = new NBXplorerNetworkProvider(networkType);
|
||||
NetworkType = networkType;
|
||||
InitBitcoin();
|
||||
@ -102,9 +106,14 @@ namespace BTCPayServer
|
||||
{
|
||||
return _Networks.ContainsKey(cryptoCode.ToUpperInvariant());
|
||||
}
|
||||
|
||||
public BTCPayNetworkBase GetNetwork(string cryptoCode)
|
||||
{
|
||||
return GetNetwork<BTCPayNetworkBase>(cryptoCode);
|
||||
}
|
||||
public T GetNetwork<T>(string cryptoCode) where T: BTCPayNetworkBase
|
||||
{
|
||||
if (cryptoCode == null)
|
||||
throw new ArgumentNullException(nameof(cryptoCode));
|
||||
if(!_Networks.TryGetValue(cryptoCode.ToUpperInvariant(), out BTCPayNetworkBase network))
|
||||
{
|
||||
if (cryptoCode == "XBT")
|
||||
|
@ -107,7 +107,7 @@ namespace BTCPayServer.Tests
|
||||
new BitcoinLikePaymentHandler(null, networkProvider, null, null),
|
||||
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
||||
});
|
||||
InvoiceEntity invoiceEntity = new InvoiceEntity() { PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary};
|
||||
InvoiceEntity invoiceEntity = new InvoiceEntity();
|
||||
invoiceEntity.Payments = new System.Collections.Generic.List<PaymentEntity>();
|
||||
invoiceEntity.ProductInformation = new ProductInformation() {Price = 100};
|
||||
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
|
||||
@ -131,8 +131,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
Accounted = true,
|
||||
CryptoCode = "BTC",
|
||||
NetworkFee = 0.00000100m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.00000100m
|
||||
}
|
||||
.SetCryptoPaymentData(new BitcoinLikePaymentData()
|
||||
{
|
||||
@ -144,8 +143,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
Accounted = true,
|
||||
CryptoCode = "BTC",
|
||||
NetworkFee = 0.00000100m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.00000100m
|
||||
}
|
||||
.SetCryptoPaymentData(new BitcoinLikePaymentData()
|
||||
{
|
||||
@ -216,7 +214,7 @@ namespace BTCPayServer.Tests
|
||||
new BitcoinLikePaymentHandler(null, networkProvider, null, null),
|
||||
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
||||
});
|
||||
var entity = new InvoiceEntity() {PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary};
|
||||
var entity = new InvoiceEntity();
|
||||
#pragma warning disable CS0618
|
||||
entity.Payments = new System.Collections.Generic.List<PaymentEntity>();
|
||||
entity.SetPaymentMethod(new PaymentMethod()
|
||||
@ -234,8 +232,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
Output = new TxOut(Money.Coins(0.5m), new Key()),
|
||||
Accounted = true,
|
||||
NetworkFee = 0.1m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
accounting = paymentMethod.Calculate();
|
||||
@ -247,8 +244,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
Output = new TxOut(Money.Coins(0.2m), new Key()),
|
||||
Accounted = true,
|
||||
NetworkFee = 0.1m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
accounting = paymentMethod.Calculate();
|
||||
@ -259,8 +255,7 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
Output = new TxOut(Money.Coins(0.6m), new Key()),
|
||||
Accounted = true,
|
||||
NetworkFee = 0.1m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
accounting = paymentMethod.Calculate();
|
||||
@ -270,15 +265,14 @@ namespace BTCPayServer.Tests
|
||||
entity.Payments.Add(new PaymentEntity()
|
||||
{
|
||||
Output = new TxOut(Money.Coins(0.2m), new Key()),
|
||||
Accounted = true,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
Accounted = true
|
||||
});
|
||||
|
||||
accounting = paymentMethod.Calculate();
|
||||
Assert.Equal(Money.Zero, accounting.Due);
|
||||
Assert.Equal(Money.Coins(1.3m), accounting.TotalDue);
|
||||
|
||||
entity = new InvoiceEntity() {PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary};
|
||||
entity = new InvoiceEntity();
|
||||
entity.ProductInformation = new ProductInformation() {Price = 5000};
|
||||
PaymentMethodDictionary paymentMethods = new PaymentMethodDictionary();
|
||||
paymentMethods.Add(
|
||||
@ -301,8 +295,7 @@ namespace BTCPayServer.Tests
|
||||
CryptoCode = "BTC",
|
||||
Output = new TxOut(Money.Coins(1.0m), new Key()),
|
||||
Accounted = true,
|
||||
NetworkFee = 0.1m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike), null);
|
||||
@ -325,8 +318,7 @@ namespace BTCPayServer.Tests
|
||||
CryptoCode = "LTC",
|
||||
Output = new TxOut(Money.Coins(1.0m), new Key()),
|
||||
Accounted = true,
|
||||
NetworkFee = 0.01m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.01m
|
||||
});
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike), null);
|
||||
@ -351,8 +343,7 @@ namespace BTCPayServer.Tests
|
||||
CryptoCode = "BTC",
|
||||
Output = new TxOut(remaining, new Key()),
|
||||
Accounted = true,
|
||||
NetworkFee = 0.1m,
|
||||
PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary
|
||||
NetworkFee = 0.1m
|
||||
});
|
||||
|
||||
paymentMethod = entity.GetPaymentMethod(new PaymentMethodId("BTC", PaymentTypes.BTCLike), null);
|
||||
@ -423,7 +414,7 @@ namespace BTCPayServer.Tests
|
||||
new BitcoinLikePaymentHandler(null, networkProvider, null, null),
|
||||
new LightningLikePaymentHandler(null, null, networkProvider, null),
|
||||
});
|
||||
var entity = new InvoiceEntity() {PaymentMethodHandlerDictionary = paymentMethodHandlerDictionary};
|
||||
var entity = new InvoiceEntity();
|
||||
#pragma warning disable CS0618
|
||||
entity.Payments = new List<PaymentEntity>();
|
||||
entity.SetPaymentMethod(new PaymentMethod()
|
||||
@ -2252,14 +2243,13 @@ donation:
|
||||
var invoiceAddress = BitcoinAddress.Create(invoice.CryptoInfo[0].Address, cashCow.Network);
|
||||
var firstPayment = invoice.CryptoInfo[0].TotalDue - Money.Coins(0.001m);
|
||||
cashCow.SendToAddress(invoiceAddress, firstPayment);
|
||||
var handler = tester.PayTester.GetService<BitcoinLikePaymentHandler>();
|
||||
TestUtils.Eventually(() =>
|
||||
{
|
||||
var exportResultPaid = user.GetController<InvoiceController>().Export("csv").GetAwaiter().GetResult();
|
||||
var paidresult = Assert.IsType<ContentResult>(exportResultPaid);
|
||||
Assert.Equal("application/csv", paidresult.ContentType);
|
||||
Assert.Contains($",\"orderId\",\"{invoice.Id}\",", paidresult.Content);
|
||||
Assert.Contains($",\"{handler.PrettyDescription}\",\"BTC\",\"0.0991\",\"0.0001\",\"5000.0\"", paidresult.Content);
|
||||
Assert.Contains($",\"On-Chain\",\"BTC\",\"0.0991\",\"0.0001\",\"5000.0\"", paidresult.Content);
|
||||
Assert.Contains($",\"USD\",\"5.00", paidresult.Content); // Seems hacky but some plateform does not render this decimal the same
|
||||
Assert.Contains($"0\",\"500.0\",\"\",\"Some ``, description\",\"new (paidPartial)\"", paidresult.Content);
|
||||
});
|
||||
|
@ -134,6 +134,7 @@ services:
|
||||
bind-addr=0.0.0.0
|
||||
announce-addr=customer_lightningd
|
||||
log-level=debug
|
||||
funding-confirms=1
|
||||
dev-broadcast-interval=1000
|
||||
dev-bitcoind-poll=1
|
||||
ports:
|
||||
@ -177,6 +178,7 @@ services:
|
||||
bitcoin-rpcconnect=bitcoind
|
||||
bind-addr=0.0.0.0
|
||||
announce-addr=merchant_lightningd
|
||||
funding-confirms=1
|
||||
network=regtest
|
||||
log-level=debug
|
||||
dev-broadcast-interval=1000
|
||||
@ -240,6 +242,7 @@ services:
|
||||
bitcoind.zmqpubrawblock=tcp://bitcoind:28332
|
||||
bitcoind.zmqpubrawtx=tcp://bitcoind:28333
|
||||
externalip=merchant_lnd:9735
|
||||
bitcoin.defaultchanconfs=1
|
||||
no-macaroons=1
|
||||
debuglevel=debug
|
||||
noseedbackup=1
|
||||
@ -270,6 +273,7 @@ services:
|
||||
bitcoind.zmqpubrawblock=tcp://bitcoind:28332
|
||||
bitcoind.zmqpubrawtx=tcp://bitcoind:28333
|
||||
externalip=customer_lnd:10009
|
||||
bitcoin.defaultchanconfs=1
|
||||
no-macaroons=1
|
||||
debuglevel=debug
|
||||
noseedbackup=1
|
||||
|
@ -1,9 +1,9 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
dotnet test --filter Fast=Fast --no-build
|
||||
dotnet test --filter Selenium=Selenium --no-build -v n
|
||||
dotnet test --filter Integration=Integration --no-build -v n
|
||||
if [[ "$TESTS_RUN_EXTERNAL_INTEGRATION" == "true" ]]; then
|
||||
dotnet test --filter ExternalIntegration=ExternalIntegration --no-build -v n
|
||||
FILTERS=" "
|
||||
if [[ "$TEST_FILTERS" ]]; then
|
||||
FILTERS="--filter $TEST_FILTERS"
|
||||
fi
|
||||
|
||||
dotnet test $FILTERS --no-build -v n
|
||||
|
@ -52,7 +52,9 @@ namespace BTCPayServer.Configuration
|
||||
app.Option($"--{crypto}explorerurl", $"URL of the NBXplorer for {network.CryptoCode} (default: {network.NBXplorerNetwork.DefaultSettings.DefaultUrl})", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}explorercookiefile", $"Path to the cookie file (default: {network.NBXplorerNetwork.DefaultSettings.DefaultCookieFile})", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}lightning", $"Easy configuration of lightning for the server administrator: Must be a UNIX socket of c-lightning (lightning-rpc) or URL to a charge server (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}externallndgrpc", $"The LND gRPC configuration BTCPay will expose to easily connect to the internal lnd wallet from Zap wallet (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}externallndgrpc", $"The LND gRPC configuration BTCPay will expose to easily connect to the internal lnd wallet from an external wallet (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}externallndrest", $"The LND REST configuration BTCPay will expose to easily connect to the internal lnd wallet from an external wallet (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}externalrtl", $"The Ride the Lightning configuration so BTCPay will expose to easily open it in server settings (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}externalspark", $"Show spark information in Server settings / Server. The connection string to spark server (default: empty)", CommandOptionType.SingleValue);
|
||||
app.Option($"--{crypto}externalcharge", $"Show lightning charge information in Server settings/Server. The connection string to charge server (default: empty)", CommandOptionType.SingleValue);
|
||||
}
|
||||
|
@ -79,9 +79,7 @@ namespace BTCPayServer.Controllers
|
||||
new InvoiceDetailsModel.AddressModel
|
||||
{
|
||||
Destination = h.GetAddress(),
|
||||
PaymentMethod =
|
||||
invoice.PaymentMethodHandlerDictionary[h.GetPaymentMethodId()]
|
||||
.ToPrettyString(h.GetPaymentMethodId()),
|
||||
PaymentMethod = h.GetPaymentMethodId().ToPrettyString(),
|
||||
Current = !h.UnAssigned.HasValue
|
||||
}).ToArray();
|
||||
|
||||
@ -101,8 +99,7 @@ namespace BTCPayServer.Controllers
|
||||
var accounting = data.Calculate();
|
||||
var paymentMethodId = data.GetId();
|
||||
var cryptoPayment = new InvoiceDetailsModel.CryptoPayment();
|
||||
cryptoPayment.PaymentMethod = invoice.PaymentMethodHandlerDictionary[paymentMethodId]
|
||||
.ToPrettyString(data.GetId());
|
||||
cryptoPayment.PaymentMethod = paymentMethodId.ToPrettyString();
|
||||
cryptoPayment.Due = _CurrencyNameTable.DisplayFormatCurrency(accounting.Due.ToDecimal(MoneyUnit.BTC), paymentMethodId.CryptoCode);
|
||||
cryptoPayment.Paid = _CurrencyNameTable.DisplayFormatCurrency(accounting.CryptoPaid.ToDecimal(MoneyUnit.BTC), paymentMethodId.CryptoCode);
|
||||
cryptoPayment.Overpaid = _CurrencyNameTable.DisplayFormatCurrency(accounting.OverpaidHelper.ToDecimal(MoneyUnit.BTC), paymentMethodId.CryptoCode);
|
||||
@ -269,7 +266,8 @@ namespace BTCPayServer.Controllers
|
||||
(1m + (changelly.AmountMarkupPercentage / 100m)))
|
||||
: (decimal?)null;
|
||||
|
||||
var paymentMethodHandler = invoice.PaymentMethodHandlerDictionary[paymentMethodId];
|
||||
|
||||
var paymentMethodHandler = _paymentMethodHandlerDictionary[paymentMethodId];
|
||||
var model = new PaymentModel()
|
||||
{
|
||||
CryptoCode = network.CryptoCode,
|
||||
@ -317,8 +315,7 @@ namespace BTCPayServer.Controllers
|
||||
.Select(kv =>
|
||||
{
|
||||
var availableCryptoPaymentMethodId = kv.GetId();
|
||||
var availableCryptoHandler =
|
||||
invoice.PaymentMethodHandlerDictionary[availableCryptoPaymentMethodId];
|
||||
var availableCryptoHandler = _paymentMethodHandlerDictionary[availableCryptoPaymentMethodId];
|
||||
return new PaymentModel.AvailableCrypto()
|
||||
{
|
||||
PaymentMethodId = kv.GetId().ToString(),
|
||||
@ -525,7 +522,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
return new SelectList(_paymentMethodHandlerDictionary.Distinct().SelectMany(handler =>
|
||||
handler.GetSupportedPaymentMethods()
|
||||
.Select(id => new SelectListItem(handler.ToPrettyString(id), id.ToString()))),
|
||||
.Select(id => new SelectListItem(id.ToPrettyString(), id.ToString()))),
|
||||
nameof(SelectListItem.Value),
|
||||
nameof(SelectListItem.Text));
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ namespace BTCPayServer.Controllers
|
||||
var fetchingByCurrencyPair = _RateProvider.FetchRates(currencyPairsToFetch, rateRules, cancellationToken);
|
||||
var fetchingAll = WhenAllFetched(logs, fetchingByCurrencyPair);
|
||||
var supportedPaymentMethods = store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||
.Where(s => !excludeFilter.Match(s.PaymentId))
|
||||
.Where(s => !excludeFilter.Match(s.PaymentId) && _paymentMethodHandlerDictionary.Support(s.PaymentId))
|
||||
.Select(c =>
|
||||
(Handler: _paymentMethodHandlerDictionary[c.PaymentId],
|
||||
SupportedPaymentMethod: c,
|
||||
@ -243,7 +243,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
try
|
||||
{
|
||||
var logPrefix = $"{handler.ToPrettyString(supportedPaymentMethod.PaymentId)}:";
|
||||
var logPrefix = $"{supportedPaymentMethod.PaymentId.ToPrettyString()}:";
|
||||
var storeBlob = store.GetStoreBlob();
|
||||
var preparePayment = handler.PreparePayment(supportedPaymentMethod, store, network);
|
||||
var rate = await fetchingByCurrencyPair[new CurrencyPair(network.CryptoCode, entity.ProductInformation.Currency)];
|
||||
|
@ -366,7 +366,7 @@ namespace BTCPayServer.Controllers
|
||||
void SetCryptoCurrencies(CheckoutExperienceViewModel vm, Data.StoreData storeData)
|
||||
{
|
||||
var choices = storeData.GetEnabledPaymentIds(_NetworkProvider)
|
||||
.Select(o => new CheckoutExperienceViewModel.Format() { Name = _paymentMethodHandlerDictionary[o].ToPrettyString(o), Value = o.ToString(), PaymentId = o }).ToArray();
|
||||
.Select(o => new CheckoutExperienceViewModel.Format() { Name = o.ToPrettyString(), Value = o.ToString(), PaymentId = o }).ToArray();
|
||||
|
||||
var defaultPaymentId = storeData.GetDefaultPaymentId(_NetworkProvider);
|
||||
var chosen = choices.FirstOrDefault(c => c.PaymentId == defaultPaymentId);
|
||||
@ -479,7 +479,7 @@ namespace BTCPayServer.Controllers
|
||||
{
|
||||
switch (paymentMethodId.PaymentType)
|
||||
{
|
||||
case PaymentTypes.BTCLike:
|
||||
case BitcoinPaymentType _:
|
||||
var strategy = derivationByCryptoCode.TryGet(paymentMethodId.CryptoCode);
|
||||
vm.DerivationSchemes.Add(new StoreViewModel.DerivationScheme()
|
||||
{
|
||||
@ -489,7 +489,7 @@ namespace BTCPayServer.Controllers
|
||||
Enabled = !excludeFilters.Match(paymentMethodId)
|
||||
});
|
||||
break;
|
||||
case PaymentTypes.LightningLike:
|
||||
case LightningPaymentType _:
|
||||
var lightning = lightningByCryptoCode.TryGet(paymentMethodId.CryptoCode);
|
||||
vm.LightningNodes.Add(new StoreViewModel.LightningNode()
|
||||
{
|
||||
|
@ -28,9 +28,6 @@ namespace BTCPayServer.Data
|
||||
{
|
||||
public class StoreData
|
||||
{
|
||||
[NotMapped]
|
||||
[JsonIgnore]
|
||||
public PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary { get; set; }
|
||||
public string Id
|
||||
{
|
||||
get;
|
||||
@ -67,17 +64,15 @@ namespace BTCPayServer.Data
|
||||
}
|
||||
public IEnumerable<ISupportedPaymentMethod> GetSupportedPaymentMethods(BTCPayNetworkProvider networks)
|
||||
{
|
||||
networks = networks.UnfilteredNetworks;
|
||||
#pragma warning disable CS0618
|
||||
bool btcReturned = false;
|
||||
|
||||
// Legacy stuff which should go away
|
||||
if (!string.IsNullOrEmpty(DerivationStrategy))
|
||||
{
|
||||
if (networks.BTC != null)
|
||||
{
|
||||
btcReturned = true;
|
||||
yield return DerivationSchemeSettings.Parse(DerivationStrategy, networks.BTC);
|
||||
}
|
||||
btcReturned = true;
|
||||
yield return DerivationSchemeSettings.Parse(DerivationStrategy, networks.BTC);
|
||||
}
|
||||
|
||||
|
||||
@ -95,8 +90,7 @@ namespace BTCPayServer.Data
|
||||
if (strat.Value.Type == JTokenType.Null)
|
||||
continue;
|
||||
yield return
|
||||
PaymentMethodHandlerDictionary[paymentMethodId]
|
||||
.DeserializeSupportedPaymentMethod(paymentMethodId, strat.Value);
|
||||
paymentMethodId.PaymentType.DeserializeSupportedPaymentMethod(network, strat.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ namespace BTCPayServer
|
||||
}
|
||||
public static PaymentMethodId GetpaymentMethodId(this InvoiceCryptoInfo info)
|
||||
{
|
||||
return new PaymentMethodId(info.CryptoCode, Enum.Parse<PaymentTypes>(info.PaymentType));
|
||||
return new PaymentMethodId(info.CryptoCode, PaymentTypes.Parse(info.PaymentType));
|
||||
}
|
||||
public static async Task CloseSocket(this WebSocket webSocket)
|
||||
{
|
||||
|
@ -71,12 +71,10 @@ namespace BTCPayServer.Hosting
|
||||
{
|
||||
var opts = o.GetRequiredService<BTCPayServerOptions>();
|
||||
var dbContext = o.GetRequiredService<ApplicationDbContextFactory>();
|
||||
var paymentMethodHandlerDictionary = o.GetService<PaymentMethodHandlerDictionary>();
|
||||
var dbpath = Path.Combine(opts.DataDir, "InvoiceDB");
|
||||
if (!Directory.Exists(dbpath))
|
||||
Directory.CreateDirectory(dbpath);
|
||||
return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService<BTCPayNetworkProvider>(),
|
||||
paymentMethodHandlerDictionary);
|
||||
return new InvoiceRepository(dbContext, dbpath, o.GetRequiredService<BTCPayNetworkProvider>());
|
||||
});
|
||||
services.AddSingleton<BTCPayServerEnvironment>();
|
||||
services.TryAddSingleton<TokenRepository>();
|
||||
|
@ -110,11 +110,11 @@ namespace BTCPayServer.PaymentRequest
|
||||
var paymentMethodId = paymentEntity.GetPaymentMethodId();
|
||||
|
||||
string txId = paymentData.GetPaymentId();
|
||||
string link = paymentEntity.PaymentMethodHandlerDictionary[paymentMethodId].GetTransactionLink(paymentMethodId, txId);
|
||||
string link = GetTransactionLink(paymentMethodId, txId);
|
||||
return new ViewPaymentRequestViewModel.PaymentRequestInvoicePayment()
|
||||
{
|
||||
Amount = paymentData.GetValue(),
|
||||
PaymentMethod = paymentEntity.GetPaymentMethodId().ToString(),
|
||||
PaymentMethod = paymentMethodId.ToString(),
|
||||
Link = link,
|
||||
Id = txId
|
||||
};
|
||||
@ -122,5 +122,13 @@ namespace BTCPayServer.PaymentRequest
|
||||
}).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
private string GetTransactionLink(PaymentMethodId paymentMethodId, string txId)
|
||||
{
|
||||
var network = _BtcPayNetworkProvider.GetNetwork(paymentMethodId.CryptoCode);
|
||||
if (network == null)
|
||||
return null;
|
||||
return paymentMethodId.PaymentType.GetTransactionLink(network, txId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,10 +10,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
{
|
||||
public class BitcoinLikeOnChainPaymentMethod : IPaymentMethodDetails
|
||||
{
|
||||
public PaymentTypes GetPaymentType()
|
||||
{
|
||||
return PaymentTypes.BTCLike;
|
||||
}
|
||||
public PaymentType GetPaymentType() => PaymentTypes.BTCLike;
|
||||
|
||||
public string GetPaymentDestination()
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
|
||||
public class BitcoinLikePaymentData : CryptoPaymentData
|
||||
{
|
||||
public PaymentTypes GetPaymentType()
|
||||
public PaymentType GetPaymentType()
|
||||
{
|
||||
return PaymentTypes.BTCLike;
|
||||
}
|
||||
|
@ -99,45 +99,11 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
.Select(network => new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike));
|
||||
}
|
||||
|
||||
public override CryptoPaymentData GetCryptoPaymentData(PaymentEntity paymentEntity)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
|
||||
BitcoinLikePaymentData paymentData;
|
||||
if (string.IsNullOrEmpty(paymentEntity.CryptoPaymentDataType))
|
||||
{
|
||||
// For invoices created when CryptoPaymentDataType was not existing, we just consider that it is a RBFed payment for safety
|
||||
paymentData = new BitcoinLikePaymentData();
|
||||
paymentData.Outpoint = paymentEntity.Outpoint;
|
||||
paymentData.Output = paymentEntity.Output;
|
||||
paymentData.RBF = true;
|
||||
paymentData.ConfirmationCount = 0;
|
||||
paymentData.Legacy = true;
|
||||
return paymentData;
|
||||
}
|
||||
|
||||
paymentData =
|
||||
JsonConvert.DeserializeObject<BitcoinLikePaymentData>(paymentEntity.CryptoPaymentData);
|
||||
// legacy
|
||||
paymentData.Output = paymentEntity.Output;
|
||||
paymentData.Outpoint = paymentEntity.Outpoint;
|
||||
#pragma warning restore CS0618
|
||||
return paymentData;
|
||||
}
|
||||
|
||||
private string GetPaymentMethodName(BTCPayNetworkBase network)
|
||||
{
|
||||
return network.DisplayName;
|
||||
}
|
||||
|
||||
|
||||
public override string GetTransactionLink(PaymentMethodId paymentMethodId, params object[] args)
|
||||
{
|
||||
|
||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
|
||||
return string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, args);
|
||||
}
|
||||
|
||||
public override object PreparePayment(DerivationSchemeSettings supportedPaymentMethod, StoreData store,
|
||||
BTCPayNetworkBase network)
|
||||
{
|
||||
@ -149,8 +115,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
};
|
||||
}
|
||||
|
||||
public override string PrettyDescription => "On-Chain";
|
||||
public override PaymentTypes PaymentType => PaymentTypes.BTCLike;
|
||||
public override PaymentType PaymentType => PaymentTypes.BTCLike;
|
||||
|
||||
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
|
||||
DerivationSchemeSettings supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store,
|
||||
@ -176,53 +141,5 @@ namespace BTCPayServer.Payments.Bitcoin
|
||||
onchainMethod.DepositAddress = (await prepare.ReserveAddress).ToString();
|
||||
return onchainMethod;
|
||||
}
|
||||
|
||||
public override void PrepareInvoiceDto(InvoiceResponse invoiceResponse, InvoiceEntity invoiceEntity,
|
||||
InvoiceCryptoInfo invoiceCryptoInfo,
|
||||
PaymentMethodAccounting accounting, PaymentMethod info)
|
||||
{
|
||||
var scheme = info.Network.UriScheme;
|
||||
|
||||
var minerInfo = new MinerFeeInfo();
|
||||
minerInfo.TotalFee = accounting.NetworkFee.Satoshi;
|
||||
minerInfo.SatoshiPerBytes = ((BitcoinLikeOnChainPaymentMethod)info.GetPaymentMethodDetails()).FeeRate
|
||||
.GetFee(1).Satoshi;
|
||||
invoiceResponse.MinerFees.TryAdd(invoiceCryptoInfo.CryptoCode, minerInfo);
|
||||
invoiceCryptoInfo.PaymentUrls = new NBitpayClient.InvoicePaymentUrls()
|
||||
{
|
||||
BIP21 = $"{scheme}:{invoiceCryptoInfo.Address}?amount={invoiceCryptoInfo.Due}",
|
||||
};
|
||||
|
||||
#pragma warning disable 618
|
||||
if (info.CryptoCode == "BTC")
|
||||
{
|
||||
invoiceResponse.BTCPrice = invoiceCryptoInfo.Price;
|
||||
invoiceResponse.Rate = invoiceCryptoInfo.Rate;
|
||||
invoiceResponse.ExRates = invoiceCryptoInfo.ExRates;
|
||||
invoiceResponse.BitcoinAddress = invoiceCryptoInfo.Address;
|
||||
invoiceResponse.BTCPaid = invoiceCryptoInfo.Paid;
|
||||
invoiceResponse.BTCDue = invoiceCryptoInfo.Due;
|
||||
invoiceResponse.PaymentUrls = invoiceCryptoInfo.PaymentUrls;
|
||||
}
|
||||
#pragma warning restore 618
|
||||
}
|
||||
|
||||
public override ISupportedPaymentMethod DeserializeSupportedPaymentMethod(PaymentMethodId paymentMethodId, JToken value)
|
||||
{
|
||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
|
||||
if (value is JObject jobj)
|
||||
{
|
||||
var scheme = network.NBXplorerNetwork.Serializer.ToObject<DerivationSchemeSettings>(jobj);
|
||||
scheme.Network = network;
|
||||
return scheme;
|
||||
}
|
||||
// Legacy
|
||||
return DerivationSchemeSettings.Parse(((JValue)value).Value<string>(), network);
|
||||
}
|
||||
|
||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(JObject jobj)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod>(jobj.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace BTCPayServer.Payments
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetPaymentDestination();
|
||||
PaymentTypes GetPaymentType();
|
||||
PaymentType GetPaymentType();
|
||||
/// <summary>
|
||||
/// Returns fee that the merchant charge to the customer for the next payment
|
||||
/// </summary>
|
||||
|
@ -18,7 +18,6 @@ namespace BTCPayServer.Payments
|
||||
/// </summary>
|
||||
public interface IPaymentMethodHandler
|
||||
{
|
||||
string PrettyDescription { get; }
|
||||
/// <summary>
|
||||
/// Create needed to track payments of this invoice
|
||||
/// </summary>
|
||||
@ -40,13 +39,6 @@ namespace BTCPayServer.Payments
|
||||
/// <returns></returns>
|
||||
object PreparePayment(ISupportedPaymentMethod supportedPaymentMethod, StoreData store, BTCPayNetworkBase network);
|
||||
|
||||
void PrepareInvoiceDto(InvoiceResponse invoiceResponse, InvoiceEntity invoiceEntity,
|
||||
InvoiceCryptoInfo invoiceCryptoInfo,
|
||||
PaymentMethodAccounting accounting, PaymentMethod info);
|
||||
|
||||
|
||||
string ToPrettyString(PaymentMethodId paymentMethodId);
|
||||
|
||||
void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse);
|
||||
string GetCryptoImage(PaymentMethodId paymentMethodId);
|
||||
string GetPaymentMethodName(PaymentMethodId paymentMethodId);
|
||||
@ -56,12 +48,6 @@ namespace BTCPayServer.Payments
|
||||
Money amount, PaymentMethodId paymentMethodId);
|
||||
|
||||
IEnumerable<PaymentMethodId> GetSupportedPaymentMethods();
|
||||
|
||||
CryptoPaymentData GetCryptoPaymentData(PaymentEntity paymentEntity);
|
||||
|
||||
ISupportedPaymentMethod DeserializeSupportedPaymentMethod(PaymentMethodId paymentMethodId, JToken value);
|
||||
IPaymentMethodDetails DeserializePaymentMethodDetails(JObject jobj);
|
||||
string GetTransactionLink(PaymentMethodId paymentMethodId, params object[] args);
|
||||
}
|
||||
|
||||
public interface IPaymentMethodHandler<TSupportedPaymentMethod, TBTCPayNetwork> : IPaymentMethodHandler
|
||||
@ -77,16 +63,12 @@ namespace BTCPayServer.Payments
|
||||
where TSupportedPaymentMethod : ISupportedPaymentMethod
|
||||
where TBTCPayNetwork : BTCPayNetworkBase
|
||||
{
|
||||
public abstract string PrettyDescription { get; }
|
||||
public abstract PaymentTypes PaymentType { get; }
|
||||
public abstract PaymentType PaymentType { get; }
|
||||
|
||||
public abstract Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
|
||||
TSupportedPaymentMethod supportedPaymentMethod,
|
||||
PaymentMethod paymentMethod, StoreData store, TBTCPayNetwork network, object preparePaymentObject);
|
||||
|
||||
public abstract void PrepareInvoiceDto(InvoiceResponse invoiceResponse, InvoiceEntity invoiceEntity,
|
||||
InvoiceCryptoInfo invoiceCryptoInfo, PaymentMethodAccounting accounting, PaymentMethod info);
|
||||
|
||||
public abstract void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse);
|
||||
public abstract string GetCryptoImage(PaymentMethodId paymentMethodId);
|
||||
public abstract string GetPaymentMethodName(PaymentMethodId paymentMethodId);
|
||||
@ -95,12 +77,6 @@ namespace BTCPayServer.Payments
|
||||
Dictionary<CurrencyPair, Task<RateResult>> rate, Money amount, PaymentMethodId paymentMethodId);
|
||||
|
||||
public abstract IEnumerable<PaymentMethodId> GetSupportedPaymentMethods();
|
||||
public abstract CryptoPaymentData GetCryptoPaymentData(PaymentEntity paymentEntity);
|
||||
|
||||
public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(PaymentMethodId paymentMethodId, JToken value);
|
||||
public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(JObject jobj);
|
||||
public abstract string GetTransactionLink(PaymentMethodId paymentMethodId, params object[] args);
|
||||
|
||||
|
||||
public virtual object PreparePayment(TSupportedPaymentMethod supportedPaymentMethod, StoreData store,
|
||||
BTCPayNetworkBase network)
|
||||
@ -129,10 +105,5 @@ namespace BTCPayServer.Payments
|
||||
|
||||
throw new NotSupportedException("Invalid supportedPaymentMethod");
|
||||
}
|
||||
|
||||
public string ToPrettyString(PaymentMethodId paymentMethodId)
|
||||
{
|
||||
return $"{paymentMethodId.CryptoCode} ({PrettyDescription})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
return PaymentHash?.ToString() ?? BOLT11;
|
||||
}
|
||||
|
||||
public PaymentTypes GetPaymentType()
|
||||
public PaymentType GetPaymentType()
|
||||
{
|
||||
return PaymentTypes.LightningLike;
|
||||
}
|
||||
|
@ -40,8 +40,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
_socketFactory = socketFactory;
|
||||
}
|
||||
|
||||
public override string PrettyDescription => "Off-Chain";
|
||||
public override PaymentTypes PaymentType => PaymentTypes.LightningLike;
|
||||
public override PaymentType PaymentType => PaymentTypes.LightningLike;
|
||||
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(
|
||||
LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store,
|
||||
BTCPayNetwork network, object preparePaymentObject)
|
||||
@ -168,36 +167,6 @@ namespace BTCPayServer.Payments.Lightning
|
||||
}
|
||||
return "The amount of the invoice is too high to be paid with lightning";
|
||||
}
|
||||
public override CryptoPaymentData GetCryptoPaymentData(PaymentEntity paymentEntity)
|
||||
{
|
||||
#pragma warning disable CS0618
|
||||
return JsonConvert.DeserializeObject<LightningLikePaymentData>(paymentEntity.CryptoPaymentData);
|
||||
#pragma warning restore CS0618
|
||||
}
|
||||
|
||||
public override ISupportedPaymentMethod DeserializeSupportedPaymentMethod(PaymentMethodId paymentMethodId, JToken value)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<LightningSupportedPaymentMethod>(value.ToString());
|
||||
}
|
||||
|
||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(JObject jobj)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<LightningLikePaymentMethodDetails>(jobj.ToString());
|
||||
}
|
||||
|
||||
public override string GetTransactionLink(PaymentMethodId paymentMethodId, params object[] args)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override void PrepareInvoiceDto(InvoiceResponse invoiceResponse, InvoiceEntity invoiceEntity,
|
||||
InvoiceCryptoInfo invoiceCryptoInfo, PaymentMethodAccounting accounting, PaymentMethod info)
|
||||
{
|
||||
invoiceCryptoInfo.PaymentUrls = new InvoicePaymentUrls()
|
||||
{
|
||||
BOLT11 = $"lightning:{invoiceCryptoInfo.Address}"
|
||||
};
|
||||
}
|
||||
|
||||
public override void PreparePaymentModel(PaymentModel model, InvoiceResponse invoiceResponse)
|
||||
{
|
||||
|
@ -17,7 +17,7 @@ namespace BTCPayServer.Payments.Lightning
|
||||
return BOLT11;
|
||||
}
|
||||
|
||||
public PaymentTypes GetPaymentType()
|
||||
public PaymentType GetPaymentType()
|
||||
{
|
||||
return PaymentTypes.LightningLike;
|
||||
}
|
||||
|
@ -11,10 +11,12 @@ namespace BTCPayServer.Payments
|
||||
/// </summary>
|
||||
public class PaymentMethodId
|
||||
{
|
||||
public PaymentMethodId(string cryptoCode, PaymentTypes paymentType)
|
||||
public PaymentMethodId(string cryptoCode, PaymentType paymentType)
|
||||
{
|
||||
if (cryptoCode == null)
|
||||
throw new ArgumentNullException(nameof(cryptoCode));
|
||||
if (paymentType == null)
|
||||
throw new ArgumentNullException(nameof(paymentType));
|
||||
PaymentType = paymentType;
|
||||
CryptoCode = cryptoCode.ToUpperInvariant();
|
||||
}
|
||||
@ -29,7 +31,7 @@ namespace BTCPayServer.Payments
|
||||
}
|
||||
|
||||
public string CryptoCode { get; private set; }
|
||||
public PaymentTypes PaymentType { get; private set; }
|
||||
public PaymentType PaymentType { get; private set; }
|
||||
|
||||
|
||||
public override bool Equals(object obj)
|
||||
@ -66,34 +68,22 @@ namespace BTCPayServer.Payments
|
||||
return PaymentType == PaymentTypes.BTCLike ? CryptoCode : $"{CryptoCode}_{PaymentType}";
|
||||
}
|
||||
|
||||
public string ToPrettyString()
|
||||
{
|
||||
return $"{CryptoCode} ({PaymentType.ToPrettyString()})";
|
||||
}
|
||||
|
||||
public static bool TryParse(string str, out PaymentMethodId paymentMethodId)
|
||||
{
|
||||
paymentMethodId = null;
|
||||
var parts = str.Split('_', StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 0 || parts.Length > 2)
|
||||
return false;
|
||||
PaymentTypes type = PaymentTypes.BTCLike;
|
||||
PaymentType type = PaymentTypes.BTCLike;
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
var typePart = parts[1].ToLowerInvariant();
|
||||
switch (typePart)
|
||||
{
|
||||
case "btclike":
|
||||
case "onchain":
|
||||
type = PaymentTypes.BTCLike;
|
||||
break;
|
||||
case "lightninglike":
|
||||
case "offchain":
|
||||
type = PaymentTypes.LightningLike;
|
||||
break;
|
||||
default:
|
||||
if (!Enum.TryParse(typePart, true, out type ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (!PaymentTypes.TryParse(parts[1], out type))
|
||||
return false;
|
||||
}
|
||||
paymentMethodId = new PaymentMethodId(parts[0], type);
|
||||
return true;
|
||||
|
60
BTCPayServer/Payments/PaymentTypes.Bitcoin.cs
Normal file
60
BTCPayServer/Payments/PaymentTypes.Bitcoin.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Payments.Bitcoin;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Payments
|
||||
{
|
||||
public class BitcoinPaymentType : PaymentType
|
||||
{
|
||||
public static BitcoinPaymentType Instance { get; } = new BitcoinPaymentType();
|
||||
private BitcoinPaymentType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override string ToPrettyString() => "On-Chain";
|
||||
public override string GetId() => "BTCLike";
|
||||
|
||||
public override CryptoPaymentData DeserializePaymentData(string str)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<BitcoinLikePaymentData>(str);
|
||||
}
|
||||
|
||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod>(str);
|
||||
}
|
||||
|
||||
public override ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value)
|
||||
{
|
||||
if (network == null)
|
||||
throw new ArgumentNullException(nameof(network));
|
||||
if (value == null)
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
var net = (BTCPayNetwork)network;
|
||||
if (value is JObject jobj)
|
||||
{
|
||||
var scheme = net.NBXplorerNetwork.Serializer.ToObject<DerivationSchemeSettings>(jobj);
|
||||
scheme.Network = net;
|
||||
return scheme;
|
||||
}
|
||||
// Legacy
|
||||
return DerivationSchemeSettings.Parse(((JValue)value).Value<string>(), net);
|
||||
}
|
||||
|
||||
public override string GetTransactionLink(BTCPayNetworkBase network, string txId)
|
||||
{
|
||||
if (txId == null)
|
||||
throw new ArgumentNullException(nameof(txId));
|
||||
if (network?.BlockExplorerLink == null)
|
||||
return null;
|
||||
return string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, txId);
|
||||
}
|
||||
}
|
||||
}
|
43
BTCPayServer/Payments/PaymentTypes.Lightning.cs
Normal file
43
BTCPayServer/Payments/PaymentTypes.Lightning.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Payments.Lightning;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Payments
|
||||
{
|
||||
public class LightningPaymentType : PaymentType
|
||||
{
|
||||
public static LightningPaymentType Instance { get; } = new LightningPaymentType();
|
||||
private LightningPaymentType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override string ToPrettyString() => "Off-Chain";
|
||||
public override string GetId() => "LightningLike";
|
||||
|
||||
public override CryptoPaymentData DeserializePaymentData(string str)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<Payments.Lightning.LightningLikePaymentData>(str);
|
||||
}
|
||||
|
||||
public override IPaymentMethodDetails DeserializePaymentMethodDetails(string str)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<Payments.Lightning.LightningLikePaymentMethodDetails>(str);
|
||||
}
|
||||
|
||||
public override ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<LightningSupportedPaymentMethod>(value.ToString());
|
||||
}
|
||||
|
||||
public override string GetTransactionLink(BTCPayNetworkBase network, string txId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,21 +2,64 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Payments
|
||||
{
|
||||
/// <summary>
|
||||
/// The different ways to pay an invoice
|
||||
/// </summary>
|
||||
public enum PaymentTypes
|
||||
public static class PaymentTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// On-Chain UTXO based, bitcoin compatible
|
||||
/// </summary>
|
||||
BTCLike,
|
||||
public static BitcoinPaymentType BTCLike => BitcoinPaymentType.Instance;
|
||||
/// <summary>
|
||||
/// Lightning payment
|
||||
/// </summary>
|
||||
LightningLike
|
||||
public static LightningPaymentType LightningLike => LightningPaymentType.Instance;
|
||||
|
||||
public static bool TryParse(string paymentType, out PaymentType type)
|
||||
{
|
||||
switch (paymentType.ToLowerInvariant())
|
||||
{
|
||||
case "btclike":
|
||||
case "onchain":
|
||||
type = PaymentTypes.BTCLike;
|
||||
break;
|
||||
case "lightninglike":
|
||||
case "offchain":
|
||||
type = PaymentTypes.LightningLike;
|
||||
break;
|
||||
default:
|
||||
type = null;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static PaymentType Parse(string paymentType)
|
||||
{
|
||||
if (!TryParse(paymentType, out var result))
|
||||
throw new FormatException("Invalid payment type");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class PaymentType
|
||||
{
|
||||
public abstract string ToPrettyString();
|
||||
public override string ToString()
|
||||
{
|
||||
return GetId();
|
||||
}
|
||||
|
||||
public abstract string GetId();
|
||||
public abstract CryptoPaymentData DeserializePaymentData(string str);
|
||||
public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(string str);
|
||||
public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value);
|
||||
|
||||
public abstract string GetTransactionLink(BTCPayNetworkBase network, string txId);
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ namespace BTCPayServer.Services.Invoices.Export
|
||||
PaymentId = pdata.GetPaymentId(),
|
||||
CryptoCode = cryptoCode,
|
||||
ConversionRate = pmethod.Rate,
|
||||
PaymentType = invoice.PaymentMethodHandlerDictionary[payment.GetPaymentMethodId()].PrettyDescription,
|
||||
PaymentType = payment.GetPaymentMethodId().PaymentType.ToPrettyString(),
|
||||
Destination = payment.GetCryptoPaymentData().GetDestination(Networks.GetNetwork<BTCPayNetworkBase>(cryptoCode)),
|
||||
Paid = pdata.GetValue().ToString(CultureInfo.InvariantCulture),
|
||||
PaidCurrency = Math.Round(pdata.GetValue() * pmethod.Rate, currency.NumberDecimalDigits).ToString(CultureInfo.InvariantCulture),
|
||||
|
@ -114,9 +114,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
}
|
||||
public class InvoiceEntity
|
||||
{
|
||||
|
||||
[JsonIgnore]
|
||||
public PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary { get; set; }
|
||||
[JsonIgnore]
|
||||
public BTCPayNetworkProvider Networks { get; set; }
|
||||
public const int InternalTagSupport_Version = 1;
|
||||
@ -222,8 +219,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
{
|
||||
if (network == Networks.BTC && paymentMethodId.PaymentType == PaymentTypes.BTCLike)
|
||||
btcReturned = true;
|
||||
yield return PaymentMethodHandlerDictionary[paymentMethodId]
|
||||
.DeserializeSupportedPaymentMethod(paymentMethodId, strat.Value);
|
||||
yield return paymentMethodId.PaymentType.DeserializeSupportedPaymentMethod(network, strat.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,7 +440,41 @@ namespace BTCPayServer.Services.Invoices
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
PaymentMethodHandlerDictionary[paymentId].PrepareInvoiceDto(dto, this, cryptoInfo, accounting, info);
|
||||
|
||||
if (paymentId.PaymentType == PaymentTypes.LightningLike)
|
||||
{
|
||||
cryptoInfo.PaymentUrls = new InvoicePaymentUrls()
|
||||
{
|
||||
BOLT11 = $"lightning:{cryptoInfo.Address}"
|
||||
};
|
||||
}
|
||||
else if (paymentId.PaymentType == PaymentTypes.BTCLike)
|
||||
{
|
||||
var scheme = info.Network.UriScheme;
|
||||
|
||||
var minerInfo = new MinerFeeInfo();
|
||||
minerInfo.TotalFee = accounting.NetworkFee.Satoshi;
|
||||
minerInfo.SatoshiPerBytes = ((BitcoinLikeOnChainPaymentMethod)info.GetPaymentMethodDetails()).FeeRate
|
||||
.GetFee(1).Satoshi;
|
||||
dto.MinerFees.TryAdd(cryptoInfo.CryptoCode, minerInfo);
|
||||
cryptoInfo.PaymentUrls = new NBitpayClient.InvoicePaymentUrls()
|
||||
{
|
||||
BIP21 = $"{scheme}:{cryptoInfo.Address}?amount={cryptoInfo.Due}",
|
||||
};
|
||||
|
||||
#pragma warning disable 618
|
||||
if (info.CryptoCode == "BTC")
|
||||
{
|
||||
dto.BTCPrice = cryptoInfo.Price;
|
||||
dto.Rate = cryptoInfo.Rate;
|
||||
dto.ExRates = cryptoInfo.ExRates;
|
||||
dto.BitcoinAddress = cryptoInfo.Address;
|
||||
dto.BTCPaid = cryptoInfo.Paid;
|
||||
dto.BTCDue = cryptoInfo.Due;
|
||||
dto.PaymentUrls = cryptoInfo.PaymentUrls;
|
||||
}
|
||||
#pragma warning restore 618
|
||||
}
|
||||
|
||||
dto.CryptoInfo.Add(cryptoInfo);
|
||||
dto.PaymentCodes.Add(paymentId.ToString(), cryptoInfo.PaymentUrls);
|
||||
@ -494,7 +524,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
GetPaymentMethods().TryGetValue(paymentMethodId, out var data);
|
||||
return data;
|
||||
}
|
||||
public PaymentMethod GetPaymentMethod(BTCPayNetworkBase network, PaymentTypes paymentType, BTCPayNetworkProvider networkProvider)
|
||||
public PaymentMethod GetPaymentMethod(BTCPayNetworkBase network, PaymentType paymentType, BTCPayNetworkProvider networkProvider)
|
||||
{
|
||||
return GetPaymentMethod(new PaymentMethodId(network.CryptoCode, paymentType), networkProvider);
|
||||
}
|
||||
@ -513,9 +543,8 @@ namespace BTCPayServer.Services.Invoices
|
||||
r.CryptoCode = paymentMethodId.CryptoCode;
|
||||
r.PaymentType = paymentMethodId.PaymentType.ToString();
|
||||
r.ParentEntity = this;
|
||||
r.Network = Networks?.GetNetwork<BTCPayNetworkBase>(r.CryptoCode);
|
||||
if (r.Network != null || Networks == null)
|
||||
paymentMethods.Add(r);
|
||||
r.Network = Networks?.UnfilteredNetworks.GetNetwork<BTCPayNetworkBase>(r.CryptoCode);
|
||||
paymentMethods.Add(r);
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
@ -723,7 +752,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
public PaymentMethodId GetId()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return new PaymentMethodId(CryptoCode, string.IsNullOrEmpty(PaymentType) ? PaymentTypes.BTCLike : Enum.Parse<PaymentTypes>(PaymentType));
|
||||
return new PaymentMethodId(CryptoCode, string.IsNullOrEmpty(PaymentType) ? PaymentTypes.BTCLike : PaymentTypes.Parse(PaymentType));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
@ -756,8 +785,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
}
|
||||
else
|
||||
{
|
||||
var details = ParentEntity.PaymentMethodHandlerDictionary[GetId()]
|
||||
.DeserializePaymentMethodDetails(PaymentMethodDetails);
|
||||
IPaymentMethodDetails details = GetId().PaymentType.DeserializePaymentMethodDetails(PaymentMethodDetails.ToString());
|
||||
if (details is Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod btcLike)
|
||||
{
|
||||
btcLike.NextNetworkFee = NextNetworkFee;
|
||||
@ -870,8 +898,6 @@ namespace BTCPayServer.Services.Invoices
|
||||
|
||||
public class PaymentEntity
|
||||
{
|
||||
[JsonIgnore]
|
||||
public PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary { get; set; }
|
||||
public int Version { get; set; }
|
||||
public DateTimeOffset ReceivedTime
|
||||
{
|
||||
@ -911,8 +937,31 @@ namespace BTCPayServer.Services.Invoices
|
||||
|
||||
public CryptoPaymentData GetCryptoPaymentData()
|
||||
{
|
||||
var paymentMethodId = GetPaymentMethodId();
|
||||
return PaymentMethodHandlerDictionary[paymentMethodId].GetCryptoPaymentData(this);
|
||||
CryptoPaymentData paymentData = null;
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
if (string.IsNullOrEmpty(CryptoPaymentData))
|
||||
{
|
||||
// For invoices created when CryptoPaymentDataType was not existing, we just consider that it is a RBFed payment for safety
|
||||
var bitcoin = new BitcoinLikePaymentData();
|
||||
bitcoin.Outpoint = Outpoint;
|
||||
bitcoin.Output = Output;
|
||||
bitcoin.RBF = true;
|
||||
bitcoin.ConfirmationCount = 0;
|
||||
bitcoin.Legacy = true;
|
||||
bitcoin.Output = Output;
|
||||
bitcoin.Outpoint = Outpoint;
|
||||
paymentData = bitcoin;
|
||||
}
|
||||
else
|
||||
{
|
||||
paymentData = GetPaymentMethodId().PaymentType.DeserializePaymentData(CryptoPaymentData);
|
||||
if (paymentData is BitcoinLikePaymentData bitcoin)
|
||||
{
|
||||
bitcoin.Output = Output;
|
||||
bitcoin.Outpoint = Outpoint;
|
||||
}
|
||||
}
|
||||
return paymentData;
|
||||
}
|
||||
|
||||
public PaymentEntity SetCryptoPaymentData(CryptoPaymentData cryptoPaymentData)
|
||||
@ -949,7 +998,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
public PaymentMethodId GetPaymentMethodId()
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return new PaymentMethodId(CryptoCode ?? "BTC", string.IsNullOrEmpty(CryptoPaymentDataType) ? PaymentTypes.BTCLike : Enum.Parse<PaymentTypes>(CryptoPaymentDataType));
|
||||
return new PaymentMethodId(CryptoCode ?? "BTC", string.IsNullOrEmpty(CryptoPaymentDataType) ? PaymentTypes.BTCLike : PaymentTypes.Parse(CryptoPaymentDataType));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
|
||||
@ -984,7 +1033,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
bool PaymentCompleted(PaymentEntity entity, BTCPayNetworkBase network);
|
||||
bool PaymentConfirmed(PaymentEntity entity, SpeedPolicy speedPolicy, BTCPayNetworkBase network);
|
||||
|
||||
PaymentTypes GetPaymentType();
|
||||
PaymentType GetPaymentType();
|
||||
string GetDestination(BTCPayNetworkBase network);
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,10 @@ namespace BTCPayServer.Services.Invoices
|
||||
|
||||
private ApplicationDbContextFactory _ContextFactory;
|
||||
private readonly BTCPayNetworkProvider _Networks;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
private CustomThreadPool _IndexerThread;
|
||||
|
||||
public InvoiceRepository(ApplicationDbContextFactory contextFactory, string dbreezePath,
|
||||
BTCPayNetworkProvider networks, PaymentMethodHandlerDictionary paymentMethodHandlerDictionary)
|
||||
BTCPayNetworkProvider networks)
|
||||
{
|
||||
int retryCount = 0;
|
||||
retry:
|
||||
@ -53,15 +52,13 @@ retry:
|
||||
catch when (retryCount++ < 5) { goto retry; }
|
||||
_IndexerThread = new CustomThreadPool(1, "Invoice Indexer");
|
||||
_ContextFactory = contextFactory;
|
||||
_Networks = networks;
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
_Networks = networks.UnfilteredNetworks;
|
||||
}
|
||||
|
||||
public InvoiceEntity CreateNewInvoice()
|
||||
{
|
||||
return new InvoiceEntity()
|
||||
{
|
||||
PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary,
|
||||
Networks = _Networks,
|
||||
Version = InvoiceEntity.Lastest_Version,
|
||||
InvoiceTime = DateTimeOffset.UtcNow,
|
||||
@ -153,7 +150,6 @@ retry:
|
||||
{
|
||||
List<string> textSearch = new List<string>();
|
||||
invoice = ToObject(ToBytes(invoice));
|
||||
invoice.PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary;
|
||||
invoice.Networks = _Networks;
|
||||
invoice.Id = Encoders.Base58.EncodeData(RandomUtils.GetBytes(16));
|
||||
#pragma warning disable CS0618
|
||||
@ -446,7 +442,6 @@ retry:
|
||||
{
|
||||
var paymentEntity = ToObject<PaymentEntity>(p.Blob, null);
|
||||
paymentEntity.Accounted = p.Accounted;
|
||||
paymentEntity.PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary;
|
||||
// PaymentEntity on version 0 does not have their own fee, because it was assumed that the payment method have fixed fee.
|
||||
// We want to hide this legacy detail in InvoiceRepository, so we fetch the fee from the PaymentMethod and assign it to the PaymentEntity.
|
||||
if (paymentEntity.Version == 0)
|
||||
@ -651,7 +646,6 @@ retry:
|
||||
if (invoice == null)
|
||||
return null;
|
||||
InvoiceEntity invoiceEntity = ToObject(invoice.Blob);
|
||||
invoiceEntity.PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary;
|
||||
PaymentMethod paymentMethod = invoiceEntity.GetPaymentMethod(new PaymentMethodId(network.CryptoCode, paymentData.GetPaymentType()), null);
|
||||
IPaymentMethodDetails paymentMethodDetails = paymentMethod.GetPaymentMethodDetails();
|
||||
PaymentEntity entity = new PaymentEntity
|
||||
@ -662,8 +656,7 @@ retry:
|
||||
#pragma warning restore CS0618
|
||||
ReceivedTime = date.UtcDateTime,
|
||||
Accounted = accounted,
|
||||
NetworkFee = paymentMethodDetails.GetNextNetworkFee(),
|
||||
PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary
|
||||
NetworkFee = paymentMethodDetails.GetNextNetworkFee()
|
||||
};
|
||||
entity.SetCryptoPaymentData(paymentData);
|
||||
|
||||
@ -720,7 +713,6 @@ retry:
|
||||
private InvoiceEntity ToObject(byte[] value)
|
||||
{
|
||||
var entity = NBitcoin.JsonConverters.Serializer.ToObject<InvoiceEntity>(ZipUtils.Unzip(value), null);
|
||||
entity.PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary;
|
||||
entity.Networks = _Networks;
|
||||
return entity;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
_Inner.TryGetValue(paymentMethodId, out var value);
|
||||
return value;
|
||||
}
|
||||
public PaymentMethod TryGet(string network, PaymentTypes paymentType)
|
||||
public PaymentMethod TryGet(string network, PaymentType paymentType)
|
||||
{
|
||||
if (network == null)
|
||||
throw new ArgumentNullException(nameof(network));
|
||||
|
@ -21,6 +21,7 @@ namespace BTCPayServer.Services.Invoices
|
||||
}
|
||||
|
||||
public IPaymentMethodHandler this[PaymentMethodId index] => _mappedHandlers[index];
|
||||
public bool Support(PaymentMethodId paymentMethod) => _mappedHandlers.ContainsKey(paymentMethod);
|
||||
public IEnumerator<IPaymentMethodHandler> GetEnumerator()
|
||||
{
|
||||
return _mappedHandlers.Values.GetEnumerator();
|
||||
|
@ -61,11 +61,6 @@ namespace BTCPayServer.Services.PaymentRequests
|
||||
string.IsNullOrEmpty(userId) ||
|
||||
(data.StoreData != null && data.StoreData.UserStores.Any(u => u.ApplicationUserId == userId)))
|
||||
.SingleOrDefaultAsync(x => x.Id == id, cancellationToken);
|
||||
if (result != null)
|
||||
{
|
||||
result.StoreData = _storeRepository.PrepareEntity(result.StoreData);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -14,12 +14,10 @@ namespace BTCPayServer.Services.Stores
|
||||
public class StoreRepository
|
||||
{
|
||||
private ApplicationDbContextFactory _ContextFactory;
|
||||
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||
|
||||
public StoreRepository(ApplicationDbContextFactory contextFactory, PaymentMethodHandlerDictionary paymentMethodHandlerDictionary)
|
||||
public StoreRepository(ApplicationDbContextFactory contextFactory)
|
||||
{
|
||||
_ContextFactory = contextFactory ?? throw new ArgumentNullException(nameof(contextFactory));
|
||||
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||
}
|
||||
|
||||
public async Task<StoreData> FindStore(string storeId)
|
||||
@ -29,7 +27,7 @@ namespace BTCPayServer.Services.Stores
|
||||
using (var ctx = _ContextFactory.CreateContext())
|
||||
{
|
||||
var result = await ctx.FindAsync<StoreData>(storeId).ConfigureAwait(false);
|
||||
return PrepareEntity(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +50,7 @@ namespace BTCPayServer.Services.Stores
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
us.Store.Role = us.Role;
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
return PrepareEntity(us.Store);
|
||||
return us.Store;
|
||||
}).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
@ -94,7 +92,7 @@ namespace BTCPayServer.Services.Stores
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
u.StoreData.Role = u.Role;
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
return PrepareEntity(u.StoreData);
|
||||
return u.StoreData;
|
||||
}).ToArray();
|
||||
}
|
||||
}
|
||||
@ -186,7 +184,7 @@ namespace BTCPayServer.Services.Stores
|
||||
ctx.Add(store);
|
||||
ctx.Add(userStore);
|
||||
await ctx.SaveChangesAsync().ConfigureAwait(false);
|
||||
return PrepareEntity(store);
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,12 +233,5 @@ namespace BTCPayServer.Services.Stores
|
||||
return ctx.Database.SupportDropForeignKey();
|
||||
}
|
||||
}
|
||||
|
||||
public StoreData PrepareEntity(StoreData storeData)
|
||||
{
|
||||
if(storeData != null)
|
||||
storeData.PaymentMethodHandlerDictionary = _paymentMethodHandlerDictionary;
|
||||
return storeData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
@if (TempData.ContainsKey("StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2 class="section-heading">@ViewData["Title"]</h2>
|
||||
|
@ -6,51 +6,40 @@
|
||||
}
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2 class="section-heading">@ViewData["Title"]</h2>
|
||||
<hr class="primary">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<section>
|
||||
<div>
|
||||
<div class="modal-dialog modal-login">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Sign In</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form asp-route-returnurl="@ViewData["ReturnUrl"]" method="post">
|
||||
<h4>Use a local account to log in.</h4>
|
||||
<hr />
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Email"></label>
|
||||
<input asp-for="Email" class="form-control" />
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<label for="Email" class="input-group-text"><span class="input-group-addon fa fa-user"></span></label>
|
||||
</div>
|
||||
|
||||
<input asp-for="Email" class="form-control" placeholder="Email" required="required" />
|
||||
</div>
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input asp-for="Password" class="form-control" />
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<label for="Password" class="input-group-text"><span class="input-group-addon fa fa-lock"></span></label>
|
||||
</div>
|
||||
<input asp-for="Password" class="form-control" placeholder="Password" required="required" />
|
||||
</div>
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label asp-for="RememberMe">
|
||||
<input asp-for="RememberMe" />
|
||||
@Html.DisplayNameFor(m => m.RememberMe)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="LoginButton">Log in</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p>
|
||||
<a asp-action="ForgotPassword">Forgot your password?</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]">Register as a new user?</a>
|
||||
</p>
|
||||
<button type="submit" class="btn btn-primary btn-block btn-lg" id="LoginButton">Sign in</button>
|
||||
</div>
|
||||
<p class="hint-text"><a asp-action="ForgotPassword">Forgot your password?</a></p>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-6 col-md-offset-2">
|
||||
</div>
|
||||
<div class="modal-footer"><span>Don't have an account? <a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]">Create one</a></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,47 +4,54 @@
|
||||
}
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2 class="section-heading">@ViewData["Title"]</h2>
|
||||
<hr class="primary">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<form asp-route-returnUrl="@ViewData["ReturnUrl"]" asp-route-logon="@ViewData["Logon"]" method="post">
|
||||
<h4>Create a new account.</h4>
|
||||
<hr />
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Email"></label>
|
||||
<input asp-for="Email" class="form-control" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input asp-for="Password" class="form-control" />
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="ConfirmPassword"></label>
|
||||
<input asp-for="ConfirmPassword" class="form-control" />
|
||||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
|
||||
</div>
|
||||
@if (ViewData["AllowIsAdmin"] is true)
|
||||
{
|
||||
<div>
|
||||
<div class="modal-dialog modal-login">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Create account</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form asp-route-returnUrl="@ViewData["ReturnUrl"]" asp-route-logon="@ViewData["Logon"]" method="post">
|
||||
<div class="form-group">
|
||||
<label asp-for="IsAdmin"></label>
|
||||
<input asp-for="IsAdmin" class="form-check" />
|
||||
<span asp-validation-for="IsAdmin" class="text-danger"></span>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<label for="Email" class="input-group-text"><span class="input-group-addon fa fa-user"></span></label>
|
||||
</div>
|
||||
<input asp-for="Email" class="form-control" placeholder="Email" required="required" />
|
||||
</div>
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
}
|
||||
<button type="submit" class="btn btn-primary" id="RegisterButton">Register</button>
|
||||
</form>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<label for="Password" class="input-group-text"><span class="input-group-addon fa fa-lock"></span></label>
|
||||
</div>
|
||||
<input asp-for="Password" class="form-control" placeholder="Password" required="required" />
|
||||
</div>
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<label for="ConfirmPassword" class="input-group-text"><span class="input-group-addon fa fa-lock"></span></label>
|
||||
</div>
|
||||
<input asp-for="ConfirmPassword" class="form-control" placeholder="Repeat password" required="required" />
|
||||
</div>
|
||||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
|
||||
</div>
|
||||
@if (ViewData["AllowIsAdmin"] is true)
|
||||
{
|
||||
<div class="form-group">
|
||||
<label asp-for="IsAdmin"></label>
|
||||
<input asp-for="IsAdmin" type="checkbox" class="form-check-inline" />
|
||||
<span asp-validation-for="IsAdmin" class="text-danger"></span>
|
||||
</div>
|
||||
}
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary btn-block btn-lg" id="RegisterButton">Create account</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<form method="post">
|
||||
|
@ -3,16 +3,16 @@
|
||||
@{
|
||||
ViewData["Title"] = "Apps";
|
||||
}
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2 class="section-heading">@ViewData["Title"]</h2>
|
||||
|
@ -30,11 +30,14 @@
|
||||
<hr class="primary">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<form method="post">
|
||||
@ -44,7 +47,6 @@
|
||||
<input asp-for="Title" class="form-control" />
|
||||
<span asp-validation-for="Title" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Tagline" class="control-label"></label>
|
||||
<input asp-for="Tagline" class="form-control" />
|
||||
@ -82,7 +84,6 @@
|
||||
<div class="form-group">
|
||||
<label asp-for="ResetEvery" class="control-label"></label>
|
||||
<div class="input-group">
|
||||
|
||||
<input type="number" asp-for="ResetEveryAmount" placeholder="Amount" class="form-control">
|
||||
<select class="custom-select" asp-for="ResetEvery">
|
||||
@foreach (var opt in Model.ResetEveryValues)
|
||||
@ -142,7 +143,6 @@
|
||||
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
<label asp-for="NotificationEmail" class="control-label"></label>
|
||||
@if (Model.NotificationEmailWarning)
|
||||
{
|
||||
@ -181,7 +181,6 @@
|
||||
<input asp-for="SoundsEnabled" type="checkbox" class="form-check" />
|
||||
<span asp-validation-for="SoundsEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Sounds"></label>
|
||||
<textarea asp-for="Sounds" class="form-control"></textarea>
|
||||
@ -192,7 +191,6 @@
|
||||
<input asp-for="AnimationsEnabled" type="checkbox" class="form-check" />
|
||||
<span asp-validation-for="AnimationsEnabled" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="AnimationColors"></label>
|
||||
<textarea asp-for="AnimationColors" class="form-control"></textarea>
|
||||
@ -208,7 +206,6 @@
|
||||
<input asp-for="DisqusShortname" class="form-control" />
|
||||
<span asp-validation-for="DisqusShortname" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<input type="hidden" asp-for="NotificationEmailWarning" />
|
||||
<div class="form-group">
|
||||
<input type="submit" class="btn btn-primary" value="Save Settings" id="SaveSettings" />
|
||||
@ -216,19 +213,15 @@
|
||||
<a class="btn btn-secondary" target="_blank" asp-action="ViewCrowdfund" asp-controller="AppsPublic" asp-route-appId="@Model.AppId" id="ViewApp">View App</a>
|
||||
<a class="btn btn-secondary" target="_blank" asp-action="ListApps">Back to the app list</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@section Scripts {
|
||||
|
||||
<script src="~/vendor/moment/moment.js"></script>
|
||||
<bundle name="wwwroot/bundles/crowdfund-admin-bundle.min.js"></bundle>
|
||||
<bundle name="wwwroot/bundles/crowdfund-admin-bundle.min.css"></bundle>
|
||||
|
||||
<script id="template-product-item" type="text/template">
|
||||
<div class="col-sm-4 col-md-3 mb-3">
|
||||
<div class="card">
|
||||
@ -241,7 +234,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="template-product-content" type="text/template">
|
||||
<div class="mb-3">
|
||||
<input class="js-product-id" type="hidden" name="id" value="{id}">
|
||||
@ -277,4 +269,3 @@
|
||||
</div>
|
||||
</script>
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
@ -30,11 +29,14 @@
|
||||
<hr class="primary">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<form method="post">
|
||||
@ -141,7 +143,6 @@
|
||||
</button>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div id="accordian-dev-info-embed-payment-button" class="collapse" aria-labelledby="accordian-dev-info-embed-payment-button-header" data-parent="#accordian-dev-info">
|
||||
<div class="card-body">
|
||||
<p>You can host point of sale buttons in an external website with the following code.</p>
|
||||
@ -201,22 +202,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<a asp-action="ListApps">Back to the app list</a>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@section Scripts {
|
||||
<link rel="stylesheet" href="~/vendor/highlightjs/default.min.css">
|
||||
<script src="~/vendor/highlightjs/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
|
||||
<script id="template-product-item" type="text/template">
|
||||
<div class="col-sm-4 col-md-3 mb-3">
|
||||
<div class="card">
|
||||
@ -229,7 +226,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="template-product-content" type="text/template">
|
||||
<div class="mb-3">
|
||||
<input class="js-product-id" type="hidden" name="id" value="{id}">
|
||||
@ -264,8 +260,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="~/products/js/products.js"></script>
|
||||
<script src="~/products/js/products.jquery.js"></script>
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
@section HeaderContent{
|
||||
<META NAME="robots" CONTENT="noindex,nofollow">
|
||||
}
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.linethrough {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
@ -15,15 +15,16 @@
|
||||
width: 140px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
@if (!string.IsNullOrEmpty(Model.StatusMessage))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
@ -90,7 +91,6 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h3>Buyer information</h3>
|
||||
<table class="table table-sm table-responsive-md removetopborder">
|
||||
|
@ -2,20 +2,20 @@
|
||||
@{
|
||||
ViewData["Title"] = "Invoices";
|
||||
}
|
||||
|
||||
@section HeadScripts {
|
||||
<script src="~/modal/btcpay.js"></script>
|
||||
}
|
||||
|
||||
@Html.HiddenFor(a=>a.Count)
|
||||
@Html.HiddenFor(a => a.Count)
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
@if (!string.IsNullOrEmpty(Model.StatusMessage))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
@ -48,7 +48,6 @@
|
||||
<div class="row no-gutter" style="margin-bottom: 5px;">
|
||||
<div class="col-lg-6">
|
||||
<a asp-action="CreateInvoice" class="btn btn-primary" role="button" id="CreateNewInvoice"><span class="fa fa-plus"></span> Create a new invoice</a>
|
||||
|
||||
<a class="btn btn-primary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Export
|
||||
</a>
|
||||
@ -60,7 +59,6 @@
|
||||
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="json" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">JSON</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<form asp-action="ListInvoices" method="get" style="float:right;">
|
||||
@ -274,7 +272,6 @@
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<nav aria-label="..." class="w-100">
|
||||
<ul class="pagination float-left">
|
||||
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
|
||||
@ -287,7 +284,6 @@
|
||||
<a class="page-link" href="@listInvoices(1, Model.Count)">»</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="pagination float-right">
|
||||
<li class="page-item disabled">
|
||||
<span class="page-link">Page Size:</span>
|
||||
@ -328,7 +324,6 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var timezoneOffset = new Date().getTimezoneOffset();
|
||||
@ -378,8 +373,8 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.invoice-payments h3 {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.ChangePassword, "Change password");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.TwoFactorAuthentication, "Enable authenticator");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<div>
|
||||
<p>To use an authenticator app go through the following steps:</p>
|
||||
<ol class="list">
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.TwoFactorAuthentication, "Recovery codes");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>
|
||||
<span class="fa fa-warning"></span>
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.Index, "Profile");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -2,7 +2,6 @@
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.TwoFactorAuthentication, "Reset authenticator key");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>
|
||||
<span class="fa fa-warning"></span>
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ManageNavPages.TwoFactorAuthentication, "Two-factor authentication");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
@if(Model.Is2faEnabled)
|
||||
{
|
||||
if(Model.RecoveryCodesLeft == 0)
|
||||
|
@ -2,7 +2,6 @@
|
||||
@using System.Globalization
|
||||
@model BTCPayServer.Models.PaymentRequestViewModels.UpdatePaymentRequestViewModel
|
||||
@addTagHelper *, BundlerMinifier.TagHelpers
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@ -11,40 +10,40 @@
|
||||
<hr class="primary">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage"/>
|
||||
@if (!string.IsNullOrEmpty(Model.StatusMessage))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<form method="post" action="@Url.Action("EditPaymentRequest", "PaymentRequest", new { id = Model.Id}, Context.Request.Scheme)">
|
||||
<input type="hidden" name="Id" value="@Model.Id"/>
|
||||
<input type="hidden" name="Id" value="@Model.Id" />
|
||||
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Title" class="control-label"></label>*
|
||||
<input asp-for="Title" class="form-control"/>
|
||||
<input asp-for="Title" class="form-control" />
|
||||
<span asp-validation-for="Title" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Amount" class="control-label"></label>*
|
||||
<input type="number" step="any" asp-for="Amount" class="form-control"/>
|
||||
<input type="number" step="any" asp-for="Amount" class="form-control" />
|
||||
<span asp-validation-for="Amount" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Currency" class="control-label"></label>*
|
||||
<input asp-for="Currency" class="form-control"/>
|
||||
<input asp-for="Currency" class="form-control" />
|
||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AllowCustomPaymentAmounts"></label>
|
||||
<input asp-for="AllowCustomPaymentAmounts" type="checkbox" class="form-check"/>
|
||||
<input asp-for="AllowCustomPaymentAmounts" type="checkbox" class="form-check" />
|
||||
<span asp-validation-for="AllowCustomPaymentAmounts" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
<label asp-for="StoreId" class="control-label"></label>
|
||||
@if (string.IsNullOrEmpty(Model.Id))
|
||||
{
|
||||
@ -52,12 +51,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="hidden" asp-for="StoreId" value="@Model.StoreId"/>
|
||||
<input type="text" class="form-control" value="@Model.Stores.Single(item => item.Value == Model.StoreId).Text" readonly/>
|
||||
<input type="hidden" asp-for="StoreId" value="@Model.StoreId" />
|
||||
<input type="text" class="form-control" value="@Model.Stores.Single(item => item.Value == Model.StoreId).Text" readonly />
|
||||
}
|
||||
|
||||
<span asp-validation-for="StoreId" class="text-danger"></span>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Email" class="control-label"></label>
|
||||
@ -67,12 +64,10 @@
|
||||
<div class="form-group">
|
||||
<label asp-for="ExpiryDate" class="control-label"></label>
|
||||
<div class="input-group ">
|
||||
<input asp-for="ExpiryDate"
|
||||
|
||||
<input asp-for="ExpiryDate"
|
||||
value="@( Model.ExpiryDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker" min="today" placeholder="No expiry date has been set for this payment request"/>
|
||||
class="form-control flatdtpicker" min="today" placeholder="No expiry date has been set for this payment request" />
|
||||
<div class="input-group-append">
|
||||
|
||||
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
|
||||
<span class=" fa fa-times"></span>
|
||||
</button>
|
||||
@ -90,7 +85,7 @@
|
||||
<a href="https://docs.btcpayserver.org/development/theme#bootstrap-themes" target="_blank">
|
||||
<span class="fa fa-question-circle-o" title="More information..."></span>
|
||||
</a>
|
||||
<input asp-for="CustomCSSLink" class="form-control"/>
|
||||
<input asp-for="CustomCSSLink" class="form-control" />
|
||||
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -98,18 +93,17 @@
|
||||
<textarea asp-for="EmbeddedCSS" rows="10" cols="40" class="form-control"></textarea>
|
||||
<span asp-validation-for="EmbeddedCSS" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary" id="SaveButton">Save</button>
|
||||
@if (!string.IsNullOrEmpty(Model.Id))
|
||||
{
|
||||
<a class="btn btn-secondary" target="_blank" asp-action="ViewPaymentRequest" id="@Model.Id" name="ViewAppButton">View</a>
|
||||
<a class="btn btn-secondary"
|
||||
<a class="btn btn-secondary"
|
||||
target="_blank"
|
||||
asp-action="ListInvoices"
|
||||
asp-controller="Invoice"
|
||||
asp-controller="Invoice"
|
||||
asp-route-searchterm="@($"orderid:{PaymentRequestRepository.GetOrderIdForPaymentRequest(Model.Id)}")">Invoices</a>
|
||||
<a class="btn btn-secondary" asp-action="ClonePaymentRequest" id="@Model.Id">Clone</a>
|
||||
<a class="btn btn-secondary" asp-action="ClonePaymentRequest" id="@Model.Id">Clone</a>
|
||||
}
|
||||
<a class="btn btn-secondary" target="_blank" asp-action="GetPaymentRequests">Back to list</a>
|
||||
</div>
|
||||
@ -118,9 +112,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@section Scripts {
|
||||
<script src= "~/vendor/moment/moment.js"></script>
|
||||
<script src="~/vendor/moment/moment.js"></script>
|
||||
<bundle name="wwwroot/bundles/payment-request-admin-bundle.min.js"></bundle>
|
||||
<bundle name="wwwroot/bundles/payment-request-admin-bundle.min.css"></bundle>
|
||||
}
|
||||
|
@ -1,69 +1,66 @@
|
||||
@using BTCPayServer.Services.PaymentRequests
|
||||
@model BTCPayServer.Models.PaymentRequestViewModels.ListPaymentRequestsViewModel
|
||||
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage"/>
|
||||
@if (!string.IsNullOrEmpty(Model.StatusMessage))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2 class="section-heading">Payment Requests</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row no-gutter" style="margin-bottom: 5px;">
|
||||
<div class="col-lg-6">
|
||||
<a asp-action="EditPaymentRequest" class="btn btn-primary" role="button" id="CreatePaymentRequest"><span class="fa fa-plus"></span> Create a new payment request</a>
|
||||
<a href="https://docs.btcpayserver.org/features/paymentrequests" target="_blank"><span class="fa fa-question-circle-o" title="More information..."></span></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<table class="table table-sm table-responsive-md">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Expiry</th>
|
||||
<th class="text-right">Price</th>
|
||||
<th class="text-right">Status</th>
|
||||
<th class="text-right">Actions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Expiry</th>
|
||||
<th class="text-right">Price</th>
|
||||
<th class="text-right">Status</th>
|
||||
<th class="text-right">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<tr>
|
||||
<td>@item.Title</td>
|
||||
<td>@(item.ExpiryDate?.ToString("g") ?? "No Expiry")</td>
|
||||
<td class="text-right">@item.Amount @item.Currency</td>
|
||||
<td class="text-right">@item.Status</td>
|
||||
<td class="text-right">
|
||||
<a asp-action="EditPaymentRequest" asp-route-id="@item.Id">Edit</a>
|
||||
<span> - </span>
|
||||
<a asp-action="ViewPaymentRequest" asp-route-id="@item.Id">View</a>
|
||||
<span> - </span>
|
||||
<a target="_blank" asp-action="ListInvoices" asp-controller="Invoice" asp-route-searchterm="@($"orderid:{PaymentRequestRepository.GetOrderIdForPaymentRequest(item.Id)}")">Invoices</a>
|
||||
<span> - </span>
|
||||
<a target="_blank" asp-action="PayPaymentRequest" asp-route-id="@item.Id">Pay</a>
|
||||
<span> - </span>
|
||||
<a target="_blank" asp-action="ClonePaymentRequest" asp-route-id="@item.Id">Clone</a>
|
||||
<span> - </span>
|
||||
<a asp-action="RemovePaymentRequestPrompt" asp-route-id="@item.Id">Remove</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<tr>
|
||||
<td>@item.Title</td>
|
||||
<td>@(item.ExpiryDate?.ToString("g") ?? "No Expiry")</td>
|
||||
<td class="text-right">@item.Amount @item.Currency</td>
|
||||
<td class="text-right">@item.Status</td>
|
||||
<td class="text-right">
|
||||
<a asp-action="EditPaymentRequest" asp-route-id="@item.Id">Edit</a>
|
||||
<span> - </span>
|
||||
<a asp-action="ViewPaymentRequest" asp-route-id="@item.Id">View</a>
|
||||
<span> - </span>
|
||||
<a target="_blank" asp-action="ListInvoices" asp-controller="Invoice" asp-route-searchterm="@($"orderid:{PaymentRequestRepository.GetOrderIdForPaymentRequest(item.Id)}")">Invoices</a>
|
||||
<span> - </span>
|
||||
<a target="_blank" asp-action="PayPaymentRequest" asp-route-id="@item.Id">Pay</a>
|
||||
<span> - </span>
|
||||
<a target="_blank" asp-action="ClonePaymentRequest" asp-route-id="@item.Id">Clone</a>
|
||||
<span> - </span>
|
||||
<a asp-action="RemovePaymentRequestPrompt" asp-route-id="@item.Id">Remove</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<nav aria-label="...">
|
||||
<ul class="pagination">
|
||||
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
|
||||
@ -86,6 +83,5 @@
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
@ -6,7 +6,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]"/>
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ServerNavPages.Services, $"Storage - Local Filesystem");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ServerNavPages.Services, $"Storage - Google Cloud Storage");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]"/>
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
</div>
|
||||
<div class="col text-right">
|
||||
<a
|
||||
|
@ -3,7 +3,6 @@
|
||||
ViewData.SetActivePageAndTitle(ServerNavPages.Logs);
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage"/>
|
||||
|
||||
<div class="row">
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -4,13 +4,15 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
@if (!this.ViewContext.ModelState.IsValid)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<form method="post">
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]"/>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
|
@ -5,7 +5,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]"/>
|
||||
@if (Model.ShowChangeWarning)
|
||||
{
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["StatusMessage"]" />
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
@ -1,7 +1,6 @@
|
||||
@model BTCPayServer.Models.ServerViewModels.EmailsViewModel
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -7,7 +7,7 @@ ViewBag.ShowMenu = ViewBag.ShowMenu ?? true;
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h2 class="section-heading">@ViewData["MainTitle"]</h2>
|
||||
<h4 class="section-heading">@ViewData["MainTitle"]: @ViewData["Title"]</h4>
|
||||
<hr class="primary ml-0">
|
||||
</div>
|
||||
</div>
|
||||
@ -33,4 +33,4 @@ ViewBag.ShowMenu = ViewBag.ShowMenu ?? true;
|
||||
|
||||
@section Scripts {
|
||||
@RenderSection("Scripts", required: false)
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@
|
||||
}
|
||||
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
|
@ -4,7 +4,6 @@
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Index, "Add lightning node (Experimental)");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
|
||||
<div class="alert alert-warning alert-dismissible" role="alert">
|
||||
|
@ -4,7 +4,6 @@
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Checkout, "Checkout experience");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -6,7 +6,6 @@
|
||||
ViewBag.ShowStores = ViewBag.ShowStores ?? false;
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
|
@ -4,7 +4,6 @@
|
||||
ViewBag.MainTitle = "Pay Button";
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
|
@ -4,7 +4,6 @@
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Rates, "Rates");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -4,7 +4,6 @@
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Users, "Manage users");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -5,7 +5,6 @@
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Index, "Update Store Changelly Settings");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage"/>
|
||||
|
||||
<div class="row">
|
||||
|
@ -5,7 +5,6 @@
|
||||
ViewData.SetActivePageAndTitle(StoreNavPages.Index, "Update Store CoinSwitch Settings");
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="StatusMessage"/>
|
||||
|
||||
<div class="row">
|
||||
|
@ -17,7 +17,6 @@
|
||||
</style>
|
||||
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
|
||||
<div class="row">
|
||||
|
@ -5,13 +5,14 @@
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<h2 class="section-heading">@ViewData["Title"]</h2>
|
||||
|
@ -5,12 +5,14 @@
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
@ -31,23 +33,23 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var wallet in Model.Wallets)
|
||||
@foreach (var wallet in Model.Wallets)
|
||||
{
|
||||
<tr>
|
||||
@if(wallet.IsOwner)
|
||||
{
|
||||
<td><a asp-action="UpdateStore" asp-controller="Stores" asp-route-storeId="@wallet.StoreId">@wallet.StoreName</a></td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td>@wallet.StoreName</td>
|
||||
}
|
||||
<td>@wallet.CryptoCode</td>
|
||||
<td>@wallet.Balance</td>
|
||||
<td style="text-align:right">
|
||||
<a asp-action="WalletTransactions" asp-route-walletId="@wallet.Id">Manage</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@if (wallet.IsOwner)
|
||||
{
|
||||
<td><a asp-action="UpdateStore" asp-controller="Stores" asp-route-storeId="@wallet.StoreId">@wallet.StoreName</a></td>
|
||||
}
|
||||
else
|
||||
{
|
||||
<td>@wallet.StoreName</td>
|
||||
}
|
||||
<td>@wallet.CryptoCode</td>
|
||||
<td>@wallet.Balance</td>
|
||||
<td style="text-align:right">
|
||||
<a asp-action="WalletTransactions" asp-route-walletId="@wallet.Id">Manage</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -4,12 +4,14 @@
|
||||
ViewData["Title"] = "PSBT";
|
||||
ViewData.SetActivePageAndTitle(WalletsNavPages.PSBT);
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
@if (Model.Errors != null && Model.Errors.Count != 0)
|
||||
|
@ -5,7 +5,6 @@
|
||||
ViewData.SetActivePageAndTitle(WalletsNavPages.Rescan);
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
@if (!Model.Ok)
|
||||
{
|
||||
|
@ -6,8 +6,6 @@
|
||||
ViewData.SetActivePageAndTitle(WalletsNavPages.Send);
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
<div class="row no-gutters">
|
||||
<div class="@(Model.Outputs.Count==1? "col-lg-6 transaction-output-form": "col-lg-8")">
|
||||
<form method="post">
|
||||
|
@ -4,14 +4,15 @@
|
||||
ViewData["Title"] = "Wallet settings";
|
||||
ViewData.SetActivePageAndTitle(WalletsNavPages.Settings);
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<p>
|
||||
@ -40,7 +41,6 @@
|
||||
<span asp-validation-for="DerivationSchemeInput" class="text-danger"></span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@for (int i = 0; i < Model.AccountKeys.Count; i++)
|
||||
{
|
||||
<hr />
|
||||
@ -68,7 +68,6 @@
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
<div class="form-group">
|
||||
<button name="command" type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
|
@ -4,8 +4,8 @@
|
||||
ViewData["Title"] = "Manage wallet";
|
||||
ViewData.SetActivePageAndTitle(WalletsNavPages.Transactions);
|
||||
}
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
.smMaxWidth {
|
||||
max-width: 200px;
|
||||
}
|
||||
@ -20,13 +20,14 @@
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
@if (TempData.ContainsKey("TempDataProperty-StatusMessage"))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-10 text-center">
|
||||
<partial name="_StatusMessage" for="@TempData["TempDataProperty-StatusMessage"]" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
If BTCPay Server shows you an invalid balance, <a asp-action="WalletRescan">rescan your wallet</a>. <br />
|
||||
|
51
BTCPayServer/wwwroot/locales/am-ET.json
Normal file
51
BTCPayServer/wwwroot/locales/am-ET.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "am-ET",
|
||||
"currentLanguage": "እንግሊዝኛ",
|
||||
"lang": "ቋንቋ",
|
||||
"Awaiting Payment...": "በመጠባበቅ ላይ ያለ ክፍያ ",
|
||||
"Pay with": "ይክፈሉ",
|
||||
"Contact and Refund Email": "ለማነጋገር እና ገንዘብ ተመላሽ ኢሜል",
|
||||
"Contact_Body": "እባክዎ ከዚህ በታች የኢሜይል አድራሻ ያቅርቡ. ክፍያዎ ላይ ችግር ካለ በዚህ አድራሻ ላይ እናገኝዎታለን.",
|
||||
"Your email": "የእርስዎ ኢሜይል",
|
||||
"Continue": "ይቀጥሉ",
|
||||
"Please enter a valid email address": "እባክዎ ልክ የሆነ የኢሜይል አድራሻ ያስገቡ",
|
||||
"Order Amount": "የትዕዛዝ መጠን",
|
||||
"Network Cost": "የአውታረ መረብ ወጪ",
|
||||
"Already Paid": "አስቀድሞ ተከፍሏል",
|
||||
"Due": "የሚከፈል",
|
||||
"Scan": "ቃኝ",
|
||||
"Copy": "ቅጂ",
|
||||
"Conversion": "ልወጣ",
|
||||
"Open in wallet": "ውስጣዊ wallet ይክፈቱ",
|
||||
"CompletePay_Body": "ክፍያዎን ለማጠናቀቅ እባክዎ {{btcDue}} {{cryptoCode}} ከዚህ በታች ባለው አድራሻ ይላኩ",
|
||||
"Amount": "መጠን",
|
||||
"Address": "አድራሻ",
|
||||
"Copied": "ተቀድቷል",
|
||||
"ConversionTab_BodyTop": "ከሌሎች ነጋዴዎች በቀጥታ የሚደግፉ altcoin በመጠቀም {{btcDue}} {{cryptoCode}} መክፈል ይችላሉ",
|
||||
"ConversionTab_BodyDesc": "ይህ አገልግሎት በ 3 ኛ ወገን ይቀርባል. እባክዎን ምን ያህል አገልግሎት ሰጪዎች ገንዘቡን እንደሚልኩ መቆጣጠር አለመቻላችንን ያስታውሱ. ደረሰኝ የተቆረጠለት ገንዘብ ከተቀበለ በኋላ ብቻ ነው {{cryptoCode}} Blockchain.",
|
||||
"ConversionTab_CalculateAmount_Error": "እንደገና ሞክር",
|
||||
"ConversionTab_LoadCurrencies_Error": "እንደገና ሞክር",
|
||||
"ConversionTab_Lightning": "ለ Lightning አውታረ መረብ ክፍያዎች ምንም የልወጣ አቅራቢዎች አይገኙም.",
|
||||
"ConversionTab_CurrencyList_Select_Option": "እባክዎ የሚቀየር አንድ ምንዛሬ ይምረጡ",
|
||||
"Invoice expiring soon...": "ይህ ደረሰኝ በቅርቡ ጊዜው ያልፍበታል",
|
||||
"Invoice expired": "ደረሰኝ ጊዜው አልፎበታል",
|
||||
"What happened?": "ምን ተፈጠረ?",
|
||||
"InvoiceExpired_Body_1": "ይህ ደረሰኝ ጊዜው አልፎበታል. ደረሰኝ ለ {{maxTimeMinutes}} ደቂቃ ብቻ ነው የሚሰራው.\nክፍያዎን እንደገና ለማስገባት የሚፈልጉ ከሆነ ወደ {{storeName}} መመለስ ይችላሉ.",
|
||||
"InvoiceExpired_Body_2": "ክፍያ ለመላክ ከሞከሩ, ገና በአውታረ መረቡ ተቀባይነት አላገኘም. ገንዘብዎን ገና አልተቀበልንም.",
|
||||
"InvoiceExpired_Body_3": "በኋላ ላይ ከደረሰን, የተመላሽ ገንዘብን ለማዘጋጀት ትዕዛዝዎን እንሰራለን ወይም እርስዎን ያነጋግሩን",
|
||||
"Invoice ID": "ደረሰኝ መታወቂያ",
|
||||
"Order ID": "የትዕዛዝ መታወቂያ",
|
||||
"Return to StoreName": "ወደ {{storeName}}",
|
||||
"This invoice has been paid": "ይህ ደረሰኝ ተከፍሏል",
|
||||
"This invoice has been archived": "ይህ ደረሰኝ ተመዝግቧል",
|
||||
"Archived_Body": "እባክዎ ለማዘዝ ለሽርሽር መረጃ ወይም ለእርዳታ ያነጋግሩ",
|
||||
"BOLT 11 Invoice": "BOLT 11 ክፍያ መጠየቂያ",
|
||||
"Node Info": "Node መረጃ",
|
||||
"txCount": "{{count}} ግብይት",
|
||||
"txCount_plural": "{{count}} ግብይቶች",
|
||||
"Pay with CoinSwitch": "በ CoinSwitch ይክፈሉ",
|
||||
"Pay with Changelly": "በ Changelly ይክፈሉ",
|
||||
"Close": "ዝጋ",
|
||||
"NotPaid_ExtraTransaction": "ደረሰኙ ሙሉ በሙሉ አልተከፈለውም. እባክዎ የገንዘብ መጠን ለመሸፈን ሌላ ግብይት ይላኩ"
|
||||
}
|
51
BTCPayServer/wwwroot/locales/bs-BA.json
Normal file
51
BTCPayServer/wwwroot/locales/bs-BA.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"NOTICE_WARN": "THIS CODE HAS BEEN AUTOMATICALLY GENERATED FROM TRANSIFEX, IF YOU WISH TO HELP TRANSLATION COME ON THE SLACK http://slack.btcpayserver.org TO REQUEST PERMISSION TO https://www.transifex.com/btcpayserver/btcpayserver/",
|
||||
"code": "bs-BA",
|
||||
"currentLanguage": "Engleski",
|
||||
"lang": "Jezik",
|
||||
"Awaiting Payment...": "Čekam uplatu...",
|
||||
"Pay with": "Plati sa",
|
||||
"Contact and Refund Email": "Kontakt i email za refundaciju",
|
||||
"Contact_Body": "Ispod upišite vašu email adresu. Kontaktiraćemo vas na ovoj adresi u slučaju problema sa vašom uplatom.",
|
||||
"Your email": "Vaš email",
|
||||
"Continue": "Nastavi",
|
||||
"Please enter a valid email address": "Upišite validnu email adresu",
|
||||
"Order Amount": "Količina narudžbi",
|
||||
"Network Cost": "Cijena mreže",
|
||||
"Already Paid": "Već plaćeno",
|
||||
"Due": "Dužan",
|
||||
"Scan": "Skeniraj",
|
||||
"Copy": "Kopiraj",
|
||||
"Conversion": "Konverzija",
|
||||
"Open in wallet": "Otvori u novčaniku",
|
||||
"CompletePay_Body": "Da bi završili vašu uplatu, pošaljite {{btcDue}} {{cryptoCode}} na adresu koja je prikazan ispod.",
|
||||
"Amount": "Količina",
|
||||
"Address": "Adresa",
|
||||
"Copied": "Kopirano",
|
||||
"ConversionTab_BodyTop": "Možete uplatiti {{btcDue}} {{cryptoCode}} koristeći altcoine koji nisu prikazani kao prodržani od strane prodavača.",
|
||||
"ConversionTab_BodyDesc": "Koristite servis treće strane. Molimo vas da imate na umu da mi nemamo kontrolu kako drugi provajderi proslijeđuju vaša sredstva. Predračun će biti markiran kao plaćen nakon što su sredstva primljena na {{cryptoCode}} Blockchain.",
|
||||
"ConversionTab_CalculateAmount_Error": "Ponovi",
|
||||
"ConversionTab_LoadCurrencies_Error": "Ponovi",
|
||||
"ConversionTab_Lightning": "Nepostojeći provider plaćanja za Lightning mrežu.",
|
||||
"ConversionTab_CurrencyList_Select_Option": "Izaberite valutu koju mjenjate",
|
||||
"Invoice expiring soon...": "Predračun ističe uskoro...",
|
||||
"Invoice expired": "Predračun istekao",
|
||||
"What happened?": "Šta se desilo?",
|
||||
"InvoiceExpired_Body_1": "Ovaj predračun je istekao. Predračun je validan {{maxTimeMinutes}} minutes. \nMožete vratiti {{storeName}} ukoliko želite da ponovite vašu narudžbu.",
|
||||
"InvoiceExpired_Body_2": "Poslali ste uplatu koja još nije prihvaćena u mreži. Sredstva još nisu zaprimljena.",
|
||||
"InvoiceExpired_Body_3": "Ukoliko zaprimimo kasnije, procesuiraćemo vašu narudžbu ili vas kontaktirati za refundaciju...",
|
||||
"Invoice ID": "Broj predračuna",
|
||||
"Order ID": "Broj računa",
|
||||
"Return to StoreName": "Vrati na {{storeName}}",
|
||||
"This invoice has been paid": "Predračun je plaćen",
|
||||
"This invoice has been archived": "Predračun je arhiviran",
|
||||
"Archived_Body": "Kontaktirajte trgovinu za informaciju o produktu",
|
||||
"BOLT 11 Invoice": "BOLT 11 Predračun",
|
||||
"Node Info": "Node info",
|
||||
"txCount": "{{count}} transakcija",
|
||||
"txCount_plural": "{{count}} transakcija",
|
||||
"Pay with CoinSwitch": "Plati sa CoinSwitch",
|
||||
"Pay with Changelly": "Plati sa Changelly",
|
||||
"Close": "Zatvori",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transaccions",
|
||||
"Pay with CoinSwitch": "Pagueu amb CoinSwitch",
|
||||
"Pay with Changelly": "Pagueu amb Changelly",
|
||||
"Close": "Tancar"
|
||||
"Close": "Tancar",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transakcí",
|
||||
"Pay with CoinSwitch": "Pay with CoinSwitch",
|
||||
"Pay with Changelly": "Pay with Changelly",
|
||||
"Close": "Close"
|
||||
"Close": "Close",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transaktioner",
|
||||
"Pay with CoinSwitch": "Betal med CoinSwitch",
|
||||
"Pay with Changelly": "Betal med Changelly",
|
||||
"Close": "Luk"
|
||||
"Close": "Luk",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} Transaktionen",
|
||||
"Pay with CoinSwitch": "Zahlen mit CoinSwitch",
|
||||
"Pay with Changelly": "Zahlen mit Changelly",
|
||||
"Close": "Schließen"
|
||||
"Close": "Schließen",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} συναλλαγών",
|
||||
"Pay with CoinSwitch": "Πληρώστε με CoinSwitch",
|
||||
"Pay with Changelly": "Πληρώστε με Changelly",
|
||||
"Close": "Κλείσιμο"
|
||||
"Close": "Κλείσιμο",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transactions",
|
||||
"Pay with CoinSwitch": "Pay with CoinSwitch",
|
||||
"Pay with Changelly": "Pay with Changelly",
|
||||
"Close": "Close"
|
||||
"Close": "Close",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
"Order Amount": "Total del pedido",
|
||||
"Network Cost": "Costo de la red",
|
||||
"Already Paid": "Ya has pagado",
|
||||
"Due": "Aún debes",
|
||||
"Due": "Faltante",
|
||||
"Scan": "Escanear",
|
||||
"Copy": "Copiar",
|
||||
"Conversion": "Conversión",
|
||||
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transacciones",
|
||||
"Pay with CoinSwitch": "Pagar con CoinSwitch",
|
||||
"Pay with Changelly": "Pagar con Changelly",
|
||||
"Close": "Cerrar"
|
||||
"Close": "Cerrar",
|
||||
"NotPaid_ExtraTransaction": "La factura no ha sido pagada en su totalidad. Por favor envía otra transacción para cubrir el monto faltante."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} suoritukset",
|
||||
"Pay with CoinSwitch": "Maksa käyttäen CoinSwitch:iä",
|
||||
"Pay with Changelly": "Maksa käyttäen Changelly:ä",
|
||||
"Close": "Sulje"
|
||||
"Close": "Sulje",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transactions",
|
||||
"Pay with CoinSwitch": "Payer avec CoinSwitch",
|
||||
"Pay with Changelly": "Payer avec Changelly",
|
||||
"Close": "Fermer"
|
||||
"Close": "Fermer",
|
||||
"NotPaid_ExtraTransaction": "La facture n'as pas été réglée dans sa totalité. Veuillez envoyer une autre transaction pour la compléter."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} लेनदेनों",
|
||||
"Pay with CoinSwitch": "CoinSwitch के साथ भुगतान करें",
|
||||
"Pay with Changelly": "Changelly के साथ भुगतान करें",
|
||||
"Close": "बंद करे"
|
||||
"Close": "बंद करे",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transactions",
|
||||
"Pay with CoinSwitch": "Pay with CoinSwitch",
|
||||
"Pay with Changelly": "Pay with Changelly",
|
||||
"Close": "Close"
|
||||
"Close": "Close",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} tranzakció",
|
||||
"Pay with CoinSwitch": "Fizess CoinSwitch-csel",
|
||||
"Pay with Changelly": "Fizess Changelly-vel",
|
||||
"Close": "Bezár"
|
||||
"Close": "Bezár",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} reikningar",
|
||||
"Pay with CoinSwitch": "Borga með Coinswitch",
|
||||
"Pay with Changelly": "Borgar með Changelly",
|
||||
"Close": "Loka"
|
||||
"Close": "Loka",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "{{count}} transazioni",
|
||||
"Pay with CoinSwitch": "Paga con CoinSwitch",
|
||||
"Pay with Changelly": "Paga con Changelly",
|
||||
"Close": "Chiudi"
|
||||
"Close": "Chiudi",
|
||||
"NotPaid_ExtraTransaction": "La fattura non è stata pagata per intero. Per favore effettua una nuova transazione per coprire l'importo dovuto."
|
||||
}
|
@ -46,5 +46,6 @@
|
||||
"txCount_plural": "取引 {{count}} 個",
|
||||
"Pay with CoinSwitch": "CoinSwitchでのお支払い",
|
||||
"Pay with Changelly": "Changellyでのお支払い",
|
||||
"Close": "閉じる"
|
||||
"Close": "閉じる",
|
||||
"NotPaid_ExtraTransaction": "The invoice hasn't been paid in full. Please send another transaction to cover amount Due."
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user