btcpayserver/BTCPayServer/Services/Invoices/InvoiceEntity.cs

878 lines
29 KiB
C#
Raw Normal View History

2017-09-13 15:47:34 +09:00
using NBitcoin;
using System.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using BTCPayServer.Models;
using Newtonsoft.Json.Linq;
using NBitcoin.DataEncoders;
using BTCPayServer.Data;
2017-11-06 00:31:02 -08:00
using NBXplorer.Models;
using NBXplorer;
using NBXplorer.DerivationStrategy;
using BTCPayServer.Payments;
2017-09-13 15:47:34 +09:00
2017-10-20 14:06:37 -05:00
namespace BTCPayServer.Services.Invoices
2017-09-13 15:47:34 +09:00
{
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;
}
2017-09-13 15:47:34 +09:00
[JsonProperty(PropertyName = "buyerPhone")]
public string BuyerPhone
{
get; set;
}
}
2017-09-13 15:47:34 +09:00
public class ProductInformation
{
[JsonProperty(PropertyName = "itemDesc")]
public string ItemDesc
{
get; set;
}
[JsonProperty(PropertyName = "itemCode")]
public string ItemCode
{
get; set;
}
[JsonProperty(PropertyName = "physical")]
public bool Physical
{
get; set;
}
2017-09-13 15:47:34 +09:00
[JsonProperty(PropertyName = "price")]
public decimal Price
{
get; set;
}
2017-09-13 15:47:34 +09:00
[JsonProperty(PropertyName = "currency")]
public string Currency
{
get; set;
}
}
2017-09-13 15:47:34 +09:00
public enum SpeedPolicy
{
HighSpeed = 0,
MediumSpeed = 1,
LowSpeed = 2
}
public class InvoiceEntity
{
public string Id
{
get; set;
}
public string StoreId
{
get; set;
}
2017-09-14 01:06:11 +09:00
public string OrderId
{
get; set;
}
2017-09-13 15:47:34 +09:00
public SpeedPolicy SpeedPolicy
{
get; set;
}
[Obsolete("Use GetCryptoData(network).Rate instead")]
public decimal Rate
{
get; set;
}
public DateTimeOffset InvoiceTime
{
get; set;
}
public DateTimeOffset ExpirationTime
{
get; set;
}
[Obsolete("Use GetCryptoData(network).DepositAddress instead")]
public string DepositAddress
{
get; set;
}
public ProductInformation ProductInformation
{
get; set;
}
public BuyerInformation BuyerInformation
{
get; set;
}
public string PosData
{
get;
set;
}
[Obsolete("Use GetDerivationStrategies instead")]
public string DerivationStrategy
{
get;
set;
}
[Obsolete("Use GetDerivationStrategies instead")]
public string DerivationStrategies
{
get;
set;
}
public DerivationStrategyBase GetDerivationStrategy(BTCPayNetwork network)
{
#pragma warning disable CS0618
if (!string.IsNullOrEmpty(DerivationStrategies))
{
JObject strategies = JObject.Parse(DerivationStrategies);
#pragma warning restore CS0618
foreach (var strat in strategies.Properties())
{
if (strat.Name == network.CryptoCode)
{
return BTCPayServer.DerivationStrategy.Parse(strat.Value.Value<string>(), network).DerivationStrategyBase;
}
}
}
#pragma warning disable CS0618
if (network.IsBTC && !string.IsNullOrEmpty(DerivationStrategy))
{
return BTCPayServer.DerivationStrategy.Parse(DerivationStrategy, network).DerivationStrategyBase;
}
return null;
#pragma warning restore CS0618
}
public IEnumerable<DerivationStrategy> GetDerivationStrategies(BTCPayNetworkProvider networks)
{
#pragma warning disable CS0618
bool btcReturned = false;
if (!string.IsNullOrEmpty(DerivationStrategies))
{
JObject strategies = JObject.Parse(DerivationStrategies);
foreach (var strat in strategies.Properties())
{
var network = networks.GetNetwork(strat.Name);
if (network != null)
{
2018-01-10 18:30:45 +09:00
if (network == networks.BTC)
btcReturned = true;
yield return BTCPayServer.DerivationStrategy.Parse(strat.Value.Value<string>(), network);
}
}
}
if (!btcReturned && !string.IsNullOrEmpty(DerivationStrategy))
{
if (networks.BTC != null)
{
yield return BTCPayServer.DerivationStrategy.Parse(DerivationStrategy, networks.BTC);
}
}
#pragma warning restore CS0618
}
internal void SetDerivationStrategies(IEnumerable<DerivationStrategy> derivationStrategies)
{
JObject obj = new JObject();
foreach (var strat in derivationStrategies)
{
obj.Add(strat.Network.CryptoCode, new JValue(strat.DerivationStrategyBase.ToString()));
#pragma warning disable CS0618
if (strat.Network.IsBTC)
DerivationStrategy = strat.DerivationStrategyBase.ToString();
}
DerivationStrategies = JsonConvert.SerializeObject(obj);
#pragma warning restore CS0618
}
public string Status
{
get;
set;
}
public string ExceptionStatus
{
get; set;
}
2018-01-10 18:30:45 +09:00
[Obsolete("Use GetPayments instead")]
public List<PaymentEntity> Payments
{
get; set;
}
2018-01-10 18:30:45 +09:00
#pragma warning disable CS0618
public List<PaymentEntity> GetPayments()
{
return Payments.ToList();
}
public List<PaymentEntity> GetPayments(string cryptoCode)
{
return Payments.Where(p => p.CryptoCode == cryptoCode).ToList();
2018-01-10 18:30:45 +09:00
}
public List<PaymentEntity> GetPayments(BTCPayNetwork network)
{
return GetPayments(network.CryptoCode);
}
#pragma warning restore CS0618
public bool Refundable
{
get;
set;
}
public string RefundMail
{
get;
set;
}
public string RedirectURL
{
get;
set;
}
[Obsolete("Use GetCryptoData(network).TxFee instead")]
public Money TxFee
{
get;
set;
}
public bool FullNotifications
{
get;
set;
}
public string NotificationURL
{
get;
set;
}
public string ServerUrl
{
get;
set;
}
[Obsolete("Use Set/GetCryptoData() instead")]
public JObject CryptoData { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public DateTimeOffset MonitoringExpiration
{
get;
set;
}
public HistoricalAddressInvoiceData[] HistoricalAddresses
{
get;
set;
}
2017-09-13 15:47:34 +09:00
2017-11-06 00:31:02 -08:00
public HashSet<string> AvailableAddressHashes
{
get;
set;
}
2018-01-08 04:14:35 +09:00
public bool ExtendedNotifications { get; set; }
2018-01-14 21:48:23 +09:00
public List<InvoiceEventData> Events { get; internal set; }
2017-11-06 00:31:02 -08:00
public bool IsExpired()
{
return DateTimeOffset.UtcNow > ExpirationTime;
}
2017-09-13 15:47:34 +09:00
public InvoiceResponse EntityToDTO(BTCPayNetworkProvider networkProvider)
{
ServerUrl = ServerUrl ?? "";
InvoiceResponse dto = new InvoiceResponse
{
Id = Id,
OrderId = OrderId,
PosData = PosData,
CurrentTime = DateTimeOffset.UtcNow,
InvoiceTime = InvoiceTime,
ExpirationTime = ExpirationTime,
Status = Status,
Currency = ProductInformation.Currency,
Flags = new Flags() { Refundable = Refundable }
};
dto.CryptoInfo = new List<NBitpayClient.InvoiceCryptoInfo>();
foreach (var info in this.GetCryptoData(networkProvider, true))
{
var accounting = info.Calculate();
var cryptoInfo = new NBitpayClient.InvoiceCryptoInfo();
cryptoInfo.CryptoCode = info.GetId().CryptoCode;
cryptoInfo.PaymentType = info.GetId().PaymentType.ToString();
cryptoInfo.Rate = info.Rate;
cryptoInfo.Price = Money.Coins(ProductInformation.Price / cryptoInfo.Rate).ToString();
cryptoInfo.Due = accounting.Due.ToString();
cryptoInfo.Paid = accounting.Paid.ToString();
cryptoInfo.TotalDue = accounting.TotalDue.ToString();
cryptoInfo.NetworkFee = accounting.NetworkFee.ToString();
cryptoInfo.TxCount = accounting.TxCount;
cryptoInfo.CryptoPaid = accounting.CryptoPaid.ToString();
cryptoInfo.Address = info.GetPaymentMethod()?.GetPaymentDestination();
cryptoInfo.ExRates = new Dictionary<string, double>
{
{ ProductInformation.Currency, (double)cryptoInfo.Rate }
};
var scheme = info.Network.UriScheme;
var cryptoSuffix = cryptoInfo.CryptoCode == "BTC" ? "" : "/" + cryptoInfo.CryptoCode;
cryptoInfo.Url = ServerUrl.WithTrailingSlash() + $"invoice{cryptoSuffix}?id=" + Id;
cryptoInfo.PaymentUrls = new NBitpayClient.InvoicePaymentUrls()
{
BIP72 = $"{scheme}:{cryptoInfo.Address}?amount={cryptoInfo.Due}&r={ServerUrl.WithTrailingSlash() + ($"i/{Id}{cryptoSuffix}")}",
BIP72b = $"{scheme}:?r={ServerUrl.WithTrailingSlash() + ($"i/{Id}{cryptoSuffix}")}",
BIP73 = ServerUrl.WithTrailingSlash() + ($"i/{Id}{cryptoSuffix}"),
BIP21 = $"{scheme}:{cryptoInfo.Address}?amount={cryptoInfo.Due}",
};
#pragma warning disable CS0618
if (info.CryptoCode == "BTC")
{
dto.Url = cryptoInfo.Url;
dto.BTCPrice = cryptoInfo.Price;
dto.Rate = cryptoInfo.Rate;
dto.ExRates = cryptoInfo.ExRates;
dto.BitcoinAddress = cryptoInfo.Address;
dto.BTCPaid = cryptoInfo.Paid;
dto.BTCDue = cryptoInfo.Due;
dto.PaymentUrls = cryptoInfo.PaymentUrls;
}
#pragma warning restore CS0618
if (!info.IsPhantomBTC)
dto.CryptoInfo.Add(cryptoInfo);
}
Populate(ProductInformation, dto);
Populate(BuyerInformation, dto);
dto.Token = Encoders.Base58.EncodeData(RandomUtils.GetBytes(16)); //No idea what it is useful for
dto.Guid = Guid.NewGuid().ToString();
dto.ExceptionStatus = ExceptionStatus == null ? new JValue(false) : new JValue(ExceptionStatus);
return dto;
}
private void Populate<TFrom, TDest>(TFrom from, TDest dest)
{
var str = JsonConvert.SerializeObject(from);
JsonConvert.PopulateObject(str, dest);
}
internal bool Support(CryptoDataId cryptoDataId)
{
var rates = GetCryptoData(null);
return rates.TryGet(cryptoDataId) != null;
}
public CryptoData GetCryptoData(CryptoDataId cryptoDataId, BTCPayNetworkProvider networkProvider)
{
GetCryptoData(networkProvider).TryGetValue(cryptoDataId, out var data);
return data;
}
public CryptoData GetCryptoData(BTCPayNetwork network, PaymentTypes paymentType, BTCPayNetworkProvider networkProvider)
{
return GetCryptoData(new CryptoDataId(network.CryptoCode, paymentType), networkProvider);
}
public CryptoDataDictionary GetCryptoData(BTCPayNetworkProvider networkProvider, bool alwaysIncludeBTC = false)
{
CryptoDataDictionary rates = new CryptoDataDictionary();
var serializer = new Serializer(Dummy);
CryptoData phantom = null;
#pragma warning disable CS0618
// Legacy
if (alwaysIncludeBTC)
{
var btcNetwork = networkProvider?.GetNetwork("BTC");
2018-01-13 17:32:08 +09:00
phantom = new CryptoData() { ParentEntity = this, IsPhantomBTC = true, Rate = Rate, CryptoCode = "BTC", TxFee = TxFee, FeeRate = new FeeRate(TxFee, 100), DepositAddress = DepositAddress, Network = btcNetwork };
rates.Add(phantom);
}
if (CryptoData != null)
{
foreach (var prop in CryptoData.Properties())
{
if (prop.Name == "BTC" && phantom != null)
rates.Remove(phantom);
var r = serializer.ToObject<CryptoData>(prop.Value.ToString());
var cryptoDataId = CryptoDataId.Parse(prop.Name);
r.CryptoCode = cryptoDataId.CryptoCode;
r.PaymentType = cryptoDataId.PaymentType.ToString();
r.ParentEntity = this;
r.Network = networkProvider?.GetNetwork(r.CryptoCode);
rates.Add(r);
}
}
#pragma warning restore CS0618
return rates;
}
Network Dummy = Network.Main;
public void SetCryptoData(CryptoData cryptoData)
{
var dict = GetCryptoData(null);
dict.AddOrReplace(cryptoData);
SetCryptoData(dict);
}
public void SetCryptoData(CryptoDataDictionary cryptoData)
{
var obj = new JObject();
var serializer = new Serializer(Dummy);
#pragma warning disable CS0618
foreach (var v in cryptoData)
{
var clone = serializer.ToObject<CryptoData>(serializer.ToString(v));
clone.CryptoCode = null;
clone.PaymentType = null;
obj.Add(new JProperty(v.GetId().ToString(), JObject.Parse(serializer.ToString(clone))));
}
CryptoData = obj;
#pragma warning restore CS0618
}
}
public class CryptoDataAccounting
{
/// <summary>
/// Total amount of this invoice
/// </summary>
public Money TotalDue { get; set; }
/// <summary>
/// Amount of crypto remaining to pay this invoice
/// </summary>
public Money Due { get; set; }
/// <summary>
/// Total amount of the invoice paid after conversion to this crypto currency
/// </summary>
public Money Paid { get; set; }
/// <summary>
/// Total amount of the invoice paid in this currency
/// </summary>
public Money CryptoPaid { get; set; }
/// <summary>
/// Number of transactions required to pay
/// </summary>
public int TxCount { get; set; }
/// <summary>
/// Total amount of network fee to pay to the invoice
/// </summary>
public Money NetworkFee { get; set; }
}
public class CryptoDataId
{
public CryptoDataId(string cryptoCode, PaymentTypes paymentType)
{
if (cryptoCode == null)
throw new ArgumentNullException(nameof(cryptoCode));
PaymentType = paymentType;
CryptoCode = cryptoCode;
}
public string CryptoCode { get; private set; }
public PaymentTypes PaymentType { get; private set; }
public override bool Equals(object obj)
{
CryptoDataId item = obj as CryptoDataId;
if (item == null)
return false;
return ToString().Equals(item.ToString(), StringComparison.InvariantCulture);
}
public static bool operator ==(CryptoDataId a, CryptoDataId b)
{
if (System.Object.ReferenceEquals(a, b))
return true;
if (((object)a == null) || ((object)b == null))
return false;
return a.ToString() == b.ToString();
}
public static bool operator !=(CryptoDataId a, CryptoDataId b)
{
return !(a == b);
}
public override int GetHashCode()
{
#pragma warning disable CA1307 // Specify StringComparison
return ToString().GetHashCode();
#pragma warning restore CA1307 // Specify StringComparison
}
public override string ToString()
{
if (PaymentType == PaymentTypes.BTCLike)
return CryptoCode;
return CryptoCode + "_" + PaymentType.ToString();
}
public static CryptoDataId Parse(string str)
{
var parts = str.Split('_');
return new CryptoDataId(parts[0], parts.Length == 1 ? PaymentTypes.BTCLike : Enum.Parse<PaymentTypes>(parts[1]));
}
}
public class CryptoData
{
[JsonIgnore]
public InvoiceEntity ParentEntity { get; set; }
[JsonIgnore]
public BTCPayNetwork Network { get; set; }
[JsonProperty(PropertyName = "cryptoCode", DefaultValueHandling = DefaultValueHandling.Ignore)]
[Obsolete("Use GetId().CryptoCode instead")]
public string CryptoCode { get; set; }
[JsonProperty(PropertyName = "paymentType", DefaultValueHandling = DefaultValueHandling.Ignore)]
[Obsolete("Use GetId().PaymentType instead")]
public string PaymentType { get; set; }
public CryptoDataId GetId()
{
#pragma warning disable CS0618 // Type or member is obsolete
return new CryptoDataId(CryptoCode, string.IsNullOrEmpty(PaymentType) ? PaymentTypes.BTCLike : Enum.Parse<PaymentTypes>(PaymentType));
#pragma warning restore CS0618 // Type or member is obsolete
}
public void SetId(CryptoDataId id)
{
#pragma warning disable CS0618 // Type or member is obsolete
CryptoCode = id.CryptoCode;
PaymentType = id.PaymentType.ToString();
#pragma warning restore CS0618 // Type or member is obsolete
}
[JsonProperty(PropertyName = "rate")]
public decimal Rate { get; set; }
[Obsolete("Use GetPaymentMethod() instead")]
public JObject PaymentMethod { get; set; }
public IPaymentMethod GetPaymentMethod()
{
#pragma warning disable CS0618 // Type or member is obsolete
// Legacy, old code does not have PaymentMethods
if (string.IsNullOrEmpty(PaymentType) || PaymentMethod == null)
{
return new Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod()
{
FeeRate = FeeRate,
DepositAddress = string.IsNullOrEmpty(DepositAddress) ? null : BitcoinAddress.Create(DepositAddress, Network?.NBitcoinNetwork),
TxFee = TxFee
};
}
else
{
if (GetId().PaymentType == PaymentTypes.BTCLike)
{
var method = DeserializePaymentMethod<Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod>(PaymentMethod);
method.TxFee = TxFee;
method.DepositAddress = BitcoinAddress.Create(DepositAddress, Network?.NBitcoinNetwork);
method.FeeRate = FeeRate;
return method;
}
}
throw new NotSupportedException(PaymentType);
#pragma warning restore CS0618 // Type or member is obsolete
}
private T DeserializePaymentMethod<T>(JObject jobj) where T : class, IPaymentMethod
{
return JsonConvert.DeserializeObject<T>(jobj.ToString());
}
public void SetPaymentMethod(IPaymentMethod paymentMethod)
{
#pragma warning disable CS0618 // Type or member is obsolete
// Legacy, need to fill the old fields
if (PaymentType == null)
PaymentType = paymentMethod.GetPaymentType().ToString();
else if (PaymentType != paymentMethod.GetPaymentType().ToString())
throw new InvalidOperationException("Invalid payment method affected");
if (paymentMethod is Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod bitcoinPaymentMethod)
{
TxFee = bitcoinPaymentMethod.TxFee;
FeeRate = bitcoinPaymentMethod.FeeRate;
DepositAddress = bitcoinPaymentMethod.DepositAddress.ToString();
}
var jobj = JObject.Parse(JsonConvert.SerializeObject(paymentMethod));
PaymentMethod = jobj;
#pragma warning restore CS0618 // Type or member is obsolete
}
[JsonProperty(PropertyName = "feeRate")]
[Obsolete("Use ((BitcoinLikeOnChainPaymentMethod)GetPaymentMethod()).FeeRate")]
public FeeRate FeeRate { get; set; }
[JsonProperty(PropertyName = "txFee")]
[Obsolete("Use ((BitcoinLikeOnChainPaymentMethod)GetPaymentMethod()).TxFee")]
public Money TxFee { get; set; }
[JsonProperty(PropertyName = "depositAddress")]
[Obsolete("Use ((BitcoinLikeOnChainPaymentMethod)GetPaymentMethod()).DepositAddress")]
public string DepositAddress { get; set; }
[JsonIgnore]
public bool IsPhantomBTC { get; set; }
public CryptoDataAccounting Calculate()
{
var cryptoData = ParentEntity.GetCryptoData(null, IsPhantomBTC);
var totalDue = Money.Coins(ParentEntity.ProductInformation.Price / Rate);
var paid = Money.Zero;
var cryptoPaid = Money.Zero;
var paidTxFee = Money.Zero;
bool paidEnough = totalDue <= paid;
int txCount = 0;
var payments =
2018-01-10 18:30:45 +09:00
ParentEntity.GetPayments()
.Where(p => p.Accounted)
2018-01-10 18:30:45 +09:00
.OrderBy(p => p.ReceivedTime)
.Select(_ =>
{
var txFee = _.GetValue(cryptoData, GetId(), cryptoData[_.GetCryptoDataId()].GetTxFee());
paid += _.GetValue(cryptoData, GetId());
2018-01-09 17:27:26 +09:00
if (!paidEnough)
{
totalDue += txFee;
paidTxFee += txFee;
}
paidEnough |= totalDue <= paid;
if (GetId() == _.GetCryptoDataId())
{
cryptoPaid += _.GetCryptoPaymentData().GetValue();
txCount++;
}
return _;
})
.ToArray();
if (!paidEnough)
{
txCount++;
totalDue += GetTxFee();
paidTxFee += GetTxFee();
}
var accounting = new CryptoDataAccounting();
accounting.TotalDue = totalDue;
accounting.Paid = paid;
accounting.TxCount = txCount;
accounting.CryptoPaid = cryptoPaid;
accounting.Due = Money.Max(accounting.TotalDue - accounting.Paid, Money.Zero);
2018-01-09 17:27:26 +09:00
accounting.NetworkFee = paidTxFee;
return accounting;
}
private Money GetTxFee()
{
var method = GetPaymentMethod();
if (method == null)
return Money.Zero;
return method.GetTxFee();
}
}
2017-09-13 15:47:34 +09:00
public class PaymentEntity
{
public DateTimeOffset ReceivedTime
{
get; set;
}
[Obsolete("Use ((BitcoinLikePaymentData)GetCryptoPaymentData()).Outpoint")]
public OutPoint Outpoint
{
get; set;
}
[Obsolete("Use ((BitcoinLikePaymentData)GetCryptoPaymentData()).Output")]
public TxOut Output
{
get; set;
}
2017-11-06 00:31:02 -08:00
public bool Accounted
{
get; set;
}
[Obsolete("Use GetCryptoDataId().CryptoCode instead")]
public string CryptoCode
{
get;
set;
}
[Obsolete("Use GetCryptoPaymentData() instead")]
public string CryptoPaymentData { get; set; }
[Obsolete("Use GetCryptoDataId().PaymentType instead")]
public string CryptoPaymentDataType { get; set; }
public CryptoPaymentData GetCryptoPaymentData()
{
#pragma warning disable CS0618
if (string.IsNullOrEmpty(CryptoPaymentDataType))
{
// In case this is a payment done before this update, consider it unconfirmed with RBF for safety
var paymentData = new Payments.Bitcoin.BitcoinLikePaymentData();
paymentData.Outpoint = Outpoint;
paymentData.Output = Output;
paymentData.RBF = true;
paymentData.ConfirmationCount = 0;
paymentData.Legacy = true;
return paymentData;
}
if (GetCryptoDataId().PaymentType == PaymentTypes.BTCLike)
{
var paymentData = JsonConvert.DeserializeObject<Payments.Bitcoin.BitcoinLikePaymentData>(CryptoPaymentData);
// legacy
paymentData.Output = Output;
paymentData.Outpoint = Outpoint;
return paymentData;
}
throw new NotSupportedException(nameof(CryptoPaymentDataType) + " does not support " + CryptoPaymentDataType);
#pragma warning restore CS0618
}
public void SetCryptoPaymentData(CryptoPaymentData cryptoPaymentData)
{
#pragma warning disable CS0618
if (cryptoPaymentData is Payments.Bitcoin.BitcoinLikePaymentData paymentData)
{
// Legacy
Outpoint = paymentData.Outpoint;
Output = paymentData.Output;
///
}
else
throw new NotSupportedException(cryptoPaymentData.ToString());
CryptoPaymentDataType = paymentData.GetPaymentType().ToString();
CryptoPaymentData = JsonConvert.SerializeObject(cryptoPaymentData);
#pragma warning restore CS0618
}
public Money GetValue(CryptoDataDictionary cryptoData, CryptoDataId cryptoDataId, Money value = null)
{
#pragma warning disable CS0618
value = value ?? Output.Value;
#pragma warning restore CS0618
var to = cryptoDataId;
var from = this.GetCryptoDataId();
if (to == from)
return value;
var fromRate = cryptoData[from].Rate;
var toRate = cryptoData[to].Rate;
var fiatValue = fromRate * value.ToDecimal(MoneyUnit.BTC);
var otherCurrencyValue = toRate == 0 ? 0.0m : fiatValue / toRate;
return Money.Coins(otherCurrencyValue);
}
public CryptoDataId GetCryptoDataId()
{
#pragma warning disable CS0618 // Type or member is obsolete
return new CryptoDataId(CryptoCode ?? "BTC", string.IsNullOrEmpty(CryptoPaymentDataType) ? PaymentTypes.BTCLike : Enum.Parse<PaymentTypes>(CryptoPaymentDataType));
#pragma warning restore CS0618 // Type or member is obsolete
}
public string GetCryptoCode()
{
#pragma warning disable CS0618
return CryptoCode ?? "BTC";
#pragma warning restore CS0618
}
}
public interface CryptoPaymentData
{
/// <summary>
/// Returns an identifier which uniquely identify the payment
/// </summary>
/// <returns>The payment id</returns>
string GetPaymentId();
/// <summary>
/// Returns terms which will be indexed and searchable in the search bar of invoice
/// </summary>
/// <returns>The search terms</returns>
string[] GetSearchTerms();
/// <summary>
/// Get value of what as been paid
/// </summary>
/// <returns>The amount paid</returns>
Money GetValue();
bool PaymentCompleted(PaymentEntity entity, BTCPayNetwork network);
bool PaymentConfirmed(PaymentEntity entity, SpeedPolicy speedPolicy, BTCPayNetwork network);
}
2017-09-13 15:47:34 +09:00
}