public async Task DisposeAsync()
        {
            List <Task> disposing = new List <Task>();

            if (Invoice != null)
            {
                _invoiceLogsService.AddInvoiceLogs(Invoice.Id, Logs);
            }
            if (!doNotBroadcast && OriginalTransaction != null)
            {
                disposing.Add(_explorerClient.BroadcastAsync(OriginalTransaction));
            }
            if (!success && LockedUTXOs != null)
            {
                disposing.Add(_payJoinRepository.TryUnlock(LockedUTXOs));
            }
            try
            {
                await Task.WhenAll(disposing);
            }
            catch (Exception ex)
            {
                BTCPayServer.Logging.Logs.PayServer.LogWarning(ex, "Error while disposing the PayjoinReceiverContext");
            }
        }
Exemple #2
0
        internal async Task <InvoiceEntity> CreateInvoiceCoreRaw(InvoiceEntity entity, StoreData store, IPaymentFilter invoicePaymentMethodFilter, CancellationToken cancellationToken = default)
        {
            InvoiceLogs logs = new InvoiceLogs();

            logs.Write("Creation of invoice starting", InvoiceEventData.EventSeverity.Info);

            var getAppsTaggingStore = _InvoiceRepository.GetAppsTaggingStore(store.Id);
            var storeBlob           = store.GetStoreBlob();

            if (entity.Metadata.BuyerEmail != null)
            {
                if (!EmailValidator.IsEmail(entity.Metadata.BuyerEmail))
                {
                    throw new BitpayHttpException(400, "Invalid email");
                }
                entity.RefundMail = entity.Metadata.BuyerEmail;
            }
            entity.Status = InvoiceStatus.New;
            HashSet <CurrencyPair> currencyPairsToFetch = new HashSet <CurrencyPair>();
            var excludeFilter = storeBlob.GetExcludedPaymentMethods(); // Here we can compose filters from other origin with PaymentFilter.Any()

            if (invoicePaymentMethodFilter != null)
            {
                excludeFilter = PaymentFilter.Or(excludeFilter,
                                                 invoicePaymentMethodFilter);
            }
            foreach (var network in store.GetSupportedPaymentMethods(_NetworkProvider)
                     .Where(s => !excludeFilter.Match(s.PaymentId))
                     .Select(c => _NetworkProvider.GetNetwork <BTCPayNetworkBase>(c.PaymentId.CryptoCode))
                     .Where(c => c != null))
            {
                currencyPairsToFetch.Add(new CurrencyPair(network.CryptoCode, entity.Currency));
                foreach (var paymentMethodCriteria in store.GetPaymentMethodCriteria(_NetworkProvider, storeBlob))
                {
                    if (paymentMethodCriteria.Value != null)
                    {
                        currencyPairsToFetch.Add(new CurrencyPair(network.CryptoCode, paymentMethodCriteria.Value.Currency));
                    }
                }
            }

            var rateRules = storeBlob.GetRateRules(_NetworkProvider);
            var fetchingByCurrencyPair = _RateProvider.FetchRates(currencyPairsToFetch, rateRules, cancellationToken);
            var fetchingAll            = WhenAllFetched(logs, fetchingByCurrencyPair);

            List <ISupportedPaymentMethod> supported = new List <ISupportedPaymentMethod>();
            var paymentMethods = new PaymentMethodDictionary();

            // This loop ends with .ToList so we are querying all payment methods at once
            // instead of sequentially to improve response time
            foreach (var o in store.GetSupportedPaymentMethods(_NetworkProvider)
                     .Where(s => !excludeFilter.Match(s.PaymentId) && _paymentMethodHandlerDictionary.Support(s.PaymentId))
                     .Select(c =>
                             (Handler: _paymentMethodHandlerDictionary[c.PaymentId],
                              SupportedPaymentMethod: c,
                              Network: _NetworkProvider.GetNetwork <BTCPayNetworkBase>(c.PaymentId.CryptoCode)))
                     .Where(c => c.Network != null)
                     .Select(o =>
                             (SupportedPaymentMethod: o.SupportedPaymentMethod,
                              PaymentMethod: CreatePaymentMethodAsync(fetchingByCurrencyPair, o.Handler, o.SupportedPaymentMethod, o.Network, entity, store, logs)))
                     .ToList())
            {
                var paymentMethod = await o.PaymentMethod;
                if (paymentMethod == null)
                {
                    continue;
                }
                supported.Add(o.SupportedPaymentMethod);
                paymentMethods.Add(paymentMethod);
            }

            if (supported.Count == 0)
            {
                StringBuilder errors = new StringBuilder();
                if (!store.GetSupportedPaymentMethods(_NetworkProvider).Any())
                {
                    errors.AppendLine("Warning: No wallet has been linked to your BTCPay Store. See the following link for more information on how to connect your store and wallet. (https://docs.btcpayserver.org/WalletSetup/)");
                }
                foreach (var error in logs.ToList())
                {
                    errors.AppendLine(error.ToString());
                }
                throw new BitpayHttpException(400, errors.ToString());
            }

            entity.SetSupportedPaymentMethods(supported);
            entity.SetPaymentMethods(paymentMethods);
            foreach (var app in await getAppsTaggingStore)
            {
                entity.InternalTags.Add(AppService.GetAppInternalTag(app.Id));
            }

            using (logs.Measure("Saving invoice"))
            {
                entity = await _InvoiceRepository.CreateInvoiceAsync(store.Id, entity);
            }
            _ = Task.Run(async() =>
            {
                try
                {
                    await fetchingAll;
                }
                catch (AggregateException ex)
                {
                    ex.Handle(e => { logs.Write($"Error while fetching rates {ex}", InvoiceEventData.EventSeverity.Error); return(true); });
                }
                _invoiceLogsService.AddInvoiceLogs(entity.Id, logs);
            });
            _EventAggregator.Publish(new Events.InvoiceEvent(entity, InvoiceEvent.Created));
            return(entity);
        }