btcpayserver/BTCPayServer/Controllers/UIBoltcardController.cs
Nicolas Dorier d050c8e3b2
Boltcard integration (#5419)
* Boltcard integration

* Add API for boltcard registration
2023-12-06 09:17:58 +09:00

71 lines
2.8 KiB
C#

#nullable enable
using Dapper;
using System.Linq;
using System.Security;
using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.NTag424;
using BTCPayServer.Services;
using LNURL;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Threading;
using System;
using NBitcoin.DataEncoders;
using System.Text.Json.Serialization;
namespace BTCPayServer.Controllers;
public class UIBoltcardController : Controller
{
public class BoltcardSettings
{
[JsonConverter(typeof(NBitcoin.JsonConverters.HexJsonConverter))]
public byte[]? IssuerKey { get; set; }
}
public UIBoltcardController(
UILNURLController lnUrlController,
SettingsRepository settingsRepository,
ApplicationDbContextFactory contextFactory,
BTCPayServerEnvironment env)
{
LNURLController = lnUrlController;
SettingsRepository = settingsRepository;
ContextFactory = contextFactory;
Env = env;
}
public UILNURLController LNURLController { get; }
public SettingsRepository SettingsRepository { get; }
public ApplicationDbContextFactory ContextFactory { get; }
public BTCPayServerEnvironment Env { get; }
[AllowAnonymous]
[HttpGet("~/boltcard")]
public async Task<IActionResult> GetWithdrawRequest([FromQuery] string? p, [FromQuery] string? c, [FromQuery] string? pr, [FromQuery] string? k1, CancellationToken cancellationToken)
{
if (p is null || c is null)
{
var k1s = k1?.Split('-');
if (k1s is not { Length: 2 })
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Missing p, c, or k1 query parameter" });
p = k1s[0];
c = k1s[1];
}
var issuerKey = await SettingsRepository.GetIssuerKey(Env);
var piccData = issuerKey.TryDecrypt(p);
if (piccData is null)
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Invalid PICCData" });
var registration = await ContextFactory.GetBoltcardRegistration(issuerKey, piccData, updateCounter: pr is not null);
if (registration?.PullPaymentId is null)
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Replayed or expired query" });
var cardKey = issuerKey.CreateCardKey(piccData.Uid, registration.Version);
if (!cardKey.CheckSunMac(c, piccData))
return BadRequest(new LNUrlStatusResponse { Status = "ERROR", Reason = "Replayed or expired query" });
LNURLController.ControllerContext.HttpContext = HttpContext;
return await LNURLController.GetLNURLForPullPayment("BTC", registration.PullPaymentId, pr, $"{p}-{c}", cancellationToken);
}
}