mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
[Greenfield] Can create an invoice for a payment request via Greenfield (#4243)
* [Greenfield] Can create an invoice for a payment request via Greenfield * Add allowPendingInvoiceReuse so payment request invoices can be reused * Add PayPaymentRequest to the LocalBTCPayServerClient * Allow amount to be specified if same as PR amount
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
using BTCPayServer.Abstractions.Extensions;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.PaymentRequest;
|
||||
using BTCPayServer.Security;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using BTCPayServer.Services.PaymentRequests;
|
||||
using BTCPayServer.Services.Rates;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Cors;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
|
||||
|
||||
namespace BTCPayServer.Controllers.Greenfield
|
||||
@@ -22,14 +26,26 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
public class GreenfieldPaymentRequestsController : ControllerBase
|
||||
{
|
||||
private readonly InvoiceRepository _InvoiceRepository;
|
||||
private readonly UIInvoiceController _invoiceController;
|
||||
private readonly PaymentRequestRepository _paymentRequestRepository;
|
||||
private readonly CurrencyNameTable _currencyNameTable;
|
||||
private readonly LinkGenerator _linkGenerator;
|
||||
|
||||
public GreenfieldPaymentRequestsController(PaymentRequestRepository paymentRequestRepository,
|
||||
CurrencyNameTable currencyNameTable)
|
||||
public GreenfieldPaymentRequestsController(
|
||||
InvoiceRepository invoiceRepository,
|
||||
UIInvoiceController invoiceController,
|
||||
PaymentRequestRepository paymentRequestRepository,
|
||||
PaymentRequestService paymentRequestService,
|
||||
CurrencyNameTable currencyNameTable,
|
||||
LinkGenerator linkGenerator)
|
||||
{
|
||||
_InvoiceRepository = invoiceRepository;
|
||||
_invoiceController = invoiceController;
|
||||
_paymentRequestRepository = paymentRequestRepository;
|
||||
PaymentRequestService = paymentRequestService;
|
||||
_currencyNameTable = currencyNameTable;
|
||||
_linkGenerator = linkGenerator;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewPaymentRequests, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
@@ -56,6 +72,62 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return Ok(FromModel(pr.First()));
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewPaymentRequests, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[HttpPost("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}/pay")]
|
||||
public async Task<IActionResult> PayPaymentRequest(string storeId, string paymentRequestId, [FromBody] PayPaymentRequestRequest pay, CancellationToken cancellationToken)
|
||||
{
|
||||
var pr = await this.PaymentRequestService.GetPaymentRequest(paymentRequestId);
|
||||
if (pr is null || pr.StoreId != storeId)
|
||||
return PaymentRequestNotFound();
|
||||
|
||||
var amount = pay?.Amount;
|
||||
if (amount.HasValue && amount.Value <= 0)
|
||||
{
|
||||
ModelState.AddModelError(nameof(pay.Amount), "The amount should be more than 0");
|
||||
}
|
||||
if (amount.HasValue && !pr.AllowCustomPaymentAmounts && amount.Value != pr.AmountDue)
|
||||
{
|
||||
ModelState.AddModelError(nameof(pay.Amount), "This payment request doesn't allow custom payment amount");
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
return this.CreateValidationError(ModelState);
|
||||
|
||||
if (pr.Archived)
|
||||
{
|
||||
return this.CreateAPIError("archived", "You cannot pay an archived payment request");
|
||||
}
|
||||
|
||||
if (pr.AmountDue <= 0)
|
||||
{
|
||||
return this.CreateAPIError("already-paid", "This payment request is already paid");
|
||||
}
|
||||
|
||||
if (pr.ExpiryDate.HasValue && DateTime.UtcNow >= pr.ExpiryDate)
|
||||
{
|
||||
return this.CreateAPIError("expired", "This payment request is expired");
|
||||
}
|
||||
|
||||
if (pay?.AllowPendingInvoiceReuse is true)
|
||||
{
|
||||
if (pr.Invoices.GetReusableInvoice(amount)?.Id is string invoiceId)
|
||||
{
|
||||
var inv = await _InvoiceRepository.GetInvoice(invoiceId);
|
||||
return Ok(GreenfieldInvoiceController.ToModel(inv, _linkGenerator, Request));
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var invoice = await _invoiceController.CreatePaymentRequestInvoice(pr, amount, this.StoreData, Request, cancellationToken);
|
||||
return Ok(GreenfieldInvoiceController.ToModel(invoice, _linkGenerator, Request));
|
||||
}
|
||||
catch (BitpayHttpException e)
|
||||
{
|
||||
return this.CreateAPIError(null, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanModifyPaymentRequests,
|
||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[HttpDelete("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}")]
|
||||
@@ -97,6 +169,9 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
return Ok(FromModel(pr));
|
||||
}
|
||||
public Data.StoreData StoreData => HttpContext.GetStoreData();
|
||||
|
||||
public PaymentRequestService PaymentRequestService { get; }
|
||||
|
||||
[HttpPut("~/api/v1/stores/{storeId}/payment-requests/{paymentRequestId}")]
|
||||
[Authorize(Policy = Policies.CanModifyPaymentRequests,
|
||||
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
|
||||
Reference in New Issue
Block a user