mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-10 09:19:24 +01:00
This commit is contained in:
parent
4a2f61de9f
commit
247532e3c4
4 changed files with 57 additions and 19 deletions
|
@ -2247,6 +2247,17 @@ namespace BTCPayServer.Tests
|
|||
Assert.Equal("BTC", pp.Currency);
|
||||
Assert.True(pp.AutoApproveClaims);
|
||||
Assert.Equal(0.79m, pp.Amount);
|
||||
|
||||
// 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
|
||||
{
|
||||
PaymentMethod = method.PaymentMethodId,
|
||||
RefundVariant = RefundVariant.CurrentRate
|
||||
});
|
||||
Assert.Equal(1.0m, refund.Amount);
|
||||
Assert.Equal("BTC", refund.Currency);
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
|
|
|
@ -408,10 +408,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
var supported = _payoutHandlers.GetSupportedPayoutMethods(store);
|
||||
if (supported.Contains(payoutMethodId))
|
||||
{
|
||||
var paymentMethodId = PaymentMethodId.GetSimilarities([payoutMethodId], invoice.GetPayments(false).Select(p => p.PaymentMethodId))
|
||||
.OrderByDescending(o => o.similarity)
|
||||
.Select(o => o.b)
|
||||
.FirstOrDefault();
|
||||
var paymentMethodId = invoice.GetClosestPaymentMethodId([payoutMethodId]);
|
||||
paymentPrompt = paymentMethodId is null ? null : invoice.GetPaymentPrompt(paymentMethodId);
|
||||
}
|
||||
}
|
||||
|
@ -426,6 +423,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
|
||||
var accounting = paymentPrompt.Calculate();
|
||||
var cryptoPaid = accounting.Paid;
|
||||
var dueAmount = accounting.TotalDue;
|
||||
|
||||
// If no payment, but settled and marked, assume it has been fully paid
|
||||
if (cryptoPaid is 0 && invoice is { Status: InvoiceStatus.Settled, ExceptionStatus: InvoiceExceptionStatus.Marked })
|
||||
{
|
||||
cryptoPaid = accounting.TotalDue;
|
||||
dueAmount = 0;
|
||||
}
|
||||
var cdCurrency = _currencyNameTable.GetCurrencyData(invoice.Currency, true);
|
||||
var paidCurrency = Math.Round(cryptoPaid * paymentPrompt.Rate, cdCurrency.Divisibility);
|
||||
var rateResult = await _rateProvider.FetchRate(
|
||||
|
@ -491,8 +496,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||
{
|
||||
return this.CreateValidationError(ModelState);
|
||||
}
|
||||
|
||||
var dueAmount = accounting.TotalDue;
|
||||
createPullPayment.Currency = paymentPrompt.Currency;
|
||||
createPullPayment.Amount = Math.Round(paidAmount - dueAmount, appliedDivisibility);
|
||||
createPullPayment.AutoApproveClaims = true;
|
||||
|
|
|
@ -302,12 +302,7 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
// Find the most similar payment method to the one used for the invoice
|
||||
var defaultRefund =
|
||||
PaymentMethodId.GetSimilarities(
|
||||
invoice.Payments.Select(o => o.GetPaymentMethodId()),
|
||||
payoutMethodIds)
|
||||
.OrderByDescending(o => o.similarity)
|
||||
.Select(o => o.b)
|
||||
.FirstOrDefault();
|
||||
invoice.GetClosestPayoutMethodId(payoutMethodIds);
|
||||
|
||||
var refund = new RefundModel
|
||||
{
|
||||
|
@ -353,11 +348,7 @@ namespace BTCPayServer.Controllers
|
|||
return View("_RefundModal", model);
|
||||
}
|
||||
|
||||
var availablePaymentMethodIds = invoice.GetPaymentPrompts().Select(p => p.PaymentMethodId).Where(p => _handlers.Support(p)).ToArray();
|
||||
var paymentMethodId = PaymentMethodId.GetSimilarities([pmi], availablePaymentMethodIds)
|
||||
.OrderByDescending(o => o.similarity)
|
||||
.Select(o => o.b)
|
||||
.FirstOrDefault();
|
||||
var paymentMethodId = invoice.GetClosestPaymentMethodId([pmi]);
|
||||
|
||||
var paymentMethod = paymentMethodId is null ? null : invoice.GetPaymentPrompt(paymentMethodId);
|
||||
if (paymentMethod?.Currency is null)
|
||||
|
@ -367,8 +358,16 @@ namespace BTCPayServer.Controllers
|
|||
}
|
||||
|
||||
var accounting = paymentMethod.Calculate();
|
||||
decimal cryptoPaid = accounting.Paid;
|
||||
decimal dueAmount = accounting.TotalDue;
|
||||
var cryptoPaid = accounting.Paid;
|
||||
var dueAmount = accounting.TotalDue;
|
||||
|
||||
// If no payment, but settled and marked, assume it has been fully paid
|
||||
if (cryptoPaid is 0 && invoice is { Status: InvoiceStatus.Settled, ExceptionStatus: InvoiceExceptionStatus.Marked })
|
||||
{
|
||||
cryptoPaid = accounting.TotalDue;
|
||||
dueAmount = 0;
|
||||
}
|
||||
|
||||
var paymentMethodCurrency = paymentMethod.Currency;
|
||||
|
||||
var isPaidOver = invoice.ExceptionStatus == InvoiceExceptionStatus.PaidOver;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using BTCPayServer.Payments;
|
||||
using BTCPayServer.Payouts;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using NBitpayClient;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -26,6 +29,28 @@ namespace BTCPayServer.Data
|
|||
invoiceData.Amount = blob.Price;
|
||||
invoiceData.HasTypedBlob<InvoiceEntity>().SetBlob(blob, DefaultSerializer);
|
||||
}
|
||||
#nullable enable
|
||||
public static PayoutMethodId? GetClosestPayoutMethodId(this InvoiceData invoice, IEnumerable<PayoutMethodId> pmids)
|
||||
{
|
||||
var paymentMethodIds = invoice.Payments.Select(o => o.GetPaymentMethodId()).ToArray();
|
||||
if (paymentMethodIds.Length == 0)
|
||||
paymentMethodIds = invoice.GetBlob().GetPaymentPrompts().Select(p => p.PaymentMethodId).ToArray();
|
||||
return PaymentMethodId.GetSimilarities(pmids, paymentMethodIds)
|
||||
.OrderByDescending(o => o.similarity)
|
||||
.Select(o => o.a)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
public static PaymentMethodId? GetClosestPaymentMethodId(this InvoiceEntity invoice, IEnumerable<PayoutMethodId> pmids)
|
||||
{
|
||||
var paymentMethodIds = invoice.GetPayments(false).Select(o => o.PaymentMethodId).ToArray();
|
||||
if (paymentMethodIds.Length == 0)
|
||||
paymentMethodIds = invoice.GetPaymentPrompts().Select(p => p.PaymentMethodId).ToArray();
|
||||
return PaymentMethodId.GetSimilarities(pmids, paymentMethodIds)
|
||||
.OrderByDescending(o => o.similarity)
|
||||
.Select(o => o.b)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
#nullable restore
|
||||
public static InvoiceEntity GetBlob(this InvoiceData invoiceData)
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
|
Loading…
Add table
Reference in a new issue