mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 06:24:24 +01:00
Webhook tests + FIXES + DOCS (#5686)
* webhook tests * fixes and add docs * Do not update FormResponse and StoreId in update/create PullPayment --------- Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
This commit is contained in:
@@ -7,11 +7,11 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class WebhookPayoutEvent : StoreWebhookEvent
|
||||
{
|
||||
public WebhookPayoutEvent(string evtType, string storeId)
|
||||
public WebhookPayoutEvent(string type, string storeId)
|
||||
{
|
||||
if (!evtType.StartsWith("payout", StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new ArgumentException("Invalid event type", nameof(evtType));
|
||||
Type = evtType;
|
||||
if (!type.StartsWith("payout", StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new ArgumentException("Invalid event type", nameof(type));
|
||||
Type = type;
|
||||
StoreId = storeId;
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@ namespace BTCPayServer.Client.Models
|
||||
}
|
||||
public class WebhookPaymentRequestEvent : StoreWebhookEvent
|
||||
{
|
||||
public WebhookPaymentRequestEvent(string evtType, string storeId)
|
||||
public WebhookPaymentRequestEvent(string type, string storeId)
|
||||
{
|
||||
if (!evtType.StartsWith("paymentrequest", StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new ArgumentException("Invalid event type", nameof(evtType));
|
||||
Type = evtType;
|
||||
if (!type.StartsWith("paymentrequest", StringComparison.InvariantCultureIgnoreCase))
|
||||
throw new ArgumentException("Invalid event type", nameof(type));
|
||||
Type = type;
|
||||
StoreId = storeId;
|
||||
}
|
||||
|
||||
|
||||
@@ -2331,7 +2331,7 @@ namespace BTCPayServer.Tests
|
||||
if (marked == InvoiceStatus.Settled)
|
||||
{
|
||||
Assert.Equal(InvoiceStatus.Settled, result.Status);
|
||||
user.AssertHasWebhookEvent<WebhookInvoiceSettledEvent>(WebhookEventType.InvoiceSettled,
|
||||
await user.AssertHasWebhookEvent<WebhookInvoiceSettledEvent>(WebhookEventType.InvoiceSettled,
|
||||
o =>
|
||||
{
|
||||
Assert.Equal(inv.Id, o.InvoiceId);
|
||||
@@ -2341,7 +2341,7 @@ namespace BTCPayServer.Tests
|
||||
if (marked == InvoiceStatus.Invalid)
|
||||
{
|
||||
Assert.Equal(InvoiceStatus.Invalid, result.Status);
|
||||
var evt = user.AssertHasWebhookEvent<WebhookInvoiceInvalidEvent>(WebhookEventType.InvoiceInvalid,
|
||||
var evt = await user.AssertHasWebhookEvent<WebhookInvoiceInvalidEvent>(WebhookEventType.InvoiceInvalid,
|
||||
o =>
|
||||
{
|
||||
Assert.Equal(inv.Id, o.InvoiceId);
|
||||
|
||||
@@ -452,9 +452,9 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
private Client.Models.StoreWebhookData _wh;
|
||||
private FakeServer _server;
|
||||
private readonly List<WebhookInvoiceEvent> _webhookEvents;
|
||||
private readonly List<StoreWebhookEvent> _webhookEvents;
|
||||
private CancellationTokenSource _cts;
|
||||
public WebhookListener(Client.Models.StoreWebhookData wh, FakeServer server, List<WebhookInvoiceEvent> webhookEvents)
|
||||
public WebhookListener(Client.Models.StoreWebhookData wh, FakeServer server, List<StoreWebhookEvent> webhookEvents)
|
||||
{
|
||||
_wh = wh;
|
||||
_server = server;
|
||||
@@ -472,7 +472,7 @@ namespace BTCPayServer.Tests
|
||||
var callback = Encoding.UTF8.GetString(bytes);
|
||||
lock (_webhookEvents)
|
||||
{
|
||||
_webhookEvents.Add(JsonConvert.DeserializeObject<WebhookInvoiceEvent>(callback));
|
||||
_webhookEvents.Add(JsonConvert.DeserializeObject<DummyStoreWebhookEvent>(callback));
|
||||
}
|
||||
req.Response.StatusCode = 200;
|
||||
_server.Done();
|
||||
@@ -485,8 +485,13 @@ namespace BTCPayServer.Tests
|
||||
}
|
||||
}
|
||||
|
||||
public List<WebhookInvoiceEvent> WebhookEvents { get; set; } = new List<WebhookInvoiceEvent>();
|
||||
public TEvent AssertHasWebhookEvent<TEvent>(string eventType, Action<TEvent> assert) where TEvent : class
|
||||
public class DummyStoreWebhookEvent : StoreWebhookEvent
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public List<StoreWebhookEvent> WebhookEvents { get; set; } = new List<StoreWebhookEvent>();
|
||||
public async Task<TEvent> AssertHasWebhookEvent<TEvent>(string eventType, Action<TEvent> assert) where TEvent : class
|
||||
{
|
||||
int retry = 0;
|
||||
retry:
|
||||
@@ -510,7 +515,7 @@ retry:
|
||||
}
|
||||
if (retry < 3)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
await Task.Delay(1000);
|
||||
retry++;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,9 @@ using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
using Xunit.Sdk;
|
||||
using CreateInvoiceRequest = BTCPayServer.Client.Models.CreateInvoiceRequest;
|
||||
using CreatePaymentRequestRequest = BTCPayServer.Client.Models.CreatePaymentRequestRequest;
|
||||
using MarkPayoutRequest = BTCPayServer.Client.Models.MarkPayoutRequest;
|
||||
using PaymentRequestData = BTCPayServer.Client.Models.PaymentRequestData;
|
||||
using RatesViewModel = BTCPayServer.Models.StoreViewModels.RatesViewModel;
|
||||
|
||||
namespace BTCPayServer.Tests
|
||||
@@ -1943,6 +1946,173 @@ namespace BTCPayServer.Tests
|
||||
entity.GetPaymentMethods().First().Calculate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[Fact()]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task EnsureWebhooksTrigger()
|
||||
{
|
||||
using var tester = CreateServerTester();
|
||||
await tester.StartAsync();
|
||||
var user = tester.NewAccount();
|
||||
await user.GrantAccessAsync();
|
||||
user.RegisterDerivationScheme("BTC");
|
||||
await user.SetupWebhook();
|
||||
var client = await user.CreateClient();
|
||||
|
||||
|
||||
var invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = 0.00m,
|
||||
Currency = "BTC"
|
||||
});;
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceCreated, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
|
||||
|
||||
//invoice payment webhooks
|
||||
invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = 0.01m,
|
||||
Currency = "BTC"
|
||||
});
|
||||
|
||||
var invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)).Single(model =>
|
||||
PaymentMethodId.Parse(model.PaymentMethod) ==
|
||||
new PaymentMethodId("BTC", BitcoinPaymentType.Instance))
|
||||
.PaymentLink, tester.ExplorerNode.Network);
|
||||
var halfPaymentTx = await tester.ExplorerNode.SendToAddressAsync(invoicePaymentRequest.Address, Money.Coins(invoicePaymentRequest.Amount.ToDecimal(MoneyUnit.BTC)/2m));
|
||||
|
||||
invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)).Single(model =>
|
||||
PaymentMethodId.Parse(model.PaymentMethod) ==
|
||||
new PaymentMethodId("BTC", BitcoinPaymentType.Instance))
|
||||
.PaymentLink, tester.ExplorerNode.Network);
|
||||
var remainingPaymentTx = await tester.ExplorerNode.SendToAddressAsync(invoicePaymentRequest.Address, Money.Coins(invoicePaymentRequest.Amount.ToDecimal(MoneyUnit.BTC)));
|
||||
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceCreated, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceProcessing, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceReceivedPayment,
|
||||
(WebhookInvoiceReceivedPaymentEvent x) =>
|
||||
{
|
||||
Assert.Equal(invoice.Id, x.InvoiceId);
|
||||
Assert.Contains(halfPaymentTx.ToString(), x.Payment.Id);
|
||||
});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceReceivedPayment,
|
||||
(WebhookInvoiceReceivedPaymentEvent x) =>
|
||||
{
|
||||
Assert.Equal(invoice.Id, x.InvoiceId);
|
||||
Assert.Contains(remainingPaymentTx.ToString(), x.Payment.Id);
|
||||
});
|
||||
|
||||
await tester.ExplorerNode.GenerateAsync(1);
|
||||
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoicePaymentSettled,
|
||||
(WebhookInvoiceReceivedPaymentEvent x) =>
|
||||
{
|
||||
Assert.Equal(invoice.Id, x.InvoiceId);
|
||||
Assert.Contains(halfPaymentTx.ToString(), x.Payment.Id);
|
||||
});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoicePaymentSettled,
|
||||
(WebhookInvoiceReceivedPaymentEvent x) =>
|
||||
{
|
||||
Assert.Equal(invoice.Id, x.InvoiceId);
|
||||
Assert.Contains(remainingPaymentTx.ToString(), x.Payment.Id);
|
||||
});
|
||||
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceSettled, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
|
||||
|
||||
invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = 0.01m,
|
||||
Currency = "BTC",
|
||||
});
|
||||
invoicePaymentRequest = new BitcoinUrlBuilder((await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id)).Single(model =>
|
||||
PaymentMethodId.Parse(model.PaymentMethod) ==
|
||||
new PaymentMethodId("BTC", BitcoinPaymentType.Instance))
|
||||
.PaymentLink, tester.ExplorerNode.Network);
|
||||
halfPaymentTx = await tester.ExplorerNode.SendToAddressAsync(invoicePaymentRequest.Address, Money.Coins(invoicePaymentRequest.Amount.ToDecimal(MoneyUnit.BTC)/2m));
|
||||
|
||||
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceCreated, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.InvoiceReceivedPayment,
|
||||
(WebhookInvoiceReceivedPaymentEvent x) =>
|
||||
{
|
||||
Assert.Equal(invoice.Id, x.InvoiceId);
|
||||
Assert.Contains(halfPaymentTx.ToString(), x.Payment.Id);
|
||||
});
|
||||
|
||||
invoice = await client.CreateInvoice(user.StoreId, new CreateInvoiceRequest()
|
||||
{
|
||||
Amount = 0.01m,
|
||||
Currency = "BTC"
|
||||
});
|
||||
|
||||
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 user.AssertHasWebhookEvent(WebhookEventType.InvoiceInvalid, (WebhookInvoiceEvent x)=> Assert.Equal(invoice.Id, x.InvoiceId));
|
||||
|
||||
//payment request webhook test
|
||||
var pr = await client.CreatePaymentRequest(user.StoreId, new CreatePaymentRequestRequest()
|
||||
{
|
||||
Amount = 100m,
|
||||
Currency = "USD",
|
||||
Title = "test pr",
|
||||
//TODO: this is a bug, we should not have these props in create request
|
||||
StoreId = user.StoreId,
|
||||
FormResponse = new JObject(),
|
||||
//END todo
|
||||
Description = "lala baba"
|
||||
});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.PaymentRequestCreated, (WebhookPaymentRequestEvent x)=> Assert.Equal(pr.Id, x.PaymentRequestId));
|
||||
pr = await client.UpdatePaymentRequest(user.StoreId, pr.Id,
|
||||
new UpdatePaymentRequestRequest() { Title = "test pr updated", Amount = 100m,
|
||||
Currency = "USD",
|
||||
//TODO: this is a bug, we should not have these props in create request
|
||||
StoreId = user.StoreId,
|
||||
FormResponse = new JObject(),
|
||||
//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() {});
|
||||
|
||||
await client.MarkInvoiceStatus(user.StoreId, inv.Id, new MarkInvoiceStatusRequest() { Status = InvoiceStatus.Settled});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.PaymentRequestStatusChanged, (WebhookPaymentRequestEvent x)=>
|
||||
{
|
||||
Assert.Equal(PaymentRequestData.PaymentRequestStatus.Completed, x.Status);
|
||||
Assert.Equal(pr.Id, x.PaymentRequestId);
|
||||
});
|
||||
await client.ArchivePaymentRequest(user.StoreId, 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,
|
||||
new CreatePayoutThroughStoreRequest()
|
||||
{
|
||||
Amount = 0.0001m,
|
||||
Destination = (await tester.ExplorerNode.GetNewAddressAsync()).ToString(),
|
||||
Approved = true,
|
||||
PaymentMethod = "BTC"
|
||||
});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.PayoutCreated, (WebhookPayoutEvent x)=> Assert.Equal(payout.Id, x.PayoutId));
|
||||
await client.MarkPayout(user.StoreId, payout.Id, new MarkPayoutRequest(){ State = PayoutState.AwaitingApproval});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.PayoutUpdated, (WebhookPayoutEvent x)=>
|
||||
{
|
||||
Assert.Equal(payout.Id, x.PayoutId);
|
||||
Assert.Equal(PayoutState.AwaitingApproval, x.PayoutState);
|
||||
});
|
||||
|
||||
await client.ApprovePayout(user.StoreId, payout.Id, new ApprovePayoutRequest(){});
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.PayoutApproved, (WebhookPayoutEvent x)=>
|
||||
{
|
||||
Assert.Equal(payout.Id, x.PayoutId);
|
||||
Assert.Equal(PayoutState.AwaitingPayment, x.PayoutState);
|
||||
});
|
||||
await client.CancelPayout(user.StoreId, payout.Id );
|
||||
await user.AssertHasWebhookEvent(WebhookEventType.PayoutUpdated, (WebhookPayoutEvent x)=>
|
||||
{
|
||||
Assert.Equal(payout.Id, x.PayoutId);
|
||||
Assert.Equal(PayoutState.Cancelled, x.PayoutState);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact(Timeout = LongRunningTestTimeout)]
|
||||
[Trait("Integration", "Integration")]
|
||||
public async Task InvoiceFlowThroughDifferentStatesCorrectly()
|
||||
|
||||
@@ -168,6 +168,8 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
Status = Client.Models.PaymentRequestData.PaymentRequestStatus.Pending,
|
||||
Created = DateTimeOffset.UtcNow
|
||||
};
|
||||
request.FormResponse = null;
|
||||
request.StoreId = storeId;
|
||||
pr.SetBlob(request);
|
||||
pr = await _paymentRequestRepository.CreateOrUpdatePaymentRequest(pr);
|
||||
return Ok(FromModel(pr));
|
||||
@@ -196,6 +198,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
}
|
||||
|
||||
var updatedPr = pr.First();
|
||||
var blob = updatedPr.GetBlob();
|
||||
request.FormResponse = blob.FormResponse;
|
||||
request.StoreId = storeId;
|
||||
updatedPr.SetBlob(request);
|
||||
|
||||
return Ok(FromModel(await _paymentRequestRepository.CreateOrUpdatePaymentRequest(updatedPr)));
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace BTCPayServer.Data.Payouts.LightningLike
|
||||
{
|
||||
if (payout.State != PayoutState.AwaitingPayment)
|
||||
{
|
||||
_eventAggregator.Publish(new PayoutEvent(null, payout));
|
||||
_eventAggregator.Publish(new PayoutEvent(PayoutEvent.PayoutEventType.Updated, payout));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,7 +517,7 @@ namespace BTCPayServer.HostedServices
|
||||
}
|
||||
payout.State = req.Request.State;
|
||||
await ctx.SaveChangesAsync();
|
||||
_eventAggregator.Publish(new PayoutEvent(null, payout));
|
||||
_eventAggregator.Publish(new PayoutEvent(PayoutEvent.PayoutEventType.Updated, payout));
|
||||
req.Completion.SetResult(MarkPayoutRequest.PayoutPaidResult.Ok);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -739,7 +739,7 @@ namespace BTCPayServer.HostedServices
|
||||
foreach (var keyValuePair in result.Where(pair => pair.Value == MarkPayoutRequest.PayoutPaidResult.Ok))
|
||||
{
|
||||
var payout = payouts.First(p => p.Id == keyValuePair.Key);
|
||||
_eventAggregator.Publish(new PayoutEvent(null, payout));
|
||||
_eventAggregator.Publish(new PayoutEvent(PayoutEvent.PayoutEventType.Updated, payout));
|
||||
}
|
||||
cancel.Completion.TrySetResult(result);
|
||||
}
|
||||
@@ -959,7 +959,7 @@ namespace BTCPayServer.HostedServices
|
||||
public JObject Metadata { get; set; }
|
||||
}
|
||||
|
||||
public record PayoutEvent(PayoutEvent.PayoutEventType? Type, PayoutData Payout)
|
||||
public record PayoutEvent(PayoutEvent.PayoutEventType Type, PayoutData Payout)
|
||||
{
|
||||
public enum PayoutEventType
|
||||
{
|
||||
|
||||
@@ -120,7 +120,7 @@ public abstract class BaseAutomatedPayoutProcessor<T> : BaseAsyncService where T
|
||||
|
||||
foreach (var payoutData in payouts.Where(payoutData => payoutData.State != PayoutState.AwaitingPayment))
|
||||
{
|
||||
_eventAggregator.Publish(new PayoutEvent(null, payoutData));
|
||||
_eventAggregator.Publish(new PayoutEvent(PayoutEvent.PayoutEventType.Updated, payoutData));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -693,10 +693,10 @@
|
||||
"nullable": false
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "User-supplied metadata added to the invoice at the time of its creation",
|
||||
"nullable": false
|
||||
}
|
||||
"type": "object",
|
||||
"description": "User-supplied metadata added to the invoice at the time of its creation",
|
||||
"nullable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -1129,6 +1129,420 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PaymentRequestCreated": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PaymentRequestCreated",
|
||||
"summary": "PaymentRequestCreated",
|
||||
"description": "A new payment request has been created",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"paymentRequestId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payment request",
|
||||
"nullable": false
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Pending",
|
||||
"Completed",
|
||||
"Expired"
|
||||
],
|
||||
"description": "The status of the payment request",
|
||||
"nullable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PaymentRequestUpdated": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PaymentRequestUpdated",
|
||||
"summary": "PaymentRequestUpdated",
|
||||
"description": "A payment request has been updated",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"paymentRequestId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payment request",
|
||||
"nullable": false
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Pending",
|
||||
"Completed",
|
||||
"Expired"
|
||||
],
|
||||
"description": "The status of the payment request",
|
||||
"nullable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PaymentRequestArchived": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PaymentRequestArchved",
|
||||
"summary": "PaymentRequestArchived",
|
||||
"description": "A payment request has been archived",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"paymentRequestId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payment request",
|
||||
"nullable": false
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Pending",
|
||||
"Completed",
|
||||
"Expired"
|
||||
],
|
||||
"description": "The status of the payment request",
|
||||
"nullable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PaymentRequestStatusChanged": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PaymentRequestStatusChanged",
|
||||
"summary": "PaymentRequestStatusChanged",
|
||||
"description": "A payment request has had its status changed",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"paymentRequestId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payment request",
|
||||
"nullable": false
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Pending",
|
||||
"Completed",
|
||||
"Expired"
|
||||
],
|
||||
"description": "The status of the payment request",
|
||||
"nullable": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PayoutCreated": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PayoutCreated",
|
||||
"summary": "PayoutCreated",
|
||||
"description": "A payout has been created",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"payoutId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payout",
|
||||
"nullable": false
|
||||
},
|
||||
"pullPaymentId": {
|
||||
"type": "string",
|
||||
"description": "The id of the pull payment this payout belongs to",
|
||||
"nullable": true
|
||||
},
|
||||
"payoutState": {
|
||||
"$ref": "#/components/schemas/PayoutState"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PayoutApproved": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PayoutApproved",
|
||||
"summary": "PayoutApproved",
|
||||
"description": "A payout has been approved",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"payoutId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payout",
|
||||
"nullable": false
|
||||
},
|
||||
"pullPaymentId": {
|
||||
"type": "string",
|
||||
"description": "The id of the pull payment this payout belongs to",
|
||||
"nullable": true
|
||||
},
|
||||
"payoutState": {
|
||||
"$ref": "#/components/schemas/PayoutState"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PayoutUpdated": {
|
||||
"post": {
|
||||
"operationId": "Webhook_PayoutUpdated",
|
||||
"summary": "PayoutUpdated",
|
||||
"description": "A payout has been updated",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "header",
|
||||
"name": "BTCPay-Sig",
|
||||
"required": true,
|
||||
"description": "The HMAC of the body's byte with the secret's of the webhook. `sha256=HMAC256(UTF8(webhook's secret), body)`",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"example": "sha256=b438519edde5c8144a4f9bcec51a9d346eca6506887c2ceeae1c0092884a97b9"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Webhooks"
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"payoutId": {
|
||||
"type": "string",
|
||||
"description": "The id of the payout",
|
||||
"nullable": false
|
||||
},
|
||||
"pullPaymentId": {
|
||||
"type": "string",
|
||||
"description": "The id of the pull payment this payout belongs to",
|
||||
"nullable": true
|
||||
},
|
||||
"payoutState": {
|
||||
"$ref": "#/components/schemas/PayoutState"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"default": {
|
||||
"description": "Unexpected error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/ProblemDetails"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
|
||||
Reference in New Issue
Block a user