Beispiel #1
0
 public Task <decimal> GetRateAsync(string currency)
 {
     return(_MemoryCache.GetOrCreateAsync("CURR_" + currency, (ICacheEntry entry) =>
     {
         entry.AbsoluteExpiration = DateTimeOffset.UtcNow + CacheSpan;
         return _Inner.GetRateAsync(currency);
     }));
 }
        internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl, double expiryMinutes = 15)
        {
            //TODO: expiryMinutes (time before a new invoice can become paid) and monitoringMinutes (time before a paid invoice becomes invalid)  should be configurable at store level
            var derivationStrategy = store.DerivationStrategy;
            var entity             = new InvoiceEntity
            {
                InvoiceTime        = DateTimeOffset.UtcNow,
                DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy")
            };
            var storeBlob       = store.GetStoreBlob(_Network);
            Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null;

            if (notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https")) //TODO: Filer non routable addresses ?
            {
                notificationUri = null;
            }
            EmailAddressAttribute emailValidator = new EmailAddressAttribute();

            entity.ExpirationTime       = entity.InvoiceTime.AddMinutes(expiryMinutes);
            entity.MonitoringExpiration = entity.ExpirationTime + TimeSpan.FromMinutes(storeBlob.MonitoringExpiration);
            entity.OrderId           = invoice.OrderId;
            entity.ServerUrl         = serverUrl;
            entity.FullNotifications = invoice.FullNotifications;
            entity.NotificationURL   = notificationUri?.AbsoluteUri;
            entity.BuyerInformation  = Map <Invoice, BuyerInformation>(invoice);
            //Another way of passing buyer info to support
            FillBuyerInfo(invoice.Buyer, entity.BuyerInformation);
            if (entity?.BuyerInformation?.BuyerEmail != null)
            {
                if (!EmailValidator.IsEmail(entity.BuyerInformation.BuyerEmail))
                {
                    throw new BitpayHttpException(400, "Invalid email");
                }
                entity.RefundMail = entity.BuyerInformation.BuyerEmail;
            }
            entity.ProductInformation = Map <Invoice, ProductInformation>(invoice);
            entity.RedirectURL        = invoice.RedirectURL ?? store.StoreWebsite;
            entity.Status             = "new";
            entity.SpeedPolicy        = ParseSpeedPolicy(invoice.TransactionSpeed, store.SpeedPolicy);

            var getFeeRate = _FeeProvider.GetFeeRateAsync();
            var getRate    = _RateProvider.GetRateAsync(invoice.Currency);
            var getAddress = _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy));

            entity.TxFee          = storeBlob.NetworkFeeDisabled ? Money.Zero : (await getFeeRate).GetFee(100); // assume price for 100 bytes
            entity.Rate           = (double)await getRate;
            entity.PosData        = invoice.PosData;
            entity.DepositAddress = await getAddress;
            entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity);

            _Watcher.Watch(entity.Id);
            var resp = entity.EntityToDTO();

            return(new DataWrapper <InvoiceResponse>(resp)
            {
                Facade = "pos/invoice"
            });
        }
Beispiel #3
0
        public async Task <decimal> GetRateAsync(string currency)
        {
            var rate = await rateProvider.GetRateAsync(currency);

            foreach (var rule in rateRules)
            {
                rate = rule.Apply(network, rate);
            }
            return(rate);
        }
Beispiel #4
0
        internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl)
        {
            var derivationStrategy = store.DerivationStrategy;
            var entity             = new InvoiceEntity
            {
                InvoiceTime        = DateTimeOffset.UtcNow,
                DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy")
            };
            Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null;

            if (notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https"))            //TODO: Filer non routable addresses ?
            {
                notificationUri = null;
            }
            EmailAddressAttribute emailValidator = new EmailAddressAttribute();

            entity.ExpirationTime    = entity.InvoiceTime + TimeSpan.FromMinutes(15.0);
            entity.ServerUrl         = serverUrl;
            entity.FullNotifications = invoice.FullNotifications;
            entity.NotificationURL   = notificationUri?.AbsoluteUri;
            entity.BuyerInformation  = Map <Invoice, BuyerInformation>(invoice);
            //Another way of passing buyer info to support
            FillBuyerInfo(invoice.Buyer, entity.BuyerInformation);
            if (entity?.BuyerInformation?.BuyerEmail != null)
            {
                if (!EmailValidator.IsEmail(entity.BuyerInformation.BuyerEmail))
                {
                    throw new BitpayHttpException(400, "Invalid email");
                }
                entity.RefundMail = entity.BuyerInformation.BuyerEmail;
            }
            entity.ProductInformation = Map <Invoice, ProductInformation>(invoice);
            entity.RedirectURL        = invoice.RedirectURL ?? store.StoreWebsite;
            entity.Status             = "new";
            entity.SpeedPolicy        = store.SpeedPolicy;
            entity.TxFee = (await _FeeProvider.GetFeeRateAsync()).GetFee(100);             // assume price for 100 bytes
            entity.Rate  = (double)await _RateProvider.GetRateAsync(invoice.Currency);

            entity.PosData        = invoice.PosData;
            entity.DepositAddress = await _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy));

            entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity);

            await _Wallet.MapAsync(entity.DepositAddress.ScriptPubKey, entity.Id);

            await _Watcher.WatchAsync(entity.Id);

            var resp = entity.EntityToDTO();

            return(new DataWrapper <InvoiceResponse>(resp)
            {
                Facade = "pos/invoice"
            });
        }
        internal async Task <DataWrapper <InvoiceResponse> > CreateInvoiceCore(Invoice invoice, StoreData store, string serverUrl, double expiryMinutes = 15)
        {
            var derivationStrategy = store.DerivationStrategy;
            var entity             = new InvoiceEntity
            {
                InvoiceTime        = DateTimeOffset.UtcNow,
                DerivationStrategy = derivationStrategy ?? throw new BitpayHttpException(400, "This store has not configured the derivation strategy")
            };
            var storeBlob       = store.GetStoreBlob();
            Uri notificationUri = Uri.IsWellFormedUriString(invoice.NotificationURL, UriKind.Absolute) ? new Uri(invoice.NotificationURL, UriKind.Absolute) : null;

            if (notificationUri == null || (notificationUri.Scheme != "http" && notificationUri.Scheme != "https")) //TODO: Filer non routable addresses ?
            {
                notificationUri = null;
            }
            EmailAddressAttribute emailValidator = new EmailAddressAttribute();

            entity.ExpirationTime       = entity.InvoiceTime.AddMinutes(expiryMinutes);
            entity.MonitoringExpiration = entity.ExpirationTime + TimeSpan.FromMinutes(storeBlob.MonitoringExpiration);
            entity.OrderId           = invoice.OrderId;
            entity.ServerUrl         = serverUrl;
            entity.FullNotifications = invoice.FullNotifications;
            entity.NotificationURL   = notificationUri?.AbsoluteUri;
            entity.BuyerInformation  = Map <Invoice, BuyerInformation>(invoice);
            //Another way of passing buyer info to support
            FillBuyerInfo(invoice.Buyer, entity.BuyerInformation);
            if (entity?.BuyerInformation?.BuyerEmail != null)
            {
                if (!EmailValidator.IsEmail(entity.BuyerInformation.BuyerEmail))
                {
                    throw new BitpayHttpException(400, "Invalid email");
                }
                entity.RefundMail = entity.BuyerInformation.BuyerEmail;
            }
            entity.ProductInformation = Map <Invoice, ProductInformation>(invoice);
            entity.RedirectURL        = invoice.RedirectURL ?? store.StoreWebsite;
            entity.Status             = "new";
            entity.SpeedPolicy        = ParseSpeedPolicy(invoice.TransactionSpeed, store.SpeedPolicy);

            var queries = storeBlob.GetSupportedCryptoCurrencies()
                          .Select(n => _NetworkProvider.GetNetwork(n))
                          .Where(n => n != null)
                          .Select(network =>
            {
                return(new
                {
                    network = network,
                    getFeeRate = _FeeProviderFactory.CreateFeeProvider(network).GetFeeRateAsync(),
                    getRate = _RateProvider.GetRateAsync(invoice.Currency),
                    getAddress = _Wallet.ReserveAddressAsync(ParseDerivationStrategy(derivationStrategy, network))
                });
            });

            var cryptoDatas = new Dictionary <string, CryptoData>();

            foreach (var q in queries)
            {
                CryptoData cryptoData = new CryptoData();
                cryptoData.CryptoCode     = q.network.CryptoCode;
                cryptoData.FeeRate        = (await q.getFeeRate);
                cryptoData.TxFee          = storeBlob.NetworkFeeDisabled ? Money.Zero : cryptoData.FeeRate.GetFee(100); // assume price for 100 bytes
                cryptoData.Rate           = await q.getRate;
                cryptoData.DepositAddress = (await q.getAddress).ToString();

#pragma warning disable CS0618
                if (q.network.CryptoCode == "BTC")
                {
                    entity.TxFee          = cryptoData.TxFee;
                    entity.Rate           = cryptoData.Rate;
                    entity.DepositAddress = cryptoData.DepositAddress;
                }
#pragma warning restore CS0618
                cryptoDatas.Add(cryptoData.CryptoCode, cryptoData);
            }
            entity.SetCryptoData(cryptoDatas);
            entity.PosData = invoice.PosData;
            entity         = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity, _NetworkProvider);

            _Watcher.Watch(entity.Id);
            var resp = entity.EntityToDTO(_NetworkProvider);
            return(new DataWrapper <InvoiceResponse>(resp)
            {
                Facade = "pos/invoice"
            });
        }