mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 09:54:30 +01:00
Add Greenfield API endpoint for pull payment LNURL items (#4472)
* Add Greenfield API endpoint for pull payment LNURL items close #4365 * Rename GetLNURLs to GetPullPaymentLNURL * update "ln-url-not-supported" to "lnurl-not-supported" * remove hardcoding of "BTC" * update "PullPayments_LNURL" to "PullPayments_GetPullPaymentLNURL" * update description of 400 status code response Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
This commit is contained in:
parent
de4ac2c830
commit
438dcc4c6f
@ -97,5 +97,15 @@ namespace BTCPayServer.Client
|
|||||||
method: HttpMethod.Post, bodyPayload: request), cancellationToken);
|
method: HttpMethod.Post, bodyPayload: request), cancellationToken);
|
||||||
await HandleResponse(response);
|
await HandleResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual async Task<PullPaymentLNURL> GetPullPaymentLNURL(string pullPaymentId,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var response = await _httpClient.SendAsync(
|
||||||
|
CreateHttpRequest(
|
||||||
|
$"/api/v1/pull-payments/{pullPaymentId}/lnurl",
|
||||||
|
method: HttpMethod.Get), cancellationToken);
|
||||||
|
return await HandleResponse<PullPaymentLNURL>(response);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
BTCPayServer.Client/Models/PullPaymentLNURL.cs
Normal file
8
BTCPayServer.Client/Models/PullPaymentLNURL.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace BTCPayServer.Client.Models
|
||||||
|
{
|
||||||
|
public class PullPaymentLNURL
|
||||||
|
{
|
||||||
|
public string LNURLBech32 { get; set; }
|
||||||
|
public string LNURLUri { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -672,10 +672,12 @@ namespace BTCPayServer.Tests
|
|||||||
public async Task CanUsePullPaymentViaAPI()
|
public async Task CanUsePullPaymentViaAPI()
|
||||||
{
|
{
|
||||||
using var tester = CreateServerTester();
|
using var tester = CreateServerTester();
|
||||||
|
tester.ActivateLightning();
|
||||||
await tester.StartAsync();
|
await tester.StartAsync();
|
||||||
|
await tester.EnsureChannelsSetup();
|
||||||
var acc = tester.NewAccount();
|
var acc = tester.NewAccount();
|
||||||
acc.Register();
|
await acc.GrantAccessAsync(true);
|
||||||
await acc.CreateStoreAsync();
|
acc.RegisterLightningNode("BTC", LightningConnectionType.CLightning, false);
|
||||||
var storeId = (await acc.RegisterDerivationSchemeAsync("BTC", importKeysToNBX: true)).StoreId;
|
var storeId = (await acc.RegisterDerivationSchemeAsync("BTC", importKeysToNBX: true)).StoreId;
|
||||||
var client = await acc.CreateClient();
|
var client = await acc.CreateClient();
|
||||||
var result = await client.CreatePullPayment(storeId, new CreatePullPaymentRequest()
|
var result = await client.CreatePullPayment(storeId, new CreatePullPaymentRequest()
|
||||||
@ -856,6 +858,8 @@ namespace BTCPayServer.Tests
|
|||||||
PaymentMethods = new[] { "BTC" }
|
PaymentMethods = new[] { "BTC" }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.AssertAPIError("lnurl-not-supported", async () => await unauthenticated.GetPullPaymentLNURL(pp.Id));
|
||||||
|
|
||||||
destination = (await tester.ExplorerNode.GetNewAddressAsync()).ToString();
|
destination = (await tester.ExplorerNode.GetNewAddressAsync()).ToString();
|
||||||
TestLogs.LogInformation("Try to pay it in BTC");
|
TestLogs.LogInformation("Try to pay it in BTC");
|
||||||
payout = await unauthenticated.CreatePayout(pp.Id, new CreatePayoutRequest()
|
payout = await unauthenticated.CreatePayout(pp.Id, new CreatePayoutRequest()
|
||||||
@ -907,6 +911,17 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(PayoutState.Completed, payout.State);
|
Assert.Equal(PayoutState.Completed, payout.State);
|
||||||
await AssertAPIError("invalid-state", async () => await client.MarkPayoutPaid(storeId, payout.Id));
|
await AssertAPIError("invalid-state", async () => await client.MarkPayoutPaid(storeId, payout.Id));
|
||||||
|
|
||||||
|
// Test LNURL values
|
||||||
|
var test4 = await client.CreatePullPayment(storeId, new Client.Models.CreatePullPaymentRequest()
|
||||||
|
{
|
||||||
|
Name = "Test 3",
|
||||||
|
Amount = 12.303228134m,
|
||||||
|
Currency = "BTC",
|
||||||
|
PaymentMethods = new[] { "BTC", "BTC-LightningNetwork", "BTC_LightningLike" }
|
||||||
|
});
|
||||||
|
var lnrURLs = await unauthenticated.GetPullPaymentLNURL(test4.Id);
|
||||||
|
Assert.IsType<string>(lnrURLs.LNURLBech32);
|
||||||
|
Assert.IsType<string>(lnrURLs.LNURLUri);
|
||||||
|
|
||||||
//permission test around auto approved pps and payouts
|
//permission test around auto approved pps and payouts
|
||||||
var nonApproved = await acc.CreateClient(Policies.CanCreateNonApprovedPullPayments);
|
var nonApproved = await acc.CreateClient(Policies.CanCreateNonApprovedPullPayments);
|
||||||
|
@ -34,6 +34,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
private readonly CurrencyNameTable _currencyNameTable;
|
private readonly CurrencyNameTable _currencyNameTable;
|
||||||
private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings;
|
private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings;
|
||||||
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
|
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
|
||||||
|
private readonly BTCPayNetworkProvider _networkProvider;
|
||||||
private readonly IAuthorizationService _authorizationService;
|
private readonly IAuthorizationService _authorizationService;
|
||||||
|
|
||||||
public GreenfieldPullPaymentController(PullPaymentHostedService pullPaymentService,
|
public GreenfieldPullPaymentController(PullPaymentHostedService pullPaymentService,
|
||||||
@ -42,6 +43,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
CurrencyNameTable currencyNameTable,
|
CurrencyNameTable currencyNameTable,
|
||||||
Services.BTCPayNetworkJsonSerializerSettings serializerSettings,
|
Services.BTCPayNetworkJsonSerializerSettings serializerSettings,
|
||||||
IEnumerable<IPayoutHandler> payoutHandlers,
|
IEnumerable<IPayoutHandler> payoutHandlers,
|
||||||
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
IAuthorizationService authorizationService)
|
IAuthorizationService authorizationService)
|
||||||
{
|
{
|
||||||
_pullPaymentService = pullPaymentService;
|
_pullPaymentService = pullPaymentService;
|
||||||
@ -50,6 +52,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
_currencyNameTable = currencyNameTable;
|
_currencyNameTable = currencyNameTable;
|
||||||
_serializerSettings = serializerSettings;
|
_serializerSettings = serializerSettings;
|
||||||
_payoutHandlers = payoutHandlers;
|
_payoutHandlers = payoutHandlers;
|
||||||
|
_networkProvider = btcPayNetworkProvider;
|
||||||
_authorizationService = authorizationService;
|
_authorizationService = authorizationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,6 +246,33 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
return base.Ok(ToModel(payout));
|
return base.Ok(ToModel(payout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("~/api/v1/pull-payments/{pullPaymentId}/lnurl")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> GetPullPaymentLNURL(string pullPaymentId)
|
||||||
|
{
|
||||||
|
var pp = await _pullPaymentService.GetPullPayment(pullPaymentId, false);
|
||||||
|
if (pp is null)
|
||||||
|
return PullPaymentNotFound();
|
||||||
|
|
||||||
|
var blob = pp.GetBlob();
|
||||||
|
var pms = blob.SupportedPaymentMethods.FirstOrDefault(id => id.PaymentType == LightningPaymentType.Instance && _networkProvider.DefaultNetwork.CryptoCode == id.CryptoCode);
|
||||||
|
if (pms is not null && blob.Currency.Equals(pms.CryptoCode, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
var lnurlEndpoint = new Uri(Url.Action("GetLNURLForPullPayment", "UILNURL", new
|
||||||
|
{
|
||||||
|
cryptoCode = _networkProvider.DefaultNetwork.CryptoCode,
|
||||||
|
pullPaymentId = pullPaymentId
|
||||||
|
}, Request.Scheme, Request.Host.ToString()));
|
||||||
|
|
||||||
|
return base.Ok(new PullPaymentLNURL() {
|
||||||
|
LNURLBech32 = LNURL.LNURL.EncodeUri(lnurlEndpoint, "withdrawRequest", true).ToString(),
|
||||||
|
LNURLUri = LNURL.LNURL.EncodeUri(lnurlEndpoint, "withdrawRequest", false).ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.CreateAPIError("lnurl-not-supported", "LNURL not supported for this pull payment");
|
||||||
|
}
|
||||||
|
|
||||||
private Client.Models.PayoutData ToModel(Data.PayoutData p)
|
private Client.Models.PayoutData ToModel(Data.PayoutData p)
|
||||||
{
|
{
|
||||||
var blob = p.GetBlob(_serializerSettings);
|
var blob = p.GetBlob(_serializerSettings);
|
||||||
|
@ -1242,6 +1242,11 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
return GetFromActionResult<PayoutData>(await GetController<GreenfieldPullPaymentController>().GetPayout(pullPaymentId, payoutId));
|
return GetFromActionResult<PayoutData>(await GetController<GreenfieldPullPaymentController>().GetPayout(pullPaymentId, payoutId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task<PullPaymentLNURL> GetPullPaymentLNURL(string pullPaymentId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
return GetFromActionResult<PullPaymentLNURL>(await GetController<GreenfieldPullPaymentController>().GetPullPaymentLNURL(pullPaymentId));
|
||||||
|
}
|
||||||
|
|
||||||
public override async Task<PayoutData> GetStorePayout(string storeId, string payoutId,
|
public override async Task<PayoutData> GetStorePayout(string storeId, string payoutId,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
@ -402,6 +402,46 @@
|
|||||||
"security": []
|
"security": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/v1/pull-payments/{pullPaymentId}/lnurl": {
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "pullPaymentId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"description": "The ID of the pull payment",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"get": {
|
||||||
|
"summary": "Get Pull Payment LNURL details",
|
||||||
|
"operationId": "PullPayments_GetPullPaymentLNURL",
|
||||||
|
"description": "Get Pull Payment LNURL details",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Pull payment LNURL details",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/LNURLData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Pull payment not found"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Pull payment found but does not support LNURL"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"Pull payments (Public)"
|
||||||
|
],
|
||||||
|
"security": []
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/v1/stores/{storeId}/payouts": {
|
"/api/v1/stores/{storeId}/payouts": {
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
@ -1028,6 +1068,21 @@
|
|||||||
"description": "The link to a page to claim payouts to this pull payment"
|
"description": "The link to a page to claim payouts to this pull payment"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"LNURLData": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"lnurlBech32": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Bech32 representation of LNRURL",
|
||||||
|
"example": "lightning:lnurl1dp68gup69uhnzv3h9cczuvpwxyarzdp3xsez7sj5gvh42j2vfe24ynp0wa5hg6rywfshwtmswqhngvntdd6x6uzvx4jrvu2kvvur23n8v46rwjpexcc45563fn53w7"
|
||||||
|
},
|
||||||
|
"lnurlUri": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Bech32 representation of LNURL",
|
||||||
|
"example": "lnurlw://example.com/BTC/UILNURL/withdraw/pp/42kktmpL5d6qVc85Fget7H961ZSQ"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user