mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-03 17:36:59 +01:00
GreenField: Update invoice metadata (#2095)
* GreenField: Update invoice metadata * add swagger Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
This commit is contained in:
parent
b1e9c005b7
commit
034b732e7c
6 changed files with 156 additions and 5 deletions
|
@ -54,6 +54,17 @@ namespace BTCPayServer.Client
|
||||||
return await HandleResponse<InvoiceData>(response);
|
return await HandleResponse<InvoiceData>(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual async Task<InvoiceData> UpdateInvoice(string storeId, string invoiceId,
|
||||||
|
UpdateInvoiceRequest request, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
if (request == null)
|
||||||
|
throw new ArgumentNullException(nameof(request));
|
||||||
|
var response = await _httpClient.SendAsync(
|
||||||
|
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}", bodyPayload: request,
|
||||||
|
method: HttpMethod.Put), token);
|
||||||
|
return await HandleResponse<InvoiceData>(response);
|
||||||
|
}
|
||||||
|
|
||||||
public virtual async Task<InvoiceData> MarkInvoiceStatus(string storeId, string invoiceId,
|
public virtual async Task<InvoiceData> MarkInvoiceStatus(string storeId, string invoiceId,
|
||||||
MarkInvoiceStatusRequest request, CancellationToken token = default)
|
MarkInvoiceStatusRequest request, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
|
|
9
BTCPayServer.Client/Models/UpdateInvoiceRequest.cs
Normal file
9
BTCPayServer.Client/Models/UpdateInvoiceRequest.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace BTCPayServer.Client.Models
|
||||||
|
{
|
||||||
|
public class UpdateInvoiceRequest
|
||||||
|
{
|
||||||
|
public JObject Metadata { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -978,7 +978,22 @@ namespace BTCPayServer.Tests
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await AssertHttpError(403, async () =>
|
||||||
|
{
|
||||||
|
await viewOnly.UpdateInvoice(user.StoreId, newInvoice.Id,
|
||||||
|
new UpdateInvoiceRequest()
|
||||||
|
{
|
||||||
|
Metadata = JObject.Parse("{\"itemCode\": \"updated\", newstuff: [1,2,3,4,5]}")
|
||||||
|
});
|
||||||
|
});
|
||||||
|
invoice = await client.UpdateInvoice(user.StoreId, newInvoice.Id,
|
||||||
|
new UpdateInvoiceRequest()
|
||||||
|
{
|
||||||
|
Metadata = JObject.Parse("{\"itemCode\": \"updated\", newstuff: [1,2,3,4,5]}")
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal("updated",invoice.Metadata["itemCode"].Value<string>());
|
||||||
|
Assert.Equal(15,((JArray) invoice.Metadata["newstuff"]).Values<int>().Sum());
|
||||||
//archive
|
//archive
|
||||||
await AssertHttpError(403, async () =>
|
await AssertHttpError(403, async () =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,21 +4,16 @@ using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Models.InvoicingModels;
|
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Security;
|
using BTCPayServer.Security;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Validation;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitpayClient;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using CreateInvoiceRequest = BTCPayServer.Client.Models.CreateInvoiceRequest;
|
using CreateInvoiceRequest = BTCPayServer.Client.Models.CreateInvoiceRequest;
|
||||||
using InvoiceData = BTCPayServer.Client.Models.InvoiceData;
|
using InvoiceData = BTCPayServer.Client.Models.InvoiceData;
|
||||||
|
|
||||||
|
@ -100,6 +95,26 @@ namespace BTCPayServer.Controllers.GreenField
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Policy = Policies.CanModifyStoreSettings,
|
||||||
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
|
[HttpPut("~/api/v1/stores/{storeId}/invoices/{invoiceId}")]
|
||||||
|
public async Task<IActionResult> UpdateInvoice(string storeId, string invoiceId, UpdateInvoiceRequest request)
|
||||||
|
{
|
||||||
|
var store = HttpContext.GetStoreData();
|
||||||
|
if (store == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _invoiceRepository.UpdateInvoiceMetadata(invoiceId, storeId, request.Metadata);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return Ok(ToModel(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
[Authorize(Policy = Policies.CanCreateInvoice,
|
[Authorize(Policy = Policies.CanCreateInvoice,
|
||||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||||
[HttpPost("~/api/v1/stores/{storeId}/invoices")]
|
[HttpPost("~/api/v1/stores/{storeId}/invoices")]
|
||||||
|
|
|
@ -441,6 +441,22 @@ retry:
|
||||||
await context.SaveChangesAsync().ConfigureAwait(false);
|
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async Task<InvoiceEntity> UpdateInvoiceMetadata(string invoiceId, string storeId, JObject metadata)
|
||||||
|
{
|
||||||
|
using (var context = _ContextFactory.CreateContext())
|
||||||
|
{
|
||||||
|
var invoiceData = await GetInvoiceRaw(invoiceId);
|
||||||
|
if (invoiceData == null || (storeId != null &&
|
||||||
|
!invoiceData.StoreDataId.Equals(storeId,
|
||||||
|
StringComparison.InvariantCultureIgnoreCase)))
|
||||||
|
return null;
|
||||||
|
var blob = invoiceData.GetBlob(_Networks);
|
||||||
|
blob.Metadata = InvoiceMetadata.FromJObject(metadata);
|
||||||
|
invoiceData.Blob = ToBytes(blob);
|
||||||
|
await context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
return ToEntity(invoiceData);
|
||||||
|
}
|
||||||
|
}
|
||||||
public async Task<bool> MarkInvoiceStatus(string invoiceId, InvoiceStatus status)
|
public async Task<bool> MarkInvoiceStatus(string invoiceId, InvoiceStatus status)
|
||||||
{
|
{
|
||||||
using (var context = _ContextFactory.CreateContext())
|
using (var context = _ContextFactory.CreateContext())
|
||||||
|
|
|
@ -214,6 +214,80 @@
|
||||||
"Basic": []
|
"Basic": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"tags": [
|
||||||
|
"Invoices"
|
||||||
|
],
|
||||||
|
"summary": "Update invoice",
|
||||||
|
"description": "Updates the specified invoice.",
|
||||||
|
"operationId": "Invoices_UpdateInvoice",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "storeId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"description": "The store the invoice belongs to",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "invoiceId",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"description": "The invoice to update",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "The invoice that has been updated",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/InvoiceData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "A list of errors that occurred when updating the invoice",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ValidationProblemDetails"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"description": "If you are authenticated but forbidden to update the specified invoice"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "The key is not found for this invoice"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/UpdateInvoiceRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"API Key": [
|
||||||
|
"btcpay.store.canmodifystoresettings"
|
||||||
|
],
|
||||||
|
"Basic": []
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods": {
|
"/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods": {
|
||||||
|
@ -628,6 +702,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"UpdateInvoiceRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"metadata": {
|
||||||
|
"type": "object",
|
||||||
|
"nullable": true,
|
||||||
|
"description": "Additional information around the invoice that can be supplied."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"CheckoutOptions": {
|
"CheckoutOptions": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
Loading…
Add table
Reference in a new issue