customized api/v1/invoices query parameters to filter results (#2461)

* customized api/v1/invoices query parameters to filter results

* customized api/v1/invoices query parameters to filter results

* update swagger and make parameters as arrays

* change startDate and endDate types to UnixTimestamp

* update invoice status type in swagger and better handle dateTimeoffset

* change status type to array of InvoiceStatus to match controller

* change status type to array of InvoiceStatus to match controller

Co-authored-by: somera <somera@tesla.com>
This commit is contained in:
Saker Omera
2021-04-25 19:32:44 -07:00
committed by GitHub
parent e0ff03068a
commit ded55a1440
4 changed files with 113 additions and 8 deletions

View File

@@ -1,21 +1,41 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using NBitcoin;
namespace BTCPayServer.Client namespace BTCPayServer.Client
{ {
public partial class BTCPayServerClient public partial class BTCPayServerClient
{ {
public virtual async Task<IEnumerable<InvoiceData>> GetInvoices(string storeId, bool includeArchived = false, public virtual async Task<IEnumerable<InvoiceData>> GetInvoices(string storeId, string orderId = null, InvoiceStatus[] status = null,
long? startDate = null,
long? endDate = null,
bool includeArchived = false,
CancellationToken token = default) CancellationToken token = default)
{ {
Dictionary<string, object> queryPayload = new Dictionary<string, object>();
queryPayload.Add(nameof(includeArchived), includeArchived);
if (startDate != null)
queryPayload.Add(nameof(startDate), startDate);
if (endDate != null)
queryPayload.Add(nameof(endDate), endDate);
if (orderId != null)
queryPayload.Add(nameof(orderId), orderId);
if (status != null)
queryPayload.Add(nameof(status), status.Select(s=> s.ToString().ToLower()).ToArray());
var response = var response =
await _httpClient.SendAsync( await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices", CreateHttpRequest($"api/v1/stores/{storeId}/invoices",
new Dictionary<string, object>() {{nameof(includeArchived), includeArchived}}), token); queryPayload), token);
return await HandleResponse<IEnumerable<InvoiceData>>(response); return await HandleResponse<IEnumerable<InvoiceData>>(response);
} }

View File

@@ -951,7 +951,7 @@ namespace BTCPayServer.Tests
}); });
await user.RegisterDerivationSchemeAsync("BTC"); await user.RegisterDerivationSchemeAsync("BTC");
var newInvoice = await client.CreateInvoice(user.StoreId, var newInvoice = await client.CreateInvoice(user.StoreId,
new CreateInvoiceRequest() { Currency = "USD", Amount = 1, Metadata = JObject.Parse("{\"itemCode\": \"testitem\"}"), Checkout = new CreateInvoiceRequest.CheckoutOptions() new CreateInvoiceRequest() { Currency = "USD", Amount = 1, Metadata = JObject.Parse("{\"itemCode\": \"testitem\", \"orderId\": \"testOrder\"}"), Checkout = new CreateInvoiceRequest.CheckoutOptions()
{ {
RedirectAutomatically = true RedirectAutomatically = true
}}); }});
@@ -964,6 +964,49 @@ namespace BTCPayServer.Tests
Assert.Single(invoices); Assert.Single(invoices);
Assert.Equal(newInvoice.Id, invoices.First().Id); Assert.Equal(newInvoice.Id, invoices.First().Id);
//list Filtered
var invoicesFiltered = await viewOnly.GetInvoices(user.StoreId,
orderId: null, status: null, NBitcoin.Utils.DateTimeToUnixTime(DateTimeOffset.Now.AddHours(-1)),
NBitcoin.Utils.DateTimeToUnixTime(DateTimeOffset.Now.AddHours(1)));
Assert.NotNull(invoicesFiltered);
Assert.Single(invoicesFiltered);
Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id);
//list Yesterday
var invoicesYesterday = await viewOnly.GetInvoices(user.StoreId,
orderId: null, status: null, NBitcoin.Utils.DateTimeToUnixTime(DateTimeOffset.Now.AddDays(-2)),
NBitcoin.Utils.DateTimeToUnixTime(DateTimeOffset.Now.AddDays(-1)));
Assert.NotNull(invoicesYesterday);
Assert.Empty(invoicesYesterday);
//list Existing OrderId
var invoicesExistingOrderId =
await viewOnly.GetInvoices(user.StoreId, orderId: newInvoice.Metadata["orderId"].ToString());
Assert.NotNull(invoicesExistingOrderId);
Assert.Single(invoicesFiltered);
Assert.Equal(newInvoice.Id, invoicesFiltered.First().Id);
//list NonExisting OrderId
var invoicesNonExistingOrderId =
await viewOnly.GetInvoices(user.StoreId, orderId: "NonExistingOrderId");
Assert.NotNull(invoicesNonExistingOrderId);
Assert.Empty(invoicesNonExistingOrderId);
//list Existing Status
var invoicesExistingStatus =
await viewOnly.GetInvoices(user.StoreId, status:new []{newInvoice.Status});
Assert.NotNull(invoicesExistingStatus);
Assert.Single(invoicesExistingStatus);
Assert.Equal(newInvoice.Id, invoicesExistingStatus.First().Id);
//list NonExisting Status
var invoicesNonExistingStatus = await viewOnly.GetInvoices(user.StoreId,
status: new []{BTCPayServer.Client.Models.InvoiceStatus.Invalid});
Assert.NotNull(invoicesNonExistingStatus);
Assert.Empty(invoicesNonExistingStatus);
//get //get
var invoice = await viewOnly.GetInvoice(user.StoreId, newInvoice.Id); var invoice = await viewOnly.GetInvoice(user.StoreId, newInvoice.Id);
Assert.Equal(newInvoice.Metadata, invoice.Metadata); Assert.Equal(newInvoice.Metadata, invoice.Metadata);

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Globalization;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Client; using BTCPayServer.Client;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
@@ -47,7 +48,9 @@ namespace BTCPayServer.Controllers.GreenField
[Authorize(Policy = Policies.CanViewInvoices, [Authorize(Policy = Policies.CanViewInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)] AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/invoices")] [HttpGet("~/api/v1/stores/{storeId}/invoices")]
public async Task<IActionResult> GetInvoices(string storeId, bool includeArchived = false) public async Task<IActionResult> GetInvoices(string storeId, [FromQuery] string[] orderId = null, [FromQuery] string[] status = null,
[FromQuery] long? startDate = null,
[FromQuery] long? endDate = null, [FromQuery] bool includeArchived = false)
{ {
var store = HttpContext.GetStoreData(); var store = HttpContext.GetStoreData();
if (store == null) if (store == null)
@@ -55,17 +58,23 @@ namespace BTCPayServer.Controllers.GreenField
return StoreNotFound(); return StoreNotFound();
} }
DateTimeOffset startDateTimeOffset = Utils.UnixTimeToDateTime(startDate.GetValueOrDefault(DateTimeOffset.MinValue.ToUnixTimeSeconds()));
DateTimeOffset endDateTimeOffset = Utils.UnixTimeToDateTime(endDate.GetValueOrDefault(DateTimeOffset.MaxValue.ToUnixTimeSeconds()));
var invoices = var invoices =
await _invoiceRepository.GetInvoices(new InvoiceQuery() await _invoiceRepository.GetInvoices(new InvoiceQuery()
{ {
StoreId = new[] {store.Id}, StoreId = new[] {store.Id},
IncludeArchived = includeArchived IncludeArchived = includeArchived,
StartDate = startDateTimeOffset,
EndDate = endDateTimeOffset,
OrderId = orderId,
Status = status
}); });
return Ok(invoices.Select(ToModel)); return Ok(invoices.Select(ToModel));
} }
[Authorize(Policy = Policies.CanViewInvoices, [Authorize(Policy = Policies.CanViewInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)] AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/invoices/{invoiceId}")] [HttpGet("~/api/v1/stores/{storeId}/invoices/{invoiceId}")]

View File

@@ -15,6 +15,39 @@
"schema": { "schema": {
"type": "string" "type": "string"
} }
},
{
"name": "orderId",
"in": "query",
"required": false,
"description": "Array of OrderIds to fetch the invoices for",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"name": "status",
"in": "query",
"required": false,
"description": "Array of statuses of invoices to be fetched",
"$ref": "#/components/schemas/InvoiceStatus"
},
{
"name": "startDate",
"in": "query",
"required": false,
"description": "Start date of the period to retrieve invoices",
"$ref": "#/components/schemas/UnixTimestamp"
},
{
"name": "endDate",
"in": "query",
"required": false,
"description": "End date of the period to retrieve invoices",
"$ref": "#/components/schemas/UnixTimestamp"
} }
], ],
"description": "View information about the existing invoices", "description": "View information about the existing invoices",