diff --git a/BTCPayServer.Client/BTCPayServerClient.Lightning.Store.cs b/BTCPayServer.Client/BTCPayServerClient.Lightning.Store.cs index fd07b1eca..27e98bca0 100644 --- a/BTCPayServer.Client/BTCPayServerClient.Lightning.Store.cs +++ b/BTCPayServer.Client/BTCPayServerClient.Lightning.Store.cs @@ -65,7 +65,7 @@ namespace BTCPayServer.Client return await HandleResponse(response); } - public virtual async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request, + public virtual async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request, CancellationToken token = default) { if (request == null) @@ -73,7 +73,7 @@ namespace BTCPayServer.Client var response = await _httpClient.SendAsync( CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices/pay", bodyPayload: request, method: HttpMethod.Post), token); - await HandleResponse(response); + return await HandleResponse(response); } public virtual async Task GetLightningPayment(string storeId, string cryptoCode, diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs index be441952e..407fedd38 100644 --- a/BTCPayServer.Tests/GreenfieldAPITests.cs +++ b/BTCPayServer.Tests/GreenfieldAPITests.cs @@ -1722,10 +1722,17 @@ namespace BTCPayServer.Tests Assert.NotEmpty(merchantPendingInvoices); Assert.Contains(merchantPendingInvoices, i => i.Id == merchantInvoice.Id); - await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest() + var payResponse = await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest { BOLT11 = merchantInvoice.BOLT11 }); + Assert.Equal(merchantInvoice.BOLT11, payResponse.BOLT11); + Assert.Equal(LightningPaymentStatus.Complete, payResponse.Status); + Assert.NotNull(payResponse.Preimage); + Assert.NotNull(payResponse.FeeAmount); + Assert.NotNull(payResponse.TotalAmount); + Assert.NotNull(payResponse.PaymentHash); + await Assert.ThrowsAsync(async () => await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest() { BOLT11 = "lol" diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs index acb241d10..d2f705ca4 100644 --- a/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs +++ b/BTCPayServer/Controllers/GreenField/GreenfieldLightningNodeApiController.cs @@ -209,9 +209,10 @@ namespace BTCPayServer.Controllers.Greenfield { var lightningClient = await GetLightningClient(cryptoCode, true); var network = _btcPayNetworkProvider.GetNetwork(cryptoCode); - - if (lightningInvoice?.BOLT11 is null || - !BOLT11PaymentRequest.TryParse(lightningInvoice.BOLT11, out _, network.NBitcoinNetwork)) + BOLT11PaymentRequest bolt11 = null; + + if (string.IsNullOrEmpty(lightningInvoice.BOLT11) || + !BOLT11PaymentRequest.TryParse(lightningInvoice.BOLT11, out bolt11, network.NBitcoinNetwork)) { ModelState.AddModelError(nameof(lightningInvoice.BOLT11), "The BOLT11 invoice was invalid."); } @@ -221,11 +222,28 @@ namespace BTCPayServer.Controllers.Greenfield return this.CreateValidationError(ModelState); } - var param = lightningInvoice?.MaxFeeFlat != null || lightningInvoice?.MaxFeePercent != null || lightningInvoice?.Amount != null + var param = lightningInvoice.MaxFeeFlat != null || lightningInvoice.MaxFeePercent != null || lightningInvoice.Amount != null ? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat, Amount = lightningInvoice.Amount } : null; var result = await lightningClient.Pay(lightningInvoice.BOLT11, param, cancellationToken); + if (result.Result == PayResult.Ok && bolt11?.PaymentHash is not null) + { + var paymentHash = bolt11.PaymentHash.ToString(); + var payment = await lightningClient.GetPayment(paymentHash, cancellationToken); + return Ok(new LightningPaymentData + { + Id = payment.Id, + PaymentHash = paymentHash, + Status = payment.Status, + BOLT11 = payment.BOLT11, + Preimage = payment.Preimage, + CreatedAt = payment.CreatedAt, + TotalAmount = payment.AmountSent, + FeeAmount = payment.Fee, + }); + } + return result.Result switch { PayResult.CouldNotFindRoute => this.CreateAPIError("could-not-find-route", "Impossible to find a route to the peer"), diff --git a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs index 3dc47812c..ba33a7c92 100644 --- a/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs +++ b/BTCPayServer/Controllers/GreenField/LocalBTCPayServerClient.cs @@ -381,10 +381,11 @@ namespace BTCPayServer.Controllers.Greenfield await GetController().GetDepositAddress(cryptoCode, token)); } - public override async Task PayLightningInvoice(string storeId, string cryptoCode, + public override async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request, CancellationToken token = default) { - HandleActionResult(await GetController().PayInvoice(cryptoCode, request, token)); + return GetFromActionResult( + await GetController().PayInvoice(cryptoCode, request, token)); } public override async Task GetLightningInvoice(string storeId, string cryptoCode,