Greenfield: Fix missing payment data (#4233)

* Greenfield: Fix missing payment data

Fixes #4229.

* Client: Return payment data from PayLightningInvoice

* Add test for PayLightningInvoice response
This commit is contained in:
d11n 2022-10-27 01:56:24 +02:00 committed by GitHub
parent 8b79212a6e
commit 57557748e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 9 deletions

View file

@ -65,7 +65,7 @@ namespace BTCPayServer.Client
return await HandleResponse<string>(response); return await HandleResponse<string>(response);
} }
public virtual async Task PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request, public virtual async Task<LightningPaymentData> PayLightningInvoice(string storeId, string cryptoCode, PayLightningInvoiceRequest request,
CancellationToken token = default) CancellationToken token = default)
{ {
if (request == null) if (request == null)
@ -73,7 +73,7 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync( var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices/pay", bodyPayload: request, CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices/pay", bodyPayload: request,
method: HttpMethod.Post), token); method: HttpMethod.Post), token);
await HandleResponse(response); return await HandleResponse<LightningPaymentData>(response);
} }
public virtual async Task<LightningPaymentData> GetLightningPayment(string storeId, string cryptoCode, public virtual async Task<LightningPaymentData> GetLightningPayment(string storeId, string cryptoCode,

View file

@ -1722,10 +1722,17 @@ namespace BTCPayServer.Tests
Assert.NotEmpty(merchantPendingInvoices); Assert.NotEmpty(merchantPendingInvoices);
Assert.Contains(merchantPendingInvoices, i => i.Id == merchantInvoice.Id); 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 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<GreenfieldValidationException>(async () => await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest() await Assert.ThrowsAsync<GreenfieldValidationException>(async () => await client.PayLightningInvoice(user.StoreId, "BTC", new PayLightningInvoiceRequest()
{ {
BOLT11 = "lol" BOLT11 = "lol"

View file

@ -209,9 +209,10 @@ namespace BTCPayServer.Controllers.Greenfield
{ {
var lightningClient = await GetLightningClient(cryptoCode, true); var lightningClient = await GetLightningClient(cryptoCode, true);
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode); var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
BOLT11PaymentRequest bolt11 = null;
if (lightningInvoice?.BOLT11 is null || if (string.IsNullOrEmpty(lightningInvoice.BOLT11) ||
!BOLT11PaymentRequest.TryParse(lightningInvoice.BOLT11, out _, network.NBitcoinNetwork)) !BOLT11PaymentRequest.TryParse(lightningInvoice.BOLT11, out bolt11, network.NBitcoinNetwork))
{ {
ModelState.AddModelError(nameof(lightningInvoice.BOLT11), "The BOLT11 invoice was invalid."); ModelState.AddModelError(nameof(lightningInvoice.BOLT11), "The BOLT11 invoice was invalid.");
} }
@ -221,11 +222,28 @@ namespace BTCPayServer.Controllers.Greenfield
return this.CreateValidationError(ModelState); 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 } ? new PayInvoiceParams { MaxFeePercent = lightningInvoice.MaxFeePercent, MaxFeeFlat = lightningInvoice.MaxFeeFlat, Amount = lightningInvoice.Amount }
: null; : null;
var result = await lightningClient.Pay(lightningInvoice.BOLT11, param, cancellationToken); 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 return result.Result switch
{ {
PayResult.CouldNotFindRoute => this.CreateAPIError("could-not-find-route", "Impossible to find a route to the peer"), PayResult.CouldNotFindRoute => this.CreateAPIError("could-not-find-route", "Impossible to find a route to the peer"),

View file

@ -381,10 +381,11 @@ namespace BTCPayServer.Controllers.Greenfield
await GetController<GreenfieldStoreLightningNodeApiController>().GetDepositAddress(cryptoCode, token)); await GetController<GreenfieldStoreLightningNodeApiController>().GetDepositAddress(cryptoCode, token));
} }
public override async Task PayLightningInvoice(string storeId, string cryptoCode, public override async Task<LightningPaymentData> PayLightningInvoice(string storeId, string cryptoCode,
PayLightningInvoiceRequest request, CancellationToken token = default) PayLightningInvoiceRequest request, CancellationToken token = default)
{ {
HandleActionResult(await GetController<GreenfieldStoreLightningNodeApiController>().PayInvoice(cryptoCode, request, token)); return GetFromActionResult<LightningPaymentData>(
await GetController<GreenfieldStoreLightningNodeApiController>().PayInvoice(cryptoCode, request, token));
} }
public override async Task<LightningInvoiceData> GetLightningInvoice(string storeId, string cryptoCode, public override async Task<LightningInvoiceData> GetLightningInvoice(string storeId, string cryptoCode,