Save paymentRequestId in Metadata when creating invoice for Payment Request (#2644)

* Save paymentRequestId in Metadata when creating invoice

* Added Payment Request ID + link on invoice detail page

* Added paymentRequestId to the webhook payload

* Removed PaymentRequestId from webhook payload (rolled back previous change)

* Using strongly typed InvoiceMetadata

* Added OrderUrl metadata field to invoice + link

* Added Metadata.OrderUrl to docs

* Made orderUrl visible when no orderId is present
This commit is contained in:
Wouter Samaey
2021-07-14 13:43:13 +02:00
committed by GitHub
parent 73c89ac28d
commit 15be593bbd
6 changed files with 71 additions and 19 deletions

View File

@@ -110,6 +110,7 @@ namespace BTCPayServer.Controllers
StoreId = store.Id, StoreId = store.Id,
StoreName = store.StoreName, StoreName = store.StoreName,
StoreLink = Url.Action(nameof(StoresController.UpdateStore), "Stores", new { storeId = store.Id }), StoreLink = Url.Action(nameof(StoresController.UpdateStore), "Stores", new { storeId = store.Id }),
PaymentRequestLink = Url.Action(nameof(PaymentRequestController.ViewPaymentRequest), "PaymentRequest", new { id = invoice.Metadata.PaymentRequestId }),
Id = invoice.Id, Id = invoice.Id,
State = invoice.GetInvoiceState().ToString(), State = invoice.GetInvoiceState().ToString(),
TransactionSpeed = invoice.SpeedPolicy == SpeedPolicy.HighSpeed ? "high" : TransactionSpeed = invoice.SpeedPolicy == SpeedPolicy.HighSpeed ? "high" :

View File

@@ -8,12 +8,9 @@ using BTCPayServer.Abstractions.Extensions;
using BTCPayServer.Abstractions.Models; using BTCPayServer.Abstractions.Models;
using BTCPayServer.Client.Models; using BTCPayServer.Client.Models;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events;
using BTCPayServer.Filters; using BTCPayServer.Filters;
using BTCPayServer.Models;
using BTCPayServer.Models.PaymentRequestViewModels; using BTCPayServer.Models.PaymentRequestViewModels;
using BTCPayServer.PaymentRequest; using BTCPayServer.PaymentRequest;
using BTCPayServer.Security;
using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.PaymentRequests; using BTCPayServer.Services.PaymentRequests;
using BTCPayServer.Services.Rates; using BTCPayServer.Services.Rates;
@@ -23,7 +20,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using BitpayCreateInvoiceRequest = BTCPayServer.Models.BitpayCreateInvoiceRequest; using Newtonsoft.Json.Linq;
using PaymentRequestData = BTCPayServer.Data.PaymentRequestData; using PaymentRequestData = BTCPayServer.Data.PaymentRequestData;
using StoreData = BTCPayServer.Data.StoreData; using StoreData = BTCPayServer.Data.StoreData;
@@ -266,25 +263,33 @@ namespace BTCPayServer.Controllers
try try
{ {
var redirectUrl = _linkGenerator.PaymentRequestLink(id, Request.Scheme, Request.Host, Request.PathBase); var redirectUrl = _linkGenerator.PaymentRequestLink(id, Request.Scheme, Request.Host, Request.PathBase);
var newInvoiceId = (await _InvoiceController.CreateInvoiceCore(new BitpayCreateInvoiceRequest()
var invoiceMetadata =
new InvoiceMetadata
{ {
OrderId = $"{PaymentRequestRepository.GetOrderIdForPaymentRequest(id)}", OrderId = PaymentRequestRepository.GetOrderIdForPaymentRequest(id),
PaymentRequestId = id,
BuyerEmail = result.Email
};
var invoiceRequest =
new CreateInvoiceRequest
{
Metadata = invoiceMetadata.ToJObject(),
Currency = blob.Currency, Currency = blob.Currency,
Price = amount.Value, Amount = amount.Value,
FullNotifications = true, Checkout = {RedirectURL = redirectUrl}
BuyerEmail = result.Email, };
RedirectURL = redirectUrl,
}, store, HttpContext.Request.GetAbsoluteRoot(), var additionalTags = new List<string>() {PaymentRequestRepository.GetInternalTag(id)};
new List<string>() { PaymentRequestRepository.GetInternalTag(id) }, var newInvoice = await _InvoiceController.CreateInvoiceCoreRaw(invoiceRequest,store, "/",additionalTags, cancellationToken);
cancellationToken: cancellationToken))
.Data.Id;
if (redirectToInvoice) if (redirectToInvoice)
{ {
return RedirectToAction("Checkout", "Invoice", new { Id = newInvoiceId }); return RedirectToAction("Checkout", "Invoice", new { Id = newInvoice.Id });
} }
return Ok(newInvoiceId); return Ok(newInvoice.Id);
} }
catch (BitpayHttpException e) catch (BitpayHttpException e)
{ {

View File

@@ -97,6 +97,13 @@ namespace BTCPayServer.Models.InvoicingModels
get; get;
set; set;
} }
public string PaymentRequestLink
{
get;
set;
}
public string NotificationUrl public string NotificationUrl
{ {
get; get;

View File

@@ -38,6 +38,18 @@ namespace BTCPayServer.Services.Invoices
set => SetMetadata("orderId", value); set => SetMetadata("orderId", value);
} }
[JsonIgnore] [JsonIgnore]
public string OrderUrl
{
get => GetMetadata<string>("orderUrl");
set => SetMetadata("orderUrl", value);
}
[JsonIgnore]
public string PaymentRequestId
{
get => GetMetadata<string>("paymentRequestId");
set => SetMetadata("paymentRequestId", value);
}
[JsonIgnore]
public string BuyerName{ public string BuyerName{
get => GetMetadata<string>("buyerName"); get => GetMetadata<string>("buyerName");
set => SetMetadata("buyerName", value); set => SetMetadata("buyerName", value);

View File

@@ -66,7 +66,29 @@
</tr> </tr>
<tr> <tr>
<th>Order Id</th> <th>Order Id</th>
<td>@Model.TypedMetadata.OrderId</td> <td>
@if (string.IsNullOrEmpty(Model.TypedMetadata.OrderUrl))
{
@Model.TypedMetadata.OrderId
}
else
{
<a href="@Model.TypedMetadata.OrderUrl" rel="noreferrer noopener" target="_blank">
@if (string.IsNullOrEmpty(Model.TypedMetadata.OrderId))
{
<span>View Order</span>
}
else
{
@Model.TypedMetadata.OrderId
}
</a>
}
</td>
</tr>
<tr>
<th>Payment Request Id</th>
<td><a href="@Model.PaymentRequestLink">@Model.TypedMetadata.PaymentRequestId</a></td>
</tr> </tr>
<tr> <tr>
<th>State</th> <th>State</th>

View File

@@ -800,6 +800,11 @@
"type": "string", "type": "string",
"nullable": true, "nullable": true,
"description": "You can use this property to store the ID of an external system. We allow you to search in the invoice list based on this ID." "description": "You can use this property to store the ID of an external system. We allow you to search in the invoice list based on this ID."
},
"orderUrl": {
"type": "string",
"nullable": true,
"description": "You can use this property to store the URL to the order of an external system. This makes navigating to the order easier."
} }
} }
}, },