mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-21 14:04:12 +01:00
Poll for charge invoice
This commit is contained in:
parent
adc6bea4dc
commit
5924f1730c
3 changed files with 53 additions and 16 deletions
|
@ -37,9 +37,9 @@ namespace BTCPayServer.Payments.Lightning.CLightning
|
|||
this._Uri = uri;
|
||||
this._Network = network;
|
||||
if (uri.UserInfo == null)
|
||||
throw new ArgumentException(paramName:nameof(uri), message:"User information not present in uri");
|
||||
throw new ArgumentException(paramName: nameof(uri), message: "User information not present in uri");
|
||||
var userInfo = uri.UserInfo.Split(':');
|
||||
if(userInfo.Length != 2)
|
||||
if (userInfo.Length != 2)
|
||||
throw new ArgumentException(paramName: nameof(uri), message: "User information not present in uri");
|
||||
Credentials = new NetworkCredential(userInfo[0], userInfo[1]);
|
||||
}
|
||||
|
@ -85,6 +85,18 @@ namespace BTCPayServer.Payments.Lightning.CLightning
|
|||
{
|
||||
return GetInfoAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public async Task<ChargeInvoice> GetInvoice(string invoiceId, CancellationToken cancellation = default(CancellationToken))
|
||||
{
|
||||
var request = CreateMessage(HttpMethod.Get, $"invoice/{invoiceId}");
|
||||
var message = await _Client.SendAsync(request, cancellation);
|
||||
if (message.StatusCode == HttpStatusCode.NotFound)
|
||||
return null;
|
||||
message.EnsureSuccessStatusCode();
|
||||
var content = await message.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<ChargeInvoice>(content);
|
||||
}
|
||||
|
||||
public async Task<GetInfoResponse> GetInfoAsync(CancellationToken cancellation = default(CancellationToken))
|
||||
{
|
||||
var request = CreateMessage(HttpMethod.Get, "info");
|
||||
|
|
|
@ -10,7 +10,7 @@ using Newtonsoft.Json;
|
|||
|
||||
namespace BTCPayServer.Payments.Lightning.CLightning
|
||||
{
|
||||
public class ChargeInvoiceNotification
|
||||
public class ChargeInvoice
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace BTCPayServer.Payments.Lightning.CLightning
|
|||
}
|
||||
|
||||
ArraySegment<byte> _Buffer;
|
||||
public async Task<ChargeInvoiceNotification> NextEvent(CancellationToken cancellation = default(CancellationToken))
|
||||
public async Task<ChargeInvoice> NextEvent(CancellationToken cancellation = default(CancellationToken))
|
||||
{
|
||||
var buffer = _Buffer;
|
||||
var array = _Buffer.Array;
|
||||
|
@ -96,10 +96,10 @@ namespace BTCPayServer.Payments.Lightning.CLightning
|
|||
}
|
||||
|
||||
UTF8Encoding UTF8 = new UTF8Encoding(false, true);
|
||||
private ChargeInvoiceNotification ParseMessage(ArraySegment<byte> buffer)
|
||||
private ChargeInvoice ParseMessage(ArraySegment<byte> buffer)
|
||||
{
|
||||
var str = UTF8.GetString(buffer.Array, 0, buffer.Count);
|
||||
return JsonConvert.DeserializeObject<ChargeInvoiceNotification>(str, new JsonSerializerSettings());
|
||||
return JsonConvert.DeserializeObject<ChargeInvoice>(str, new JsonSerializerSettings());
|
||||
}
|
||||
|
||||
private async Task CloseSocketAndThrow(WebSocketCloseStatus status, string description, CancellationToken cancellation)
|
||||
|
|
|
@ -44,24 +44,25 @@ namespace BTCPayServer.Payments.Lightning
|
|||
{
|
||||
if (inv.Name == "invoice_created")
|
||||
{
|
||||
await EnsureListening(inv.InvoiceId);
|
||||
await EnsureListening(inv.InvoiceId, false);
|
||||
}
|
||||
}));
|
||||
|
||||
_ListenPoller = new Timer(async s =>
|
||||
{
|
||||
await Task.WhenAll((await _InvoiceRepository.GetPendingInvoices())
|
||||
.Select(async invoiceId => await EnsureListening(invoiceId))
|
||||
.Select(async invoiceId => await EnsureListening(invoiceId, true))
|
||||
.ToArray());
|
||||
}, null, 0, (int)PollInterval.TotalMilliseconds);
|
||||
leases.Add(_ListenPoller);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task EnsureListening(string invoiceId)
|
||||
private async Task EnsureListening(string invoiceId, bool poll)
|
||||
{
|
||||
if (Listening(invoiceId))
|
||||
return;
|
||||
|
||||
var invoice = await _InvoiceRepository.GetInvoice(null, invoiceId);
|
||||
foreach (var paymentMethod in invoice.GetPaymentMethods(_NetworkProvider)
|
||||
.Where(c => c.GetId().PaymentType == PaymentTypes.LightningLike))
|
||||
|
@ -74,6 +75,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||
if (lightningSupportedMethod == null)
|
||||
continue;
|
||||
var network = _NetworkProvider.GetNetwork(paymentMethod.GetId().CryptoCode);
|
||||
|
||||
var listenedInvoice = new ListenedInvoice()
|
||||
{
|
||||
Uri = lightningSupportedMethod.GetLightningChargeUrl(false).AbsoluteUri,
|
||||
|
@ -83,6 +85,19 @@ namespace BTCPayServer.Payments.Lightning
|
|||
Network = network,
|
||||
InvoiceId = invoice.Id
|
||||
};
|
||||
|
||||
if (poll)
|
||||
{
|
||||
var charge = GetChargeClient(lightningSupportedMethod, network);
|
||||
var chargeInvoice = await charge.GetInvoice(lightningMethod.InvoiceId);
|
||||
if (chargeInvoice == null)
|
||||
continue;
|
||||
if(chargeInvoice.Status == "paid")
|
||||
await AddPayment(network, chargeInvoice, listenedInvoice);
|
||||
if (chargeInvoice.Status == "paid" || chargeInvoice.Status == "expired")
|
||||
continue;
|
||||
}
|
||||
|
||||
StartListening(listenedInvoice);
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +125,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||
try
|
||||
{
|
||||
Logs.PayServer.LogInformation($"{supportedPaymentMethod.CryptoCode} (Lightning): Start listening {supportedPaymentMethod.GetLightningChargeUrl(false)}");
|
||||
var charge = new ChargeClient(supportedPaymentMethod.GetLightningChargeUrl(true), network.NBitcoinNetwork);
|
||||
var charge = GetChargeClient(supportedPaymentMethod, network);
|
||||
var session = await charge.Listen(_Cts.Token);
|
||||
while (true)
|
||||
{
|
||||
|
@ -124,12 +139,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||
{
|
||||
if (notification.Status == "paid" && notification.PaidAt.HasValue)
|
||||
{
|
||||
await _InvoiceRepository.AddPayment(listenedInvoice.InvoiceId, notification.PaidAt.Value, new LightningLikePaymentData()
|
||||
{
|
||||
BOLT11 = notification.PaymentRequest,
|
||||
Amount = notification.MilliSatoshi
|
||||
}, network.CryptoCode, accounted: true);
|
||||
_Aggregator.Publish(new InvoiceEvent(listenedInvoice.InvoiceId, 1002, "invoice_receivedPayment"));
|
||||
await AddPayment(network, notification, listenedInvoice);
|
||||
if (DoneListening(listenedInvoice))
|
||||
break;
|
||||
}
|
||||
|
@ -151,6 +161,21 @@ namespace BTCPayServer.Payments.Lightning
|
|||
Logs.PayServer.LogInformation($"{supportedPaymentMethod.CryptoCode} (Lightning): Stop listening {supportedPaymentMethod.GetLightningChargeUrl(false)}");
|
||||
}
|
||||
|
||||
private async Task AddPayment(BTCPayNetwork network, ChargeInvoice notification, ListenedInvoice listenedInvoice)
|
||||
{
|
||||
await _InvoiceRepository.AddPayment(listenedInvoice.InvoiceId, notification.PaidAt.Value, new LightningLikePaymentData()
|
||||
{
|
||||
BOLT11 = notification.PaymentRequest,
|
||||
Amount = notification.MilliSatoshi
|
||||
}, network.CryptoCode, accounted: true);
|
||||
_Aggregator.Publish(new InvoiceEvent(listenedInvoice.InvoiceId, 1002, "invoice_receivedPayment"));
|
||||
}
|
||||
|
||||
private static ChargeClient GetChargeClient(LightningSupportedPaymentMethod supportedPaymentMethod, BTCPayNetwork network)
|
||||
{
|
||||
return new ChargeClient(supportedPaymentMethod.GetLightningChargeUrl(true), network.NBitcoinNetwork);
|
||||
}
|
||||
|
||||
List<Task> _ListeningLightning = new List<Task>();
|
||||
MultiValueDictionary<string, ListenedInvoice> _ListenedInvoiceByLightningUrl = new MultiValueDictionary<string, ListenedInvoice>();
|
||||
Dictionary<string, ListenedInvoice> _ListenedInvoiceByChargeInvoiceId = new Dictionary<string, ListenedInvoice>();
|
||||
|
|
Loading…
Add table
Reference in a new issue