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.Equal("BTC", pp.Currency);
|
||||||
Assert.True(pp.AutoApproveClaims);
|
Assert.True(pp.AutoApproveClaims);
|
||||||
Assert.Equal(0.79m, pp.Amount);
|
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)]
|
[Fact(Timeout = TestTimeout)]
|
||||||
|
|
|
@ -408,10 +408,7 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
var supported = _payoutHandlers.GetSupportedPayoutMethods(store);
|
var supported = _payoutHandlers.GetSupportedPayoutMethods(store);
|
||||||
if (supported.Contains(payoutMethodId))
|
if (supported.Contains(payoutMethodId))
|
||||||
{
|
{
|
||||||
var paymentMethodId = PaymentMethodId.GetSimilarities([payoutMethodId], invoice.GetPayments(false).Select(p => p.PaymentMethodId))
|
var paymentMethodId = invoice.GetClosestPaymentMethodId([payoutMethodId]);
|
||||||
.OrderByDescending(o => o.similarity)
|
|
||||||
.Select(o => o.b)
|
|
||||||
.FirstOrDefault();
|
|
||||||
paymentPrompt = paymentMethodId is null ? null : invoice.GetPaymentPrompt(paymentMethodId);
|
paymentPrompt = paymentMethodId is null ? null : invoice.GetPaymentPrompt(paymentMethodId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -426,6 +423,14 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
|
|
||||||
var accounting = paymentPrompt.Calculate();
|
var accounting = paymentPrompt.Calculate();
|
||||||
var cryptoPaid = accounting.Paid;
|
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 cdCurrency = _currencyNameTable.GetCurrencyData(invoice.Currency, true);
|
||||||
var paidCurrency = Math.Round(cryptoPaid * paymentPrompt.Rate, cdCurrency.Divisibility);
|
var paidCurrency = Math.Round(cryptoPaid * paymentPrompt.Rate, cdCurrency.Divisibility);
|
||||||
var rateResult = await _rateProvider.FetchRate(
|
var rateResult = await _rateProvider.FetchRate(
|
||||||
|
@ -491,8 +496,6 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||||
{
|
{
|
||||||
return this.CreateValidationError(ModelState);
|
return this.CreateValidationError(ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dueAmount = accounting.TotalDue;
|
|
||||||
createPullPayment.Currency = paymentPrompt.Currency;
|
createPullPayment.Currency = paymentPrompt.Currency;
|
||||||
createPullPayment.Amount = Math.Round(paidAmount - dueAmount, appliedDivisibility);
|
createPullPayment.Amount = Math.Round(paidAmount - dueAmount, appliedDivisibility);
|
||||||
createPullPayment.AutoApproveClaims = true;
|
createPullPayment.AutoApproveClaims = true;
|
||||||
|
|
|
@ -302,12 +302,7 @@ namespace BTCPayServer.Controllers
|
||||||
|
|
||||||
// Find the most similar payment method to the one used for the invoice
|
// Find the most similar payment method to the one used for the invoice
|
||||||
var defaultRefund =
|
var defaultRefund =
|
||||||
PaymentMethodId.GetSimilarities(
|
invoice.GetClosestPayoutMethodId(payoutMethodIds);
|
||||||
invoice.Payments.Select(o => o.GetPaymentMethodId()),
|
|
||||||
payoutMethodIds)
|
|
||||||
.OrderByDescending(o => o.similarity)
|
|
||||||
.Select(o => o.b)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
var refund = new RefundModel
|
var refund = new RefundModel
|
||||||
{
|
{
|
||||||
|
@ -353,11 +348,7 @@ namespace BTCPayServer.Controllers
|
||||||
return View("_RefundModal", model);
|
return View("_RefundModal", model);
|
||||||
}
|
}
|
||||||
|
|
||||||
var availablePaymentMethodIds = invoice.GetPaymentPrompts().Select(p => p.PaymentMethodId).Where(p => _handlers.Support(p)).ToArray();
|
var paymentMethodId = invoice.GetClosestPaymentMethodId([pmi]);
|
||||||
var paymentMethodId = PaymentMethodId.GetSimilarities([pmi], availablePaymentMethodIds)
|
|
||||||
.OrderByDescending(o => o.similarity)
|
|
||||||
.Select(o => o.b)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
var paymentMethod = paymentMethodId is null ? null : invoice.GetPaymentPrompt(paymentMethodId);
|
var paymentMethod = paymentMethodId is null ? null : invoice.GetPaymentPrompt(paymentMethodId);
|
||||||
if (paymentMethod?.Currency is null)
|
if (paymentMethod?.Currency is null)
|
||||||
|
@ -367,8 +358,16 @@ namespace BTCPayServer.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
var accounting = paymentMethod.Calculate();
|
var accounting = paymentMethod.Calculate();
|
||||||
decimal cryptoPaid = accounting.Paid;
|
var cryptoPaid = accounting.Paid;
|
||||||
decimal dueAmount = accounting.TotalDue;
|
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 paymentMethodCurrency = paymentMethod.Currency;
|
||||||
|
|
||||||
var isPaidOver = invoice.ExceptionStatus == InvoiceExceptionStatus.PaidOver;
|
var isPaidOver = invoice.ExceptionStatus == InvoiceExceptionStatus.PaidOver;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection.Metadata;
|
using System.Reflection.Metadata;
|
||||||
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using NBitpayClient;
|
using NBitpayClient;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
@ -26,6 +29,28 @@ namespace BTCPayServer.Data
|
||||||
invoiceData.Amount = blob.Price;
|
invoiceData.Amount = blob.Price;
|
||||||
invoiceData.HasTypedBlob<InvoiceEntity>().SetBlob(blob, DefaultSerializer);
|
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)
|
public static InvoiceEntity GetBlob(this InvoiceData invoiceData)
|
||||||
{
|
{
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
|
|
Loading…
Add table
Reference in a new issue