mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-19 05:33:31 +01:00
do not crash invoice if wellknown metadata keys used with different e… (#2448)
* do not crash invoice if wellknown metadata keys used with different expected types * fix * add bits from alt PR
This commit is contained in:
parent
5fe3c1c61f
commit
4e1b18e2bb
@ -2366,7 +2366,9 @@ namespace BTCPayServer.Tests
|
||||
{
|
||||
("{ invalidjson file here}",
|
||||
new Dictionary<string, object>() {{String.Empty, "{ invalidjson file here}"}})
|
||||
}
|
||||
},
|
||||
// Duplicate keys should not crash things
|
||||
{("{ \"key\": true, \"key\": true}", new Dictionary<string, object>() {{"key", "True"}})}
|
||||
};
|
||||
|
||||
testCases.ForEach(tuple =>
|
||||
|
@ -903,21 +903,20 @@ namespace BTCPayServer.Controllers
|
||||
var jObject = JObject.Parse(posData);
|
||||
foreach (var item in jObject)
|
||||
{
|
||||
|
||||
switch (item.Value.Type)
|
||||
{
|
||||
case JTokenType.Array:
|
||||
var items = item.Value.AsEnumerable().ToList();
|
||||
for (var i = 0; i < items.Count; i++)
|
||||
{
|
||||
result.Add($"{item.Key}[{i}]", ParsePosData(items[i].ToString()));
|
||||
result.TryAdd($"{item.Key}[{i}]", ParsePosData(items[i].ToString()));
|
||||
}
|
||||
break;
|
||||
case JTokenType.Object:
|
||||
result.Add(item.Key, ParsePosData(item.Value.ToString()));
|
||||
result.TryAdd(item.Key, ParsePosData(item.Value.ToString()));
|
||||
break;
|
||||
default:
|
||||
result.Add(item.Key, item.Value.ToString());
|
||||
result.TryAdd(item.Key, item.Value.ToString());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -925,7 +924,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
catch
|
||||
{
|
||||
result.Add(string.Empty, posData);
|
||||
result.TryAdd(string.Empty, posData);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using BTCPayServer.Abstractions.Contracts;
|
||||
using BTCPayServer.Configuration;
|
||||
using McMaster.NETCore.Plugins;
|
||||
@ -28,7 +27,7 @@ namespace BTCPayServer.Plugins
|
||||
|
||||
public static bool IsExceptionByPlugin(Exception exception)
|
||||
{
|
||||
return _pluginAssemblies.Any(assembly => assembly.FullName.Contains(exception.Source, StringComparison.OrdinalIgnoreCase));
|
||||
return _pluginAssemblies.Any(assembly => assembly?.FullName?.Contains(exception.Source!, StringComparison.OrdinalIgnoreCase) is true);
|
||||
}
|
||||
public static IMvcBuilder AddPlugins(this IMvcBuilder mvcBuilder, IServiceCollection serviceCollection,
|
||||
IConfiguration config, ILoggerFactory loggerFactory)
|
||||
|
@ -30,70 +30,136 @@ namespace BTCPayServer.Services.Invoices
|
||||
seria.ContractResolver = new CamelCasePropertyNamesContractResolver();
|
||||
MetadataSerializer = seria;
|
||||
}
|
||||
public string OrderId { get; set; }
|
||||
[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; }
|
||||
|
||||
[JsonProperty(PropertyName = "itemDesc")]
|
||||
public string ItemDesc { get; set; }
|
||||
[JsonProperty(PropertyName = "itemCode")]
|
||||
public string ItemCode { get; set; }
|
||||
[JsonProperty(PropertyName = "physical")]
|
||||
public bool? Physical { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "taxIncluded", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||
public decimal? TaxIncluded { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string OrderId
|
||||
{
|
||||
get => GetMetadata<string>("orderId");
|
||||
set => SetMetadata("orderId", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerName{
|
||||
get => GetMetadata<string>("buyerName");
|
||||
set => SetMetadata("buyerName", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerEmail {
|
||||
get => GetMetadata<string>("buyerEmail");
|
||||
set => SetMetadata("buyerEmail", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerCountry {
|
||||
get => GetMetadata<string>("buyerCountry");
|
||||
set => SetMetadata("buyerCountry", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerZip {
|
||||
get => GetMetadata<string>("buyerZip");
|
||||
set => SetMetadata("buyerZip", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerState{
|
||||
get => GetMetadata<string>("buyerState");
|
||||
set => SetMetadata("buyerState", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerCity {
|
||||
get => GetMetadata<string>("buyerCity");
|
||||
set => SetMetadata("buyerCity", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerAddress2{
|
||||
get => GetMetadata<string>("buyerAddress2");
|
||||
set => SetMetadata("buyerAddress2", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerAddress1 {
|
||||
get => GetMetadata<string>("buyerAddress1");
|
||||
set => SetMetadata("buyerAddress1", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string BuyerPhone {
|
||||
get => GetMetadata<string>("buyerPhone");
|
||||
set => SetMetadata("buyerPhone", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string ItemDesc {
|
||||
get => GetMetadata<string>("itemDesc");
|
||||
set => SetMetadata("itemDesc", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string ItemCode{
|
||||
get => GetMetadata<string>("itemCode");
|
||||
set => SetMetadata("itemCode", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public bool? Physical {
|
||||
get => GetMetadata<bool?>("physical");
|
||||
set => SetMetadata("physical", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public decimal? TaxIncluded {
|
||||
get => GetMetadata<decimal?>("taxIncluded");
|
||||
set => SetMetadata("taxIncluded", value);
|
||||
}
|
||||
[JsonIgnore]
|
||||
public string PosData
|
||||
{
|
||||
get
|
||||
{
|
||||
return PosRawData?.ToString();
|
||||
get => GetMetadata<string>("posData");
|
||||
set => SetMetadata("posData", value);
|
||||
}
|
||||
set
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> AdditionalData { get; set; }
|
||||
|
||||
public T GetMetadata<T>(string propName)
|
||||
{
|
||||
if (AdditionalData == null || !(AdditionalData.TryGetValue(propName, out var jt) is true)) return default;
|
||||
if (jt.Type == JTokenType.Null)
|
||||
return default;
|
||||
if (typeof(T) == typeof(string))
|
||||
{
|
||||
return (T)(object)jt.ToString();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return jt.Value<T>();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
public void SetMetadata<T>(string propName, T value)
|
||||
{
|
||||
JToken data;
|
||||
if (value is null)
|
||||
{
|
||||
PosRawData = JValue.CreateNull();
|
||||
AdditionalData?.Remove(propName);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
PosRawData = JToken.Parse(value);
|
||||
if (value is string s)
|
||||
{
|
||||
data = JToken.Parse(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = JToken.FromObject(value);
|
||||
}
|
||||
}
|
||||
catch (Exception )
|
||||
{
|
||||
PosRawData = JToken.FromObject(value);
|
||||
}
|
||||
data = JToken.FromObject(value);
|
||||
}
|
||||
|
||||
AdditionalData ??= new Dictionary<string, JToken>();
|
||||
AdditionalData.AddOrReplace(propName, data);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "posData")]
|
||||
public JToken PosRawData { get; set; }
|
||||
[JsonExtensionData]
|
||||
public IDictionary<string, JToken> AdditionalData { get; set; }
|
||||
|
||||
public static InvoiceMetadata FromJObject(JObject jObject)
|
||||
{
|
||||
return jObject.ToObject<InvoiceMetadata>(MetadataSerializer);
|
||||
|
Loading…
Reference in New Issue
Block a user