mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 14:34:23 +01:00
Fix LNURL-Withdraw payments
Fixes comparisons of `long` and `LightMoney`, which did not work, because the `amount` provided was in sats and Lightmoney compares to millisats. Closes #4663.
This commit is contained in:
@@ -27,6 +27,7 @@ using BTCPayServer.Services.Stores;
|
|||||||
using LNURL;
|
using LNURL;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Routing;
|
using Microsoft.AspNetCore.Routing;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -84,7 +85,6 @@ namespace BTCPayServer
|
|||||||
[HttpGet("withdraw/pp/{pullPaymentId}")]
|
[HttpGet("withdraw/pp/{pullPaymentId}")]
|
||||||
public async Task<IActionResult> GetLNURLForPullPayment(string cryptoCode, string pullPaymentId, string pr, CancellationToken cancellationToken)
|
public async Task<IActionResult> GetLNURLForPullPayment(string cryptoCode, string pullPaymentId, string pr, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
|
||||||
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
|
||||||
if (network is null || !network.SupportLightning)
|
if (network is null || !network.SupportLightning)
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ namespace BTCPayServer
|
|||||||
var progress = _pullPaymentHostedService.CalculatePullPaymentProgress(pp, DateTimeOffset.UtcNow);
|
var progress = _pullPaymentHostedService.CalculatePullPaymentProgress(pp, DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
var remaining = progress.Limit - progress.Completed - progress.Awaiting;
|
var remaining = progress.Limit - progress.Completed - progress.Awaiting;
|
||||||
var request = new LNURLWithdrawRequest()
|
var request = new LNURLWithdrawRequest
|
||||||
{
|
{
|
||||||
MaxWithdrawable = LightMoney.FromUnit(remaining, LightMoneyUnit.BTC),
|
MaxWithdrawable = LightMoney.FromUnit(remaining, LightMoneyUnit.BTC),
|
||||||
K1 = pullPaymentId,
|
K1 = pullPaymentId,
|
||||||
@@ -121,7 +121,7 @@ namespace BTCPayServer
|
|||||||
Callback = new Uri(Request.GetCurrentUrl()),
|
Callback = new Uri(Request.GetCurrentUrl()),
|
||||||
// It's not `pp.GetBlob().Description` because this would be HTML
|
// It's not `pp.GetBlob().Description` because this would be HTML
|
||||||
// and LNUrl UI's doesn't expect HTML there
|
// and LNUrl UI's doesn't expect HTML there
|
||||||
DefaultDescription = pp.GetBlob().Name ?? String.Empty,
|
DefaultDescription = pp.GetBlob().Name ?? string.Empty,
|
||||||
};
|
};
|
||||||
if (pr is null)
|
if (pr is null)
|
||||||
{
|
{
|
||||||
@@ -130,11 +130,11 @@ namespace BTCPayServer
|
|||||||
|
|
||||||
if (!BOLT11PaymentRequest.TryParse(pr, out var result, network.NBitcoinNetwork) || result is null)
|
if (!BOLT11PaymentRequest.TryParse(pr, out var result, network.NBitcoinNetwork) || result is null)
|
||||||
{
|
{
|
||||||
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr was not a valid BOLT11" });
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Payment request was not a valid BOLT11" });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.MinimumAmount < request.MinWithdrawable || result.MinimumAmount > request.MaxWithdrawable)
|
if (result.MinimumAmount < request.MinWithdrawable || result.MinimumAmount > request.MaxWithdrawable)
|
||||||
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr was not within bounds" });
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = $"Payment request was not within bounds ({request.MinWithdrawable.ToUnit(LightMoneyUnit.Satoshi)} - {request.MaxWithdrawable.ToUnit(LightMoneyUnit.Satoshi)} sats)" });
|
||||||
var store = await _storeRepository.FindStore(pp.StoreId);
|
var store = await _storeRepository.FindStore(pp.StoreId);
|
||||||
var pm = store!.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
var pm = store!.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
||||||
.OfType<LightningSupportedPaymentMethod>()
|
.OfType<LightningSupportedPaymentMethod>()
|
||||||
@@ -154,7 +154,7 @@ namespace BTCPayServer
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (claimResponse.Result != ClaimRequest.ClaimResult.Ok)
|
if (claimResponse.Result != ClaimRequest.ClaimResult.Ok)
|
||||||
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr could not be paid" });
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Payment request could not be paid" });
|
||||||
switch (claimResponse.PayoutData.State)
|
switch (claimResponse.PayoutData.State)
|
||||||
{
|
{
|
||||||
case PayoutState.AwaitingPayment:
|
case PayoutState.AwaitingPayment:
|
||||||
@@ -169,7 +169,7 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
case PayResult.Ok:
|
case PayResult.Ok:
|
||||||
case PayResult.Unknown:
|
case PayResult.Unknown:
|
||||||
await _pullPaymentHostedService.MarkPaid(new MarkPayoutRequest()
|
await _pullPaymentHostedService.MarkPaid(new MarkPayoutRequest
|
||||||
{
|
{
|
||||||
PayoutId = claimResponse.PayoutData.Id,
|
PayoutId = claimResponse.PayoutData.Id,
|
||||||
State = claimResponse.PayoutData.State,
|
State = claimResponse.PayoutData.State,
|
||||||
@@ -185,15 +185,13 @@ namespace BTCPayServer
|
|||||||
case PayResult.Error:
|
case PayResult.Error:
|
||||||
default:
|
default:
|
||||||
await _pullPaymentHostedService.Cancel(
|
await _pullPaymentHostedService.Cancel(
|
||||||
new PullPaymentHostedService.CancelRequest(new string[]
|
new PullPaymentHostedService.CancelRequest(new []
|
||||||
{
|
{ claimResponse.PayoutData.Id }, null));
|
||||||
claimResponse.PayoutData.Id
|
|
||||||
}, null));
|
|
||||||
|
|
||||||
return Ok(new LNUrlStatusResponse
|
return BadRequest(new LNUrlStatusResponse
|
||||||
{
|
{
|
||||||
Status = "ERROR",
|
Status = "ERROR",
|
||||||
Reason = payResult.Message
|
Reason = payResult.Message ?? payResult.Result.ToString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,7 +206,7 @@ namespace BTCPayServer
|
|||||||
case PayoutState.Completed:
|
case PayoutState.Completed:
|
||||||
return Ok(new LNUrlStatusResponse { Status = "OK" });
|
return Ok(new LNUrlStatusResponse { Status = "OK" });
|
||||||
case PayoutState.Cancelled:
|
case PayoutState.Cancelled:
|
||||||
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Pr could not be paid" });
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Payment request could not be paid" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(request);
|
return Ok(request);
|
||||||
@@ -514,8 +512,8 @@ namespace BTCPayServer
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var min = new LightMoney(isTopup ? 1m : accounting.Due.ToUnit(MoneyUnit.Satoshi),
|
var amt = amount.HasValue ? new LightMoney(amount.Value) : null;
|
||||||
LightMoneyUnit.Satoshi);
|
var min = new LightMoney(isTopup ? 1m : accounting.Due.ToUnit(MoneyUnit.Satoshi), LightMoneyUnit.Satoshi);
|
||||||
var max = isTopup ? LightMoney.FromUnit(6.12m, LightMoneyUnit.BTC) : min;
|
var max = isTopup ? LightMoney.FromUnit(6.12m, LightMoneyUnit.BTC) : min;
|
||||||
|
|
||||||
List<string[]> lnurlMetadata = new();
|
List<string[]> lnurlMetadata = new();
|
||||||
@@ -533,13 +531,12 @@ namespace BTCPayServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
var metadata = JsonConvert.SerializeObject(lnurlMetadata);
|
var metadata = JsonConvert.SerializeObject(lnurlMetadata);
|
||||||
if (amount.HasValue && (amount < min || amount > max))
|
if (amt != null && (amt < min || amount > max))
|
||||||
{
|
{
|
||||||
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Amount is out of bounds." });
|
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Amount is out of bounds." });
|
||||||
}
|
}
|
||||||
|
|
||||||
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction successAction = null;
|
LNURLPayRequest.LNURLPayRequestCallbackResponse.ILNURLPayRequestSuccessAction successAction = null;
|
||||||
|
|
||||||
if ((i.ReceiptOptions?.Enabled ?? blob.ReceiptOptions.Enabled) is true)
|
if ((i.ReceiptOptions?.Enabled ?? blob.ReceiptOptions.Enabled) is true)
|
||||||
{
|
{
|
||||||
successAction =
|
successAction =
|
||||||
@@ -547,11 +544,17 @@ namespace BTCPayServer
|
|||||||
{
|
{
|
||||||
Tag = "url",
|
Tag = "url",
|
||||||
Description = "Thank you for your purchase. Here is your receipt",
|
Description = "Thank you for your purchase. Here is your receipt",
|
||||||
Url = _linkGenerator.GetUriByAction(HttpContext, "InvoiceReceipt", "UIInvoice", new { invoiceId })
|
Url = _linkGenerator.GetUriByAction(
|
||||||
|
nameof(UIInvoiceController.InvoiceReceipt),
|
||||||
|
"UIInvoice",
|
||||||
|
new { invoiceId },
|
||||||
|
Request.Scheme,
|
||||||
|
Request.Host,
|
||||||
|
Request.PathBase)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount is null)
|
if (amt is null)
|
||||||
{
|
{
|
||||||
return Ok(new LNURLPayRequest
|
return Ok(new LNURLPayRequest
|
||||||
{
|
{
|
||||||
@@ -564,7 +567,7 @@ namespace BTCPayServer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(paymentMethodDetails.BOLT11) || paymentMethodDetails.GeneratedBoltAmount != amount)
|
if (string.IsNullOrEmpty(paymentMethodDetails.BOLT11) || paymentMethodDetails.GeneratedBoltAmount != amt)
|
||||||
{
|
{
|
||||||
var client =
|
var client =
|
||||||
_lightningLikePaymentHandler.CreateLightningClient(
|
_lightningLikePaymentHandler.CreateLightningClient(
|
||||||
@@ -585,7 +588,7 @@ namespace BTCPayServer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var expiry = i.ExpirationTime.ToUniversalTime() - DateTimeOffset.UtcNow;
|
var expiry = i.ExpirationTime.ToUniversalTime() - DateTimeOffset.UtcNow;
|
||||||
var param = new CreateInvoiceParams(amount.Value, metadata, expiry)
|
var param = new CreateInvoiceParams(amt, metadata, expiry)
|
||||||
{
|
{
|
||||||
PrivateRouteHints = blob.LightningPrivateRouteHints,
|
PrivateRouteHints = blob.LightningPrivateRouteHints,
|
||||||
DescriptionHashOnly = true
|
DescriptionHashOnly = true
|
||||||
@@ -615,7 +618,7 @@ namespace BTCPayServer
|
|||||||
paymentMethodDetails.PaymentHash = string.IsNullOrEmpty(invoice.PaymentHash) ? null : uint256.Parse(invoice.PaymentHash);
|
paymentMethodDetails.PaymentHash = string.IsNullOrEmpty(invoice.PaymentHash) ? null : uint256.Parse(invoice.PaymentHash);
|
||||||
paymentMethodDetails.Preimage = string.IsNullOrEmpty(invoice.Preimage) ? null : uint256.Parse(invoice.Preimage);
|
paymentMethodDetails.Preimage = string.IsNullOrEmpty(invoice.Preimage) ? null : uint256.Parse(invoice.Preimage);
|
||||||
paymentMethodDetails.InvoiceId = invoice.Id;
|
paymentMethodDetails.InvoiceId = invoice.Id;
|
||||||
paymentMethodDetails.GeneratedBoltAmount = new LightMoney(amount.Value);
|
paymentMethodDetails.GeneratedBoltAmount = amt;
|
||||||
if (lnurlSupportedPaymentMethod.LUD12Enabled)
|
if (lnurlSupportedPaymentMethod.LUD12Enabled)
|
||||||
{
|
{
|
||||||
paymentMethodDetails.ProvidedComment = comment;
|
paymentMethodDetails.ProvidedComment = comment;
|
||||||
@@ -635,7 +638,7 @@ namespace BTCPayServer
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paymentMethodDetails.GeneratedBoltAmount == amount)
|
if (paymentMethodDetails.GeneratedBoltAmount == amt)
|
||||||
{
|
{
|
||||||
if (lnurlSupportedPaymentMethod.LUD12Enabled && paymentMethodDetails.ProvidedComment != comment)
|
if (lnurlSupportedPaymentMethod.LUD12Enabled && paymentMethodDetails.ProvidedComment != comment)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data.Payouts.LightningLike;
|
using BTCPayServer.Data.Payouts.LightningLike;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
@@ -13,6 +14,7 @@ using LNURL;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.NFC
|
namespace BTCPayServer.Plugins.NFC
|
||||||
{
|
{
|
||||||
@@ -21,19 +23,16 @@ namespace BTCPayServer.Plugins.NFC
|
|||||||
{
|
{
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly InvoiceRepository _invoiceRepository;
|
private readonly InvoiceRepository _invoiceRepository;
|
||||||
private readonly UILNURLController _uilnurlController;
|
|
||||||
private readonly InvoiceActivator _invoiceActivator;
|
private readonly InvoiceActivator _invoiceActivator;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
|
|
||||||
public NFCController(IHttpClientFactory httpClientFactory,
|
public NFCController(IHttpClientFactory httpClientFactory,
|
||||||
InvoiceRepository invoiceRepository,
|
InvoiceRepository invoiceRepository,
|
||||||
UILNURLController uilnurlController,
|
|
||||||
InvoiceActivator invoiceActivator,
|
InvoiceActivator invoiceActivator,
|
||||||
StoreRepository storeRepository)
|
StoreRepository storeRepository)
|
||||||
{
|
{
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_invoiceRepository = invoiceRepository;
|
_invoiceRepository = invoiceRepository;
|
||||||
_uilnurlController = uilnurlController;
|
|
||||||
_invoiceActivator = invoiceActivator;
|
_invoiceActivator = invoiceActivator;
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
}
|
}
|
||||||
@@ -86,8 +85,17 @@ namespace BTCPayServer.Plugins.NFC
|
|||||||
var httpClient = _httpClientFactory.CreateClient(uri.IsOnion()
|
var httpClient = _httpClientFactory.CreateClient(uri.IsOnion()
|
||||||
? LightningLikePayoutHandler.LightningLikePayoutHandlerOnionNamedClient
|
? LightningLikePayoutHandler.LightningLikePayoutHandlerOnionNamedClient
|
||||||
: LightningLikePayoutHandler.LightningLikePayoutHandlerClearnetNamedClient);
|
: LightningLikePayoutHandler.LightningLikePayoutHandlerClearnetNamedClient);
|
||||||
var info = (await
|
LNURLWithdrawRequest info;
|
||||||
LNURL.LNURL.FetchInformation(uri, "withdrawRequest", httpClient)) as LNURLWithdrawRequest;
|
try
|
||||||
|
{
|
||||||
|
info = await LNURL.LNURL.FetchInformation(uri, tag, httpClient) as LNURLWithdrawRequest;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var details = ex.InnerException?.Message ?? ex.Message;
|
||||||
|
return BadRequest($"Could not fetch info from LNURL-Withdraw: {details}");
|
||||||
|
}
|
||||||
|
|
||||||
if (info?.Callback is null)
|
if (info?.Callback is null)
|
||||||
{
|
{
|
||||||
return BadRequest("Could not fetch info from lnurl-withdraw ");
|
return BadRequest("Could not fetch info from lnurl-withdraw ");
|
||||||
@@ -101,10 +109,7 @@ namespace BTCPayServer.Plugins.NFC
|
|||||||
|
|
||||||
if (lnPaymentMethod is not null)
|
if (lnPaymentMethod is not null)
|
||||||
{
|
{
|
||||||
if (lnPaymentMethod.GetPaymentMethodDetails() is LightningLikePaymentMethodDetails
|
if (lnPaymentMethod.GetPaymentMethodDetails() is LightningLikePaymentMethodDetails { Activated: false } lnPMD)
|
||||||
{
|
|
||||||
Activated: false
|
|
||||||
} lnPMD)
|
|
||||||
{
|
{
|
||||||
var store = await _storeRepository.FindStore(invoice.StoreId);
|
var store = await _storeRepository.FindStore(invoice.StoreId);
|
||||||
await _invoiceActivator.ActivateInvoicePaymentMethod(lnPaymentMethod.GetId(), invoice, store);
|
await _invoiceActivator.ActivateInvoicePaymentMethod(lnPaymentMethod.GetId(), invoice, store);
|
||||||
@@ -149,27 +154,29 @@ namespace BTCPayServer.Plugins.NFC
|
|||||||
due = lnurlPaymentMethod.Calculate().Due;
|
due = lnurlPaymentMethod.Calculate().Due;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = await _uilnurlController.GetLNURLForInvoice(request.InvoiceId, "BTC",
|
var amount = LightMoney.Satoshis(due.Satoshi);
|
||||||
due.Satoshi);
|
var actionPath = Url.Action(nameof(UILNURLController.GetLNURLForInvoice), "UILNURL",
|
||||||
|
new { invoiceId = request.InvoiceId, cryptoCode = "BTC", amount = amount.MilliSatoshi });
|
||||||
|
var url = Request.GetAbsoluteUri(actionPath);
|
||||||
|
var resp = await httpClient.GetAsync(url);
|
||||||
|
var response = await resp.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
if (response is ObjectResult objectResult)
|
if (resp.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
switch (objectResult.Value)
|
var res = JObject.Parse(response).ToObject<LNURLPayRequest.LNURLPayRequestCallbackResponse>();
|
||||||
{
|
bolt11 = res.Pr;
|
||||||
case LNURLPayRequest.LNURLPayRequestCallbackResponse lnurlPayRequestCallbackResponse:
|
}
|
||||||
bolt11 = lnurlPayRequestCallbackResponse.Pr;
|
else
|
||||||
break;
|
{
|
||||||
case LNUrlStatusResponse lnUrlStatusResponse:
|
var res = JObject.Parse(response).ToObject<LNUrlStatusResponse>();
|
||||||
|
return BadRequest(
|
||||||
return BadRequest(
|
$"Could not fetch BOLT11 invoice to pay to: {res.Reason}");
|
||||||
$"Could not fetch bolt11 invoice to pay to: {lnUrlStatusResponse.Reason}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bolt11 is null)
|
if (bolt11 is null)
|
||||||
{
|
{
|
||||||
return BadRequest("Could not fetch bolt11 invoice to pay to.");
|
return BadRequest("Could not fetch BOLT11 invoice to pay to.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await info.SendRequest(bolt11, httpClient);
|
var result = await info.SendRequest(bolt11, httpClient);
|
||||||
|
|||||||
@@ -2,19 +2,23 @@
|
|||||||
@using BTCPayServer.Abstractions.TagHelpers
|
@using BTCPayServer.Abstractions.TagHelpers
|
||||||
<template id="lnurl-withdraw-template">
|
<template id="lnurl-withdraw-template">
|
||||||
<template v-if="display">
|
<template v-if="display">
|
||||||
<button v-if="isV2" class="btn btn-secondary rounded-pill w-100 mt-4" type="button"
|
<div class="mt-4">
|
||||||
:disabled="scanning || submitting" v-on:click="startScan" :id="btnId"
|
<p id="CheatSuccessMessage" class="alert alert-success text-break" v-if="successMessage" v-text="successMessage"></p>
|
||||||
:class="{ 'loading': scanning || submitting, 'text-secondary': !supported }">{{btnText}}</button>
|
<p id="CheatErrorMessage" class="alert alert-danger text-break" v-if="errorMessage" v-text="errorMessage"></p>
|
||||||
<bp-loading-button v-else>
|
<button v-if="isV2" class="btn btn-secondary rounded-pill w-100" type="button"
|
||||||
<button class="action-button" style="margin: 0 45px;width:calc(100% - 90px) !important"
|
:disabled="scanning || submitting" v-on:click="startScan" :id="btnId"
|
||||||
:disabled="scanning || submitting" v-on:click="startScan" :id="btnId"
|
:class="{ 'loading': scanning || submitting, 'text-secondary': !supported }">{{btnText}}</button>
|
||||||
:class="{ 'loading': scanning || submitting, 'action-button': supported, 'btn btn-text w-100': !supported }">
|
<bp-loading-button v-else>
|
||||||
<span class="button-text">{{btnText}}</span>
|
<button class="action-button" style="margin: 0 45px;width:calc(100% - 90px) !important"
|
||||||
<div class="loader-wrapper">
|
:disabled="scanning || submitting" v-on:click="startScan" :id="btnId"
|
||||||
@await Html.PartialAsync("~/Views/UIInvoice/Checkout-Spinner.cshtml")
|
:class="{ 'loading': scanning || submitting, 'action-button': supported, 'btn btn-text w-100': !supported }">
|
||||||
</div>
|
<span class="button-text">{{btnText}}</span>
|
||||||
</button>
|
<div class="loader-wrapper">
|
||||||
</bp-loading-button>
|
@await Html.PartialAsync("~/Views/UIInvoice/Checkout-Spinner.cshtml")
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</bp-loading-button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
@@ -61,7 +65,9 @@ Vue.component("lnurl-withdraw-checkout", {
|
|||||||
scanning: false,
|
scanning: false,
|
||||||
submitting: false,
|
submitting: false,
|
||||||
readerAbortController: null,
|
readerAbortController: null,
|
||||||
amount: 0
|
amount: 0,
|
||||||
|
successMessage: null,
|
||||||
|
errorMessage: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -72,13 +78,13 @@ Vue.component("lnurl-withdraw-checkout", {
|
|||||||
}
|
}
|
||||||
if (this.model.isUnsetTopUp) {
|
if (this.model.isUnsetTopUp) {
|
||||||
const amountStr = prompt("How many sats do you want to pay?")
|
const amountStr = prompt("How many sats do you want to pay?")
|
||||||
if (amountStr){
|
if (amountStr) {
|
||||||
try {
|
try {
|
||||||
this.amount = parseInt(amountStr)
|
this.amount = parseInt(amountStr)
|
||||||
} catch {
|
} catch {
|
||||||
alert("Please provide a valid number amount in sats");
|
alert("Please provide a valid number amount in sats");
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,9 +93,9 @@ Vue.component("lnurl-withdraw-checkout", {
|
|||||||
self.submitting = false;
|
self.submitting = false;
|
||||||
self.scanning = true;
|
self.scanning = true;
|
||||||
if (!this.supported) {
|
if (!this.supported) {
|
||||||
const result = prompt("Enter LNURL withdraw");
|
const result = prompt("Enter LNURL-Withdraw");
|
||||||
if (result) {
|
if (result) {
|
||||||
self.sendData.bind(self)(result);
|
await self.sendData.bind(self)(result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.scanning = false;
|
self.scanning = false;
|
||||||
@@ -103,7 +109,7 @@ Vue.component("lnurl-withdraw-checkout", {
|
|||||||
self.readerAbortController.abort()
|
self.readerAbortController.abort()
|
||||||
})
|
})
|
||||||
|
|
||||||
ndef.addEventListener('reading', ({message, serialNumber}) => {
|
ndef.addEventListener('reading', async ({message, serialNumber}) => {
|
||||||
//Decode NDEF data from tag
|
//Decode NDEF data from tag
|
||||||
const record = message.records[0]
|
const record = message.records[0]
|
||||||
const textDecoder = new TextDecoder('utf-8')
|
const textDecoder = new TextDecoder('utf-8')
|
||||||
@@ -111,38 +117,38 @@ Vue.component("lnurl-withdraw-checkout", {
|
|||||||
|
|
||||||
//User feedback, show loader icon
|
//User feedback, show loader icon
|
||||||
self.scanning = false;
|
self.scanning = false;
|
||||||
self.sendData.bind(self)(lnurl);
|
await self.sendData.bind(self)(lnurl);
|
||||||
|
|
||||||
})
|
})
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
self.scanning = false;
|
self.scanning = false;
|
||||||
self.submitting = false;
|
self.submitting = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sendData: function (lnurl) {
|
sendData: async function (lnurl) {
|
||||||
this.submitting = true;
|
this.submitting = true;
|
||||||
//Post LNURLW data to server
|
this.successMessage = null;
|
||||||
var xhr = new XMLHttpRequest()
|
this.errorMessage = null;
|
||||||
xhr.open('POST', this.url, true)
|
|
||||||
xhr.setRequestHeader('Content-Type', 'application/json')
|
// Post LNURL-Withdraw data to server
|
||||||
xhr.send(JSON.stringify({lnurl, invoiceId: this.model.invoiceId, amount: this.amount}))
|
const body = JSON.stringify({ lnurl, invoiceId: this.model.invoiceId, amount: this.amount })
|
||||||
const self = this;
|
const opts = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body }
|
||||||
//User feedback, reset on failure
|
const response = await fetch(this.url, opts)
|
||||||
xhr.onload = function () {
|
|
||||||
if (xhr.readyState === xhr.DONE) {
|
// Handle response
|
||||||
console.log(xhr.response);
|
try {
|
||||||
console.log(xhr.responseText);
|
const result = await response.text()
|
||||||
self.scanning = false;
|
if (response.ok) {
|
||||||
self.submitting = false;
|
this.successMessage = result;
|
||||||
|
} else {
|
||||||
if(self.readerAbortController) {
|
this.errorMessage = result;
|
||||||
self.readerAbortController.abort()
|
|
||||||
}
|
|
||||||
|
|
||||||
if(xhr.response){
|
|
||||||
alert(xhr.response)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.errorMessage = error;
|
||||||
|
}
|
||||||
|
this.scanning = false;
|
||||||
|
this.submitting = false;
|
||||||
|
if (this.readerAbortController) {
|
||||||
|
this.readerAbortController.abort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user