mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 14:04:26 +01:00
Greenfield: Add payment hash and preimage to Lightning invoices (#4520)
* Greenfield: Add payment hash and preimage to Lightning invoices Closes #4475. * Greenfield: Add payment hash and preimage to invoice payment method details * Refactor LN payment method details retrieval
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.20" />
|
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.21" />
|
||||||
<PackageReference Include="NBitcoin" Version="7.0.23" />
|
<PackageReference Include="NBitcoin" Version="7.0.23" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -16,9 +16,15 @@ namespace BTCPayServer.Client.Models
|
|||||||
|
|
||||||
[JsonProperty("BOLT11")]
|
[JsonProperty("BOLT11")]
|
||||||
public string BOLT11 { get; set; }
|
public string BOLT11 { get; set; }
|
||||||
|
|
||||||
|
public string PaymentHash { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string Preimage { get; set; }
|
||||||
|
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||||
public DateTimeOffset? PaidAt { get; set; }
|
public DateTimeOffset? PaidAt { get; set; }
|
||||||
|
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||||
public DateTimeOffset ExpiresAt { get; set; }
|
public DateTimeOffset ExpiresAt { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ using BTCPayServer.Services;
|
|||||||
using BTCPayServer.Services.Custodian.Client.MockCustodian;
|
using BTCPayServer.Services.Custodian.Client.MockCustodian;
|
||||||
using BTCPayServer.Services.Notifications;
|
using BTCPayServer.Services.Notifications;
|
||||||
using BTCPayServer.Services.Notifications.Blobs;
|
using BTCPayServer.Services.Notifications.Blobs;
|
||||||
using BTCPayServer.Services.Stores;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -1723,7 +1721,7 @@ namespace BTCPayServer.Tests
|
|||||||
using var tester = CreateServerTester();
|
using var tester = CreateServerTester();
|
||||||
await tester.StartAsync();
|
await tester.StartAsync();
|
||||||
var user = tester.NewAccount();
|
var user = tester.NewAccount();
|
||||||
await user.GrantAccessAsync();
|
await user.GrantAccessAsync(true);
|
||||||
await user.MakeAdmin();
|
await user.MakeAdmin();
|
||||||
await user.SetupWebhook();
|
await user.SetupWebhook();
|
||||||
var client = await user.CreateClient(Policies.Unrestricted);
|
var client = await user.CreateClient(Policies.Unrestricted);
|
||||||
@@ -2104,9 +2102,13 @@ namespace BTCPayServer.Tests
|
|||||||
merchant.RegisterLightningNode("BTC", LightningConnectionType.LndREST);
|
merchant.RegisterLightningNode("BTC", LightningConnectionType.LndREST);
|
||||||
var merchantClient = await merchant.CreateClient($"{Policies.CanUseLightningNodeInStore}:{merchant.StoreId}");
|
var merchantClient = await merchant.CreateClient($"{Policies.CanUseLightningNodeInStore}:{merchant.StoreId}");
|
||||||
var merchantInvoice = await merchantClient.CreateLightningInvoice(merchant.StoreId, "BTC", new CreateLightningInvoiceRequest(LightMoney.Satoshis(1_000), "hey", TimeSpan.FromSeconds(60)));
|
var merchantInvoice = await merchantClient.CreateLightningInvoice(merchant.StoreId, "BTC", new CreateLightningInvoiceRequest(LightMoney.Satoshis(1_000), "hey", TimeSpan.FromSeconds(60)));
|
||||||
|
Assert.NotNull(merchantInvoice.Id);
|
||||||
|
Assert.NotNull(merchantInvoice.PaymentHash);
|
||||||
|
Assert.Equal(merchantInvoice.Id, merchantInvoice.PaymentHash);
|
||||||
|
|
||||||
// The default client is using charge, so we should not be able to query channels
|
// The default client is using charge, so we should not be able to query channels
|
||||||
var chargeClient = await user.CreateClient(Policies.CanUseInternalLightningNode);
|
var chargeClient = await user.CreateClient(Policies.CanUseInternalLightningNode);
|
||||||
|
|
||||||
var info = await chargeClient.GetLightningNodeInfo("BTC");
|
var info = await chargeClient.GetLightningNodeInfo("BTC");
|
||||||
Assert.Single(info.NodeURIs);
|
Assert.Single(info.NodeURIs);
|
||||||
Assert.NotEqual(0, info.BlockHeight);
|
Assert.NotEqual(0, info.BlockHeight);
|
||||||
@@ -2175,6 +2177,14 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.NotNull(payResponse.FeeAmount);
|
Assert.NotNull(payResponse.FeeAmount);
|
||||||
Assert.NotNull(payResponse.TotalAmount);
|
Assert.NotNull(payResponse.TotalAmount);
|
||||||
Assert.NotNull(payResponse.PaymentHash);
|
Assert.NotNull(payResponse.PaymentHash);
|
||||||
|
|
||||||
|
// check the get invoice response
|
||||||
|
var merchInvoice = await merchantClient.GetLightningInvoice(merchant.StoreId, "BTC", merchantInvoice.Id);
|
||||||
|
Assert.NotNull(merchInvoice);
|
||||||
|
Assert.NotNull(merchInvoice.Preimage);
|
||||||
|
Assert.NotNull(merchInvoice.PaymentHash);
|
||||||
|
Assert.Equal(payResponse.Preimage, merchInvoice.Preimage);
|
||||||
|
Assert.Equal(payResponse.PaymentHash, merchInvoice.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()
|
||||||
{
|
{
|
||||||
@@ -2191,6 +2201,8 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
var invoice = await merchantClient.GetLightningInvoice(merchant.StoreId, "BTC", merchantInvoice.Id);
|
var invoice = await merchantClient.GetLightningInvoice(merchant.StoreId, "BTC", merchantInvoice.Id);
|
||||||
Assert.NotNull(invoice.PaidAt);
|
Assert.NotNull(invoice.PaidAt);
|
||||||
|
Assert.NotNull(invoice.PaymentHash);
|
||||||
|
Assert.NotNull(invoice.Preimage);
|
||||||
Assert.Equal(LightMoney.Satoshis(1000), invoice.Amount);
|
Assert.Equal(LightMoney.Satoshis(1000), invoice.Amount);
|
||||||
|
|
||||||
// check list for store with paid invoice
|
// check list for store with paid invoice
|
||||||
@@ -2232,6 +2244,45 @@ namespace BTCPayServer.Tests
|
|||||||
await AssertPermissionError("btcpay.store.canuselightningnode", () => client.GetLightningNodeInfo(user.StoreId, "BTC"));
|
await AssertPermissionError("btcpay.store.canuselightningnode", () => client.GetLightningNodeInfo(user.StoreId, "BTC"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact(Timeout = 60 * 20 * 1000)]
|
||||||
|
[Trait("Integration", "Integration")]
|
||||||
|
[Trait("Lightning", "Lightning")]
|
||||||
|
public async Task CanAccessInvoiceLightningPaymentMethodDetails()
|
||||||
|
{
|
||||||
|
using var tester = CreateServerTester();
|
||||||
|
tester.ActivateLightning();
|
||||||
|
await tester.StartAsync();
|
||||||
|
await tester.EnsureChannelsSetup();
|
||||||
|
var user = tester.NewAccount();
|
||||||
|
await user.GrantAccessAsync(true);
|
||||||
|
user.RegisterLightningNode("BTC", LightningConnectionType.CLightning);
|
||||||
|
|
||||||
|
var client = await user.CreateClient(Policies.Unrestricted);
|
||||||
|
var invoice = await client.CreateInvoice(user.StoreId,
|
||||||
|
new CreateInvoiceRequest
|
||||||
|
{
|
||||||
|
Currency = "USD",
|
||||||
|
Amount = 100,
|
||||||
|
Checkout = new CreateInvoiceRequest.CheckoutOptions
|
||||||
|
{
|
||||||
|
PaymentMethods = new[] { "BTC-LightningNetwork" },
|
||||||
|
DefaultPaymentMethod = "BTC_LightningLike"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
|
||||||
|
Assert.False(pm.AdditionalData.HasValues);
|
||||||
|
|
||||||
|
var resp = await tester.CustomerLightningD.Pay(pm.Destination);
|
||||||
|
Assert.Equal(PayResult.Ok, resp.Result);
|
||||||
|
Assert.NotNull(resp.Details.PaymentHash);
|
||||||
|
Assert.NotNull(resp.Details.Preimage);
|
||||||
|
|
||||||
|
pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
|
||||||
|
Assert.True(pm.AdditionalData.HasValues);
|
||||||
|
Assert.Equal(resp.Details.PaymentHash.ToString(), pm.AdditionalData.GetValue("paymentHash"));
|
||||||
|
Assert.Equal(resp.Details.Preimage.ToString(), pm.AdditionalData.GetValue("preimage"));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact(Timeout = 60 * 20 * 1000)]
|
[Fact(Timeout = 60 * 20 * 1000)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
[Trait("Lightning", "Lightning")]
|
[Trait("Lightning", "Lightning")]
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BIP78.Sender" Version="0.2.2" />
|
<PackageReference Include="BIP78.Sender" Version="0.2.2" />
|
||||||
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.2" />
|
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.2" />
|
||||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.16" />
|
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.4.18" />
|
||||||
<PackageReference Include="CsvHelper" Version="15.0.5" />
|
<PackageReference Include="CsvHelper" Version="15.0.5" />
|
||||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||||
<PackageReference Include="Fido2" Version="2.0.2" />
|
<PackageReference Include="Fido2" Version="2.0.2" />
|
||||||
|
|||||||
@@ -534,7 +534,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
var payments = method.ParentEntity.GetPayments(includeAccountedPaymentOnly).Where(paymentEntity =>
|
var payments = method.ParentEntity.GetPayments(includeAccountedPaymentOnly).Where(paymentEntity =>
|
||||||
paymentEntity.GetPaymentMethodId() == method.GetId());
|
paymentEntity.GetPaymentMethodId() == method.GetId());
|
||||||
|
|
||||||
return new InvoicePaymentMethodDataModel()
|
return new InvoicePaymentMethodDataModel
|
||||||
{
|
{
|
||||||
Activated = details.Activated,
|
Activated = details.Activated,
|
||||||
PaymentMethod = method.GetId().ToStringNormalized(),
|
PaymentMethod = method.GetId().ToStringNormalized(),
|
||||||
|
|||||||
@@ -264,9 +264,12 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
}),
|
}),
|
||||||
PayResult.Ok => Ok(new LightningPaymentData
|
PayResult.Ok => Ok(new LightningPaymentData
|
||||||
{
|
{
|
||||||
|
BOLT11 = bolt11?.ToString(),
|
||||||
Status = LightningPaymentStatus.Complete,
|
Status = LightningPaymentStatus.Complete,
|
||||||
TotalAmount = result.Details?.TotalAmount,
|
TotalAmount = result.Details?.TotalAmount,
|
||||||
FeeAmount = result.Details?.FeeAmount
|
FeeAmount = result.Details?.FeeAmount,
|
||||||
|
PaymentHash = result.Details?.PaymentHash.ToString(),
|
||||||
|
Preimage = result.Details?.Preimage.ToString()
|
||||||
}),
|
}),
|
||||||
_ => throw new NotSupportedException("Unsupported PayResult")
|
_ => throw new NotSupportedException("Unsupported PayResult")
|
||||||
};
|
};
|
||||||
@@ -353,7 +356,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
AmountReceived = invoice.AmountReceived,
|
AmountReceived = invoice.AmountReceived,
|
||||||
PaidAt = invoice.PaidAt,
|
PaidAt = invoice.PaidAt,
|
||||||
BOLT11 = invoice.BOLT11,
|
BOLT11 = invoice.BOLT11,
|
||||||
ExpiresAt = invoice.ExpiresAt
|
ExpiresAt = invoice.ExpiresAt,
|
||||||
|
PaymentHash = invoice.PaymentHash,
|
||||||
|
Preimage = invoice.Preimage
|
||||||
};
|
};
|
||||||
|
|
||||||
if (invoice.CustomRecords != null)
|
if (invoice.CustomRecords != null)
|
||||||
|
|||||||
@@ -594,6 +594,8 @@ namespace BTCPayServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
paymentMethodDetails.BOLT11 = invoice.BOLT11;
|
paymentMethodDetails.BOLT11 = invoice.BOLT11;
|
||||||
|
paymentMethodDetails.PaymentHash = string.IsNullOrEmpty(invoice.PaymentHash) ? null : uint256.Parse(invoice.PaymentHash);
|
||||||
|
paymentMethodDetails.Preimage = string.IsNullOrEmpty(invoice.Preimage) ? null : uint256.Parse(invoice.Preimage);
|
||||||
paymentMethodDetails.InvoiceId = invoice.Id;
|
paymentMethodDetails.InvoiceId = invoice.Id;
|
||||||
paymentMethodDetails.GeneratedBoltAmount = new LightMoney(amount.Value);
|
paymentMethodDetails.GeneratedBoltAmount = new LightMoney(amount.Value);
|
||||||
if (lnurlSupportedPaymentMethod.LUD12Enabled)
|
if (lnurlSupportedPaymentMethod.LUD12Enabled)
|
||||||
@@ -604,7 +606,6 @@ namespace BTCPayServer
|
|||||||
lightningPaymentMethod.SetPaymentMethodDetails(paymentMethodDetails);
|
lightningPaymentMethod.SetPaymentMethodDetails(paymentMethodDetails);
|
||||||
await _invoiceRepository.UpdateInvoicePaymentMethod(invoiceId, lightningPaymentMethod);
|
await _invoiceRepository.UpdateInvoicePaymentMethod(invoiceId, lightningPaymentMethod);
|
||||||
|
|
||||||
|
|
||||||
_eventAggregator.Publish(new InvoiceNewPaymentDetailsEvent(invoiceId,
|
_eventAggregator.Publish(new InvoiceNewPaymentDetailsEvent(invoiceId,
|
||||||
paymentMethodDetails, pmi));
|
paymentMethodDetails, pmi));
|
||||||
return Ok(new LNURLPayRequest.LNURLPayRequestCallbackResponse
|
return Ok(new LNURLPayRequest.LNURLPayRequestCallbackResponse
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace BTCPayServer.Payments
|
namespace BTCPayServer.Payments
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using BTCPayServer.Client.JsonConverters;
|
using BTCPayServer.Client.JsonConverters;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,19 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
{
|
{
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public BTCPayNetworkBase Network { get; set; }
|
public BTCPayNetworkBase Network { get; set; }
|
||||||
|
|
||||||
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
||||||
public LightMoney Amount { get; set; }
|
public LightMoney Amount { get; set; }
|
||||||
|
|
||||||
public string BOLT11 { get; set; }
|
public string BOLT11 { get; set; }
|
||||||
|
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
||||||
public uint256 PaymentHash { get; set; }
|
public uint256 PaymentHash { get; set; }
|
||||||
|
|
||||||
|
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public uint256 Preimage { get; set; }
|
||||||
|
|
||||||
public string PaymentType { get; set; }
|
public string PaymentType { get; set; }
|
||||||
|
|
||||||
public string GetDestination()
|
public string GetDestination()
|
||||||
@@ -25,7 +33,6 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
|
|
||||||
public decimal NetworkFee { get; set; }
|
public decimal NetworkFee { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public string GetPaymentId()
|
public string GetPaymentId()
|
||||||
{
|
{
|
||||||
// Legacy, some old payments don't have the PaymentHash set
|
// Legacy, some old payments don't have the PaymentHash set
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
if (expiry < TimeSpan.Zero)
|
if (expiry < TimeSpan.Zero)
|
||||||
expiry = TimeSpan.FromSeconds(1);
|
expiry = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
LightningInvoice? lightningInvoice = null;
|
LightningInvoice? lightningInvoice;
|
||||||
|
|
||||||
string description = storeBlob.LightningDescriptionTemplate;
|
string description = storeBlob.LightningDescriptionTemplate;
|
||||||
description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
|
description = description.Replace("{StoreName}", store.StoreName ?? "", StringComparison.OrdinalIgnoreCase)
|
||||||
@@ -118,6 +118,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
Activated = true,
|
Activated = true,
|
||||||
BOLT11 = lightningInvoice.BOLT11,
|
BOLT11 = lightningInvoice.BOLT11,
|
||||||
PaymentHash = BOLT11PaymentRequest.Parse(lightningInvoice.BOLT11, network.NBitcoinNetwork).PaymentHash,
|
PaymentHash = BOLT11PaymentRequest.Parse(lightningInvoice.BOLT11, network.NBitcoinNetwork).PaymentHash,
|
||||||
|
Preimage = string.IsNullOrEmpty(lightningInvoice.Preimage) ? null : uint256.Parse(lightningInvoice.Preimage),
|
||||||
InvoiceId = lightningInvoice.Id,
|
InvoiceId = lightningInvoice.Id,
|
||||||
NodeInfo = (await nodeInfo).FirstOrDefault()?.ToString()
|
NodeInfo = (await nodeInfo).FirstOrDefault()?.ToString()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
@@ -9,6 +11,7 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
{
|
{
|
||||||
public string BOLT11 { get; set; }
|
public string BOLT11 { get; set; }
|
||||||
public uint256 PaymentHash { get; set; }
|
public uint256 PaymentHash { get; set; }
|
||||||
|
public uint256 Preimage { get; set; }
|
||||||
public string InvoiceId { get; set; }
|
public string InvoiceId { get; set; }
|
||||||
public string NodeInfo { get; set; }
|
public string NodeInfo { get; set; }
|
||||||
|
|
||||||
@@ -45,7 +48,12 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
|
|
||||||
public virtual JObject GetAdditionalData()
|
public virtual JObject GetAdditionalData()
|
||||||
{
|
{
|
||||||
return new();
|
var result = new JObject();
|
||||||
|
if (PaymentHash != null && PaymentHash != default)
|
||||||
|
result.Add("paymentHash", new JValue(PaymentHash.ToString()));
|
||||||
|
if (Preimage != null && Preimage != default)
|
||||||
|
result.Add("preimage", new JValue(Preimage.ToString()));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using Microsoft.Extensions.Caching.Memory;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
|
|
||||||
namespace BTCPayServer.Payments.Lightning
|
namespace BTCPayServer.Payments.Lightning
|
||||||
@@ -529,10 +530,11 @@ namespace BTCPayServer.Payments.Lightning
|
|||||||
|
|
||||||
public async Task<bool> AddPayment(LightningInvoice notification, string invoiceId, PaymentType paymentType)
|
public async Task<bool> AddPayment(LightningInvoice notification, string invoiceId, PaymentType paymentType)
|
||||||
{
|
{
|
||||||
var payment = await _paymentService.AddPayment(invoiceId, notification.PaidAt.Value, new LightningLikePaymentData()
|
var payment = await _paymentService.AddPayment(invoiceId, notification.PaidAt.Value, new LightningLikePaymentData
|
||||||
{
|
{
|
||||||
BOLT11 = notification.BOLT11,
|
BOLT11 = notification.BOLT11,
|
||||||
PaymentHash = BOLT11PaymentRequest.Parse(notification.BOLT11, _network.NBitcoinNetwork).PaymentHash,
|
PaymentHash = BOLT11PaymentRequest.Parse(notification.BOLT11, _network.NBitcoinNetwork).PaymentHash,
|
||||||
|
Preimage = string.IsNullOrEmpty(notification.Preimage) ? null : uint256.Parse(notification.Preimage),
|
||||||
Amount = notification.AmountReceived ?? notification.Amount, // if running old version amount received might be unavailable,
|
Amount = notification.AmountReceived ?? notification.Amount, // if running old version amount received might be unavailable,
|
||||||
PaymentType = paymentType.ToString()
|
PaymentType = paymentType.ToString()
|
||||||
}, _network, accounted: true);
|
}, _network, accounted: true);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using BTCPayServer.JsonConverters;
|
|||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Bitcoin;
|
using BTCPayServer.Payments.Bitcoin;
|
||||||
|
using BTCPayServer.Payments.Lightning;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.DataEncoders;
|
using NBitcoin.DataEncoders;
|
||||||
using NBitpayClient;
|
using NBitpayClient;
|
||||||
@@ -989,25 +990,35 @@ namespace BTCPayServer.Services.Invoices
|
|||||||
// Legacy, old code does not have PaymentMethods
|
// Legacy, old code does not have PaymentMethods
|
||||||
if (string.IsNullOrEmpty(PaymentType) || PaymentMethodDetails == null)
|
if (string.IsNullOrEmpty(PaymentType) || PaymentMethodDetails == null)
|
||||||
{
|
{
|
||||||
return new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod()
|
return new BitcoinLikeOnChainPaymentMethod
|
||||||
{
|
{
|
||||||
FeeRate = FeeRate,
|
FeeRate = FeeRate,
|
||||||
DepositAddress = string.IsNullOrEmpty(DepositAddress) ? null : DepositAddress,
|
DepositAddress = string.IsNullOrEmpty(DepositAddress) ? null : DepositAddress,
|
||||||
NextNetworkFee = NextNetworkFee
|
NextNetworkFee = NextNetworkFee
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
IPaymentMethodDetails details = GetId().PaymentType.DeserializePaymentMethodDetails(Network, PaymentMethodDetails.ToString());
|
||||||
|
switch (details)
|
||||||
{
|
{
|
||||||
IPaymentMethodDetails details = GetId().PaymentType.DeserializePaymentMethodDetails(Network, PaymentMethodDetails.ToString());
|
case BitcoinLikeOnChainPaymentMethod btcLike:
|
||||||
if (details is Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod btcLike)
|
|
||||||
{
|
|
||||||
btcLike.NextNetworkFee = NextNetworkFee;
|
btcLike.NextNetworkFee = NextNetworkFee;
|
||||||
btcLike.DepositAddress = string.IsNullOrEmpty(DepositAddress) ? null : DepositAddress;
|
btcLike.DepositAddress = string.IsNullOrEmpty(DepositAddress) ? null : DepositAddress;
|
||||||
btcLike.FeeRate = FeeRate;
|
btcLike.FeeRate = FeeRate;
|
||||||
}
|
break;
|
||||||
return details;
|
case LightningLikePaymentMethodDetails lnLike:
|
||||||
|
// use set properties and fall back to values from payment data
|
||||||
|
var payments = ParentEntity.GetPayments(true).Where(paymentEntity =>
|
||||||
|
paymentEntity.GetPaymentMethodId() == GetId());
|
||||||
|
var payment = payments.Select(p => p.GetCryptoPaymentData() as LightningLikePaymentData).FirstOrDefault();
|
||||||
|
var paymentHash = payment?.PaymentHash != null && payment.PaymentHash != default ? payment.PaymentHash : null;
|
||||||
|
var preimage = payment?.Preimage != null && payment.Preimage != default ? payment.Preimage : null;
|
||||||
|
lnLike.PaymentHash = lnLike.PaymentHash != null && lnLike.PaymentHash != default ? lnLike.PaymentHash : paymentHash;
|
||||||
|
lnLike.Preimage = lnLike.Preimage != null && lnLike.Preimage != default ? lnLike.Preimage : preimage;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
throw new NotSupportedException(PaymentType);
|
|
||||||
|
return details;
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,15 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The amount received in millisatoshi"
|
"description": "The amount received in millisatoshi"
|
||||||
},
|
},
|
||||||
|
"paymentHash": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The payment hash"
|
||||||
|
},
|
||||||
|
"preimage": {
|
||||||
|
"type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"description": "The payment preimage (available when status is complete)"
|
||||||
|
},
|
||||||
"customRecords": {
|
"customRecords": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"nullable": true,
|
"nullable": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user