mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-03-12 10:30:47 +01:00
Boltcard Balance
This commit is contained in:
parent
4c0c2d2e94
commit
a4485b5377
6 changed files with 174 additions and 2 deletions
|
@ -22,6 +22,9 @@
|
|||
<EmbeddedResource Remove="wwwroot\vendor\jquery-nice-select\**" />
|
||||
<None Remove="Build\**" />
|
||||
<None Remove="wwwroot\vendor\jquery-nice-select\**" />
|
||||
<Content Update="Plugins\BoltcardBalance\Views\ScanCard.cshtml">
|
||||
<Pack>$(IncludeRazorContentInPack)</Pack>
|
||||
</Content>
|
||||
<Content Update="Plugins\BoltcardFactory\Views\UpdateBoltcardFactory.cshtml">
|
||||
<Pack>false</Pack>
|
||||
</Content>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#nullable enable
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Abstractions.Models;
|
||||
using BTCPayServer.Abstractions.Services;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Configuration;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.HostedServices;
|
||||
using BTCPayServer.Plugins.BoltcardFactory.Controllers;
|
||||
using BTCPayServer.Plugins.PointOfSale;
|
||||
using BTCPayServer.Plugins.PointOfSale.Controllers;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace BTCPayServer.Plugins.BoltcardBalance
|
||||
{
|
||||
public class BoltcardBalancePlugin : BaseBTCPayServerPlugin
|
||||
{
|
||||
public const string ViewsDirectory = "/Plugins/BoltcardBalance/Views";
|
||||
public const string AppType = "BoltcardBalance";
|
||||
|
||||
public override string Identifier => "BTCPayServer.Plugins.BoltcardBalance";
|
||||
public override string Name => "BoltcardBalance";
|
||||
public override string Description => "Add ability to check the history and balance of a Boltcard";
|
||||
|
||||
public override void Execute(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IUIExtension>(new UIExtension($"{ViewsDirectory}/NavExtension.cshtml", "header-nav"));
|
||||
base.Execute(services);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using BTCPayServer.Plugins.BoltcardFactory;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BTCPayServer.Plugins.BoltcardBalance.Controllers
|
||||
{
|
||||
[AutoValidateAntiforgeryToken]
|
||||
public class UIBoltcardBalanceController : Controller
|
||||
{
|
||||
[HttpGet("boltcards/balance")]
|
||||
public IActionResult ScanCard()
|
||||
{
|
||||
return base.View($"{BoltcardBalancePlugin.ViewsDirectory}/ScanCard.cshtml");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
@using BTCPayServer.Client
|
||||
@using BTCPayServer.Plugins.BoltcardFactory
|
||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@using BTCPayServer.Views.Apps
|
||||
@using BTCPayServer.Abstractions.Extensions
|
||||
@using BTCPayServer.Abstractions.TagHelpers
|
||||
|
||||
|
||||
<li class="nav-item">
|
||||
<a asp-area="" asp-controller="UIBoltcardBalance" asp-action="ScanCard" class="nav-link">
|
||||
<vc:icon symbol="pay-button" />
|
||||
<span>Boltcard Balance</span>
|
||||
</a>
|
||||
</li>
|
106
BTCPayServer/Plugins/BoltcardBalance/Views/ScanCard.cshtml
Normal file
106
BTCPayServer/Plugins/BoltcardBalance/Views/ScanCard.cshtml
Normal file
|
@ -0,0 +1,106 @@
|
|||
@{
|
||||
ViewData["Title"] = "C";
|
||||
Layout = "/Views/Shared/_LayoutWizard.cshtml";
|
||||
}
|
||||
|
||||
<header class="text-center">
|
||||
<h1>Consult balance</h1>
|
||||
<p class="lead text-secondary mt-3" id="explanation">Scan your card for consulting the balance</p>
|
||||
</header>
|
||||
|
||||
<div id="body" class="my-4">
|
||||
<div id="actions" class="d-flex align-items-center justify-content-center">
|
||||
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
||||
<a id="ask-permission-btn" class="btn btn-primary" href="#">Ask permission...</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="qr" class="d-flex flex-column align-items-center justify-content-center">
|
||||
<div class="d-inline-flex flex-column" style="width:256px">
|
||||
<div class="qr-container mb-2">
|
||||
<vc:qr-code data="@Context.Request.GetCurrentUrl()" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-secondary">NFC not supported in this device</p>
|
||||
</div>
|
||||
<div id="scanning-btn" class="d-flex align-items-center justify-content-center">
|
||||
<div class="d-flex gap-3 mt-3 mt-sm-0">
|
||||
<a id="scanning-btn-link" class="btn btn-primary"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var permissionGranted = false;
|
||||
var ndef = null;
|
||||
var abortController = null;
|
||||
async function askPermissionNFC() {
|
||||
if (!('NDEFReader' in window)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
permissionGranted = navigator.permissions && (await navigator.permissions.query({ name: 'nfc' })).state === 'granted';
|
||||
} catch (e) { }
|
||||
|
||||
if (permissionGranted) {
|
||||
setState("WaitingForCard");
|
||||
ndef = new NDEFReader();
|
||||
abortController = new AbortController();
|
||||
abortController.signal.onabort = () => setState("WaitingForCard");
|
||||
|
||||
await ndef.scan({ signal: abortController.signal })
|
||||
|
||||
ndef.onreading = async ({ message }) => {
|
||||
const record = message.records[0]
|
||||
const textDecoder = new TextDecoder('utf-8')
|
||||
const decoded = textDecoder.decode(record.data)
|
||||
console.log("Read: " + decoded);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function setState(state)
|
||||
{
|
||||
if (state === "NFCNotSupported")
|
||||
{
|
||||
document.getElementById("actions").classList.add("d-none");
|
||||
document.getElementById("qr").classList.remove("d-none");
|
||||
document.getElementById("scanning-btn").classList.add("d-none");
|
||||
}
|
||||
else if (state === "WaitingForPermission")
|
||||
{
|
||||
|
||||
document.getElementById("actions").classList.remove("d-none");
|
||||
document.getElementById("qr").classList.add("d-none");
|
||||
document.getElementById("scanning-btn").classList.add("d-none");
|
||||
}
|
||||
else if (state === "WaitingForCard")
|
||||
{
|
||||
document.getElementById("actions").classList.add("d-none");
|
||||
document.getElementById("qr").classList.add("d-none");
|
||||
document.getElementById("scanning-btn").classList.remove("d-none");
|
||||
document.getElementById("scanning-btn-link").innerText = "Please, present your card..."
|
||||
}
|
||||
else if (state == "Scanning")
|
||||
{
|
||||
document.getElementById("actions").classList.add("d-none");
|
||||
document.getElementById("qr").classList.add("d-none");
|
||||
document.getElementById("scanning-btn").classList.remove("d-none");
|
||||
document.getElementById("scanning-btn-link").innerText = "Reading..."
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
var nfcSupported = 'NDEFReader' in window;
|
||||
if (!nfcSupported) {
|
||||
setState("NFCNotSupported");
|
||||
}
|
||||
else {
|
||||
setState("WaitingForPermission");
|
||||
askPermissionNFC();
|
||||
}
|
||||
delegate('click', "#ask-permission-btn", askPermissionNFC);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
@model ViewBoltcardFactoryViewModel
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "C";
|
||||
ViewData["Title"] = "Boltcard factory";
|
||||
Layout = "/Views/Shared/_LayoutWizard.cshtml";
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
|||
<vc:qr-code data="@Context.Request.GetCurrentUrl()" />
|
||||
</div>
|
||||
</div>
|
||||
</di>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue