public abstract string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData);
public override IPaymentMethodDetails DeserializePaymentMethodDetails(BTCPayNetworkBase network, string str) { return(((BTCPayNetwork)network).ToObject <BitcoinLikeOnChainPaymentMethod>(str)); }
public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str) { return(((BTCPayNetwork)network).ToObject <LightningLikePaymentData>(str)); }
public override IPaymentMethodDetails DeserializePaymentMethodDetails(BTCPayNetworkBase network, string str) { return(JsonConvert.DeserializeObject <Payments.Lightning.LightningLikePaymentMethodDetails>(str)); }
//TODO: abstract private async Task <PaymentModel> GetInvoiceModel(string invoiceId, PaymentMethodId paymentMethodId) { var invoice = await _InvoiceRepository.GetInvoice(invoiceId); if (invoice == null) { return(null); } var store = await _StoreRepository.FindStore(invoice.StoreId); bool isDefaultPaymentId = false; if (paymentMethodId == null) { paymentMethodId = store.GetDefaultPaymentId(_NetworkProvider); isDefaultPaymentId = true; } BTCPayNetworkBase network = _NetworkProvider.GetNetwork <BTCPayNetwork>(paymentMethodId.CryptoCode); if (network == null && isDefaultPaymentId) { //TODO: need to look into a better way for this as it does not scale network = _NetworkProvider.GetAll().OfType <BTCPayNetwork>().FirstOrDefault(); paymentMethodId = new PaymentMethodId(network.CryptoCode, PaymentTypes.BTCLike); } if (invoice == null || network == null) { return(null); } if (!invoice.Support(paymentMethodId)) { if (!isDefaultPaymentId) { return(null); } var paymentMethodTemp = invoice.GetPaymentMethods() .Where(c => paymentMethodId.CryptoCode == c.GetId().CryptoCode) .FirstOrDefault(); if (paymentMethodTemp == null) { paymentMethodTemp = invoice.GetPaymentMethods().First(); } network = paymentMethodTemp.Network; paymentMethodId = paymentMethodTemp.GetId(); } var paymentMethod = invoice.GetPaymentMethod(paymentMethodId); var paymentMethodDetails = paymentMethod.GetPaymentMethodDetails(); var dto = invoice.EntityToDTO(); var cryptoInfo = dto.CryptoInfo.First(o => o.GetpaymentMethodId() == paymentMethodId); var storeBlob = store.GetStoreBlob(); var currency = invoice.ProductInformation.Currency; var accounting = paymentMethod.Calculate(); ChangellySettings changelly = (storeBlob.ChangellySettings != null && storeBlob.ChangellySettings.Enabled && storeBlob.ChangellySettings.IsConfigured()) ? storeBlob.ChangellySettings : null; CoinSwitchSettings coinswitch = (storeBlob.CoinSwitchSettings != null && storeBlob.CoinSwitchSettings.Enabled && storeBlob.CoinSwitchSettings.IsConfigured()) ? storeBlob.CoinSwitchSettings : null; var changellyAmountDue = changelly != null ? (accounting.Due.ToDecimal(MoneyUnit.BTC) * (1m + (changelly.AmountMarkupPercentage / 100m))) : (decimal?)null; var paymentMethodHandler = _paymentMethodHandlerDictionary[paymentMethodId]; var model = new PaymentModel() { CryptoCode = network.CryptoCode, RootPath = this.Request.PathBase.Value.WithTrailingSlash(), OrderId = invoice.OrderId, InvoiceId = invoice.Id, DefaultLang = storeBlob.DefaultLang ?? "en", HtmlTitle = storeBlob.HtmlTitle ?? "BTCPay Invoice", CustomCSSLink = storeBlob.CustomCSS?.AbsoluteUri, CustomLogoLink = storeBlob.CustomLogo?.AbsoluteUri, CryptoImage = Request.GetRelativePathOrAbsolute(paymentMethodHandler.GetCryptoImage(paymentMethodId)), LightningAmountInSatoshi = storeBlob.LightningAmountInSatoshi, BtcAddress = paymentMethodDetails.GetPaymentDestination(), BtcDue = accounting.Due.ToString(), OrderAmount = (accounting.TotalDue - accounting.NetworkFee).ToString(), OrderAmountFiat = OrderAmountFromInvoice(network.CryptoCode, invoice.ProductInformation), CustomerEmail = invoice.RefundMail, RequiresRefundEmail = storeBlob.RequiresRefundEmail, ExpirationSeconds = Math.Max(0, (int)(invoice.ExpirationTime - DateTimeOffset.UtcNow).TotalSeconds), MaxTimeSeconds = (int)(invoice.ExpirationTime - invoice.InvoiceTime).TotalSeconds, MaxTimeMinutes = (int)(invoice.ExpirationTime - invoice.InvoiceTime).TotalMinutes, ItemDesc = invoice.ProductInformation.ItemDesc, Rate = ExchangeRate(paymentMethod), MerchantRefLink = invoice.RedirectURL ?? "/", RedirectAutomatically = invoice.RedirectAutomatically, StoreName = store.StoreName, PeerInfo = (paymentMethodDetails as LightningLikePaymentMethodDetails)?.NodeInfo, TxCount = accounting.TxRequired, BtcPaid = accounting.Paid.ToString(), #pragma warning disable CS0618 // Type or member is obsolete Status = invoice.StatusString, #pragma warning restore CS0618 // Type or member is obsolete NetworkFee = paymentMethodDetails.GetNextNetworkFee(), IsMultiCurrency = invoice.GetPayments().Select(p => p.GetPaymentMethodId()).Concat(new[] { paymentMethod.GetId() }).Distinct().Count() > 1, ChangellyEnabled = changelly != null, ChangellyMerchantId = changelly?.ChangellyMerchantId, ChangellyAmountDue = changellyAmountDue, CoinSwitchEnabled = coinswitch != null, CoinSwitchAmountMarkupPercentage = coinswitch?.AmountMarkupPercentage ?? 0, CoinSwitchMerchantId = coinswitch?.MerchantId, CoinSwitchMode = coinswitch?.Mode, StoreId = store.Id, AvailableCryptos = invoice.GetPaymentMethods() .Where(i => i.Network != null) .Select(kv => { var availableCryptoPaymentMethodId = kv.GetId(); var availableCryptoHandler = _paymentMethodHandlerDictionary[availableCryptoPaymentMethodId]; return(new PaymentModel.AvailableCrypto() { PaymentMethodId = kv.GetId().ToString(), CryptoCode = kv.GetId().CryptoCode, PaymentMethodName = availableCryptoHandler.GetPaymentMethodName(availableCryptoPaymentMethodId), IsLightning = kv.GetId().PaymentType == PaymentTypes.LightningLike, CryptoImage = Request.GetRelativePathOrAbsolute(availableCryptoHandler.GetCryptoImage(availableCryptoPaymentMethodId)), Link = Url.Action(nameof(Checkout), new { invoiceId = invoiceId, paymentMethodId = kv.GetId().ToString() }) }); }).Where(c => c.CryptoImage != "/") .OrderByDescending(a => a.CryptoCode == "BTC").ThenBy(a => a.PaymentMethodName).ThenBy(a => a.IsLightning ? 1 : 0) .ToList() }; paymentMethodHandler.PreparePaymentModel(model, dto); model.PaymentMethodId = paymentMethodId.ToString(); var expiration = TimeSpan.FromSeconds(model.ExpirationSeconds); model.TimeLeft = expiration.PrettyPrint(); return(model); }
/// <summary> /// Add a payment to an invoice /// </summary> /// <param name="invoiceId"></param> /// <param name="date"></param> /// <param name="paymentData"></param> /// <param name="cryptoCode"></param> /// <param name="accounted"></param> /// <returns>The PaymentEntity or null if already added</returns> public async Task <PaymentEntity> AddPayment(string invoiceId, DateTimeOffset date, CryptoPaymentData paymentData, BTCPayNetworkBase network, bool accounted = false) { using (var context = _ContextFactory.CreateContext()) { var invoice = context.Invoices.Find(invoiceId); if (invoice == null) { return(null); } InvoiceEntity invoiceEntity = ToObject(invoice.Blob); PaymentMethod paymentMethod = invoiceEntity.GetPaymentMethod(new PaymentMethodId(network.CryptoCode, paymentData.GetPaymentType())); IPaymentMethodDetails paymentMethodDetails = paymentMethod.GetPaymentMethodDetails(); PaymentEntity entity = new PaymentEntity { Version = 1, #pragma warning disable CS0618 CryptoCode = network.CryptoCode, #pragma warning restore CS0618 ReceivedTime = date.UtcDateTime, Accounted = accounted, NetworkFee = paymentMethodDetails.GetNextNetworkFee(), Network = network }; entity.SetCryptoPaymentData(paymentData); //TODO: abstract if (paymentMethodDetails is Payments.Bitcoin.BitcoinLikeOnChainPaymentMethod bitcoinPaymentMethod && bitcoinPaymentMethod.NetworkFeeMode == NetworkFeeMode.MultiplePaymentsOnly && bitcoinPaymentMethod.NextNetworkFee == Money.Zero) { bitcoinPaymentMethod.NextNetworkFee = bitcoinPaymentMethod.NetworkFeeRate.GetFee(100); // assume price for 100 bytes paymentMethod.SetPaymentMethodDetails(bitcoinPaymentMethod); invoiceEntity.SetPaymentMethod(paymentMethod); invoice.Blob = ToBytes(invoiceEntity, network); } PaymentData data = new PaymentData { Id = paymentData.GetPaymentId(), Blob = ToBytes(entity, entity.Network), InvoiceDataId = invoiceId, Accounted = accounted }; context.Payments.Add(data); try { await context.SaveChangesAsync().ConfigureAwait(false); } catch (DbUpdateException) { return(null); } // Already exists AddToTextSearch(invoiceId, paymentData.GetSearchTerms()); return(entity); } }
public override string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData) { return(JsonConvert.SerializeObject(paymentData)); }
private string GetCryptoImage(BTCPayNetworkBase network) { return(network.CryptoImagePath); }
public abstract string GetTransactionLink(BTCPayNetworkBase network, string txId);
public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str) { return(JsonConvert.DeserializeObject <MoneroLikePaymentData>(str)); }
public abstract ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value);
public abstract string SerializePaymentMethodDetails(BTCPayNetworkBase network, IPaymentMethodDetails details);
public abstract IPaymentMethodDetails DeserializePaymentMethodDetails(BTCPayNetworkBase network, string str);
public override string SerializePaymentMethodDetails(BTCPayNetworkBase network, IPaymentMethodDetails details) { return(((BTCPayNetwork)network).ToString((BitcoinLikeOnChainPaymentMethod)details)); }
public override IPaymentMethodDetails DeserializePaymentMethodDetails(BTCPayNetworkBase network, string str) { return(JsonConvert.DeserializeObject <MoneroLikeOnChainPaymentMethodDetails>(str)); }
private async Task <PaymentMethod?> CreatePaymentMethodAsync( Dictionary <CurrencyPair, Task <RateResult> > fetchingByCurrencyPair, IPaymentMethodHandler handler, ISupportedPaymentMethod supportedPaymentMethod, BTCPayNetworkBase network, InvoiceEntity entity, StoreData store, InvoiceLogs logs, HashSet <PaymentMethodId> invoicePaymentMethods) { try { var logPrefix = $"{supportedPaymentMethod.PaymentId.ToPrettyString()}:"; var storeBlob = store.GetStoreBlob(); object?preparePayment; if (storeBlob.LazyPaymentMethods) { preparePayment = null; } else { preparePayment = handler.PreparePayment(supportedPaymentMethod, store, network); } var rate = await fetchingByCurrencyPair[new CurrencyPair(network.CryptoCode, entity.Currency)]; if (rate.BidAsk == null) { return(null); } var paymentMethod = new PaymentMethod { ParentEntity = entity, Network = network, Rate = rate.BidAsk.Bid, PreferOnion = Uri.TryCreate(entity.ServerUrl, UriKind.Absolute, out var u) && u.DnsSafeHost.EndsWith(".onion", StringComparison.OrdinalIgnoreCase) }; paymentMethod.SetId(supportedPaymentMethod.PaymentId); using (logs.Measure($"{logPrefix} Payment method details creation")) { var paymentDetails = await handler.CreatePaymentMethodDetails(logs, supportedPaymentMethod, paymentMethod, store, network, preparePayment, invoicePaymentMethods); paymentMethod.SetPaymentMethodDetails(paymentDetails); } var criteria = storeBlob.PaymentMethodCriteria?.Find(methodCriteria => methodCriteria.PaymentMethod == supportedPaymentMethod.PaymentId); if (criteria?.Value != null && entity.Type != InvoiceType.TopUp) { var currentRateToCrypto = await fetchingByCurrencyPair[new CurrencyPair(supportedPaymentMethod.PaymentId.CryptoCode, criteria.Value.Currency)]; if (currentRateToCrypto?.BidAsk != null) { var amount = paymentMethod.Calculate().Due.GetValue(network as BTCPayNetwork); var limitValueCrypto = criteria.Value.Value / currentRateToCrypto.BidAsk.Bid; if (amount < limitValueCrypto && criteria.Above) { logs.Write($"{logPrefix} invoice amount below accepted value for payment method", InvoiceEventData.EventSeverity.Error); return(null); } if (amount > limitValueCrypto && !criteria.Above) { logs.Write($"{logPrefix} invoice amount above accepted value for payment method", InvoiceEventData.EventSeverity.Error); return(null); } } else { var suffix = currentRateToCrypto?.EvaluatedRule is string s ? $" ({s})" : string.Empty; logs.Write($"{logPrefix} This payment method should be created only if the amount of this invoice is in proper range. However, we are unable to fetch the rate of those limits. {suffix}", InvoiceEventData.EventSeverity.Warning); } } #pragma warning disable CS0618 if (paymentMethod.GetId().IsBTCOnChain) { entity.TxFee = paymentMethod.NextNetworkFee; entity.Rate = paymentMethod.Rate; entity.DepositAddress = paymentMethod.DepositAddress; } #pragma warning restore CS0618 return(paymentMethod); } catch (PaymentMethodUnavailableException ex) { logs.Write($"{supportedPaymentMethod.PaymentId.CryptoCode}: Payment method unavailable ({ex.Message})", InvoiceEventData.EventSeverity.Error); } catch (Exception ex) { logs.Write($"{supportedPaymentMethod.PaymentId.CryptoCode}: Unexpected exception ({ex})", InvoiceEventData.EventSeverity.Error); } return(null); }
public override ISupportedPaymentMethod DeserializeSupportedPaymentMethod(BTCPayNetworkBase network, JToken value) { return(JsonConvert.DeserializeObject <MoneroSupportedPaymentMethod>(value.ToString())); }
private string GetPaymentMethodName(BTCPayNetworkBase network) { return(network.DisplayName); }
public override string GetTransactionLink(BTCPayNetworkBase network, string txId) { return(string.Format(CultureInfo.InvariantCulture, network.BlockExplorerLink, txId)); }
public async Task <bool> NewAddress(string invoiceId, IPaymentMethodDetails paymentMethod, BTCPayNetworkBase network) { using (var context = _ContextFactory.CreateContext()) { var invoice = (await context.Invoices.Where(i => i.Id == invoiceId).ToListAsync()).FirstOrDefault(); if (invoice == null) { return(false); } var invoiceEntity = ToObject(invoice.Blob); var currencyData = invoiceEntity.GetPaymentMethod(network, paymentMethod.GetPaymentType()); if (currencyData == null) { return(false); } var existingPaymentMethod = currencyData.GetPaymentMethodDetails(); if (existingPaymentMethod.GetPaymentDestination() != null) { MarkUnassigned(invoiceId, invoiceEntity, context, currencyData.GetId()); } existingPaymentMethod.SetPaymentDestination(paymentMethod.GetPaymentDestination()); currencyData.SetPaymentMethodDetails(existingPaymentMethod); #pragma warning disable CS0618 if (network.IsBTC) { invoiceEntity.DepositAddress = currencyData.DepositAddress; } #pragma warning restore CS0618 invoiceEntity.SetPaymentMethod(currencyData); invoice.Blob = ToBytes(invoiceEntity, network); context.AddressInvoices.Add(new AddressInvoiceData() { InvoiceDataId = invoiceId, CreatedTime = DateTimeOffset.UtcNow } .Set(GetDestination(currencyData), currencyData.GetId())); context.HistoricalAddressInvoices.Add(new HistoricalAddressInvoiceData() { InvoiceDataId = invoiceId, Assigned = DateTimeOffset.UtcNow }.SetAddress(paymentMethod.GetPaymentDestination(), network.CryptoCode)); await context.SaveChangesAsync(); AddToTextSearch(invoice.Id, paymentMethod.GetPaymentDestination()); return(true); } }
public override string GetPaymentLink(BTCPayNetworkBase network, IPaymentMethodDetails paymentMethodDetails, Money cryptoInfoDue, string serverUri) { return ($"{(network as MoneroLikeSpecificBtcPayNetwork).UriScheme}:{paymentMethodDetails.GetPaymentDestination()}?tx_amount={cryptoInfoDue.ToDecimal(MoneyUnit.BTC)}"); }
private byte[] ToBytes <T>(T obj, BTCPayNetworkBase network = null) { return(ZipUtils.Zip(ToString(obj, network))); }
public BTCPayWallet GetWallet(BTCPayNetworkBase network) { ArgumentNullException.ThrowIfNull(network); return(GetWallet(network.CryptoCode)); }
public override string SerializePaymentData(BTCPayNetworkBase network, CryptoPaymentData paymentData) { return(((BTCPayNetwork)network).ToString(paymentData)); }
public bool IsAvailable(BTCPayNetworkBase network) { return(_Client.IsAvailable(network)); }
public override string SerializePaymentMethodDetails(BTCPayNetworkBase network, IPaymentMethodDetails details) { return(JsonConvert.SerializeObject(details)); }
public abstract CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str);