btcpayserver/BTCPayServer/Controllers/InvoiceController.cs

126 lines
5.1 KiB
C#
Raw Normal View History

2017-09-13 08:47:34 +02:00
using BTCPayServer.Authentication;
using System.Reflection;
using System.Linq;
using Microsoft.Extensions.Logging;
using BTCPayServer.Logging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NBitpayClient;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using BTCPayServer.Models;
using Newtonsoft.Json;
using System.Globalization;
using NBitcoin;
using NBitcoin.DataEncoders;
using BTCPayServer.Filters;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System.Net;
using Microsoft.AspNetCore.Identity;
using Newtonsoft.Json.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using NBitcoin.Payment;
using BTCPayServer.Data;
using BTCPayServer.Models.InvoicingModels;
using System.Security.Claims;
using BTCPayServer.Services;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using BTCPayServer.Services.Stores;
using BTCPayServer.Servcices.Invoices;
using BTCPayServer.Services.Rates;
using BTCPayServer.Services.Wallets;
2017-09-27 07:18:09 +02:00
using BTCPayServer.Validations;
using Microsoft.EntityFrameworkCore;
2017-09-27 08:16:30 +02:00
using Microsoft.AspNetCore.Mvc.Routing;
using NBXplorer.DerivationStrategy;
using NBXplorer;
2017-09-13 08:47:34 +02:00
namespace BTCPayServer.Controllers
{
public partial class InvoiceController : Controller
{
TokenRepository _TokenRepository;
InvoiceRepository _InvoiceRepository;
BTCPayWallet _Wallet;
IRateProvider _RateProvider;
private InvoiceWatcher _Watcher;
StoreRepository _StoreRepository;
Network _Network;
UserManager<ApplicationUser> _UserManager;
IFeeProvider _FeeProvider;
ExplorerClient _Explorer;
2017-09-13 08:47:34 +02:00
public InvoiceController(
Network network,
InvoiceRepository invoiceRepository,
UserManager<ApplicationUser> userManager,
TokenRepository tokenRepository,
BTCPayWallet wallet,
IRateProvider rateProvider,
StoreRepository storeRepository,
InvoiceWatcher watcher,
ExplorerClient explorerClient,
2017-09-13 08:47:34 +02:00
IFeeProvider feeProvider)
{
_Explorer = explorerClient ?? throw new ArgumentNullException(nameof(explorerClient));
2017-09-13 08:47:34 +02:00
_StoreRepository = storeRepository ?? throw new ArgumentNullException(nameof(storeRepository));
_Network = network ?? throw new ArgumentNullException(nameof(network));
_TokenRepository = tokenRepository ?? throw new ArgumentNullException(nameof(tokenRepository));
_InvoiceRepository = invoiceRepository ?? throw new ArgumentNullException(nameof(invoiceRepository));
_Wallet = wallet ?? throw new ArgumentNullException(nameof(wallet));
_RateProvider = rateProvider ?? throw new ArgumentNullException(nameof(rateProvider));
_Watcher = watcher ?? throw new ArgumentNullException(nameof(watcher));
_UserManager = userManager;
_FeeProvider = feeProvider ?? throw new ArgumentNullException(nameof(feeProvider));
}
private async Task<DataWrapper<InvoiceResponse>> CreateInvoiceCore(Invoice invoice, StoreData store)
{
var derivationStrategy = store.DerivationStrategy;
var entity = new InvoiceEntity
{
InvoiceTime = DateTimeOffset.UtcNow,
2017-09-13 16:50:36 +02:00
DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy")
2017-09-13 08:47:34 +02:00
};
Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null;
if(notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https")) //TODO: Filer non routable addresses ?
notificationUri = null;
2017-09-13 08:47:34 +02:00
EmailAddressAttribute emailValidator = new EmailAddressAttribute();
entity.ExpirationTime = entity.InvoiceTime + TimeSpan.FromMinutes(15.0);
2017-09-27 08:16:30 +02:00
entity.ServerUrl = HttpContext.Request.GetAbsoluteRoot();
entity.FullNotifications = invoice.FullNotifications;
entity.NotificationURL = notificationUri?.AbsoluteUri;
2017-09-13 08:47:34 +02:00
entity.BuyerInformation = Map<Invoice, BuyerInformation>(invoice);
2017-09-27 07:18:09 +02:00
entity.RefundMail = EmailValidator.IsEmail(entity?.BuyerInformation?.BuyerEmail) ? entity.BuyerInformation.BuyerEmail : null;
2017-09-13 08:47:34 +02:00
entity.ProductInformation = Map<Invoice, ProductInformation>(invoice);
entity.RedirectURL = invoice.RedirectURL ?? store.StoreWebsite;
entity.Status = "new";
entity.SpeedPolicy = store.SpeedPolicy;
entity.TxFee = (await _FeeProvider.GetFeeRateAsync()).GetFee(100); // assume price for 100 bytes
entity.Rate = (double)await _RateProvider.GetRateAsync(invoice.Currency);
entity.PosData = invoice.PosData;
entity.DepositAddress = await _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy));
2017-09-13 08:47:34 +02:00
entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity);
await _Wallet.MapAsync(entity.DepositAddress.ScriptPubKey, entity.Id);
2017-09-13 08:47:34 +02:00
await _Watcher.WatchAsync(entity.Id);
2017-09-27 08:16:30 +02:00
var resp = entity.EntityToDTO();
2017-09-13 08:47:34 +02:00
return new DataWrapper<InvoiceResponse>(resp) { Facade = "pos/invoice" };
}
private DerivationStrategyBase ParseDerivationStrategy(string derivationStrategy)
{
return new DerivationStrategyFactory(_Network).Parse(derivationStrategy);
}
2017-09-13 08:47:34 +02:00
private TDest Map<TFrom, TDest>(TFrom data)
{
return JsonConvert.DeserializeObject<TDest>(JsonConvert.SerializeObject(data));
}
}
}