mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +01:00
Refactor CreateInvoiceCore to better give feedback on payment method errors to the merchant, be faster, and give NodeInfo
This commit is contained in:
@@ -79,28 +79,6 @@ namespace BTCPayServer.Controllers
|
|||||||
|
|
||||||
internal async Task<DataWrapper<InvoiceResponse>> CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl)
|
internal async Task<DataWrapper<InvoiceResponse>> CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl)
|
||||||
{
|
{
|
||||||
var supportedPaymentMethods = store.GetSupportedPaymentMethods(_NetworkProvider)
|
|
||||||
.Select(c =>
|
|
||||||
(Handler: (IPaymentMethodHandler)_ServiceProvider.GetService(typeof(IPaymentMethodHandler<>).MakeGenericType(c.GetType())),
|
|
||||||
SupportedPaymentMethod: c,
|
|
||||||
Network: _NetworkProvider.GetNetwork(c.PaymentId.CryptoCode),
|
|
||||||
IsAvailable: Task.FromResult(false)))
|
|
||||||
.Where(c => c.Network != null)
|
|
||||||
.Select(c =>
|
|
||||||
{
|
|
||||||
c.IsAvailable = c.Handler.IsAvailable(c.SupportedPaymentMethod, c.Network);
|
|
||||||
return c;
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
foreach (var supportedPaymentMethod in supportedPaymentMethods.ToList())
|
|
||||||
{
|
|
||||||
if (!await supportedPaymentMethod.IsAvailable)
|
|
||||||
{
|
|
||||||
supportedPaymentMethods.Remove(supportedPaymentMethod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (supportedPaymentMethods.Count == 0)
|
|
||||||
throw new BitpayHttpException(400, "No derivation strategy are available now for this store");
|
|
||||||
var entity = new InvoiceEntity
|
var entity = new InvoiceEntity
|
||||||
{
|
{
|
||||||
InvoiceTime = DateTimeOffset.UtcNow
|
InvoiceTime = DateTimeOffset.UtcNow
|
||||||
@@ -132,61 +110,68 @@ namespace BTCPayServer.Controllers
|
|||||||
entity.Status = "new";
|
entity.Status = "new";
|
||||||
entity.SpeedPolicy = ParseSpeedPolicy(invoice.TransactionSpeed, store.SpeedPolicy);
|
entity.SpeedPolicy = ParseSpeedPolicy(invoice.TransactionSpeed, store.SpeedPolicy);
|
||||||
|
|
||||||
var methods = supportedPaymentMethods
|
|
||||||
.Select(async o =>
|
|
||||||
{
|
|
||||||
var rate = await storeBlob.ApplyRateRules(o.Network, _RateProviders.GetRateProvider(o.Network, false)).GetRateAsync(invoice.Currency);
|
|
||||||
PaymentMethod paymentMethod = new PaymentMethod();
|
|
||||||
paymentMethod.ParentEntity = entity;
|
|
||||||
paymentMethod.Network = o.Network;
|
|
||||||
paymentMethod.SetId(o.SupportedPaymentMethod.PaymentId);
|
|
||||||
paymentMethod.Rate = rate;
|
|
||||||
var paymentDetails = await o.Handler.CreatePaymentMethodDetails(o.SupportedPaymentMethod, paymentMethod, o.Network);
|
|
||||||
if (storeBlob.NetworkFeeDisabled)
|
|
||||||
paymentDetails.SetNoTxFee();
|
|
||||||
paymentMethod.SetPaymentMethodDetails(paymentDetails);
|
|
||||||
#pragma warning disable CS0618
|
|
||||||
if (paymentMethod.GetId().IsBTCOnChain)
|
|
||||||
{
|
|
||||||
entity.TxFee = paymentMethod.TxFee;
|
|
||||||
entity.Rate = paymentMethod.Rate;
|
|
||||||
entity.DepositAddress = paymentMethod.DepositAddress;
|
|
||||||
}
|
|
||||||
#pragma warning restore CS0618
|
|
||||||
return (SupportedPaymentMethod: o.SupportedPaymentMethod, PaymentMethod: paymentMethod);
|
|
||||||
});
|
|
||||||
|
|
||||||
var paymentMethods = new PaymentMethodDictionary();
|
var supportedPaymentMethods = store.GetSupportedPaymentMethods(_NetworkProvider)
|
||||||
|
.Select(c =>
|
||||||
|
(Handler: (IPaymentMethodHandler)_ServiceProvider.GetService(typeof(IPaymentMethodHandler<>).MakeGenericType(c.GetType())),
|
||||||
|
SupportedPaymentMethod: c,
|
||||||
|
Network: _NetworkProvider.GetNetwork(c.PaymentId.CryptoCode)))
|
||||||
|
.Where(c => c.Network != null)
|
||||||
|
.Select(o =>
|
||||||
|
(SupportedPaymentMethod: o.SupportedPaymentMethod,
|
||||||
|
PaymentMethod: CreatePaymentMethodAsync(o.Handler, o.SupportedPaymentMethod, o.Network, entity, storeBlob)))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
List<string> paymentMethodErrors = new List<string>();
|
||||||
List<ISupportedPaymentMethod> supported = new List<ISupportedPaymentMethod>();
|
List<ISupportedPaymentMethod> supported = new List<ISupportedPaymentMethod>();
|
||||||
foreach (var method in methods)
|
var paymentMethods = new PaymentMethodDictionary();
|
||||||
|
foreach (var o in supportedPaymentMethods)
|
||||||
{
|
{
|
||||||
var o = await method;
|
try
|
||||||
|
|
||||||
// Check if Lightning Max value is exceeded
|
|
||||||
if(o.SupportedPaymentMethod.PaymentId.PaymentType == PaymentTypes.LightningLike &&
|
|
||||||
storeBlob.LightningMaxValue != null)
|
|
||||||
{
|
{
|
||||||
var lightningMaxValue = storeBlob.LightningMaxValue;
|
var paymentMethod = await o.PaymentMethod;
|
||||||
decimal rate = 0.0m;
|
if (paymentMethod == null)
|
||||||
if (lightningMaxValue.Currency == invoice.Currency)
|
throw new PaymentMethodUnavailableException("Payment method unavailable (The handler returned null)");
|
||||||
rate = o.PaymentMethod.Rate;
|
// Check if Lightning Max value is exceeded
|
||||||
else
|
if (o.SupportedPaymentMethod.PaymentId.PaymentType == PaymentTypes.LightningLike &&
|
||||||
rate = await storeBlob.ApplyRateRules(o.PaymentMethod.Network, _RateProviders.GetRateProvider(o.PaymentMethod.Network, false)).GetRateAsync(lightningMaxValue.Currency);
|
storeBlob.LightningMaxValue != null)
|
||||||
|
|
||||||
var lightningMaxValueCrypto = Money.Coins(lightningMaxValue.Value / rate);
|
|
||||||
if (o.PaymentMethod.Calculate().Due > lightningMaxValueCrypto)
|
|
||||||
{
|
{
|
||||||
continue;
|
var lightningMaxValue = storeBlob.LightningMaxValue;
|
||||||
|
decimal rate = 0.0m;
|
||||||
|
if (lightningMaxValue.Currency == invoice.Currency)
|
||||||
|
rate = paymentMethod.Rate;
|
||||||
|
else
|
||||||
|
rate = await storeBlob.ApplyRateRules(paymentMethod.Network, _RateProviders.GetRateProvider(paymentMethod.Network, false)).GetRateAsync(lightningMaxValue.Currency);
|
||||||
|
|
||||||
|
var lightningMaxValueCrypto = Money.Coins(lightningMaxValue.Value / rate);
|
||||||
|
if (paymentMethod.Calculate().Due > lightningMaxValueCrypto)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
///////////////
|
||||||
|
supported.Add(o.SupportedPaymentMethod);
|
||||||
|
paymentMethods.Add(paymentMethod);
|
||||||
|
}
|
||||||
|
catch (PaymentMethodUnavailableException ex)
|
||||||
|
{
|
||||||
|
paymentMethodErrors.Add($"{o.SupportedPaymentMethod.PaymentId.CryptoCode} ({o.SupportedPaymentMethod.PaymentId.PaymentType}): Payment method unavailable ({ex.Message})");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
paymentMethodErrors.Add($"{o.SupportedPaymentMethod.PaymentId.CryptoCode} ({o.SupportedPaymentMethod.PaymentId.PaymentType}): Unexpected exception ({ex.ToString()})");
|
||||||
}
|
}
|
||||||
///////////////
|
|
||||||
supported.Add(o.SupportedPaymentMethod);
|
|
||||||
paymentMethods.Add(o.PaymentMethod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(supported.Count == 0)
|
if (supported.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BitpayHttpException(400, "No derivation strategy are available now for this store");
|
StringBuilder errors = new StringBuilder();
|
||||||
|
errors.AppendLine("No payment method available for this store");
|
||||||
|
foreach(var error in paymentMethodErrors)
|
||||||
|
{
|
||||||
|
errors.AppendLine(error);
|
||||||
|
}
|
||||||
|
throw new BitpayHttpException(400, errors.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.SetSupportedPaymentMethods(supported);
|
entity.SetSupportedPaymentMethods(supported);
|
||||||
@@ -209,12 +194,36 @@ namespace BTCPayServer.Controllers
|
|||||||
#pragma warning restore CS0618
|
#pragma warning restore CS0618
|
||||||
}
|
}
|
||||||
entity.PosData = invoice.PosData;
|
entity.PosData = invoice.PosData;
|
||||||
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, _NetworkProvider);
|
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, paymentMethodErrors, _NetworkProvider);
|
||||||
|
|
||||||
_EventAggregator.Publish(new Events.InvoiceEvent(entity, 1001, "invoice_created"));
|
_EventAggregator.Publish(new Events.InvoiceEvent(entity, 1001, "invoice_created"));
|
||||||
var resp = entity.EntityToDTO(_NetworkProvider);
|
var resp = entity.EntityToDTO(_NetworkProvider);
|
||||||
return new DataWrapper<InvoiceResponse>(resp) { Facade = "pos/invoice" };
|
return new DataWrapper<InvoiceResponse>(resp) { Facade = "pos/invoice" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<PaymentMethod> CreatePaymentMethodAsync(IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network, InvoiceEntity entity, StoreBlob storeBlob)
|
||||||
|
{
|
||||||
|
var rate = await storeBlob.ApplyRateRules(network, _RateProviders.GetRateProvider(network, false)).GetRateAsync(entity.ProductInformation.Currency);
|
||||||
|
PaymentMethod paymentMethod = new PaymentMethod();
|
||||||
|
paymentMethod.ParentEntity = entity;
|
||||||
|
paymentMethod.Network = network;
|
||||||
|
paymentMethod.SetId(supportedPaymentMethod.PaymentId);
|
||||||
|
paymentMethod.Rate = rate;
|
||||||
|
var paymentDetails = await handler.CreatePaymentMethodDetails(supportedPaymentMethod, paymentMethod, network);
|
||||||
|
if (storeBlob.NetworkFeeDisabled)
|
||||||
|
paymentDetails.SetNoTxFee();
|
||||||
|
paymentMethod.SetPaymentMethodDetails(paymentDetails);
|
||||||
|
#pragma warning disable CS0618
|
||||||
|
if (paymentMethod.GetId().IsBTCOnChain)
|
||||||
|
{
|
||||||
|
entity.TxFee = paymentMethod.TxFee;
|
||||||
|
entity.Rate = paymentMethod.Rate;
|
||||||
|
entity.DepositAddress = paymentMethod.DepositAddress;
|
||||||
|
}
|
||||||
|
#pragma warning restore CS0618
|
||||||
|
return paymentMethod;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma warning disable CS0618
|
#pragma warning disable CS0618
|
||||||
private static Money GetTxFee(StoreBlob storeBlob, FeeRate feeRate)
|
private static Money GetTxFee(StoreBlob storeBlob, FeeRate feeRate)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
|
|
||||||
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network)
|
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(DerivationStrategy supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network)
|
||||||
{
|
{
|
||||||
|
if (!_ExplorerProvider.IsAvailable(network))
|
||||||
|
throw new PaymentMethodUnavailableException($"Full node not available");
|
||||||
var getFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync();
|
var getFeeRate = _FeeRateProviderFactory.CreateFeeProvider(network).GetFeeRateAsync();
|
||||||
var getAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.DerivationStrategyBase);
|
var getAddress = _WalletProvider.GetWallet(network).ReserveAddressAsync(supportedPaymentMethod.DerivationStrategyBase);
|
||||||
Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod onchainMethod = new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod();
|
Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod onchainMethod = new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod();
|
||||||
@@ -37,10 +39,5 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
onchainMethod.DepositAddress = (await getAddress).ToString();
|
onchainMethod.DepositAddress = (await getAddress).ToString();
|
||||||
return onchainMethod;
|
return onchainMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<bool> IsAvailable(DerivationStrategy supportedPaymentMethod, BTCPayNetwork network)
|
|
||||||
{
|
|
||||||
return Task.FromResult(_ExplorerProvider.IsAvailable(network));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,6 @@ namespace BTCPayServer.Payments
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IPaymentMethodHandler
|
public interface IPaymentMethodHandler
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Returns true if the dependencies for a specific payment method are satisfied.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="supportedPaymentMethod"></param>
|
|
||||||
/// <param name="network"></param>
|
|
||||||
/// <returns>true if this payment method is available</returns>
|
|
||||||
Task<bool> IsAvailable(ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create needed to track payments of this invoice
|
/// Create needed to track payments of this invoice
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -31,7 +23,6 @@ namespace BTCPayServer.Payments
|
|||||||
|
|
||||||
public interface IPaymentMethodHandler<T> : IPaymentMethodHandler where T : ISupportedPaymentMethod
|
public interface IPaymentMethodHandler<T> : IPaymentMethodHandler where T : ISupportedPaymentMethod
|
||||||
{
|
{
|
||||||
Task<bool> IsAvailable(T supportedPaymentMethod, BTCPayNetwork network);
|
|
||||||
Task<IPaymentMethodDetails> CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network);
|
Task<IPaymentMethodDetails> CreatePaymentMethodDetails(T supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,16 +38,5 @@ namespace BTCPayServer.Payments
|
|||||||
}
|
}
|
||||||
throw new NotSupportedException("Invalid supportedPaymentMethod");
|
throw new NotSupportedException("Invalid supportedPaymentMethod");
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Task<bool> IsAvailable(T supportedPaymentMethod, BTCPayNetwork network);
|
|
||||||
|
|
||||||
Task<bool> IPaymentMethodHandler.IsAvailable(ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
|
|
||||||
{
|
|
||||||
if(supportedPaymentMethod is T method)
|
|
||||||
{
|
|
||||||
return IsAvailable(method, network);
|
|
||||||
}
|
|
||||||
return Task.FromResult(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,30 +25,32 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
}
|
}
|
||||||
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network)
|
public override async Task<IPaymentMethodDetails> CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network)
|
||||||
{
|
{
|
||||||
|
var test = Test(supportedPaymentMethod, network);
|
||||||
var invoice = paymentMethod.ParentEntity;
|
var invoice = paymentMethod.ParentEntity;
|
||||||
var due = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, 8);
|
var due = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, 8);
|
||||||
var client = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
|
var client = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
|
||||||
var expiry = invoice.ExpirationTime - DateTimeOffset.UtcNow;
|
var expiry = invoice.ExpirationTime - DateTimeOffset.UtcNow;
|
||||||
if (expiry < TimeSpan.Zero)
|
if (expiry < TimeSpan.Zero)
|
||||||
expiry = TimeSpan.FromSeconds(1);
|
expiry = TimeSpan.FromSeconds(1);
|
||||||
var lightningInvoice = await client.CreateInvoice(new LightMoney(due, LightMoneyUnit.BTC), expiry);
|
|
||||||
|
LightningInvoice lightningInvoice = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lightningInvoice = await client.CreateInvoice(new LightMoney(due, LightMoneyUnit.BTC), expiry);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
throw new PaymentMethodUnavailableException($"Impossible to create lightning invoice ({ex.Message})", ex);
|
||||||
|
}
|
||||||
|
var nodeInfo = await test;
|
||||||
return new LightningLikePaymentMethodDetails()
|
return new LightningLikePaymentMethodDetails()
|
||||||
{
|
{
|
||||||
BOLT11 = lightningInvoice.BOLT11,
|
BOLT11 = lightningInvoice.BOLT11,
|
||||||
InvoiceId = lightningInvoice.Id
|
InvoiceId = lightningInvoice.Id,
|
||||||
|
NodeInfo = nodeInfo.ToString()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task<bool> IsAvailable(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Test(supportedPaymentMethod, network);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used for testing
|
/// Used for testing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -57,7 +59,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
public async Task<NodeInfo> Test(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
|
public async Task<NodeInfo> Test(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
|
||||||
{
|
{
|
||||||
if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
|
if (!_Dashboard.IsFullySynched(network.CryptoCode, out var summary))
|
||||||
throw new Exception($"Full node not available");
|
throw new PaymentMethodUnavailableException($"Full node not available");
|
||||||
|
|
||||||
var cts = new CancellationTokenSource(5000);
|
var cts = new CancellationTokenSource(5000);
|
||||||
var client = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
|
var client = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
|
||||||
@@ -68,37 +70,39 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
}
|
}
|
||||||
catch (OperationCanceledException) when (cts.IsCancellationRequested)
|
catch (OperationCanceledException) when (cts.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
throw new Exception($"The lightning node did not replied in a timely maner");
|
throw new PaymentMethodUnavailableException($"The lightning node did not replied in a timely maner");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new Exception($"Error while connecting to the API ({ex.Message})");
|
throw new PaymentMethodUnavailableException($"Error while connecting to the API ({ex.Message})");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info.Address == null)
|
if (info.Address == null)
|
||||||
{
|
{
|
||||||
throw new Exception($"No lightning node public address has been configured");
|
throw new PaymentMethodUnavailableException($"No lightning node public address has been configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
var blocksGap = Math.Abs(info.BlockHeight - summary.Status.ChainHeight);
|
var blocksGap = Math.Abs(info.BlockHeight - summary.Status.ChainHeight);
|
||||||
if (blocksGap > 10)
|
if (blocksGap > 10)
|
||||||
{
|
{
|
||||||
throw new Exception($"The lightning is not synched ({blocksGap} blocks)");
|
throw new PaymentMethodUnavailableException($"The lightning is not synched ({blocksGap} blocks)");
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(!SkipP2PTest)
|
if (!SkipP2PTest)
|
||||||
|
{
|
||||||
await TestConnection(info.Address, info.P2PPort, cts.Token);
|
await TestConnection(info.Address, info.P2PPort, cts.Token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new Exception($"Error while connecting to the lightning node via {info.Address}:{info.P2PPort} ({ex.Message})");
|
throw new PaymentMethodUnavailableException($"Error while connecting to the lightning node via {info.Address}:{info.P2PPort} ({ex.Message})");
|
||||||
}
|
}
|
||||||
return new NodeInfo(info.NodeId, info.Address, info.P2PPort);
|
return new NodeInfo(info.NodeId, info.Address, info.P2PPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> TestConnection(string addressStr, int port, CancellationToken cancellation)
|
private async Task TestConnection(string addressStr, int port, CancellationToken cancellation)
|
||||||
{
|
{
|
||||||
IPAddress address = null;
|
IPAddress address = null;
|
||||||
try
|
try
|
||||||
@@ -107,25 +111,16 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
try
|
address = (await Dns.GetHostAddressesAsync(addressStr)).FirstOrDefault();
|
||||||
{
|
|
||||||
address = (await Dns.GetHostAddressesAsync(addressStr)).FirstOrDefault();
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address == null)
|
if (address == null)
|
||||||
throw new Exception($"DNS did not resolved {addressStr}");
|
throw new PaymentMethodUnavailableException($"DNS did not resolved {addressStr}");
|
||||||
|
|
||||||
using (var tcp = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
|
using (var tcp = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
|
||||||
{
|
{
|
||||||
try
|
await WithTimeout(tcp.ConnectAsync(new IPEndPoint(address, port)), cancellation);
|
||||||
{
|
|
||||||
await WithTimeout(tcp.ConnectAsync(new IPEndPoint(address, port)), cancellation);
|
|
||||||
}
|
|
||||||
catch { return false; }
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Task WithTimeout(Task task, CancellationToken token)
|
static Task WithTimeout(Task task, CancellationToken token)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
{
|
{
|
||||||
public string BOLT11 { get; set; }
|
public string BOLT11 { get; set; }
|
||||||
public string InvoiceId { get; set; }
|
public string InvoiceId { get; set; }
|
||||||
|
public string NodeInfo { get; set; }
|
||||||
|
|
||||||
public string GetPaymentDestination()
|
public string GetPaymentDestination()
|
||||||
{
|
{
|
||||||
|
|||||||
19
BTCPayServer/Payments/PaymentMethodUnavailableException.cs
Normal file
19
BTCPayServer/Payments/PaymentMethodUnavailableException.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Payments
|
||||||
|
{
|
||||||
|
public class PaymentMethodUnavailableException : Exception
|
||||||
|
{
|
||||||
|
public PaymentMethodUnavailableException(string message) : base(message)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public PaymentMethodUnavailableException(string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,7 +101,7 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<InvoiceEntity> CreateInvoiceAsync(string storeId, InvoiceEntity invoice, BTCPayNetworkProvider networkProvider)
|
public async Task<InvoiceEntity> CreateInvoiceAsync(string storeId, InvoiceEntity invoice, IEnumerable<string> creationLogs, BTCPayNetworkProvider networkProvider)
|
||||||
{
|
{
|
||||||
List<string> textSearch = new List<string>();
|
List<string> textSearch = new List<string>();
|
||||||
invoice = Clone(invoice, null);
|
invoice = Clone(invoice, null);
|
||||||
@@ -146,6 +146,17 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
textSearch.Add(paymentMethod.Calculate().TotalDue.ToString());
|
textSearch.Add(paymentMethod.Calculate().TotalDue.ToString());
|
||||||
}
|
}
|
||||||
context.PendingInvoices.Add(new PendingInvoiceData() { Id = invoice.Id });
|
context.PendingInvoices.Add(new PendingInvoiceData() { Id = invoice.Id });
|
||||||
|
|
||||||
|
foreach(var log in creationLogs)
|
||||||
|
{
|
||||||
|
context.InvoiceEvents.Add(new InvoiceEventData()
|
||||||
|
{
|
||||||
|
InvoiceDataId = invoice.Id,
|
||||||
|
Message = log,
|
||||||
|
Timestamp = invoice.InvoiceTime,
|
||||||
|
UniqueId = Encoders.Hex.EncodeData(RandomUtils.GetBytes(10))
|
||||||
|
});
|
||||||
|
}
|
||||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user