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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 8 deletions

View File

@ -1,21 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
using NBitcoin;
namespace BTCPayServer.Client
{
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)
{
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 =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices",
new Dictionary<string, object>() {{nameof(includeArchived), includeArchived}}), token);
queryPayload), token);
return await HandleResponse<IEnumerable<InvoiceData>>(response);
}

View File

@ -951,7 +951,7 @@ namespace BTCPayServer.Tests
});
await user.RegisterDerivationSchemeAsync("BTC");
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
}});
@ -964,6 +964,49 @@ namespace BTCPayServer.Tests
Assert.Single(invoices);
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
var invoice = await viewOnly.GetInvoice(user.StoreId, newInvoice.Id);
Assert.Equal(newInvoice.Metadata, invoice.Metadata);

View File

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

View File

@ -15,6 +15,39 @@
"schema": {
"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",