mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
View offchain payments in Invoice screen
This commit is contained in:
@@ -85,54 +85,66 @@ namespace BTCPayServer.Controllers
|
||||
model.CryptoPayments.Add(cryptoPayment);
|
||||
}
|
||||
|
||||
var payments = invoice
|
||||
var onChainPayments = invoice
|
||||
.GetPayments()
|
||||
.Where(p => p.GetPaymentMethodId().PaymentType == PaymentTypes.BTCLike)
|
||||
.Select(async payment =>
|
||||
.Select<PaymentEntity, Task<object>>(async payment =>
|
||||
{
|
||||
var paymentData = (Payments.Bitcoin.BitcoinLikePaymentData)payment.GetCryptoPaymentData();
|
||||
var m = new InvoiceDetailsModel.Payment();
|
||||
var paymentNetwork = _NetworkProvider.GetNetwork(payment.GetCryptoCode());
|
||||
m.PaymentMethod = ToString(payment.GetPaymentMethodId());
|
||||
m.DepositAddress = paymentData.Output.ScriptPubKey.GetDestinationAddress(paymentNetwork.NBitcoinNetwork);
|
||||
|
||||
int confirmationCount = 0;
|
||||
if ( (paymentData.ConfirmationCount < paymentNetwork.MaxTrackedConfirmation && payment.Accounted)
|
||||
&& (paymentData.Legacy || invoice.MonitoringExpiration < DateTimeOffset.UtcNow)) // The confirmation count in the paymentData is not up to date
|
||||
var paymentData = payment.GetCryptoPaymentData();
|
||||
if (paymentData is Payments.Bitcoin.BitcoinLikePaymentData onChainPaymentData)
|
||||
{
|
||||
confirmationCount = (await ((ExplorerClientProvider)_ServiceProvider.GetService(typeof(ExplorerClientProvider))).GetExplorerClient(payment.GetCryptoCode())?.GetTransactionAsync(paymentData.Outpoint.Hash))?.Confirmations ?? 0;
|
||||
paymentData.ConfirmationCount = confirmationCount;
|
||||
payment.SetCryptoPaymentData(paymentData);
|
||||
await _InvoiceRepository.UpdatePayments(new List<PaymentEntity> { payment });
|
||||
var m = new InvoiceDetailsModel.Payment();
|
||||
m.Crypto = payment.GetPaymentMethodId().CryptoCode;
|
||||
m.DepositAddress = onChainPaymentData.Output.ScriptPubKey.GetDestinationAddress(paymentNetwork.NBitcoinNetwork);
|
||||
|
||||
int confirmationCount = 0;
|
||||
if ((onChainPaymentData.ConfirmationCount < paymentNetwork.MaxTrackedConfirmation && payment.Accounted)
|
||||
&& (onChainPaymentData.Legacy || invoice.MonitoringExpiration < DateTimeOffset.UtcNow)) // The confirmation count in the paymentData is not up to date
|
||||
{
|
||||
confirmationCount = (await ((ExplorerClientProvider)_ServiceProvider.GetService(typeof(ExplorerClientProvider))).GetExplorerClient(payment.GetCryptoCode())?.GetTransactionAsync(onChainPaymentData.Outpoint.Hash))?.Confirmations ?? 0;
|
||||
onChainPaymentData.ConfirmationCount = confirmationCount;
|
||||
payment.SetCryptoPaymentData(onChainPaymentData);
|
||||
await _InvoiceRepository.UpdatePayments(new List<PaymentEntity> { payment });
|
||||
}
|
||||
else
|
||||
{
|
||||
confirmationCount = onChainPaymentData.ConfirmationCount;
|
||||
}
|
||||
if (confirmationCount >= paymentNetwork.MaxTrackedConfirmation)
|
||||
{
|
||||
m.Confirmations = "At least " + (paymentNetwork.MaxTrackedConfirmation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Confirmations = confirmationCount.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
m.TransactionId = onChainPaymentData.Outpoint.Hash.ToString();
|
||||
m.ReceivedTime = payment.ReceivedTime;
|
||||
m.TransactionLink = string.Format(CultureInfo.InvariantCulture, paymentNetwork.BlockExplorerLink, m.TransactionId);
|
||||
m.Replaced = !payment.Accounted;
|
||||
return m;
|
||||
}
|
||||
else
|
||||
{
|
||||
confirmationCount = paymentData.ConfirmationCount;
|
||||
var lightningPaymentData = (Payments.Lightning.LightningLikePaymentData)paymentData;
|
||||
return new InvoiceDetailsModel.OffChainPayment()
|
||||
{
|
||||
Crypto = paymentNetwork.CryptoCode,
|
||||
BOLT11 = lightningPaymentData.BOLT11
|
||||
};
|
||||
}
|
||||
if (confirmationCount >= paymentNetwork.MaxTrackedConfirmation)
|
||||
{
|
||||
m.Confirmations = "At least " + (paymentNetwork.MaxTrackedConfirmation);
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Confirmations = confirmationCount.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
m.TransactionId = paymentData.Outpoint.Hash.ToString();
|
||||
m.ReceivedTime = payment.ReceivedTime;
|
||||
m.TransactionLink = string.Format(CultureInfo.InvariantCulture, paymentNetwork.BlockExplorerLink, m.TransactionId);
|
||||
m.Replaced = !payment.Accounted;
|
||||
return m;
|
||||
})
|
||||
.ToArray();
|
||||
await Task.WhenAll(payments);
|
||||
await Task.WhenAll(onChainPayments);
|
||||
model.Addresses = invoice.HistoricalAddresses.Select(h => new InvoiceDetailsModel.AddressModel
|
||||
{
|
||||
Destination = h.GetAddress(),
|
||||
PaymentMethod = ToString(h.GetPaymentMethodId()),
|
||||
Current = !h.UnAssigned.HasValue
|
||||
}).ToArray();
|
||||
model.Payments = payments.Select(p => p.GetAwaiter().GetResult()).ToList();
|
||||
model.OnChainPayments = onChainPayments.Select(p => p.GetAwaiter().GetResult()).OfType<InvoiceDetailsModel.Payment>().ToList();
|
||||
model.OffChainPayments = onChainPayments.Select(p => p.GetAwaiter().GetResult()).OfType<InvoiceDetailsModel.OffChainPayment>().ToList();
|
||||
model.StatusMessage = StatusMessage;
|
||||
return View(model);
|
||||
}
|
||||
@@ -439,7 +451,7 @@ namespace BTCPayServer.Controllers
|
||||
return View(model);
|
||||
}
|
||||
|
||||
if(StatusMessage != null)
|
||||
if (StatusMessage != null)
|
||||
{
|
||||
return RedirectToAction(nameof(StoresController.UpdateStore), "Stores", new
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||
}
|
||||
public class Payment
|
||||
{
|
||||
public string PaymentMethod { get; set; }
|
||||
public string Crypto { get; set; }
|
||||
public string Confirmations
|
||||
{
|
||||
get; set;
|
||||
@@ -72,7 +72,13 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||
get; set;
|
||||
} = new List<CryptoPayment>();
|
||||
|
||||
public List<Payment> Payments { get; set; } = new List<Payment>();
|
||||
public List<Payment> OnChainPayments { get; set; } = new List<Payment>();
|
||||
public List<OffChainPayment> OffChainPayments { get; set; } = new List<OffChainPayment>();
|
||||
public class OffChainPayment
|
||||
{
|
||||
public string Crypto { get; set; }
|
||||
public string BOLT11 { get; set; }
|
||||
}
|
||||
|
||||
public string Status
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.money {
|
||||
text-align: right;
|
||||
}
|
||||
@@ -165,46 +166,74 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var payment in Model.CryptoPayments)
|
||||
{
|
||||
<tr>
|
||||
<td>@payment.PaymentMethod</td>
|
||||
<td>@payment.Address</td>
|
||||
<td class="money">@payment.Rate</td>
|
||||
<td class="money">@payment.Paid</td>
|
||||
<td class="money">@payment.Due</td>
|
||||
</tr>
|
||||
}
|
||||
{
|
||||
<tr>
|
||||
<td>@payment.PaymentMethod</td>
|
||||
<td>@payment.Address</td>
|
||||
<td class="money">@payment.Rate</td>
|
||||
<td class="money">@payment.Paid</td>
|
||||
<td class="money">@payment.Due</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>Payments</h3>
|
||||
<table class="table table-sm">
|
||||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<th style="white-space:nowrap;">Payment method</th>
|
||||
<th>Deposit address</th>
|
||||
<th>Transaction Id</th>
|
||||
<th style="text-align:right;">Confirmations</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var payment in Model.Payments)
|
||||
{
|
||||
var replaced = payment.Replaced ? "text-decoration: line-through;" : "";
|
||||
<tr>
|
||||
<td style="@replaced">@payment.PaymentMethod</td>
|
||||
<td style="@replaced">@payment.DepositAddress</td>
|
||||
<td style="@replaced"><a href="@payment.TransactionLink" target="_blank">@payment.TransactionId</a></td>
|
||||
<td style="text-align:right;">@payment.Confirmations</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@if(Model.OnChainPayments.Count > 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>On-Chain payments</h3>
|
||||
<table class="table table-sm">
|
||||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<th style="white-space:nowrap;">Crypto</th>
|
||||
<th>Deposit address</th>
|
||||
<th>Transaction Id</th>
|
||||
<th style="text-align:right;">Confirmations</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var payment in Model.OnChainPayments)
|
||||
{
|
||||
var replaced = payment.Replaced ? "text-decoration: line-through;" : "";
|
||||
<tr>
|
||||
<td style="@replaced">@payment.Crypto</td>
|
||||
<td style="@replaced">@payment.DepositAddress</td>
|
||||
<td style="@replaced"><a href="@payment.TransactionLink" target="_blank">@payment.TransactionId</a></td>
|
||||
<td style="text-align:right;">@payment.Confirmations</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if(Model.OffChainPayments.Count > 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>Off-Chain payments</h3>
|
||||
<table class="table table-sm">
|
||||
<thead class="thead-inverse">
|
||||
<tr>
|
||||
<th style="white-space:nowrap;">Crypto</th>
|
||||
<th>BOLT11</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(var payment in Model.OffChainPayments)
|
||||
{
|
||||
<tr>
|
||||
<td style="width:50px;">@payment.Crypto</td>
|
||||
<td style="max-width:100px;overflow:hidden;">@payment.BOLT11</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3>Addresses</h3>
|
||||
@@ -219,11 +248,11 @@
|
||||
@foreach(var address in Model.Addresses)
|
||||
{
|
||||
var current = address.Current ? "font-weight: bold;" : "";
|
||||
<tr>
|
||||
<td style="width:100px;@current">@address.PaymentMethod</td>
|
||||
<td style="max-width:100px;overflow:hidden;@current">@address.Destination</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td style="width:100px;@current">@address.PaymentMethod</td>
|
||||
<td style="max-width:100px;overflow:hidden;@current">@address.Destination</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user