diff --git a/BTCPayServer.Client/Models/CreateInvoiceRequest.cs b/BTCPayServer.Client/Models/CreateInvoiceRequest.cs index 3987ff1c9..23fba6566 100644 --- a/BTCPayServer.Client/Models/CreateInvoiceRequest.cs +++ b/BTCPayServer.Client/Models/CreateInvoiceRequest.cs @@ -9,13 +9,9 @@ namespace BTCPayServer.Client.Models { [JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))] public decimal Amount { get; set; } - public string Currency { get; set; } - - public ProductInformation Metadata { get; set; } - - public BuyerInformation Customer { get; set; } = new BuyerInformation(); - + public string Metadata { get; set; } + public string CustomerEmail { get; set; } public CheckoutOptions Checkout { get; set; } = new CheckoutOptions(); public class CheckoutOptions @@ -34,49 +30,5 @@ namespace BTCPayServer.Client.Models [JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))] public double? PaymentTolerance { get; set; } } - - public class BuyerInformation - { - [JsonProperty(PropertyName = "buyerName")] - public string BuyerName { get; set; } - - [JsonProperty(PropertyName = "buyerEmail")] - public string BuyerEmail { get; set; } - - [JsonProperty(PropertyName = "buyerCountry")] - public string BuyerCountry { get; set; } - - [JsonProperty(PropertyName = "buyerZip")] - public string BuyerZip { get; set; } - - [JsonProperty(PropertyName = "buyerState")] - public string BuyerState { get; set; } - - [JsonProperty(PropertyName = "buyerCity")] - public string BuyerCity { get; set; } - - [JsonProperty(PropertyName = "buyerAddress2")] - public string BuyerAddress2 { get; set; } - - [JsonProperty(PropertyName = "buyerAddress1")] - public string BuyerAddress1 { get; set; } - - [JsonProperty(PropertyName = "buyerPhone")] - public string BuyerPhone { get; set; } - } - - public class ProductInformation - { - public string OrderId { get; set; } - public string PosData { get; set; } - - public string ItemDesc { get; set; } - - public string ItemCode { get; set; } - - public bool Physical { get; set; } - - public decimal? TaxIncluded { get; set; } - } } } diff --git a/BTCPayServer/Controllers/GreenField/InvoiceController.cs b/BTCPayServer/Controllers/GreenField/InvoiceController.cs index e0dd86743..2a3cd87aa 100644 --- a/BTCPayServer/Controllers/GreenField/InvoiceController.cs +++ b/BTCPayServer/Controllers/GreenField/InvoiceController.cs @@ -13,6 +13,8 @@ using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using NBitcoin; using NBitpayClient; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using CreateInvoiceRequest = BTCPayServer.Client.Models.CreateInvoiceRequest; using InvoiceData = BTCPayServer.Client.Models.InvoiceData; @@ -121,10 +123,10 @@ namespace BTCPayServer.Controllers.GreenField } } - if (!string.IsNullOrEmpty(request.Customer.BuyerEmail) && - !EmailValidator.IsEmail(request.Customer.BuyerEmail)) + if (!string.IsNullOrEmpty(request.CustomerEmail) && + !EmailValidator.IsEmail(request.CustomerEmail)) { - request.AddModelError(invoiceRequest => invoiceRequest.Customer.BuyerEmail, "Invalid email address", + request.AddModelError(invoiceRequest => invoiceRequest.CustomerEmail, "Invalid email address", this); } @@ -226,27 +228,8 @@ namespace BTCPayServer.Controllers.GreenField Status = entity.Status, ExceptionStatus = entity.ExceptionStatus, Currency = entity.ProductInformation.Currency, - Metadata = new CreateInvoiceRequest.ProductInformation() - { - Physical = entity.ProductInformation.Physical, - ItemCode = entity.ProductInformation.ItemCode, - ItemDesc = entity.ProductInformation.ItemDesc, - OrderId = entity.OrderId, - PosData = entity.PosData, - TaxIncluded = entity.ProductInformation.TaxIncluded - }, - Customer = new CreateInvoiceRequest.BuyerInformation() - { - BuyerAddress1 = entity.BuyerInformation.BuyerAddress1, - BuyerAddress2 = entity.BuyerInformation.BuyerAddress2, - BuyerCity = entity.BuyerInformation.BuyerCity, - BuyerCountry = entity.BuyerInformation.BuyerCountry, - BuyerEmail = entity.BuyerInformation.BuyerEmail, - BuyerName = entity.BuyerInformation.BuyerName, - BuyerPhone = entity.BuyerInformation.BuyerPhone, - BuyerState = entity.BuyerInformation.BuyerState, - BuyerZip = entity.BuyerInformation.BuyerZip - }, + Metadata = entity.PosData, + CustomerEmail = entity.RefundMail ?? entity.BuyerInformation.BuyerEmail, Checkout = new CreateInvoiceRequest.CheckoutOptions() { ExpirationTime = entity.ExpirationTime, @@ -306,37 +289,45 @@ namespace BTCPayServer.Controllers.GreenField private Models.CreateInvoiceRequest FromModel(CreateInvoiceRequest entity) { + Buyer buyer = null; + ProductInformation pi = null; + JToken? orderId = null; + if (!string.IsNullOrEmpty(entity.Metadata) && entity.Metadata.StartsWith('{')) + { + //metadata was provided and is json. Let's try and match props + try + { + buyer = JsonConvert.DeserializeObject(entity.Metadata); + pi = JsonConvert.DeserializeObject(entity.Metadata); + JObject.Parse(entity.Metadata).TryGetValue("orderid", StringComparison.InvariantCultureIgnoreCase, + out orderId); + } + catch + { + // ignored + } + } return new Models.CreateInvoiceRequest() { - Buyer = new Buyer() - { - country = entity.Customer.BuyerCountry, - email = entity.Customer.BuyerEmail, - phone = entity.Customer.BuyerPhone, - zip = entity.Customer.BuyerZip, - Address1 = entity.Customer.BuyerAddress1, - Address2 = entity.Customer.BuyerAddress2, - City = entity.Customer.BuyerCity, - Name = entity.Customer.BuyerName, - State = entity.Customer.BuyerState, - }, + Buyer = buyer, + BuyerEmail = entity.CustomerEmail, Currency = entity.Currency, - Physical = entity.Metadata.Physical, Price = entity.Amount, Refundable = true, ExtendedNotifications = true, FullNotifications = true, RedirectURL = entity.Checkout.RedirectUri, RedirectAutomatically = entity.Checkout.RedirectAutomatically, - ItemCode = entity.Metadata.ItemCode, - ItemDesc = entity.Metadata.ItemDesc, ExpirationTime = entity.Checkout.ExpirationTime, TransactionSpeed = entity.Checkout.SpeedPolicy?.ToString(), PaymentCurrencies = entity.Checkout.PaymentMethods, - TaxIncluded = entity.Metadata.TaxIncluded, - OrderId = entity.Metadata.OrderId, NotificationURL = entity.Checkout.RedirectUri, - PosData = entity.Metadata.PosData + PosData = entity.Metadata, + Physical = pi?.Physical??false, + ItemCode = pi?.ItemCode, + ItemDesc = pi?.ItemDesc, + TaxIncluded = pi?.TaxIncluded, + OrderId = orderId?.ToString() }; } } diff --git a/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json b/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json index 78179f9ec..26d5ce0d1 100644 --- a/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json +++ b/BTCPayServer/wwwroot/swagger/v1/swagger.template.invoices.json @@ -521,28 +521,21 @@ "format": "decimal", "description": "The amount of the invoice" }, + "customerEmail": { + "type": "string", + "format": "email", + "nullable": true, + "description": "The email of the customer. If the store is configured to ask for a refund email, the checkout UI will prompt for one when not provided." + }, "currency": { "type": "string", "nullable": true, "description": "The currency the invoice will use" }, "metadata": { + "type": "string", "nullable": true, - "oneOf": [ - { - "$ref": "#/components/schemas/ProductInformation" - } - ], - "description": "Additional information around the invoice" - }, - "customer": { - "nullable": true, - "oneOf": [ - { - "$ref": "#/components/schemas/BuyerInformation" - } - ], - "description": "Additional information around the entity the invoice is addressed to" + "description": "Additional information around the invoice that can be supplied.
You can pass a json body with values of `ProductInformation` `BuyerInformation` which will populate the fields to stay compatible with previous workflows (and bitpay invoice api)./>" }, "checkout": { "nullable": true,