2017-09-13 08:47:34 +02:00
|
|
|
|
using BTCPayServer.Filters;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using BTCPayServer.Logging;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using NBitcoin;
|
|
|
|
|
using NBitcoin.Payment;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace BTCPayServer.Controllers
|
|
|
|
|
{
|
|
|
|
|
public partial class InvoiceController
|
|
|
|
|
{
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("i/{invoiceId}")]
|
|
|
|
|
[AcceptMediaTypeConstraint("application/bitcoin-paymentrequest")]
|
2017-12-21 07:52:04 +01:00
|
|
|
|
public async Task<IActionResult> GetInvoiceRequest(string invoiceId, string cryptoCode = null)
|
2017-10-27 10:53:04 +02:00
|
|
|
|
{
|
2017-12-21 07:52:04 +01:00
|
|
|
|
if (cryptoCode == null)
|
|
|
|
|
cryptoCode = "BTC";
|
2017-10-27 10:53:04 +02:00
|
|
|
|
var invoice = await _InvoiceRepository.GetInvoice(null, invoiceId);
|
2017-12-21 07:52:04 +01:00
|
|
|
|
var network = _NetworkProvider.GetNetwork(cryptoCode);
|
|
|
|
|
if (invoice == null || invoice.IsExpired() || network == null || !invoice.Support(network))
|
2017-10-27 10:53:04 +02:00
|
|
|
|
return NotFound();
|
2017-09-13 08:47:34 +02:00
|
|
|
|
|
2017-12-21 07:52:04 +01:00
|
|
|
|
var dto = invoice.EntityToDTO(_NetworkProvider);
|
|
|
|
|
var cryptoData = dto.CryptoInfo.First(c => c.CryptoCode.Equals(cryptoCode, StringComparison.OrdinalIgnoreCase));
|
2017-10-27 10:53:04 +02:00
|
|
|
|
PaymentRequest request = new PaymentRequest
|
|
|
|
|
{
|
|
|
|
|
DetailsVersion = 1
|
|
|
|
|
};
|
|
|
|
|
request.Details.Expires = invoice.ExpirationTime;
|
|
|
|
|
request.Details.Memo = invoice.ProductInformation.ItemDesc;
|
2017-12-21 07:52:04 +01:00
|
|
|
|
request.Details.Network = network.NBitcoinNetwork;
|
|
|
|
|
request.Details.Outputs.Add(new PaymentOutput() { Amount = cryptoData.Due, Script = BitcoinAddress.Create(cryptoData.Address, network.NBitcoinNetwork).ScriptPubKey });
|
2017-10-27 10:53:04 +02:00
|
|
|
|
request.Details.MerchantData = Encoding.UTF8.GetBytes(invoice.Id);
|
|
|
|
|
request.Details.Time = DateTimeOffset.UtcNow;
|
|
|
|
|
request.Details.PaymentUrl = new Uri(invoice.ServerUrl.WithTrailingSlash() + ($"i/{invoice.Id}"), UriKind.Absolute);
|
2017-09-13 08:47:34 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
var store = await _StoreRepository.FindStore(invoice.StoreId);
|
|
|
|
|
if (store == null)
|
|
|
|
|
throw new BitpayHttpException(401, "Unknown store");
|
2017-09-13 08:47:34 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
if (store.StoreCertificate != null)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
request.Sign(store.StoreCertificate, PKIType.X509SHA256);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Logs.PayServer.LogWarning(ex, "Error while signing payment request");
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-13 08:47:34 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
return new PaymentRequestActionResult(request);
|
|
|
|
|
}
|
2017-09-13 08:47:34 +02:00
|
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
|
[HttpPost]
|
|
|
|
|
[Route("i/{invoiceId}", Order = 99)]
|
|
|
|
|
[MediaTypeConstraint("application/bitcoin-payment")]
|
|
|
|
|
public async Task<IActionResult> PostPayment(string invoiceId)
|
|
|
|
|
{
|
|
|
|
|
var invoice = await _InvoiceRepository.GetInvoice(null, invoiceId);
|
|
|
|
|
if (invoice == null || invoice.IsExpired())
|
|
|
|
|
return NotFound();
|
|
|
|
|
var payment = PaymentMessage.Load(Request.Body);
|
|
|
|
|
var unused = _Wallet.BroadcastTransactionsAsync(payment.Transactions);
|
|
|
|
|
await _InvoiceRepository.AddRefundsAsync(invoiceId, payment.RefundTo.Select(p => new TxOut(p.Amount, p.Script)).ToArray());
|
|
|
|
|
return new PaymentAckActionResult(payment.CreateACK(invoiceId + " is currently processing, thanks for your purchase..."));
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-13 08:47:34 +02:00
|
|
|
|
}
|