Greenfield: Provide negative undue when overpaid. (#2936)

* Greenfield: Provide negative undue when overpaid.

closes #2935

* Invoice's due can be negative, fix Amount field of invoice

* Update swagger.template.invoices.json

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
This commit is contained in:
Andrew Camilleri
2021-10-15 07:23:34 +02:00
committed by GitHub
parent 3671e7f18c
commit d64fb15ac2
3 changed files with 67 additions and 3 deletions

View File

@@ -1024,6 +1024,38 @@ namespace BTCPayServer.Tests
} }
} }
[Fact(Timeout = TestTimeout)]
[Trait("Integration", "Integration")]
public async Task CanOverpayInvoice()
{
using (var tester = ServerTester.Create())
{
await tester.StartAsync();
var user = tester.NewAccount();
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 method = methods.First();
var amount = method.Amount;
Assert.Equal(amount, method.Due);
#pragma warning disable CS0618 // Type or member is obsolete
var btc = tester.NetworkProvider.BTC.NBitcoinNetwork;
#pragma warning restore CS0618 // Type or member is obsolete
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);
Assert.True(invoice.Status == InvoiceStatus.Processing);
methods = await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id);
method = methods.First();
Assert.Equal(amount, method.Amount);
Assert.Equal(-1.0m, method.Due);
Assert.Equal(amount + 1.0m, method.TotalPaid);
});
}
}
[Fact(Timeout = TestTimeout)] [Fact(Timeout = TestTimeout)]
[Trait("Integration", "Integration")] [Trait("Integration", "Integration")]
public async Task InvoiceTests() public async Task InvoiceTests()
@@ -1327,7 +1359,39 @@ namespace BTCPayServer.Tests
}); });
Assert.Equal("BTC", invoiceWithdefaultPaymentMethodOnChain.Checkout.DefaultPaymentMethod); Assert.Equal("BTC", invoiceWithdefaultPaymentMethodOnChain.Checkout.DefaultPaymentMethod);
store = await client.GetStore(user.StoreId);
store.LazyPaymentMethods = false;
store = await client.UpdateStore(store.Id,
JObject.FromObject(store).ToObject<UpdateStoreRequest>());
//let's see the overdue amount
invoice = await client.CreateInvoice(user.StoreId,
new CreateInvoiceRequest()
{
Currency = "BTC",
Amount = 0.0001m,
Checkout = new CreateInvoiceRequest.CheckoutOptions()
{
PaymentMethods = new[] { "BTC" },
DefaultPaymentMethod = "BTC"
}
});
var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
Assert.Equal(0.0001m, pm.Due);
await tester.WaitForEvent<NewOnChainTransactionEvent>(async () =>
{
await tester.ExplorerNode.SendToAddressAsync(
BitcoinAddress.Create(pm.Destination, tester.ExplorerClient.Network.NBitcoinNetwork),
new Money(0.0002m, MoneyUnit.BTC));
});
await TestUtils.EventuallyAsync(async () =>
{
var pm = Assert.Single(await client.GetInvoicePaymentMethods(user.StoreId, invoice.Id));
Assert.Single(pm.Payments);
Assert.Equal(-0.0001m, pm.Due);
});
} }
} }

View File

@@ -356,10 +356,10 @@ namespace BTCPayServer.Controllers.GreenField
PaymentMethod = method.GetId().ToStringNormalized(), PaymentMethod = method.GetId().ToStringNormalized(),
Destination = details.GetPaymentDestination(), Destination = details.GetPaymentDestination(),
Rate = method.Rate, Rate = method.Rate,
Due = accounting.Due.ToDecimal(MoneyUnit.BTC), Due = accounting.DueUncapped.ToDecimal(MoneyUnit.BTC),
TotalPaid = accounting.Paid.ToDecimal(MoneyUnit.BTC), TotalPaid = accounting.Paid.ToDecimal(MoneyUnit.BTC),
PaymentMethodPaid = accounting.CryptoPaid.ToDecimal(MoneyUnit.BTC), PaymentMethodPaid = accounting.CryptoPaid.ToDecimal(MoneyUnit.BTC),
Amount = accounting.Due.ToDecimal(MoneyUnit.BTC), Amount = accounting.TotalDue.ToDecimal(MoneyUnit.BTC),
NetworkFee = accounting.NetworkFee.ToDecimal(MoneyUnit.BTC), NetworkFee = accounting.NetworkFee.ToDecimal(MoneyUnit.BTC),
PaymentLink = PaymentLink =
method.GetId().PaymentType.GetPaymentLink(method.Network, details, accounting.Due, method.GetId().PaymentType.GetPaymentLink(method.Network, details, accounting.Due,

View File

@@ -1144,7 +1144,7 @@
"due": { "due": {
"type": "string", "type": "string",
"format": "decimal", "format": "decimal",
"description": "The total amount left to be paid, converted to this payment method's currency" "description": "The total amount left to be paid, converted to this payment method's currency (will be negative if overpaid)"
}, },
"amount": { "amount": {
"type": "string", "type": "string",