fix(API): add storeId-less routes for invoices, payment requests, and pull payments (#7313)
What changed, and why it matters
This commit changes several BTCPay Server API endpoints so that callers no longer need to supply a store ID when working with existing invoices, payment requests, and pull payments. The server now looks up the store automatically from the invoice/payment-request/pull-payment record. The old store-scoped routes are kept alongside the new shorter routes. The change is described as a convenience/cleanup fix, not as a security patch, and the diff does not show any new authorization checks being added.
Review the middleware/filters that populate HttpContext.GetInvoiceDataOrNull(), GetPaymentRequestDataOrNull(), and GetPullPaymentDataOrNull() to confirm they enforce store-ownership correctly for both the old and new routes. Re-add or replace the removed cross-store negative tests to ensure a caller with permission on store A cannot access or modify resources belonging to store B via the new storeId-less routes. Consider whether making storeId optional weakens any defense-in-depth assumptions elsewhere.
Security signals we found
API route simplification removes explicit storeId parameter for resource-scoped operations
Authorization still relies on existing resource-level middleware/filters and unchanged policy attributes
No new access-control logic is introduced in the diff
Two negative permission tests that exercised cross-store access were deleted
Client library methods drop storeId arguments, changing caller contract
Evidence from the diff
The patch adds storeId-less routes (e.g., GET /api/v1/invoices/{invoiceId}, DELETE /api/v1/payment-requests/{paymentRequestId}, DELETE /api/v1/pull-payments/{pullPaymentId}) while preserving the original /api/v1/stores/{storeId}/… routes. Controller actions accept a nullable storeId and fall back to HttpContext.GetStoreData().Id when storeId is omitted. The authorization policies remain unchanged, and the invoice/payment-request/pull-payment objects are still loaded through existing middleware/filters that enforce ownership. Tests were updated to use the new routes, and two store-scoped negative tests were removed from GreenfieldAPITests.cs.
Changed components
GreenfieldInvoiceControllerGreenfieldPaymentRequestsControllerGreenfieldPullPaymentControllerBTCPayServerClient.InvoicesBTCPayServerClient.PaymentRequestsBTCPayServerClient.PullPaymentsSwagger templates for invoices, payment-requests, pull-paymentsInspect captured patch +333 / −373
diff --git a/BTCPayServer.Client/BTCPayServerClient.Invoices.cs b/BTCPayServer.Client/BTCPayServerClient.Invoices.cs
index 421181d..1566745 100644
--- a/BTCPayServer.Client/BTCPayServerClient.Invoices.cs
+++ b/BTCPayServer.Client/BTCPayServerClient.Invoices.cs
@@ -41,13 +41,13 @@ public partial class BTCPayServerClient
return await SendHttpRequest<IEnumerable<InvoiceData>>($"api/v1/stores/{storeId}/invoices", queryPayload, HttpMethod.Get, token);
}
- public virtual async Task<InvoiceData> GetInvoice(string storeId, string invoiceId,
- CancellationToken token = default)
+ public virtual async Task<InvoiceData> GetInvoice(string invoiceId, CancellationToken token = default)
{
if (invoiceId == null) throw new ArgumentNullException(nameof(invoiceId));
- return await SendHttpRequest<InvoiceData>($"api/v1/stores/{storeId}/invoices/{invoiceId}", null, HttpMethod.Get, token);
+ return await SendHttpRequest<InvoiceData>($"api/v1/invoices/{invoiceId}", null, HttpMethod.Get, token);
}
- public virtual async Task<InvoicePaymentMethodDataModel[]> GetInvoicePaymentMethods(string storeId, string invoiceId,
+
+ public virtual async Task<InvoicePaymentMethodDataModel[]> GetInvoicePaymentMethods(string invoiceId,
bool onlyAccountedPayments = true, bool includeSensitive = false,
CancellationToken token = default)
{
@@ -56,13 +56,12 @@ public partial class BTCPayServerClient
{ nameof(onlyAccountedPayments), onlyAccountedPayments },
{ nameof(includeSensitive), includeSensitive }
};
- return await SendHttpRequest<InvoicePaymentMethodDataModel[]>($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods", queryPayload, HttpMethod.Get, token);
+ return await SendHttpRequest<InvoicePaymentMethodDataModel[]>($"api/v1/invoices/{invoiceId}/payment-methods", queryPayload, HttpMethod.Get, token);
}
- public virtual async Task ArchiveInvoice(string storeId, string invoiceId,
- CancellationToken token = default)
+ public virtual async Task ArchiveInvoice(string invoiceId, CancellationToken token = default)
{
- await SendHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}", null, HttpMethod.Delete, token);
+ await SendHttpRequest($"api/v1/invoices/{invoiceId}", null, HttpMethod.Delete, token);
}
public virtual async Task<InvoiceData> CreateInvoice(string storeId,
@@ -72,43 +71,43 @@ public partial class BTCPayServerClient
return await SendHttpRequest<InvoiceData>($"api/v1/stores/{storeId}/invoices", request, HttpMethod.Post, token);
}
- public virtual async Task<InvoiceData> UpdateInvoice(string storeId, string invoiceId,
+ public virtual async Task<InvoiceData> UpdateInvoice(string invoiceId,
UpdateInvoiceRequest request, CancellationToken token = default)
{
if (request == null) throw new ArgumentNullException(nameof(request));
- return await SendHttpRequest<InvoiceData>($"api/v1/stores/{storeId}/invoices/{invoiceId}", request, HttpMethod.Put, token);
+ return await SendHttpRequest<InvoiceData>($"api/v1/invoices/{invoiceId}", request, HttpMethod.Put, token);
}
- public virtual async Task<InvoiceData> MarkInvoiceStatus(string storeId, string invoiceId,
+ public virtual async Task<InvoiceData> MarkInvoiceStatus(string invoiceId,
MarkInvoiceStatusRequest request, CancellationToken token = default)
{
if (request == null) throw new ArgumentNullException(nameof(request));
if (request.Status != InvoiceStatus.Settled && request.Status != InvoiceStatus.Invalid) throw new ArgumentOutOfRangeException(nameof(request.Status), "Status can only be Invalid or Complete");
- return await SendHttpRequest<InvoiceData>($"api/v1/stores/{storeId}/invoices/{invoiceId}/status", request, HttpMethod.Post, token);
+ return await SendHttpRequest<InvoiceData>($"api/v1/invoices/{invoiceId}/status", request, HttpMethod.Post, token);
}
- public virtual async Task<InvoiceData> UnarchiveInvoice(string storeId, string invoiceId, CancellationToken token = default)
+ public virtual async Task<InvoiceData> UnarchiveInvoice(string invoiceId, CancellationToken token = default)
{
- return await SendHttpRequest<InvoiceData>($"api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive", null, HttpMethod.Post, token);
+ return await SendHttpRequest<InvoiceData>($"api/v1/invoices/{invoiceId}/unarchive", null, HttpMethod.Post, token);
}
- public virtual async Task ActivateInvoicePaymentMethod(string storeId, string invoiceId, string paymentMethod, CancellationToken token = default)
+ public virtual async Task ActivateInvoicePaymentMethod(string invoiceId, string paymentMethod, CancellationToken token = default)
{
- await SendHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate", null, HttpMethod.Post, token);
+ await SendHttpRequest($"api/v1/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate", null, HttpMethod.Post, token);
}
public virtual async Task<PullPaymentData> RefundInvoice(
- string storeId,
string invoiceId,
RefundInvoiceRequest request,
CancellationToken token = default
)
{
- return await SendHttpRequest<PullPaymentData>($"api/v1/stores/{storeId}/invoices/{invoiceId}/refund", request, HttpMethod.Post, token);
+ return await SendHttpRequest<PullPaymentData>($"api/v1/invoices/{invoiceId}/refund", request, HttpMethod.Post, token);
}
- public virtual async Task<InvoiceRefundTriggerData> GetInvoiceRefundTriggerData(string storeId, string invoiceId, string paymentMethodId,
+
+ public virtual async Task<InvoiceRefundTriggerData> GetInvoiceRefundTriggerData(string invoiceId, string paymentMethodId,
CancellationToken token = default)
{
- return await SendHttpRequest<InvoiceRefundTriggerData>($"api/v1/stores/{storeId}/invoices/{invoiceId}/refund/{paymentMethodId}", null, HttpMethod.Get, token);
+ return await SendHttpRequest<InvoiceRefundTriggerData>($"api/v1/invoices/{invoiceId}/refund/{paymentMethodId}", null, HttpMethod.Get, token);
}
}
diff --git a/BTCPayServer.Client/BTCPayServerClient.PaymentRequests.cs b/BTCPayServer.Client/BTCPayServerClient.PaymentRequests.cs
index b7b0135..a9517ef 100644
--- a/BTCPayServer.Client/BTCPayServerClient.PaymentRequests.cs
+++ b/BTCPayServer.Client/BTCPayServerClient.PaymentRequests.cs
@@ -17,24 +17,23 @@ public partial class BTCPayServerClient
new Dictionary<string, object> { { nameof(includeArchived), includeArchived } }, HttpMethod.Get, token);
}
- public virtual async Task<PaymentRequestBaseData> GetPaymentRequest(string storeId, string paymentRequestId,
+ public virtual async Task<PaymentRequestBaseData> GetPaymentRequest(string paymentRequestId,
CancellationToken token = default)
{
- return await SendHttpRequest<PaymentRequestBaseData>($"api/v1/stores/{storeId}/payment-requests/{paymentRequestId}", null, HttpMethod.Get, token);
+ return await SendHttpRequest<PaymentRequestBaseData>($"api/v1/payment-requests/{paymentRequestId}", null, HttpMethod.Get, token);
}
- public virtual async Task ArchivePaymentRequest(string storeId, string paymentRequestId,
+ public virtual async Task ArchivePaymentRequest(string paymentRequestId,
CancellationToken token = default)
{
- await SendHttpRequest($"api/v1/stores/{storeId}/payment-requests/{paymentRequestId}", null, HttpMethod.Delete, token);
+ await SendHttpRequest($"api/v1/payment-requests/{paymentRequestId}", null, HttpMethod.Delete, token);
}
- public virtual async Task<Client.Models.InvoiceData> PayPaymentRequest(string storeId, string paymentRequestId, PayPaymentRequestRequest request, CancellationToken token = default)
+ public virtual async Task<Client.Models.InvoiceData> PayPaymentRequest(string paymentRequestId, PayPaymentRequestRequest request, CancellationToken token = default)
{
if (request == null) throw new ArgumentNullException(nameof(request));
- if (storeId is null) throw new ArgumentNullException(nameof(storeId));
if (paymentRequestId is null) throw new ArgumentNullException(nameof(paymentRequestId));
- return await SendHttpRequest<InvoiceData>($"api/v1/stores/{storeId}/payment-requests/{paymentRequestId}/pay", request, HttpMethod.Post, token);
+ return await SendHttpRequest<InvoiceData>($"api/v1/payment-requests/{paymentRequestId}/pay", request, HttpMethod.Post, token);
}
public virtual async Task<PaymentRequestBaseData> CreatePaymentRequest(string storeId,
@@ -44,10 +43,10 @@ public partial class BTCPayServerClient
return await SendHttpRequest<PaymentRequestBaseData>($"api/v1/stores/{storeId}/payment-requests", request, HttpMethod.Post, token);
}
- public virtual async Task<PaymentRequestBaseData> UpdatePaymentRequest(string storeId, string paymentRequestId,
+ public virtual async Task<PaymentRequestBaseData> UpdatePaymentRequest(string paymentRequestId,
PaymentRequestBaseData request, CancellationToken token = default)
{
if (request == null) throw new ArgumentNullException(nameof(request));
- return await SendHttpRequest<PaymentRequestBaseData>($"api/v1/stores/{storeId}/payment-requests/{paymentRequestId}", request, HttpMethod.Put, token);
+ return await SendHttpRequest<PaymentRequestBaseData>($"api/v1/payment-requests/{paymentRequestId}", request, HttpMethod.Put, token);
}
}
diff --git a/BTCPayServer.Client/BTCPayServerClient.PullPayments.cs b/BTCPayServer.Client/BTCPayServerClient.PullPayments.cs
index 101adfa..20b95d4 100644
--- a/BTCPayServer.Client/BTCPayServerClient.PullPayments.cs
+++ b/BTCPayServer.Client/BTCPayServerClient.PullPayments.cs
@@ -30,9 +30,9 @@ public partial class BTCPayServerClient
return await SendHttpRequest<PullPaymentData[]>($"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/pull-payments", query, HttpMethod.Get, cancellationToken);
}
- public virtual async Task ArchivePullPayment(string storeId, string pullPaymentId, CancellationToken cancellationToken = default)
+ public virtual async Task ArchivePullPayment(string pullPaymentId, CancellationToken cancellationToken = default)
{
- await SendHttpRequest($"api/v1/stores/{HttpUtility.UrlEncode(storeId)}/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}", null, HttpMethod.Delete, cancellationToken);
+ await SendHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}", null, HttpMethod.Delete, cancellationToken);
}
public virtual async Task<PayoutData[]> GetPayouts(string pullPaymentId, bool includeCancelled = false, CancellationToken cancellationToken = default)
diff --git a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs
index 7f53ede..906d4f4 100644
--- a/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs
+++ b/BTCPayServer.Tests/AltcoinTests/AltcoinTests.cs
@@ -799,7 +799,7 @@ g:
Assert.Equal(0, topupInvoice.Price);
Assert.Equal("new", topupInvoice.Status);
var client = await user.CreateClient();
- var inv = await client.GetInvoice(user.StoreId, topupInvoice.Id);
+ var inv = await client.GetInvoice(topupInvoice.Id);
Assert.Equal(InvoiceType.TopUp, inv.Type);
}
}
diff --git a/BTCPayServer.Tests/GreenfieldAPITests.cs b/BTCPayServer.Tests/GreenfieldAPITests.cs
index daa9d53..e1ce5bd 100644
--- a/BTCPayServer.Tests/GreenfieldAPITests.cs
+++ b/BTCPayServer.Tests/GreenfieldAPITests.cs
@@ -1575,7 +1575,7 @@ namespace BTCPayServer.Tests
async Task<Client.Models.InvoiceData> AssertInvoiceMetadata()
{
TestLogs.LogInformation("Let's check if we can get invoice in the new format with the metadata");
- var newInvoice = await client.GetInvoice(user.StoreId, oldInvoice.Id);
+ var newInvoice = await client.GetInvoice(oldInvoice.Id);
Assert.Equal("posData", newInvoice.Metadata["posData"].Value<string>());
Assert.Equal("code", newInvoice.Metadata["itemCode"].Value<string>());
Assert.Equal("desc", newInvoice.Metadata["itemDesc"].Value<string>());
@@ -1623,7 +1623,7 @@ namespace BTCPayServer.Tests
await user.RegisterDerivationSchemeAsync("BTC");
var client = await user.CreateClient();
var invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest() { Amount = 5000.0m, Currency = "USD" });
- var methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
+ var methods = await client.GetInvoicePaymentMethods(invoice.Id);
var method = methods.First();
var amount = method.Amount;
Assert.Equal(amount, method.Due);
@@ -1633,9 +1633,9 @@ namespace BTCPayServer.Tests
await tester.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(method.Destination, btc), Money.Coins(method.Due) + Money.Coins(1.0m));
await TestUtils.EventuallyAsync(async () =>
{
- invoice = await client.GetInvoice(user.StoreId, invoice.Id);
+ invoice = await client.GetInvoice(invoice.Id);
Assert.True(invoice.Status == InvoiceStatus.Processing);
- methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
+ methods = await client.GetInvoicePaymentMethods(invoice.Id);
method = methods.First();
Assert.Equal(amount, method.Amount);
Assert.Equal(-1.0m, method.Due);
@@ -1660,7 +1660,7 @@ namespace BTCPayServer.Tests
Assert.Equal(TimeSpan.FromDays(1.0), store.RefundBOLT11Expiration);
var invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest() { Amount = 5000.0m, Currency = "USD" });
- var methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
+ var methods = await client.GetInvoicePaymentMethods(invoice.Id);
var method = methods.First();
var amount = method.Amount;
Assert.Equal(amount, method.Due);
@@ -1676,7 +1676,7 @@ namespace BTCPayServer.Tests
// test validation that the invoice exists
await AssertHttpError(404, async () =>
{
- await client.RefundInvoice(user.StoreId, "lol fake invoice id", new RefundInvoiceRequest()
+ await client.RefundInvoice("lol fake invoice id", new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.RateThen
@@ -1684,7 +1684,7 @@ namespace BTCPayServer.Tests
});
// test validation error for when invoice is not yet in the state in which it can be refunded
- var apiError = await AssertAPIError("non-refundable", () => client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ var apiError = await AssertAPIError("non-refundable", () => client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.RateThen
@@ -1693,12 +1693,12 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () =>
{
- invoice = await client.GetInvoice(user.StoreId, invoice.Id);
+ invoice = await client.GetInvoice(invoice.Id);
Assert.True(invoice.Status == InvoiceStatus.Processing);
});
// need to set the status to the one in which we can actually refund the invoice
- await client.MarkInvoiceStatus(user.StoreId, invoice.Id, new MarkInvoiceStatusRequest()
+ await client.MarkInvoiceStatus(invoice.Id, new MarkInvoiceStatusRequest()
{
Status = InvoiceStatus.Settled
});
@@ -1706,7 +1706,7 @@ namespace BTCPayServer.Tests
// test validation for the payment method
var validationError = await AssertValidationError(new[] { "PayoutMethodId" }, async () =>
{
- await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = "fake payment method",
RefundVariant = RefundVariant.RateThen
@@ -1715,7 +1715,7 @@ namespace BTCPayServer.Tests
Assert.Contains("PayoutMethodId: Please select one of the payment methods which were available for the original invoice", validationError.Message);
// test RefundVariant.RateThen
- var pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ var pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.RateThen
@@ -1727,7 +1727,7 @@ namespace BTCPayServer.Tests
Assert.Equal(pp.Name, $"Refund {invoice.Id}");
// test RefundVariant.CurrentRate
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.CurrentRate
@@ -1737,7 +1737,7 @@ namespace BTCPayServer.Tests
Assert.Equal(1, pp.Amount);
// test RefundVariant.Fiat
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.Fiat,
@@ -1751,7 +1751,7 @@ namespace BTCPayServer.Tests
// test RefundVariant.Custom
validationError = await AssertValidationError(new[] { "CustomAmount", "CustomCurrency" }, async () =>
{
- await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.Custom,
@@ -1760,7 +1760,7 @@ namespace BTCPayServer.Tests
Assert.Contains("CustomAmount: Amount must be greater than 0", validationError.Message);
Assert.Contains("CustomCurrency: Invalid currency", validationError.Message);
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.Custom,
@@ -1772,7 +1772,7 @@ namespace BTCPayServer.Tests
Assert.Equal(69420, pp.Amount);
// should auto-approve if currencies match
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest()
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest()
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.Custom,
@@ -1784,7 +1784,7 @@ namespace BTCPayServer.Tests
// test subtract percentage
validationError = await AssertValidationError(new[] { "SubtractPercentage" }, async () =>
{
- await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest
+ await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.RateThen,
@@ -1794,7 +1794,7 @@ namespace BTCPayServer.Tests
Assert.Contains("SubtractPercentage: Percentage must be a numeric value between 0 and 100", validationError.Message);
// should auto-approve
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.RateThen,
@@ -1807,7 +1807,7 @@ namespace BTCPayServer.Tests
// test RefundVariant.OverpaidAmount
validationError = await AssertValidationError(new[] { "RefundVariant" }, async () =>
{
- await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest
+ await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.OverpaidAmount
@@ -1817,16 +1817,16 @@ namespace BTCPayServer.Tests
// should auto-approve
invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest { Amount = 5000.0m, Currency = "USD" });
- methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
+ methods = await client.GetInvoicePaymentMethods(invoice.Id);
method = methods.First();
Assert.Equal(JTokenType.Null, method.AdditionalData["accountDerivation"].Type);
Assert.NotNull(method.AdditionalData["keyPath"]);
- methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id, includeSensitive: true);
+ methods = await client.GetInvoicePaymentMethods(invoice.Id, includeSensitive: true);
method = methods.First();
Assert.Equal(JTokenType.String, method.AdditionalData["accountDerivation"].Type);
var clientViewOnly = await user.CreateClient(Policies.CanViewInvoices);
- await AssertApiError(403, "missing-permission", () => clientViewOnly.GetInvoicePaymentMethods(user.StoreId, invoice.Id, includeSensitive: true));
+ await AssertApiError(403, "missing-permission", () => clientViewOnly.GetInvoicePaymentMethods(invoice.Id, includeSensitive: true));
await tester.WaitForEvent<NewOnChainTransactionEvent>(async () =>
{
@@ -1840,13 +1840,13 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () =>
{
- invoice = await client.GetInvoice(user.StoreId, invoice.Id);
+ invoice = await client.GetInvoice(invoice.Id);
Assert.True(invoice.Status == InvoiceStatus.Settled);
Assert.True(invoice.AdditionalStatus == InvoiceExceptionStatus.PaidOver);
Assert.Equal(10000m, invoice.PaidAmount); // paid twice the amount needed...
});
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.OverpaidAmount
@@ -1856,7 +1856,7 @@ namespace BTCPayServer.Tests
Assert.Equal(method.Due, pp.Amount);
// once more with subtract percentage
- pp = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest
+ pp = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.OverpaidAmount,
@@ -1868,8 +1868,8 @@ namespace BTCPayServer.Tests
// If an invoice doesn't have payment because it has been marked as paid, we should still be able to refund it.
invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest { Amount = 5000.0m, Currency = "USD" });
- await client.MarkInvoiceStatus(user.StoreId, invoice.Id, new MarkInvoiceStatusRequest { Status = InvoiceStatus.Settled });
- var refund = await client.RefundInvoice(user.StoreId, invoice.Id, new RefundInvoiceRequest
+ await client.MarkInvoiceStatus(invoice.Id, new MarkInvoiceStatusRequest { Status = InvoiceStatus.Settled });
+ var refund = await client.RefundInvoice(invoice.Id, new RefundInvoiceRequest
{
PayoutMethodId = method.PaymentMethodId,
RefundVariant = RefundVariant.CurrentRate
@@ -2006,12 +2006,11 @@ namespace BTCPayServer.Tests
//get
- var invoice = await viewOnly.GetInvoice(user.StoreId, newInvoice.Id);
+ var invoice = await viewOnly.GetInvoice(newInvoice.Id);
+
- await AssertEx.AssertApiError("missing-permission", async () => await viewOnly.GetInvoice("some-other-store", newInvoice.Id));
- await AssertEx.AssertApiError("invoice-not-found", async () => await viewOnly.GetInvoice(otherStoreId, newInvoice.Id));
Assert.True(JObject.DeepEquals(newInvoice.Metadata, invoice.Metadata));
- var paymentMethods = await viewOnly.GetInvoicePaymentMethods(user.StoreId, newInvoice.Id);
+ var paymentMethods = await viewOnly.GetInvoicePaymentMethods(newInvoice.Id);
Assert.Single(paymentMethods);
var paymentMethod = paymentMethods.First();
Assert.Equal("BTC-CHAIN", paymentMethod.PaymentMethodId);
@@ -2024,22 +2023,22 @@ namespace BTCPayServer.Tests
new CreateInvoiceRequest { Currency = "USD", Amount = 1 });
Assert.Contains(InvoiceStatus.Settled, newInvoice.AvailableStatusesForManualMarking);
Assert.Contains(InvoiceStatus.Invalid, newInvoice.AvailableStatusesForManualMarking);
- await client.MarkInvoiceStatus(user.StoreId, newInvoice.Id, new MarkInvoiceStatusRequest()
+ await client.MarkInvoiceStatus(newInvoice.Id, new MarkInvoiceStatusRequest()
{
Status = InvoiceStatus.Settled
});
- newInvoice = await client.GetInvoice(user.StoreId, newInvoice.Id);
+ newInvoice = await client.GetInvoice(newInvoice.Id);
Assert.DoesNotContain(InvoiceStatus.Settled, newInvoice.AvailableStatusesForManualMarking);
Assert.Contains(InvoiceStatus.Invalid, newInvoice.AvailableStatusesForManualMarking);
newInvoice = await client.CreateInvoice(user.StoreId,
new CreateInvoiceRequest { Currency = "USD", Amount = 1 });
- await client.MarkInvoiceStatus(user.StoreId, newInvoice.Id, new MarkInvoiceStatusRequest()
+ await client.MarkInvoiceStatus(newInvoice.Id, new MarkInvoiceStatusRequest()
{
Status = InvoiceStatus.Invalid
});
- newInvoice = await client.GetInvoice(user.StoreId, newInvoice.Id);
+ newInvoice = await client.GetInvoice(newInvoice.Id);
const string newOrderId = "UPDATED-ORDER-ID";
JObject metadataForUpdate = JObject.Parse($"{{\"orderId\": \"{newOrderId}\", \"itemCode\": \"updated\", \"newstuff\": [1,2,3,4,5]}}");
@@ -2047,13 +2046,13 @@ namespace BTCPayServer.Tests
Assert.DoesNotContain(InvoiceStatus.Invalid, newInvoice.AvailableStatusesForManualMarking);
await AssertHttpError(403, async () =>
{
- await viewOnly.UpdateInvoice(user.StoreId, invoice.Id,
+ await viewOnly.UpdateInvoice(invoice.Id,
new UpdateInvoiceRequest
{
Metadata = metadataForUpdate
});
});
- invoice = await client.UpdateInvoice(user.StoreId, invoice.Id,
+ invoice = await client.UpdateInvoice(invoice.Id,
new UpdateInvoiceRequest
{
Metadata = metadataForUpdate
@@ -2064,7 +2063,7 @@ namespace BTCPayServer.Tests
Assert.Equal(15, ((JArray)invoice.Metadata["newstuff"]).Values<int>().Sum());
//also test the metadata actually got saved
- invoice = await client.GetInvoice(user.StoreId, invoice.Id);
+ invoice = await client.GetInvoice(invoice.Id);
Assert.Equal(newOrderId, invoice.Metadata["orderId"].Value<string>());
Assert.Equal("updated", invoice.Metadata["itemCode"].Value<string>());
Assert.Equal(15, ((JArray)invoice.Metadata["newstuff"]).Values<int>().Sum());
@@ -2083,27 +2082,27 @@ namespace BTCPayServer.Tests
//archive
await AssertHttpError(403, async () =>
{
- await viewOnly.ArchiveInvoice(user.StoreId, invoice.Id);
+ await viewOnly.ArchiveInvoice(invoice.Id);
});
- await client.ArchiveInvoice(user.StoreId, invoice.Id);
+ await client.ArchiveInvoice(invoice.Id);
Assert.DoesNotContain(invoice.Id,
(await client.GetInvoices(user.StoreId)).Select(data => data.Id));
//unarchive
- await client.UnarchiveInvoice(user.StoreId, invoice.Id);
- Assert.NotNull(await client.GetInvoice(user.StoreId, invoice.Id));
+ await client.UnarchiveInvoice(invoice.Id);
+ Assert.NotNull(await client.GetInvoice(invoice.Id));
foreach (var marked in new[] { InvoiceStatus.Settled, InvoiceStatus.Invalid })
{
var inv = await client.CreateInvoice(user.StoreId,
new CreateInvoiceRequest { Currency = "USD", Amount = 100 });
await user.PayInvoice(inv.Id);
- await client.MarkInvoiceStatus(user.StoreId, inv.Id, new MarkInvoiceStatusRequest
+ await client.MarkInvoiceStatus(inv.Id, new MarkInvoiceStatusRequest
{
Status = marked
});
- var result = await client.GetInvoice(user.StoreId, inv.Id);
+ var result = await client.GetInvoice(inv.Id);
if (marked == InvoiceStatus.Settled)
{
Assert.Equal(InvoiceStatus.Settled, result.Status);
@@ -2186,15 +2185,15 @@ namespace BTCPayServer.Tests
Assert.DoesNotContain(await invoiceRepo.GetMonitoredInvoices(PaymentMethodId.Parse("BTC-CHAIN")), i => i.Id == invoice.Id);
//
- paymentMethods = await client.GetInvoicePaymentMethods(store.Id, invoice.Id);
+ paymentMethods = await client.GetInvoicePaymentMethods(invoice.Id);
Assert.Single(paymentMethods);
Assert.False(paymentMethods.First().Activated);
- await client.ActivateInvoicePaymentMethod(user.StoreId, invoice.Id,
+ await client.ActivateInvoicePaymentMethod(invoice.Id,
paymentMethods.First().PaymentMethodId);
invoiceObject = await client.GetOnChainWalletObject(user.StoreId, "BTC", new OnChainWalletObjectId("invoice", invoice.Id), false);
Assert.Contains(invoiceObject.Links.Select(l => l.Type), t => t == "address");
- paymentMethods = await client.GetInvoicePaymentMethods(store.Id, invoice.Id);
+ paymentMethods = await client.GetInvoicePaymentMethods(invoice.Id);
Assert.Single(paymentMethods);
Assert.True(paymentMethods.First().Activated);
@@ -2264,7 +2263,7 @@ namespace BTCPayServer.Tests
DefaultPaymentMethod = "BTC"
}
});
- var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
+ var pm = Assert.Single(await client.GetInvoicePaymentMethods(invoice.Id));
Assert.Equal(0.0001m, pm.Due);
await tester.WaitForEvent<NewOnChainTransactionEvent>(async () =>
@@ -2276,7 +2275,7 @@ namespace BTCPayServer.Tests
await TestUtils.EventuallyAsync(async () =>
{
- var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
+ var pm = Assert.Single(await client.GetInvoicePaymentMethods(invoice.Id));
Assert.Single(pm.Payments);
Assert.Equal(-0.0001m, pm.Due);
@@ -2285,7 +2284,7 @@ namespace BTCPayServer.Tests
});
// retrieve invoice refund trigger data
- var accounting = await client.GetInvoiceRefundTriggerData(store.Id, invoice.Id, paymentMethod.PaymentMethodId);
+ var accounting = await client.GetInvoiceRefundTriggerData(invoice.Id, paymentMethod.PaymentMethodId);
Assert.NotNull(accounting);
Assert.Equal("BTC", accounting.InvoiceCurrency);
Assert.Equal(0.0002M, accounting.PaymentAmountThen);
@@ -3794,5 +3793,6 @@ clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfi
await AssertValidationError(new[] { "PreferredSource", "currencyPair" }, () =>
clientBasic.PreviewUpdateStoreRateConfiguration(user.StoreId, new StoreRateConfiguration() { IsCustomScript = false, PreferredSource = "coingeckoOOO" }, new[] { "BTCUSDUSDBTC" }));
}
+
}
}
diff --git a/BTCPayServer.Tests/LightningTests.cs b/BTCPayServer.Tests/LightningTests.cs
index d0a6a28..06a433b 100644
--- a/BTCPayServer.Tests/LightningTests.cs
+++ b/BTCPayServer.Tests/LightningTests.cs
@@ -65,7 +65,7 @@ public class LightningTests(ITestOutputHelper testOutputHelper) : UnitTestBase(t
var pm = new InvoicePaymentMethodDataModel[invoices.Length];
for (int i = 0; i < invoices.Length; i++)
{
- pm[i] = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, (await invoices[i]).Id));
+ pm[i] = Assert.Single(await client.GetInvoicePaymentMethods((await invoices[i]).Id));
Assert.True(pm[i].AdditionalData.HasValues);
}
@@ -85,7 +85,7 @@ public class LightningTests(ITestOutputHelper testOutputHelper) : UnitTestBase(t
Assert.NotNull(resp.Details.Preimage);
await TestUtils.EventuallyAsync(async () =>
{
- pm[i] = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, (await invoices[i]).Id));
+ pm[i] = Assert.Single(await client.GetInvoicePaymentMethods((await invoices[i]).Id));
Assert.True(pm[i].AdditionalData.HasValues);
Assert.Equal(resp.Details.PaymentHash.ToString(), ((JObject)pm[i].AdditionalData).GetValue("paymentHash"));
Assert.Equal(resp.Details.Preimage.ToString(), ((JObject)pm[i].AdditionalData).GetValue("preimage"));
diff --git a/BTCPayServer.Tests/POSTests.cs b/BTCPayServer.Tests/POSTests.cs
index 1c40ee2..2a58cc8 100644
--- a/BTCPayServer.Tests/POSTests.cs
+++ b/BTCPayServer.Tests/POSTests.cs
@@ -178,7 +178,7 @@ fruit tea:
await invoiceRepo.UpdateInvoiceExpiry(expiredLatePaidInvoiceId, TimeSpan.Zero);
TestLogs.LogInformation($"Expired late paid invoice ID: {expiredLatePaidInvoiceId}");
- var address = (await client.GetInvoicePaymentMethods(s.StoreId, expiredLatePaidInvoiceId))[0].Destination;
+ var address = (await client.GetInvoicePaymentMethods(expiredLatePaidInvoiceId))[0].Destination;
await s.Server.ExplorerNode.SendToAddressAsync(BitcoinAddress.Create(address, Network.RegTest), Money.Coins(1.0m));
// One 0 amount invoice
@@ -192,11 +192,11 @@ fruit tea:
await s.PayInvoice(amount: 0.4m, mine: false);
await s.PayInvoice(mine: true);
- var expiredLatePaidInvoice = await client.GetInvoice(s.StoreId, expiredLatePaidInvoiceId);
+ var expiredLatePaidInvoice = await client.GetInvoice(expiredLatePaidInvoiceId);
Assert.Equal(InvoiceStatus.Expired, expiredLatePaidInvoice.Status);
Assert.Equal(InvoiceExceptionStatus.PaidLate, expiredLatePaidInvoice.AdditionalStatus);
- var expiredInvoice = await client.GetInvoice(s.StoreId, expiredInvoiceId);
+ var expiredInvoice = await client.GetInvoice(expiredInvoiceId);
Assert.Equal(InvoiceStatus.Expired, expiredInvoice.Status);
Assert.Equal(InvoiceExceptionStatus.None, expiredInvoice.AdditionalStatus);
@@ -207,7 +207,7 @@ fruit tea:
periodicTask.Now = DateTimeOffset.UtcNow.AddMonths(8);
deleted = await periodicTask.RunScript("Invoice Cleanup");
Assert.NotEqual(0, deleted);
- await AssertEx.AssertApiError(404, "invoice-not-found", () => client.GetInvoice(s.StoreId, expiredInvoiceId));
+ await AssertEx.AssertApiError(404, "invoice-not-found", () => client.GetInvoice(expiredInvoiceId));
await s.GoToStore(s.StoreId);
await s.CreateApp("PointOfSale");
@@ -347,7 +347,7 @@ goodies:
Assert.Equal("InvoiceReceipt", redirectToCheckout.ActionName);
var invoiceId = redirectToCheckout.RouteValues!["invoiceId"]!.ToString();
var client = await user.CreateClient();
- var inv = await client.GetInvoice(user.StoreId, invoiceId);
+ var inv = await client.GetInvoice(invoiceId);
Assert.Equal(0, inv.Amount);
Assert.NotEqual(InvoiceType.TopUp, inv.Type);
diff --git a/BTCPayServer.Tests/PaymentRequestTests.cs b/BTCPayServer.Tests/PaymentRequestTests.cs
index c08dbbe..8bdda8e 100644
--- a/BTCPayServer.Tests/PaymentRequestTests.cs
+++ b/BTCPayServer.Tests/PaymentRequestTests.cs
@@ -65,7 +65,7 @@ namespace BTCPayServer.Tests
Assert.Equal(newPaymentRequest.Id, paymentRequests.First().Id);
//get payment request
- var paymentRequest = await viewOnly.GetPaymentRequest(user.StoreId, newPaymentRequest.Id);
+ var paymentRequest = await viewOnly.GetPaymentRequest(newPaymentRequest.Id);
Assert.Equal(newPaymentRequest.Title, paymentRequest.Title);
Assert.Equal(newPaymentRequest.StoreId, user.StoreId);
Assert.Equal(newPaymentRequest.ReferenceId, paymentRequest.ReferenceId);
@@ -76,20 +76,20 @@ namespace BTCPayServer.Tests
updateRequest.ReferenceId = "EmperorNicolasGeneralRockstar";
await AssertEx.AssertHttpError(403, async () =>
{
- await viewOnly.UpdatePaymentRequest(user.StoreId, paymentRequest.Id, updateRequest);
+ await viewOnly.UpdatePaymentRequest(paymentRequest.Id, updateRequest);
});
- await client.UpdatePaymentRequest(user.StoreId, paymentRequest.Id, updateRequest);
- paymentRequest = await client.GetPaymentRequest(user.StoreId, newPaymentRequest.Id);
+ await client.UpdatePaymentRequest(paymentRequest.Id, updateRequest);
+ paymentRequest = await client.GetPaymentRequest(newPaymentRequest.Id);
Assert.Equal(updateRequest.Title, paymentRequest.Title);
Assert.Equal(updateRequest.ReferenceId, paymentRequest.ReferenceId);
//archive payment request
await AssertEx.AssertHttpError(403, async () =>
{
- await viewOnly.ArchivePaymentRequest(user.StoreId, paymentRequest.Id);
+ await viewOnly.ArchivePaymentRequest(paymentRequest.Id);
});
- await client.ArchivePaymentRequest(user.StoreId, paymentRequest.Id);
+ await client.ArchivePaymentRequest(paymentRequest.Id);
Assert.DoesNotContain(paymentRequest.Id,
(await client.GetPaymentRequests(user.StoreId)).Select(data => data.Id));
var archivedPrId = paymentRequest.Id;
@@ -116,14 +116,14 @@ namespace BTCPayServer.Tests
{
Assert.Equal(Invoice.STATUS_PAID, (await user.BitPay.GetInvoiceAsync(invoiceId2)).Status);
if (!partialPayment)
- Assert.Equal(PaymentRequestStatus.Processing, (await client.GetPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id)).Status);
+ Assert.Equal(PaymentRequestStatus.Processing, (await client.GetPaymentRequest(paymentTestPaymentRequest.Id)).Status);
});
await tester.ExplorerNode.GenerateAsync(1);
await TestUtils.EventuallyAsync(async () =>
{
Assert.Equal(Invoice.STATUS_COMPLETE, (await user.BitPay.GetInvoiceAsync(invoiceId2)).Status);
if (!partialPayment)
- Assert.Equal(PaymentRequestStatus.Completed, (await client.GetPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id)).Status);
+ Assert.Equal(PaymentRequestStatus.Completed, (await client.GetPaymentRequest(paymentTestPaymentRequest.Id)).Status);
});
}
await Pay(invoiceId);
@@ -132,11 +132,11 @@ namespace BTCPayServer.Tests
paymentTestPaymentRequest = await client.CreatePaymentRequest(user.StoreId,
new() { Amount = 0.1m, Currency = "BTC", Title = "Payment test title" });
var paidPrId = paymentTestPaymentRequest.Id;
- var invoiceData = await client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest());
+ var invoiceData = await client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest());
await Pay(invoiceData.Id);
// Can't update the amount once the invoice has been created
- await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.UpdatePaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new()
+ await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.UpdatePaymentRequest(paymentTestPaymentRequest.Id, new()
{
Amount = 294m
}));
@@ -144,22 +144,22 @@ namespace BTCPayServer.Tests
// Let's tests some unhappy path
paymentTestPaymentRequest = await client.CreatePaymentRequest(user.StoreId,
new() { Amount = 0.1m, AllowCustomPaymentAmounts = false, Currency = "BTC", Title = "Payment test title" });
- await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = -0.04m }));
- await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = 0.04m }));
- await client.UpdatePaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new()
+ await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = -0.04m }));
+ await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = 0.04m }));
+ await client.UpdatePaymentRequest(paymentTestPaymentRequest.Id, new()
{
Amount = 0.1m,
AllowCustomPaymentAmounts = true,
Currency = "BTC",
Title = "Payment test title"
});
- await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = -0.04m }));
- invoiceData = await client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = 0.04m });
+ await AssertEx.AssertValidationError(new[] { "Amount" }, () => client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = -0.04m }));
+ invoiceData = await client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { Amount = 0.04m });
Assert.Equal(0.04m, invoiceData.Amount);
var firstPaymentId = invoiceData.Id;
- await AssertEx.AssertApiError("archived", () => client.PayPaymentRequest(user.StoreId, archivedPrId, new PayPaymentRequestRequest()));
+ await AssertEx.AssertApiError("archived", () => client.PayPaymentRequest(archivedPrId, new PayPaymentRequestRequest()));
- await client.UpdatePaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new()
+ await client.UpdatePaymentRequest(paymentTestPaymentRequest.Id, new()
{
Amount = 0.1m,
AllowCustomPaymentAmounts = true,
@@ -168,10 +168,10 @@ namespace BTCPayServer.Tests
ExpiryDate = DateTimeOffset.UtcNow - TimeSpan.FromDays(1.0)
});
- await AssertEx.AssertApiError("expired", () => client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest()));
- await AssertEx.AssertApiError("already-paid", () => client.PayPaymentRequest(user.StoreId, paidPrId, new PayPaymentRequestRequest()));
+ await AssertEx.AssertApiError("expired", () => client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest()));
+ await AssertEx.AssertApiError("already-paid", () => client.PayPaymentRequest(paidPrId, new PayPaymentRequestRequest()));
- await client.UpdatePaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new()
+ await client.UpdatePaymentRequest(paymentTestPaymentRequest.Id, new()
{
Amount = 0.1m,
AllowCustomPaymentAmounts = true,
@@ -181,17 +181,17 @@ namespace BTCPayServer.Tests
});
await Pay(firstPaymentId, true);
- invoiceData = await client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest());
+ invoiceData = await client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest());
Assert.Equal(0.06m, invoiceData.Amount);
Assert.Equal("BTC", invoiceData.Currency);
var expectedInvoiceId = invoiceData.Id;
- invoiceData = await client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { AllowPendingInvoiceReuse = true });
+ invoiceData = await client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { AllowPendingInvoiceReuse = true });
Assert.Equal(expectedInvoiceId, invoiceData.Id);
var notExpectedInvoiceId = invoiceData.Id;
- invoiceData = await client.PayPaymentRequest(user.StoreId, paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { AllowPendingInvoiceReuse = false });
+ invoiceData = await client.PayPaymentRequest(paymentTestPaymentRequest.Id, new PayPaymentRequestRequest() { AllowPendingInvoiceReuse = false });
Assert.NotEqual(notExpectedInvoiceId, invoiceData.Id);
}
diff --git a/BTCPayServer.Tests/PlaywrightTester.cs b/BTCPayServer.Tests/PlaywrightTester.cs
index 04d870b..f95623f 100644
--- a/BTCPayServer.Tests/PlaywrightTester.cs
+++ b/BTCPayServer.Tests/PlaywrightTester.cs
@@ -832,7 +832,7 @@ namespace BTCPayServer.Tests
{
var txId = Regex.Replace(Page.Url, ".*/(.*)$", "$1");
var client = await this.AsTestAccount().CreateClient();
- await client.MarkInvoiceStatus(StoreId, txId, new() { Status = InvoiceStatus.Settled });
+ await client.MarkInvoiceStatus(txId, new() { Status = InvoiceStatus.Settled });
}
public WalletTransactionsPMO InWalletTransactions() => new WalletTransactionsPMO(this);
diff --git a/BTCPayServer.Tests/PlaywrightTests.cs b/BTCPayServer.Tests/PlaywrightTests.cs
index 72d4d67..a352801 100644
--- a/BTCPayServer.Tests/PlaywrightTests.cs
+++ b/BTCPayServer.Tests/PlaywrightTests.cs
@@ -402,7 +402,7 @@ namespace BTCPayServer.Tests
});
var greenfield = await s.AsTestAccount().CreateClient();
- var paymentMethods = await greenfield.GetInvoicePaymentMethods(s.StoreId, i);
+ var paymentMethods = await greenfield.GetInvoicePaymentMethods(i);
var lnurlMethod = Assert.Single(paymentMethods, p => p.PaymentMethodId == "BTC-LNURL");
Assert.Equal("lol2", lnurlMethod.AdditionalData["providedComment"]!.Value<string>());
// Standard invoice test
@@ -456,7 +456,7 @@ namespace BTCPayServer.Tests
i = await s.CreateInvoice(storeId, null, cryptoCode);
await s.GoToInvoiceCheckout(i);
await AssertBolt11();
- paymentMethods = await greenfield.GetInvoicePaymentMethods(storeId, i);
+ paymentMethods = await greenfield.GetInvoicePaymentMethods(i);
lnurlMethod = Assert.Single(paymentMethods, p => p.PaymentMethodId == "BTC-LNURL");
var lnurl = lnurlMethod.PaymentLink.Replace("lightning:", "", StringComparison.OrdinalIgnoreCase);
Assert.StartsWith("lnurlp", lnurl);
@@ -472,7 +472,7 @@ namespace BTCPayServer.Tests
var invForPP = await s.CreateInvoice(null, cryptoCode);
await s.GoToInvoiceCheckout(invForPP);
await AssertBolt11();
- paymentMethods = await greenfield.GetInvoicePaymentMethods(newStoreId, invForPP);
+ paymentMethods = await greenfield.GetInvoicePaymentMethods(invForPP);
lnurlMethod = Assert.Single(paymentMethods, p => p.PaymentMethodId == "BTC-LNURL");
lnurl = lnurlMethod.PaymentLink.Replace("lightning:", "", StringComparison.OrdinalIgnoreCase);
Assert.NotNull(lnurl);
diff --git a/BTCPayServer.Tests/PullPaymentsTests.cs b/BTCPayServer.Tests/PullPaymentsTests.cs
index 9d92ed1..10de638 100644
--- a/BTCPayServer.Tests/PullPaymentsTests.cs
+++ b/BTCPayServer.Tests/PullPaymentsTests.cs
@@ -537,7 +537,7 @@ public class PullPaymentsTests(ITestOutputHelper helper) : UnitTestBase(helper)
Amount = 0.5m,
Currency = "BTC",
}, controller.HttpContext.GetStoreData(), controller.Url.Link(null, null)!, [PullPaymentHostedService.GetInternalTag(pp.Id)]);
- await client.MarkInvoiceStatus(user.StoreId, invoice.Id, new() { Status = InvoiceStatus.Settled });
+ await client.MarkInvoiceStatus(invoice.Id, new() { Status = InvoiceStatus.Settled });
await TestUtils.EventuallyAsync(async () =>
{
@@ -685,12 +685,9 @@ public class PullPaymentsTests(ITestOutputHelper helper) : UnitTestBase(helper)
});
Assert.Equal(TimeSpan.FromDays(31.0), test2.BOLT11Expiration);
- TestLogs.LogInformation("Can't archive without knowing the walletId");
- var ex = await AssertEx.AssertApiError("missing-permission", async () => await client.ArchivePullPayment("lol", result.Id));
- Assert.Equal("btcpay.store.canarchivepullpayments", ((GreenfieldPermissionAPIError)ex.APIError).MissingPermission);
TestLogs.LogInformation("Can't archive without permission");
- await AssertEx.AssertApiError("unauthenticated", async () => await unauthenticated.ArchivePullPayment(storeId, result.Id));
- await client.ArchivePullPayment(storeId, result.Id);
+ await AssertEx.AssertApiError("unauthenticated", async () => await unauthenticated.ArchivePullPayment(result.Id));
+ await client.ArchivePullPayment(result.Id);
result = await unauthenticated.GetPullPayment(result.Id);
Assert.Equal(TimeSpan.FromDays(30.0), result.BOLT11Expiration);
Assert.True(result.Archived);
diff --git a/BTCPayServer.Tests/SubscriptionTests.cs b/BTCPayServer.Tests/SubscriptionTests.cs
index b2b0e05..ccb548a 100644
--- a/BTCPayServer.Tests/SubscriptionTests.cs
+++ b/BTCPayServer.Tests/SubscriptionTests.cs
@@ -498,7 +498,7 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
await AssertEx.AssertApiError(400, "invoice-creation-error", () => client.ProceedPlanCheckout(planCheckout.Id));
await user.RegisterDerivationSchemeAsync("BTC", importKeysToNBX: true);
planCheckout = await client.ProceedPlanCheckout(planCheckout.Id);
- var invoice = await client.GetInvoice(user.StoreId, planCheckout.InvoiceId);
+ var invoice = await client.GetInvoice(planCheckout.InvoiceId);
Assert.NotNull(invoice);
Assert.Equal("test@gmail.com", invoice.Metadata["buyerEmail"]?.ToString());
Assert.Equal("invtest", invoice.Metadata["inv"]?.ToString());
@@ -509,7 +509,7 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
var oldInvoiceId = invoice.Id;
planCheckout = await client.ProceedPlanCheckout(planCheckout.Id);
Assert.Equal(oldInvoiceId, planCheckout.InvoiceId);
- invoice = await client.GetInvoice(user.StoreId, planCheckout.InvoiceId);
+ invoice = await client.GetInvoice(planCheckout.InvoiceId);
Assert.Null(planCheckout.Subscriber);
await s.ExplorerNode.GenerateAsync(1);
@@ -786,7 +786,7 @@ public class SubscriptionTests(ITestOutputHelper testOutputHelper) : UnitTestBas
Assert.Equal("basic2@example.com", invoice.Metadata["buyerEmail"]?.ToString());
var waiting = offering.WaitEvent<SubscriptionEvent.SubscriberDisabled>();
- await api.MarkInvoiceStatus(storeId, invoiceId, new()
+ await api.MarkInvoiceStatus(invoiceId, new()
{
Status = InvoiceStatus.Invalid
});
diff --git a/BTCPayServer.Tests/TestAccount.cs b/BTCPayServer.Tests/TestAccount.cs
index aeb9e5d..a22a344 100644
--- a/BTCPayServer.Tests/TestAccount.cs
+++ b/BTCPayServer.Tests/TestAccount.cs
@@ -575,7 +575,7 @@ retry:
var cryptoCode = "BTC";
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId(cryptoCode);
var client = await CreateClient();
- var methods = await client.GetInvoicePaymentMethods(StoreId, invoiceId);
+ var methods = await client.GetInvoicePaymentMethods(invoiceId);
var method = methods.First(m => m.PaymentMethodId == pmi.ToString());
var address = method.Destination;
var tx = await client.CreateOnChainTransaction(StoreId, cryptoCode, new CreateOnChainTransactionRequest()
@@ -598,7 +598,7 @@ retry:
{
var cryptoCode = "BTC";
var client = await CreateClient();
- var methods = await client.GetInvoicePaymentMethods(StoreId, invoiceId);
+ var methods = await client.GetInvoicePaymentMethods(invoiceId);
var method = methods.First(m => m.PaymentMethodId == $"{cryptoCode}-LN");
var bolt11 = method.Destination;
await parent.CustomerLightningD.Pay(bolt11);
@@ -610,7 +610,7 @@ retry:
var cryptoCode = "BTC";
var network = SupportedNetwork.NBitcoinNetwork;
var client = await CreateClient();
- var methods = await client.GetInvoicePaymentMethods(StoreId, invoiceId);
+ var methods = await client.GetInvoicePaymentMethods(invoiceId);
var method = methods.First(m => m.PaymentMethodId == $"{cryptoCode}-LNURL");
var lnurL = LNURL.LNURL.Parse(method.PaymentLink, out var tag);
var http = new HttpClient();
@@ -626,7 +626,7 @@ retry:
return TestUtils.EventuallyAsync(async () =>
{
var client = await CreateClient();
- var invoice = await client.GetInvoice(StoreId, invoiceId);
+ var invoice = await client.GetInvoice(invoiceId);
if (invoice.Status == InvoiceStatus.Settled)
return;
Assert.Equal(InvoiceStatus.Processing, invoice.Status);
diff --git a/BTCPayServer.Tests/UnitTest1.cs b/BTCPayServer.Tests/UnitTest1.cs
index 6900b59..b6c4694 100644
--- a/BTCPayServer.Tests/UnitTest1.cs
+++ b/BTCPayServer.Tests/UnitTest1.cs
@@ -857,7 +857,7 @@ namespace BTCPayServer.Tests
});
Assert.Equal(0m, invoice.Amount);
Assert.Equal(InvoiceType.TopUp, invoice.Type);
- var btcmethod = (await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id))[0];
+ var btcmethod = (await client.GetInvoicePaymentMethods(invoice.Id))[0];
var paid = btcSent;
var invoiceAddress = BitcoinAddress.Create(btcmethod.Destination, cashCow.Network);
var btc = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
@@ -1061,7 +1061,7 @@ namespace BTCPayServer.Tests
await tester.GenerateWallet();
var invoiceId = await tester.CreateInvoice(currency: "JPY", amount: 700000m);
var client = await tester.AsTestAccount().CreateClient();
- var paymentMethods = await client.GetInvoicePaymentMethods(tester.StoreId, invoiceId);
+ var paymentMethods = await client.GetInvoicePaymentMethods(invoiceId);
Assert.Equal(1.0m, paymentMethods[0].Amount);
// The fallback doesn't support JPY anymore
@@ -1208,7 +1208,7 @@ namespace BTCPayServer.Tests
var controller = user.GetController<UIInvoiceController>();
await controller.CreateInvoice();
(await controller.CreateInvoice(new CreateInvoiceModel(), default)).AssertType<RedirectToActionResult>();
- invoice = await client.GetInvoice(user.StoreId, controller.CreatedInvoiceId);
+ invoice = await client.GetInvoice(controller.CreatedInvoiceId);
Assert.Equal("EUR", invoice.Currency);
Assert.Equal(InvoiceType.TopUp, invoice.Type);
@@ -1605,11 +1605,11 @@ namespace BTCPayServer.Tests
Assert.Equal(InvoiceStatus.New, zeroInvoice.Status);
await TestUtils.EventuallyAsync(async () =>
{
- zeroInvoice = await greenfield.GetInvoice(user.StoreId, zeroInvoice.Id);
+ zeroInvoice = await greenfield.GetInvoice(zeroInvoice.Id);
Assert.Equal(InvoiceStatus.Settled, zeroInvoice.Status);
});
- var zeroInvoicePM = await greenfield.GetInvoicePaymentMethods(user.StoreId, zeroInvoice.Id);
+ var zeroInvoicePM = await greenfield.GetInvoicePaymentMethods(zeroInvoice.Id);
Assert.Empty(zeroInvoicePM);
var invoice6 = await btcpayClient.CreateInvoice(user.StoreId,
@@ -2884,8 +2884,8 @@ namespace BTCPayServer.Tests
{
var inv = await client.CreateInvoice(acc.StoreId, new CreateInvoiceRequest() { Amount = 10m, Currency = "USD" });
await acc.PayInvoice(inv.Id);
- await client.MarkInvoiceStatus(acc.StoreId, inv.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Settled });
- var refund = await client.RefundInvoice(acc.StoreId, inv.Id, new RefundInvoiceRequest() { RefundVariant = RefundVariant.Fiat, PayoutMethodId = "BTC-CHAIN" });
+ await client.MarkInvoiceStatus(inv.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Settled });
+ var refund = await client.RefundInvoice(inv.Id, new RefundInvoiceRequest() { RefundVariant = RefundVariant.Fiat, PayoutMethodId = "BTC-CHAIN" });
async Task AssertData(string currency, decimal awaiting, decimal limit, decimal completed, bool fullyPaid)
{
diff --git a/BTCPayServer.Tests/WebhooksTests.cs b/BTCPayServer.Tests/WebhooksTests.cs
index c09aef3..01c02d8 100644
--- a/BTCPayServer.Tests/WebhooksTests.cs
+++ b/BTCPayServer.Tests/WebhooksTests.cs
@@ -173,7 +173,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
await tester.PayTester.InvoiceRepository.UpdateInvoiceExpiry(invoicePaidAfterExpiration.Id, TimeSpan.FromSeconds(0));
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceExpired, (WebhookInvoiceEvent x) => Assert.Equal(invoicePaidAfterExpiration.Id, x.InvoiceId));
- var inv = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoicePaidAfterExpiration.Id)).Single(model =>
+ var inv = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(invoicePaidAfterExpiration.Id)).Single(model =>
PaymentMethodId.Parse(model.PaymentMethodId) ==
PaymentTypes.CHAIN.GetPaymentMethodId("BTC"))
.PaymentLink, tester.ExplorerNode.Network);
@@ -194,7 +194,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
});
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceCreated, (WebhookInvoiceEvent x) => Assert.Equal(invoiceExpiredPartial.Id, x.InvoiceId));
- inv = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoiceExpiredPartial.Id)).Single(model =>
+ inv = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(invoiceExpiredPartial.Id)).Single(model =>
PaymentMethodId.Parse(model.PaymentMethodId) ==
PaymentTypes.CHAIN.GetPaymentMethodId("BTC"))
.PaymentLink, tester.ExplorerNode.Network);
@@ -238,7 +238,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
Currency = "BTC"
});
- var invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)).Single(model =>
+ var invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(invoice.Id)).Single(model =>
PaymentMethodId.Parse(model.PaymentMethodId) ==
PaymentTypes.CHAIN.GetPaymentMethodId("BTC"))
.PaymentLink, tester.ExplorerNode.Network);
@@ -251,7 +251,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
Assert.Equal(invoice.Id, x.InvoiceId);
Assert.Contains(halfPaymentTx.ToString(), x.Payment.Id);
});
- invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)).Single(model =>
+ invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(invoice.Id)).Single(model =>
PaymentMethodId.Parse(model.PaymentMethodId) ==
PaymentTypes.CHAIN.GetPaymentMethodId("BTC"))
.PaymentLink, tester.ExplorerNode.Network);
@@ -285,7 +285,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
Amount = 0.01m,
Currency = "BTC",
});
- invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)).Single(model =>
+ invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(invoice.Id)).Single(model =>
PaymentMethodId.Parse(model.PaymentMethodId) ==
PaymentTypes.CHAIN.GetPaymentMethodId("BTC"))
.PaymentLink, tester.ExplorerNode.Network);
@@ -307,7 +307,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
});
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceCreated, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
- await client.MarkInvoiceStatus(user.StoreId, invoice.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Invalid});
+ await client.MarkInvoiceStatus(invoice.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Invalid});
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceInvalid, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
//payment request webhook test
@@ -323,7 +323,7 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
Description = "lala baba"
});
await user.AssertHasWebhookEvent(WebhookEventType.PaymentRequestCreated, (WebhookPaymentRequestEvent x)=> Assert.Equal(pr.Id, x.PaymentRequestId));
- pr = await client.UpdatePaymentRequest(user.StoreId, pr.Id,
+ pr = await client.UpdatePaymentRequest(pr.Id,
new() { Title = "test pr updated", Amount = 100m,
Currency = "USD",
//TODO: this is a bug, we should not have these props in create request
@@ -332,15 +332,15 @@ public class WebhooksTests(ITestOutputHelper log) : UnitTestBase(log)
//END todo
Description = "lala baba"});
await user.AssertHasWebhookEvent(WebhookEventType.PaymentRequestUpdated, (WebhookPaymentRequestEvent x)=> Assert.Equal(pr.Id, x.PaymentRequestId));
- var inv = await client.PayPaymentRequest(user.StoreId, pr.Id, new PayPaymentRequestRequest());
+ var inv = await client.PayPaymentRequest(pr.Id, new PayPaymentRequestRequest());
- await client.MarkInvoiceStatus(user.StoreId, inv.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Settled});
+ await client.MarkInvoiceStatus(inv.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Settled});
await user.AssertHasWebhookEvent(WebhookEventType.PaymentRequestStatusChanged, (WebhookPaymentRequestEvent x)=>
{
Assert.Equal(PaymentRequestStatus.Completed, x.Status);
Assert.Equal(pr.Id, x.PaymentRequestId);
});
- await client.ArchivePaymentRequest(user.StoreId, pr.Id);
+ await client.ArchivePaymentRequest(pr.Id);
await user.AssertHasWebhookEvent(WebhookEventType.PaymentRequestArchived, (WebhookPaymentRequestEvent x)=> Assert.Equal(pr.Id, x.PaymentRequestId));
//payoyt webhooks test
var payout = await client.CreatePayout(user.StoreId,
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs
index 1468df6..2cdc1a9 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldInvoiceController.cs
@@ -128,7 +128,8 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanViewInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/invoices/{invoiceId}")]
- public async Task<IActionResult> GetInvoice(string storeId, string invoiceId)
+ [HttpGet("~/api/v1/invoices/{invoiceId}")]
+ public async Task<IActionResult> GetInvoice(string? storeId, string invoiceId)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
if (invoice is null)
@@ -139,23 +140,25 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanModifyInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpDelete("~/api/v1/stores/{storeId}/invoices/{invoiceId}")]
- public async Task<IActionResult> ArchiveInvoice(string storeId, string invoiceId)
+ [HttpDelete("~/api/v1/invoices/{invoiceId}")]
+ public async Task<IActionResult> ArchiveInvoice(string? storeId, string invoiceId)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
if (invoice is null)
return InvoiceNotFound();
- await _invoiceRepository.ToggleInvoiceArchival(invoiceId, true, storeId);
+ await _invoiceRepository.ToggleInvoiceArchival(invoiceId, true, storeId ?? HttpContext.GetStoreData().Id);
return Ok();
}
[Authorize(Policy = Policies.CanModifyInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPut("~/api/v1/stores/{storeId}/invoices/{invoiceId}")]
- public async Task<IActionResult> UpdateInvoice(string storeId, string invoiceId, UpdateInvoiceRequest request)
+ [HttpPut("~/api/v1/invoices/{invoiceId}")]
+ public async Task<IActionResult> UpdateInvoice(string? storeId, string invoiceId, UpdateInvoiceRequest request)
{
if (HttpContext.GetInvoiceDataOrNull() is null)
return InvoiceNotFound();
- var invoice = await _invoiceRepository.UpdateInvoiceMetadata(invoiceId, storeId, request.Metadata);
+ var invoice = await _invoiceRepository.UpdateInvoiceMetadata(invoiceId, storeId ?? HttpContext.GetStoreData().Id, request.Metadata);
return Ok(ToModel(invoice));
}
@@ -235,7 +238,8 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanModifyInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/invoices/{invoiceId}/status")]
- public async Task<IActionResult> MarkInvoiceStatus(string storeId, string invoiceId,
+ [HttpPost("~/api/v1/invoices/{invoiceId}/status")]
+ public async Task<IActionResult> MarkInvoiceStatus(string? storeId, string invoiceId,
MarkInvoiceStatusRequest request)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
@@ -257,7 +261,8 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanModifyInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive")]
- public async Task<IActionResult> UnarchiveInvoice(string storeId, string invoiceId)
+ [HttpPost("~/api/v1/invoices/{invoiceId}/unarchive")]
+ public async Task<IActionResult> UnarchiveInvoice(string? storeId, string invoiceId)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
if (invoice is null)
@@ -272,14 +277,15 @@ namespace BTCPayServer.Controllers.Greenfield
if (!ModelState.IsValid)
return this.CreateValidationError(ModelState);
- await _invoiceRepository.ToggleInvoiceArchival(invoiceId, false, storeId);
+ await _invoiceRepository.ToggleInvoiceArchival(invoiceId, false, storeId ?? HttpContext.GetStoreData().Id);
return await GetInvoice(storeId, invoiceId);
}
[Authorize(Policy = Policies.CanViewInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods")]
- public async Task<IActionResult> GetInvoicePaymentMethods(string storeId, string invoiceId, bool onlyAccountedPayments = true, bool includeSensitive = false)
+ [HttpGet("~/api/v1/invoices/{invoiceId}/payment-methods")]
+ public async Task<IActionResult> GetInvoicePaymentMethods(string? storeId, string invoiceId, bool onlyAccountedPayments = true, bool includeSensitive = false)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
if (invoice is null)
@@ -294,7 +300,8 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanViewInvoices,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate")]
- public async Task<IActionResult> ActivateInvoicePaymentMethod(string storeId, string invoiceId, string paymentMethod)
+ [HttpPost("~/api/v1/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate")]
+ public async Task<IActionResult> ActivateInvoicePaymentMethod(string? storeId, string invoiceId, string paymentMethod)
{
if (HttpContext.GetInvoiceDataOrNull() is null)
return InvoiceNotFound();
@@ -310,17 +317,19 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanCreateNonApprovedPullPayments,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/invoices/{invoiceId}/refund")]
+ [HttpPost("~/api/v1/invoices/{invoiceId}/refund")]
public async Task<IActionResult> RefundInvoice(
- string storeId,
+ string? storeId,
string invoiceId,
RefundInvoiceRequest request,
CancellationToken cancellationToken = default
)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
- var store = HttpContext.GetStoreData();
if (invoice is null)
return InvoiceNotFound();
+ var store = HttpContext.GetStoreData();
+ storeId ??= store.Id;
if (!invoice.GetInvoiceState().CanRefund())
return this.CreateAPIError("non-refundable", "Cannot refund this invoice");
@@ -486,7 +495,8 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanCreateNonApprovedPullPayments,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/invoices/{invoiceId}/refund/{paymentMethodId}")]
- public async Task<IActionResult> GetInvoiceRefundTriggerData(string storeId, string invoiceId, string paymentMethodId, CancellationToken cancellationToken)
+ [HttpGet("~/api/v1/invoices/{invoiceId}/refund/{paymentMethodId}")]
+ public async Task<IActionResult> GetInvoiceRefundTriggerData(string? storeId, string invoiceId, string paymentMethodId, CancellationToken cancellationToken)
{
var invoice = HttpContext.GetInvoiceDataOrNull();
if (invoice is null)
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs
index c4d38e6..7ca8ba0 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs
@@ -58,8 +58,9 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanViewPaymentRequests, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}")]
- public async Task<IActionResult> GetPaymentRequest(string storeId, string paymentRequestId)
- {
+ [HttpGet("~/api/v1/payment-requests/{paymentRequestId}")]
+ public async Task<IActionResult> GetPaymentRequest(string? storeId, string paymentRequestId)
+ {
var pr = HttpContext.GetPaymentRequestDataOrNull();
if (pr is null)
@@ -70,7 +71,8 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanViewPaymentRequests, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}/pay")]
- public async Task<IActionResult> PayPaymentRequest(string storeId, string paymentRequestId, [FromBody] PayPaymentRequestRequest pay, CancellationToken cancellationToken)
+ [HttpPost("~/api/v1/payment-requests/{paymentRequestId}/pay")]
+ public async Task<IActionResult> PayPaymentRequest(string? storeId, string paymentRequestId, [FromBody] PayPaymentRequestRequest pay, CancellationToken cancellationToken)
{
var p = HttpContext.GetPaymentRequestDataOrNull();
if (p is null)
@@ -129,11 +131,12 @@ namespace BTCPayServer.Controllers.Greenfield
[Authorize(Policy = Policies.CanModifyPaymentRequests,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpDelete("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}")]
- public async Task<IActionResult> ArchivePaymentRequest(string storeId, string paymentRequestId)
+ [HttpDelete("~/api/v1/payment-requests/{paymentRequestId}")]
+ public async Task<IActionResult> ArchivePaymentRequest(string? storeId, string paymentRequestId)
{
var pr = HttpContext.GetPaymentRequestDataOrNull();
if (pr is null || pr.Archived)
- return PaymentRequestNotFound();
+ return PaymentRequestNotFound();
await _paymentRequestRepository.ArchivePaymentRequest(pr.Id);
return Ok();
@@ -141,12 +144,13 @@ namespace BTCPayServer.Controllers.Greenfield
[HttpPost("~/api/v1/stores/{storeId}/payment-requests")]
[HttpPut("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}")]
+ [HttpPut("~/api/v1/payment-requests/{paymentRequestId}")]
[Authorize(Policy = Policies.CanModifyPaymentRequests,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
public async Task<IActionResult> CreateOrUpdatePaymentRequest(
- [FromRoute] string storeId,
+ [FromRoute] string? storeId,
PaymentRequestBaseData request,
- [FromRoute] string paymentRequestId = null)
+ [FromRoute] string? paymentRequestId = null)
{
if (request is null)
return BadRequest();
@@ -163,43 +167,43 @@ namespace BTCPayServer.Controllers.Greenfield
if (string.IsNullOrEmpty(request.Title))
ModelState.AddModelError(nameof(request.Title), "Title is required");
- var storeData = HttpContext.GetStoreData();
- PaymentRequestData pr;
- if (paymentRequestId is not null)
+ PaymentRequestData pr;
+ if (paymentRequestId is not null)
+ {
+ pr = HttpContext.GetPaymentRequestDataOrNull();
+ if (pr is null)
+ return PaymentRequestNotFound();
+ if ((pr.Amount != request.Amount && request.Amount != 0.0m) ||
+ (pr.Currency != request.Currency && request.Currency != null))
{
- pr = HttpContext.GetPaymentRequestDataOrNull();
- if (pr is null)
- return PaymentRequestNotFound();
- if ((pr.Amount != request.Amount && request.Amount != 0.0m) ||
- (pr.Currency != request.Currency && request.Currency != null))
+ var prWithInvoices = await this.PaymentRequestService.GetPaymentRequest(paymentRequestId, GetUserId());
+ if (prWithInvoices.Invoices.Any())
{
- var prWithInvoices = await this.PaymentRequestService.GetPaymentRequest(paymentRequestId, GetUserId());
- if (prWithInvoices.Invoices.Any())
- {
- ModelState.AddModelError(nameof(request.Amount), "Amount and currency are not editable once payment request has invoices");
- }
- else
- {
- if (request.Amount != 0.0m)
- pr.Amount = request.Amount;
- if (request.Currency != null)
- pr.Currency = request.Currency;
- }
+ ModelState.AddModelError(nameof(request.Amount), "Amount and currency are not editable once payment request has invoices");
}
- pr.Expiry = request.ExpiryDate;
- }
- else
- {
- pr = new PaymentRequestData()
+ else
{
- StoreDataId = storeId,
- Status = PaymentRequestStatus.Pending,
- Created = DateTimeOffset.UtcNow,
- Amount = request.Amount,
- Currency = request.Currency ?? storeData.GetStoreBlob().DefaultCurrency,
- Expiry = request.ExpiryDate,
- };
+ if (request.Amount != 0.0m)
+ pr.Amount = request.Amount;
+ if (request.Currency != null)
+ pr.Currency = request.Currency;
+ }
}
+ pr.Expiry = request.ExpiryDate;
+ }
+ else
+ {
+ var storeData = HttpContext.GetStoreData();
+ pr = new PaymentRequestData()
+ {
+ StoreDataId = storeId,
+ Status = PaymentRequestStatus.Pending,
+ Created = DateTimeOffset.UtcNow,
+ Amount = request.Amount,
+ Currency = request.Currency ?? storeData.GetStoreBlob().DefaultCurrency,
+ Expiry = request.ExpiryDate,
+ };
+ }
pr.ReferenceId = string.IsNullOrEmpty(request.ReferenceId) ? null : request.ReferenceId;
diff --git a/BTCPayServer/Controllers/GreenField/GreenfieldPullPaymentController.cs b/BTCPayServer/Controllers/GreenField/GreenfieldPullPaymentController.cs
index 9812f5f..d26910b 100644
--- a/BTCPayServer/Controllers/GreenField/GreenfieldPullPaymentController.cs
+++ b/BTCPayServer/Controllers/GreenField/GreenfieldPullPaymentController.cs
@@ -582,8 +582,9 @@ retry:
}
[HttpDelete("~/api/v1/stores/{storeId}/pull-payments/{pullPaymentId}")]
+ [HttpDelete("~/api/v1/pull-payments/{pullPaymentId}")]
[Authorize(Policy = Policies.CanArchivePullPayments, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
- public async Task<IActionResult> ArchivePullPayment(string storeId, string pullPaymentId)
+ public async Task<IActionResult> ArchivePullPayment(string? storeId, string pullPaymentId)
{
var pp = HttpContext.GetPullPaymentDataOrNull();
if (pp is null)
@@ -592,8 +593,6 @@ retry:
return Ok();
}
-
-
[HttpGet("~/api/v1/stores/{storeId}/payouts")]
[Authorize(Policy = Policies.CanViewPayouts, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
public async Task<IActionResult> GetStorePayouts(string storeId, bool includeCancelled = false)
diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json
index 353bf0f..24e06bc 100644
--- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json
+++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json
@@ -190,21 +190,18 @@
]
}
},
- "/api/v1/stores/{storeId}/invoices/{invoiceId}": {
+ "/api/v1/invoices/{invoiceId}": {
"get": {
"tags": [
"Invoices"
],
"summary": "Get invoice",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
}
],
- "description": "View information about the specified invoice",
+ "description": "View information about the specified invoice. The store is resolved automatically from the invoice.",
"operationId": "Invoices_GetInvoice",
"responses": {
"200": {
@@ -238,12 +235,9 @@
"Invoices"
],
"summary": "Archive invoice",
- "description": "Archives the specified invoice.",
+ "description": "Archives the specified invoice. The store is resolved automatically from the invoice.",
"operationId": "Invoices_ArchiveInvoice",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
}
@@ -283,12 +277,9 @@
"Invoices"
],
"summary": "Update invoice",
- "description": "Updates the specified invoice.",
+ "description": "Updates the specified invoice. The store is resolved automatically from the invoice.",
"operationId": "Invoices_UpdateInvoice",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
}
@@ -341,16 +332,13 @@
]
}
},
- "/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods": {
+ "/api/v1/invoices/{invoiceId}/payment-methods": {
"get": {
"tags": [
"Invoices"
],
"summary": "Get invoice payment methods",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
},
@@ -375,7 +363,7 @@
}
}
],
- "description": "View information about the specified invoice's payment methods",
+ "description": "View information about the specified invoice's payment methods. The store is resolved automatically from the invoice.",
"operationId": "Invoices_GetInvoicePaymentMethods",
"responses": {
"200": {
@@ -409,68 +397,18 @@
]
}
},
- "/api/v1/stores/{storeId}/invoices/{invoiceId}/refund/{paymentMethodId}": {
- "get": {
- "tags": [
- "Invoices"
- ],
- "summary": "Get invoice refund trigger data",
- "parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
- {
- "$ref": "#/components/parameters/InvoiceId"
- },
- {
- "$ref": "#/components/parameters/PaymentMethodId"
- }
- ],
- "description": "View calculated refund amounts (payment then/now, invoice, overpaid) for the specified invoice/payment-method. This can be used preceding the POST /refund call.",
- "operationId": "Invoices_GetInvoiceRefundTriggerData",
- "responses": {
- "200": {
- "description": "specified invoice refund trigger data",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/InvoiceRefundTriggerData"
- }
- }
- }
- },
- "403": {
- "description": "If you are authenticated but forbidden to view the specified invoice"
- },
- "404": {
- "description": "The key is not found for this invoice"
- }
- },
- "security": [
- {
- "API_Key": [
- "btcpay.store.cancreatepullpayments"
- ],
- "Basic": []
- }
- ]
- }
- },
- "/api/v1/stores/{storeId}/invoices/{invoiceId}/status": {
+ "/api/v1/invoices/{invoiceId}/status": {
"post": {
"tags": [
"Invoices"
],
"summary": "Mark invoice status",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
}
],
- "description": "Mark an invoice as invalid or settled.",
+ "description": "Mark an invoice as invalid or settled. The store is resolved automatically from the invoice.",
"operationId": "Invoices_MarkInvoiceStatus",
"responses": {
"200": {
@@ -517,21 +455,18 @@
]
}
},
- "/api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive": {
+ "/api/v1/invoices/{invoiceId}/unarchive": {
"post": {
"tags": [
"Invoices"
],
"summary": "Unarchive invoice",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
}
],
- "description": "Unarchive an invoice",
+ "description": "Unarchive an invoice. The store is resolved automatically from the invoice.",
"operationId": "Invoices_UnarchiveInvoice",
"responses": {
"200": {
@@ -568,16 +503,13 @@
]
}
},
- "/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethodId}/activate": {
+ "/api/v1/invoices/{invoiceId}/payment-methods/{paymentMethodId}/activate": {
"post": {
"tags": [
"Invoices"
],
"summary": "Activate Payment Method",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
},
@@ -585,7 +517,7 @@
"$ref": "#/components/parameters/PaymentMethodId"
}
],
- "description": "Activate an invoice payment method (if lazy payments mode is enabled)",
+ "description": "Activate an invoice payment method (if lazy payments mode is enabled). The store is resolved automatically from the invoice.",
"operationId": "Invoices_ActivatePaymentMethod",
"responses": {
"200": {
@@ -615,77 +547,25 @@
]
}
},
- "/api/v1/stores/{storeId}/invoices/{invoiceId}/refund": {
+ "/api/v1/invoices/{invoiceId}/refund": {
"post": {
"tags": [
"Invoices"
],
"summary": "Refund invoice",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"$ref": "#/components/parameters/InvoiceId"
}
],
- "description": "Refund invoice",
+ "description": "Refund invoice. The store is resolved automatically from the invoice.",
"operationId": "Invoices_Refund",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
- "type": "object",
- "additionalProperties": false,
- "properties": {
- "name": {
- "type": "string",
- "description": "Name of the pull payment (Default: 'Refund' followed by the invoice id)",
- "nullable": true
- },
- "description": {
- "type": "string",
- "description": "Description of the pull payment"
- },
- "payoutMethodId": {
- "$ref": "#/components/schemas/PayoutMethodId"
- },
- "refundVariant": {
- "type": "string",
- "description": "* `RateThen`: Refund the crypto currency price, at the rate the invoice got paid.\r\n* `CurrentRate`: Refund the crypto currency price, at the current rate.\r\n*`Fiat`: Refund the invoice currency, at the rate when the refund will be sent.\r\n*`OverpaidAmount`: Refund the crypto currency amount that was overpaid.\r\n*`Custom`: Specify the amount, currency, and rate of the refund. (see `customAmount` and `customCurrency`)",
- "x-enumNames": [
- "RateThen",
- "CurrentRate",
- "Fiat",
- "Custom"
- ],
- "enum": [
- "RateThen",
- "CurrentRate",
- "OverpaidAmount",
- "Fiat",
- "Custom"
- ]
- },
- "subtractPercentage": {
- "type": "string",
- "format": "decimal",
- "description": "Optional percentage by which to reduce the refund, e.g. as processing charge or to compensate for the mining fee.",
- "example": "2.1"
- },
- "customAmount": {
- "type": "string",
- "format": "decimal",
- "description": "The amount to refund if the `refundVariant` is `Custom`.",
- "example": "5.00"
- },
- "customCurrency": {
- "type": "string",
- "description": "The currency to refund if the `refundVariant` is `Custom`",
- "example": "USD"
- }
- }
+ "$ref": "#/components/schemas/RefundInvoiceRequest"
}
}
}
@@ -724,6 +604,50 @@
}
]
}
+ },
+ "/api/v1/invoices/{invoiceId}/refund/{paymentMethodId}": {
+ "get": {
+ "tags": [
+ "Invoices"
+ ],
+ "summary": "Get invoice refund trigger data",
+ "parameters": [
+ {
+ "$ref": "#/components/parameters/InvoiceId"
+ },
+ {
+ "$ref": "#/components/parameters/PaymentMethodId"
+ }
+ ],
+ "description": "View calculated refund amounts for the specified invoice/payment-method. The store is resolved automatically from the invoice.",
+ "operationId": "Invoices_GetInvoiceRefundTriggerData",
+ "responses": {
+ "200": {
+ "description": "specified invoice refund trigger data",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/InvoiceRefundTriggerData"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "If you are authenticated but forbidden to view the specified invoice"
+ },
+ "404": {
+ "description": "The key is not found for this invoice"
+ }
+ },
+ "security": [
+ {
+ "API_Key": [
+ "btcpay.store.cancreatepullpayments"
+ ],
+ "Basic": []
+ }
+ ]
+ }
}
},
"components": {
@@ -1487,6 +1411,62 @@
"Standard",
"TopUp"
]
+ },
+ "RefundInvoiceRequest": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "refundVariant"
+ ],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the pull payment (Default: 'Refund' followed by the invoice id)",
+ "nullable": true
+ },
+ "description": {
+ "type": "string",
+ "description": "Description of the pull payment"
+ },
+ "payoutMethodId": {
+ "$ref": "#/components/schemas/PayoutMethodId"
+ },
+ "refundVariant": {
+ "type": "string",
+ "description": "* `RateThen`: Refund the crypto currency price, at the rate the invoice got paid.\r\n* `CurrentRate`: Refund the crypto currency price, at the current rate.\r\n*`Fiat`: Refund the invoice currency, at the rate when the refund will be sent.\r\n*`OverpaidAmount`: Refund the crypto currency amount that was overpaid.\r\n*`Custom`: Specify the amount, currency, and rate of the refund. (see `customAmount` and `customCurrency`)",
+ "x-enumNames": [
+ "RateThen",
+ "CurrentRate",
+ "OverpaidAmount",
+ "Fiat",
+ "Custom"
+ ],
+ "enum": [
+ "RateThen",
+ "CurrentRate",
+ "OverpaidAmount",
+ "Fiat",
+ "Custom"
+ ]
+ },
+ "subtractPercentage": {
+ "type": "string",
+ "format": "decimal",
+ "description": "Optional percentage by which to reduce the refund, e.g. as processing charge or to compensate for the mining fee.",
+ "example": "2.1"
+ },
+ "customAmount": {
+ "type": "string",
+ "format": "decimal",
+ "description": "The amount to refund if the `refundVariant` is `Custom`.",
+ "example": "5.00"
+ },
+ "customCurrency": {
+ "type": "string",
+ "description": "The currency to refund if the `refundVariant` is `Custom`",
+ "example": "USD"
+ }
+ }
}
}
},
diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.payment-requests.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.payment-requests.json
index c0a40f5..5d97583 100644
--- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.payment-requests.json
+++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.payment-requests.json
@@ -101,16 +101,13 @@
]
}
},
- "/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}": {
+ "/api/v1/payment-requests/{paymentRequestId}": {
"get": {
"tags": [
"Payment Requests"
],
"summary": "Get payment request",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"name": "paymentRequestId",
"in": "path",
@@ -121,7 +118,7 @@
}
}
],
- "description": "View information about the specified payment request",
+ "description": "View information about the specified payment request. The store is resolved automatically from the payment request.",
"operationId": "PaymentRequests_GetPaymentRequest",
"responses": {
"200": {
@@ -155,12 +152,9 @@
"Payment Requests"
],
"summary": "Archive payment request",
- "description": "Archives the specified payment request.",
+ "description": "Archives the specified payment request. The store is resolved automatically from the payment request.",
"operationId": "PaymentRequests_ArchivePaymentRequest",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"name": "paymentRequestId",
"in": "path",
@@ -207,9 +201,6 @@
],
"summary": "Update payment request",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"name": "paymentRequestId",
"in": "path",
@@ -220,7 +211,7 @@
}
}
],
- "description": "Update a payment request",
+ "description": "Update a payment request. The store is resolved automatically from the payment request.",
"operationId": "PaymentRequests_UpdatePaymentRequest",
"responses": {
"200": {
@@ -267,16 +258,13 @@
]
}
},
- "/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}/pay": {
+ "/api/v1/payment-requests/{paymentRequestId}/pay": {
"post": {
"tags": [
"Payment Requests"
],
"summary": "Create a new invoice for the payment request",
"parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
{
"name": "paymentRequestId",
"in": "path",
@@ -288,7 +276,7 @@
}
],
"operationId": "PaymentRequests_Pay",
- "description": "Create a new invoice for the payment request, or reuse an existing one",
+ "description": "Create a new invoice for the payment request, or reuse an existing one. The store is resolved automatically from the payment request.",
"requestBody": {
"description": "Invoice creation request",
"content": {
diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.pull-payments.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.pull-payments.json
index f43481b..fbae7f0 100644
--- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.pull-payments.json
+++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.pull-payments.json
@@ -306,33 +306,17 @@
"Pull payments (Public)"
],
"security": []
- }
- },
- "/api/v1/stores/{storeId}/pull-payments/{pullPaymentId}": {
- "parameters": [
- {
- "$ref": "#/components/parameters/StoreId"
- },
- {
- "name": "pullPaymentId",
- "in": "path",
- "required": true,
- "description": "The ID of the pull payment",
- "schema": {
- "type": "string"
- }
- }
- ],
+ },
"delete": {
"operationId": "PullPayments_ArchivePullPayment",
"summary": "Archive a pull payment",
- "description": "Archive this pull payment (Will cancel all payouts awaiting for payment)",
+ "description": "Archive this pull payment (Will cancel all payouts awaiting for payment). The store is resolved automatically from the pull payment.",
"responses": {
"200": {
"description": "The pull payment has been archived"
},
"404": {
- "description": "The pull payment has not been found, or does not belong to this store"
+ "description": "The pull payment has not been found. Well-known error code is: `pullpayment-not-found`"
}
},
"tags": [
Why this scored 51/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.