public override async Task <IPaymentMethodDetails> CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, BTCPayNetwork network)
        {
            var test    = Test(supportedPaymentMethod, network);
            var invoice = paymentMethod.ParentEntity;
            var due     = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, 8);
            var client  = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
            var expiry  = invoice.ExpirationTime - DateTimeOffset.UtcNow;

            if (expiry < TimeSpan.Zero)
            {
                expiry = TimeSpan.FromSeconds(1);
            }

            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()
            {
                BOLT11 = lightningInvoice.BOLT11,
                InvoiceId = lightningInvoice.Id,
                NodeInfo = nodeInfo.ToString()
            });
        }
        public override async Task <IPaymentMethodDetails> CreatePaymentMethodDetails(
            InvoiceLogs logs,
            LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store,
            BTCPayNetwork network, object preparePaymentObject)
        {
            //direct casting to (BTCPayNetwork) is fixed in other pull requests with better generic interfacing for handlers
            var storeBlob = store.GetStoreBlob();
            var test      = GetNodeInfo(paymentMethod.PreferOnion, supportedPaymentMethod, (BTCPayNetwork)network);
            var invoice   = paymentMethod.ParentEntity;
            var due       = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, network.Divisibility);
            var client    = _lightningClientFactory.Create(supportedPaymentMethod.GetLightningUrl(), (BTCPayNetwork)network);
            var expiry    = invoice.ExpirationTime - DateTimeOffset.UtcNow;

            if (expiry < TimeSpan.Zero)
            {
                expiry = TimeSpan.FromSeconds(1);
            }

            LightningInvoice lightningInvoice = null;

            string description = storeBlob.LightningDescriptionTemplate;

            description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
                          .Replace("{ItemDescription}", invoice.ProductInformation.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
                          .Replace("{OrderId}", invoice.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
            using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT))
            {
                try
                {
                    var request = new CreateInvoiceParams(new LightMoney(due, LightMoneyUnit.BTC), description, expiry);
                    request.PrivateRouteHints = storeBlob.LightningPrivateRouteHints;
                    lightningInvoice          = await client.CreateInvoice(request, cts.Token);
                }
                catch (OperationCanceledException) when(cts.IsCancellationRequested)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node did not reply in a timely manner");
                }
                catch (Exception ex)
                {
                    throw new PaymentMethodUnavailableException($"Impossible to create lightning invoice ({ex.Message})", ex);
                }
            }
            var nodeInfo = await test;

            return(new LightningLikePaymentMethodDetails()
            {
                BOLT11 = lightningInvoice.BOLT11,
                InvoiceId = lightningInvoice.Id,
                NodeInfo = nodeInfo.ToString()
            });
        }
Beispiel #3
0
        public override async Task <IPaymentMethodDetails> CreatePaymentMethodDetails(LightningSupportedPaymentMethod supportedPaymentMethod, PaymentMethod paymentMethod, StoreData store, BTCPayNetwork network, object preparePaymentObject)
        {
            var storeBlob = store.GetStoreBlob();
            var test      = Test(supportedPaymentMethod, network);
            var invoice   = paymentMethod.ParentEntity;
            var due       = Extensions.RoundUp(invoice.ProductInformation.Price / paymentMethod.Rate, 8);
            var client    = _LightningClientFactory.CreateClient(supportedPaymentMethod, network);
            var expiry    = invoice.ExpirationTime - DateTimeOffset.UtcNow;

            if (expiry < TimeSpan.Zero)
            {
                expiry = TimeSpan.FromSeconds(1);
            }

            LightningInvoice lightningInvoice = null;

            string description = storeBlob.LightningDescriptionTemplate;

            description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
                          .Replace("{ItemDescription}", invoice.ProductInformation.ItemDesc ?? "", StringComparison.OrdinalIgnoreCase)
                          .Replace("{OrderId}", invoice.OrderId ?? "", StringComparison.OrdinalIgnoreCase);
            using (var cts = new CancellationTokenSource(LIGHTNING_TIMEOUT))
            {
                try
                {
                    lightningInvoice = await client.CreateInvoice(new LightMoney(due, LightMoneyUnit.BTC), description, expiry, cts.Token);
                }
                catch (OperationCanceledException) when(cts.IsCancellationRequested)
                {
                    throw new PaymentMethodUnavailableException($"The lightning node did not replied in a timely maner");
                }
                catch (Exception ex)
                {
                    throw new PaymentMethodUnavailableException($"Impossible to create lightning invoice ({ex.Message})", ex);
                }
            }
            var nodeInfo = await test;

            return(new LightningLikePaymentMethodDetails()
            {
                BOLT11 = lightningInvoice.BOLT11,
                InvoiceId = lightningInvoice.Id,
                NodeInfo = nodeInfo.ToString()
            });
        }
        private async Task EnsureListening(string invoiceId, bool poll)
        {
            if (Listening(invoiceId))
            {
                return;
            }
            var invoice = await _InvoiceRepository.GetInvoice(invoiceId);

            foreach (var paymentMethod in invoice.GetPaymentMethods(_NetworkProvider)
                     .Where(c => c.GetId().PaymentType == PaymentTypes.LightningLike))
            {
                var lightningMethod = paymentMethod.GetPaymentMethodDetails() as LightningLikePaymentMethodDetails;
                if (lightningMethod == null)
                {
                    continue;
                }
                var lightningSupportedMethod = invoice.GetSupportedPaymentMethod <LightningSupportedPaymentMethod>(_NetworkProvider)
                                               .FirstOrDefault(c => c.CryptoCode == paymentMethod.GetId().CryptoCode);
                if (lightningSupportedMethod == null)
                {
                    continue;
                }
                var network = _NetworkProvider.GetNetwork(paymentMethod.GetId().CryptoCode);

                var listenedInvoice = new ListenedInvoice()
                {
                    Uri = lightningSupportedMethod.GetLightningUrl().BaseUri.AbsoluteUri,
                    PaymentMethodDetails   = lightningMethod,
                    SupportedPaymentMethod = lightningSupportedMethod,
                    PaymentMethod          = paymentMethod,
                    Network   = network,
                    InvoiceId = invoice.Id
                };

                if (poll)
                {
                    var charge = lightningSupportedMethod.CreateClient(network);
                    LightningInvoice chargeInvoice = null;
                    try
                    {
                        chargeInvoice = await charge.GetInvoice(lightningMethod.InvoiceId);
                    }
                    catch (Exception ex)
                    {
                        Logs.PayServer.LogError(ex, $"{lightningSupportedMethod.CryptoCode} (Lightning): Can't connect to the lightning server");
                        continue;
                    }
                    if (chargeInvoice == null)
                    {
                        continue;
                    }
                    if (chargeInvoice.Status == LightningInvoiceStatus.Paid)
                    {
                        await AddPayment(network, chargeInvoice, listenedInvoice);
                    }
                    if (chargeInvoice.Status == LightningInvoiceStatus.Paid || chargeInvoice.Status == LightningInvoiceStatus.Expired)
                    {
                        continue;
                    }
                }

                StartListening(listenedInvoice);
            }
        }