Fake payment fixes (#3058)

Fixes and various minor improvements for the fake payment form.
This commit is contained in:
d11n
2021-11-11 10:31:15 +01:00
committed by GitHub
parent 28694859c9
commit 08f57558da
2 changed files with 61 additions and 95 deletions

View File

@@ -1,42 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Mime;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events;
using BTCPayServer.Filters; using BTCPayServer.Filters;
using BTCPayServer.Logging;
using BTCPayServer.HostedServices;
using BTCPayServer.Models;
using BTCPayServer.Models.InvoicingModels;
using BTCPayServer.Payments; using BTCPayServer.Payments;
using BTCPayServer.Payments.Lightning;
using BTCPayServer.Rating;
using BTCPayServer.Security;
using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Invoices.Export;
using BTCPayServer.Services.Rates;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;
using Microsoft.EntityFrameworkCore;
using NBitcoin; using NBitcoin;
using NBitcoin.RPC;
using NBitpayClient;
using NBXplorer;
using Newtonsoft.Json.Linq;
using BitpayCreateInvoiceRequest = BTCPayServer.Models.BitpayCreateInvoiceRequest;
using StoreData = BTCPayServer.Data.StoreData;
using BTCPayServer.Services; using BTCPayServer.Services;
namespace BTCPayServer.Controllers namespace BTCPayServer.Controllers
@@ -46,7 +15,9 @@ namespace BTCPayServer.Controllers
public class FakePaymentRequest public class FakePaymentRequest
{ {
public Decimal Amount { get; set; } public Decimal Amount { get; set; }
public string CryptoCode { get; set; } = "BTC";
} }
[HttpPost] [HttpPost]
[Route("i/{invoiceId}/test-payment")] [Route("i/{invoiceId}/test-payment")]
[CheatModeRoute] [CheatModeRoute]
@@ -56,21 +27,16 @@ namespace BTCPayServer.Controllers
var store = await _StoreRepository.FindStore(invoice.StoreId); var store = await _StoreRepository.FindStore(invoice.StoreId);
// TODO support altcoins, not just bitcoin // TODO support altcoins, not just bitcoin
//var network = invoice.Networks.GetNetwork(invoice.Currency); var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(request.CryptoCode);
var cryptoCode = "BTC"; var paymentMethodId = store.GetDefaultPaymentId() ?? store.GetEnabledPaymentIds(_NetworkProvider).FirstOrDefault(p => p.CryptoCode == request.CryptoCode && p.PaymentType == PaymentTypes.BTCLike);
var network = _NetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
var paymentMethodId = store.GetDefaultPaymentId();
//var network = NetworkProvider.GetNetwork<BTCPayNetwork>("BTC");
var bitcoinAddressString = invoice.GetPaymentMethod(paymentMethodId).GetPaymentMethodDetails().GetPaymentDestination(); var bitcoinAddressString = invoice.GetPaymentMethod(paymentMethodId).GetPaymentMethodDetails().GetPaymentDestination();
var bitcoinAddressObj = BitcoinAddress.Create(bitcoinAddressString, network.NBitcoinNetwork); var bitcoinAddressObj = BitcoinAddress.Create(bitcoinAddressString, network.NBitcoinNetwork);
var BtcAmount = request.Amount; var BtcAmount = request.Amount;
try try
{ {
var paymentMethod = invoice.GetPaymentMethod(paymentMethodId); var paymentMethod = invoice.GetPaymentMethod(paymentMethodId);
var rate = paymentMethod.Rate; var rate = paymentMethod.Rate;
var txid = cheater.CashCow.SendToAddress(bitcoinAddressObj, new Money(BtcAmount, MoneyUnit.BTC)).ToString(); var txid = cheater.CashCow.SendToAddress(bitcoinAddressObj, new Money(BtcAmount, MoneyUnit.BTC)).ToString();
// TODO The value of totalDue is wrong. How can we get the real total due? invoice.Price is only correct if this is the 2nd payment, not for a 3rd or 4th payment. // TODO The value of totalDue is wrong. How can we get the real total due? invoice.Price is only correct if this is the 2nd payment, not for a 3rd or 4th payment.

View File

@@ -2,22 +2,24 @@
<div id="testing"> <div id="testing">
<hr class="my-3" /> <hr class="my-3" />
<form id="test-payment" action="/i/@Model.InvoiceId/test-payment" method="post" class="form-inline my-2">
<div class="form-group mb-1">
<label for="test-payment-crypto-code" class="control-label">{{$t("Fake a @Model.CryptoCode payment for testing")}}</label>
<p class="alert alert-danger" style="display: none; word-break: break-all;"></p> <p class="alert alert-danger" style="display: none; word-break: break-all;"></p>
<p class="alert alert-success" style="display: none; word-break: break-all;"></p> <p class="alert alert-success" style="display: none; word-break: break-all;"></p>
<form id="test-payment" action="/i/@Model.InvoiceId/test-payment" method="post" class="form-inline my-2">
<input name="CryptoCode" type="hidden" value="@Model.CryptoCode">
<div class="form-group mb-1">
<label for="test-payment-amount" class="control-label">{{$t("Fake a @Model.CryptoCode payment for testing")}}</label>
<div class="input-group"> <div class="input-group">
<input id="test-payment-amount" name="amount" type="number" step="any" min="0" class="form-control" placeholder="Amount" value="@Model.BtcDue" aria-label="Amount" aria-describedby="test-payment-crypto-code"> <input id="test-payment-amount" name="Amount" type="number" step="0.00000001" min="0" class="form-control" placeholder="Amount" value="@Model.BtcDue" />
<div class="input-group-addon" id="test-payment-crypto-code">@Model.CryptoCode</div> <div id="test-payment-crypto-code" class="input-group-addon">@Model.CryptoCode</div>
</div> </div>
</div> </div>
<button class="btn btn-primary" type="submit">{{$t("Fake Payment")}}</button> <button class="btn btn-primary" type="submit">{{$t("Fake Payment")}}</button>
<p class="text-muted mt-1">{{$t("This is the same as running bitcoin-cli.sh sendtoaddress xxx")}}</p> <p class="text-muted mt-1">{{$t("This is the same as running bitcoin-cli.sh sendtoaddress xxx")}}</p>
</form> </form>
<form id="expire-invoice" action="/i/@Model.InvoiceId/expire" method="post" class="mb-1"> <form id="expire-invoice" action="/i/@Model.InvoiceId/expire" method="post" class="mb-1">
<button class="btn btn-secondary" type="submit">{{$t("Expire Invoice Now")}} (TODO)</button> <button class="btn btn-secondary" type="submit">{{$t("Expire Invoice Now")}}</button>
</form> </form>
@* TODO
<form id="expire-monitoring" action="/i/@Model.InvoiceId/expire-monitoring" method="post" class="mb-1"> <form id="expire-monitoring" action="/i/@Model.InvoiceId/expire-monitoring" method="post" class="mb-1">
<!-- TODO only show when expired --> <!-- TODO only show when expired -->
<button class="btn btn-secondary" type="submit">{{$t("Expire Monitoring Now")}} (TODO)</button> <button class="btn btn-secondary" type="submit">{{$t("Expire Monitoring Now")}} (TODO)</button>
@@ -27,81 +29,79 @@
<!-- TODO to make it work use Bitcoin RPC calls getnewaddress + generatetoaddress --> <!-- TODO to make it work use Bitcoin RPC calls getnewaddress + generatetoaddress -->
<button class="btn btn-secondary" type="submit">{{$t("Mine a block now")}} (TODO)</button> <button class="btn btn-secondary" type="submit">{{$t("Mine a block now")}} (TODO)</button>
</form> </form>
*@
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
let payForm = $('form#test-payment'); const payForm = $('form#test-payment');
let loader = $('form#test-payment-loading'); const loader = $('form#test-payment-loading');
let inputField = $('#test-payment-amount'); const inputField = $('#test-payment-amount');
let submitButton = payForm.find('button[type=submit]'); const successAlert = $('#testing p.alert-success');
let paySuccess = payForm.find('p.alert-success'); const errorAlert = $('#testing p.alert-danger');
let payAlert = payForm.find('p.alert-danger'); const submitButton = payForm.find('button[type=submit]');
const expireForm = $('form#expire-invoice');
const expireButton = expireForm.find('[type=submit]');
payForm.submit(function (e){ payForm.submit(e => {
e.preventDefault(); e.preventDefault();
let form = $(this); const form = $(e.target);
let data = form.serialize(); const url = form.attr('action');
const data = form.serialize();
paySuccess.hide(); successAlert.hide();
payAlert.hide(); errorAlert.hide();
loader.show(); loader.show();
inputField.prop('disabled', true); inputField.prop('disabled', true);
submitButton.prop('disabled', true); submitButton.prop('disabled', true);
$.post({ $.post({
url: form.attr('action'), url,
data: data, data,
success: function (data,status,xhr){ success(data) {
paySuccess.html(data.successMessage); const { successMessage, amountRemaining } = data;
paySuccess.show(); successAlert.html(successMessage);
inputField.val(data.amountRemaining); successAlert.show();
if (data.amountRemaining <= 0){ if (amountRemaining > 0) {
// No need to fake any more payments. inputField.val(amountRemaining);
} else {
form.hide(); form.hide();
expireForm.hide();
} }
}, },
complete: function (xhr,status){ error(xhr) {
const { errorMessage } = JSON.parse(xhr.responseText);
errorAlert.html(errorMessage).show();
},
complete() {
loader.hide(); loader.hide();
inputField.prop('disabled', false); inputField.prop('disabled', false);
submitButton.prop('disabled', false); submitButton.prop('disabled', false);
},
error: function (xhr,status,error){
var data = JSON.parse(xhr.responseText);
payAlert.html(data.errorMessage);
payAlert.show();
} }
}); });
}); });
// Expire invoice form // Expire invoice form
let expireForm = $('form#expire-invoice'); expireForm.submit(e => {
let expireButton = expireForm.find('[type=submit]');
let expireSuccess = expireForm.find('p.alert-success');
let expireAlert = expireForm.find('p.alert-danger');
expireForm.submit(function (e){
e.preventDefault(); e.preventDefault();
expireSuccess.hide(); successAlert.hide();
expireAlert.hide(); errorAlert.hide();
$.post({ $.post({
url: form.attr('action'), url: expireForm.attr('action'),
data: data, success(data) {
success: function (data,status,xhr){ const { successMessage } = data;
expireSuccess.html(data.successMessage); successAlert.html(successMessage).show();
expireSuccess.show();
expireButton.hide(); expireButton.hide();
}, },
complete: function (xhr,status){ complete() {
loader.hide(); loader.hide();
submitButton.prop('disabled', false); submitButton.prop('disabled', false);
}, },
error: function (xhr,status,error){ error(xhr) {
var data = JSON.parse(xhr.responseText); const { errorMessage } = JSON.parse(xhr.responseText);
expireAlert.html(data.errorMessage); errorAlert.html(errorMessage).show();
expireAlert.show();
} }
}); });
}); });