예제 #1
0
 public async Task <Data.WebhookDeliveryData> GetWebhookDelivery(string invoiceId, string deliveryId)
 {
     using var ctx = _applicationDbContextFactory.CreateContext();
     return(await ctx.InvoiceWebhookDeliveries
            .Where(d => d.InvoiceId == invoiceId && d.DeliveryId == deliveryId)
            .Select(d => d.Delivery)
            .FirstOrDefaultAsync());
 }
예제 #2
0
        private async Task MigratedInvoiceTextSearchToDb(int startFromPage)
        {
            // deleting legacy DBriize database if present
            var dbpath = Path.Combine(_datadirs.Value.DataDir, "InvoiceDB");

            if (Directory.Exists(dbpath))
            {
                Directory.Delete(dbpath, true);
            }

            var invoiceQuery = new InvoiceQuery {
                IncludeArchived = true
            };
            var totalCount = await _invoiceRepository.GetInvoicesTotal(invoiceQuery);

            const int PAGE_SIZE  = 1000;
            var       totalPages = Math.Ceiling(totalCount * 1.0m / PAGE_SIZE);

            Logs.PayServer.LogInformation($"Importing {totalCount} invoices into the search table in {totalPages - startFromPage} pages");
            for (int i = startFromPage; i < totalPages && !CancellationToken.IsCancellationRequested; i++)
            {
                Logs.PayServer.LogInformation($"Import to search table progress: {i + 1}/{totalPages} pages");
                // migrate data to new table using invoices from database
                using var ctx     = _dbContextFactory.CreateContext();
                invoiceQuery.Skip = i * PAGE_SIZE;
                invoiceQuery.Take = PAGE_SIZE;
                var invoices = await _invoiceRepository.GetInvoices(invoiceQuery);

                foreach (var invoice in invoices)
                {
                    var textSearch = new List <string>();

                    // recreating different textSearch.Adds that were previously in DBriize
                    foreach (var paymentMethod in invoice.GetPaymentMethods())
                    {
                        if (paymentMethod.Network != null)
                        {
                            var paymentDestination = paymentMethod.GetPaymentMethodDetails().GetPaymentDestination();
                            textSearch.Add(paymentDestination);
                            textSearch.Add(paymentMethod.Calculate().TotalDue.ToString());
                        }
                    }
                    //
                    textSearch.Add(invoice.Id);
                    textSearch.Add(invoice.InvoiceTime.ToString(CultureInfo.InvariantCulture));
                    textSearch.Add(invoice.Price.ToString(CultureInfo.InvariantCulture));
                    textSearch.Add(invoice.Metadata.OrderId);
                    textSearch.Add(invoice.StoreId);
                    textSearch.Add(invoice.Metadata.BuyerEmail);
                    //
                    textSearch.Add(invoice.RefundMail);
                    // TODO: Are there more things to cache? PaymentData?
                    InvoiceRepository.AddToTextSearch(ctx,
                                                      new InvoiceData {
                        Id = invoice.Id, InvoiceSearchData = new List <InvoiceSearchData>()
                    },
                                                      textSearch.ToArray());
                }

                var settings = await _settingsRepository.GetSettingAsync <MigrationSettings>();

                if (i + 1 < totalPages)
                {
                    settings.MigratedInvoiceTextSearchPages = i;
                }
                else
                {
                    // during final pass we set int.MaxValue so migration doesn't run again
                    settings.MigratedInvoiceTextSearchPages = int.MaxValue;
                }

                // this call triggers update; we're sure that MigrationSettings is already initialized in db
                // because of logic executed in MigrationStartupTask.cs
                _settingsRepository.UpdateSettingInContext(ctx, settings);
                await ctx.SaveChangesAsync();
            }
            Logs.PayServer.LogInformation($"Full invoice search import successful");
        }
예제 #3
0
 public ApplicationDbContext CreateDbContext()
 {
     return(_ContextFactory.CreateContext());
 }
예제 #4
0
 public async Task <BitTokenEntity[]> GetTokens(string sin)
 {
     if (sin == null)
     {
         return(Array.Empty <BitTokenEntity>());
     }
     using (var ctx = _Factory.CreateContext())
     {
         return((await ctx.PairedSINData.Where(p => p.SIN == sin)
                 .ToArrayAsync())
                .Select(p => CreateTokenEntity(p))
                .ToArray());
     }
 }
예제 #5
0
        public async Task <IActionResult> PullPayments(
            string storeId,
            PullPaymentState pullPaymentState,
            int skip         = 0,
            int count        = 50,
            string sortOrder = "desc"
            )
        {
            await using var ctx = _dbContextFactory.CreateContext();
            var now      = DateTimeOffset.UtcNow;
            var ppsQuery = ctx.PullPayments
                           .Include(data => data.Payouts)
                           .Where(p => p.StoreId == storeId);

            if (sortOrder != null)
            {
                switch (sortOrder)
                {
                case "desc":
                    ViewData["NextStartSortOrder"] = "asc";
                    ppsQuery = ppsQuery.OrderByDescending(p => p.StartDate);
                    break;

                case "asc":
                    ppsQuery = ppsQuery.OrderBy(p => p.StartDate);
                    ViewData["NextStartSortOrder"] = "desc";
                    break;
                }
            }

            var paymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData());

            if (!paymentMethods.Any())
            {
                TempData.SetStatusMessageModel(new StatusMessageModel
                {
                    Message  = "You must enable at least one payment method before creating a pull payment.",
                    Severity = StatusMessageModel.StatusSeverity.Error
                });
                return(RedirectToAction(nameof(UIStoresController.Dashboard), "UIStores", new { storeId }));
            }

            var vm = this.ParseListQuery(new PullPaymentsModel
            {
                Skip = skip, Count = count, ActiveState = pullPaymentState
            });

            switch (pullPaymentState)
            {
            case PullPaymentState.Active:
                ppsQuery = ppsQuery
                           .Where(
                    p => !p.Archived &&
                    (p.EndDate != null ? p.EndDate > DateTimeOffset.UtcNow : true) &&
                    p.StartDate <= DateTimeOffset.UtcNow
                    );
                break;

            case PullPaymentState.Archived:
                ppsQuery = ppsQuery.Where(p => p.Archived);
                break;

            case PullPaymentState.Expired:
                ppsQuery = ppsQuery.Where(p => DateTimeOffset.UtcNow > p.EndDate);
                break;

            case PullPaymentState.Future:
                ppsQuery = ppsQuery.Where(p => p.StartDate > DateTimeOffset.UtcNow);
                break;
            }

            var pps = await ppsQuery
                      .Skip(vm.Skip)
                      .Take(vm.Count)
                      .ToListAsync();

            vm.PullPayments.AddRange(pps.Select(pp =>
            {
                var blob = pp.GetBlob();
                return(new PullPaymentsModel.PullPaymentModel()
                {
                    StartDate = pp.StartDate,
                    EndDate = pp.EndDate,
                    Id = pp.Id,
                    Name = blob.Name,
                    AutoApproveClaims = blob.AutoApproveClaims,
                    Progress = _pullPaymentService.CalculatePullPaymentProgress(pp, now),
                    Archived = pp.Archived
                });
            }));

            return(View(vm));
        }
        public async Task <IActionResult> PullPayments(string storeId, int skip = 0, int count = 50,
                                                       string sortOrder         = "desc")
        {
            await using var ctx = _dbContextFactory.CreateContext();
            var now      = DateTimeOffset.UtcNow;
            var ppsQuery = ctx.PullPayments
                           .Include(data => data.Payouts)
                           .Where(p => p.StoreId == storeId && !p.Archived);


            if (sortOrder != null)
            {
                switch (sortOrder)
                {
                case "desc":
                    ViewData["NextStartSortOrder"] = "asc";
                    ppsQuery = ppsQuery.OrderByDescending(p => p.StartDate);
                    break;

                case "asc":
                    ppsQuery = ppsQuery.OrderBy(p => p.StartDate);
                    ViewData["NextStartSortOrder"] = "desc";
                    break;
                }
            }

            var vm = this.ParseListQuery(new PullPaymentsModel()
            {
                Skip  = skip,
                Count = count,
                Total = await ppsQuery.CountAsync()
            });
            var pps = (await ppsQuery
                       .Skip(vm.Skip)
                       .Take(vm.Count)
                       .ToListAsync()
                       );

            foreach (var pp in pps)
            {
                var totalCompleted = pp.Payouts.Where(p => (p.State == PayoutState.Completed ||
                                                            p.State == PayoutState.InProgress) && p.IsInPeriod(pp, now))
                                     .Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();
                var totalAwaiting = pp.Payouts.Where(p => (p.State == PayoutState.AwaitingPayment ||
                                                           p.State == PayoutState.AwaitingApproval) &&
                                                     p.IsInPeriod(pp, now)).Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();
                ;
                var ppBlob = pp.GetBlob();
                var ni     = _currencyNameTable.GetCurrencyData(ppBlob.Currency, true);
                var nfi    = _currencyNameTable.GetNumberFormatInfo(ppBlob.Currency, true);
                var period = pp.GetPeriod(now);
                vm.PullPayments.Add(new PullPaymentsModel.PullPaymentModel()
                {
                    StartDate = pp.StartDate,
                    EndDate   = pp.EndDate,
                    Id        = pp.Id,
                    Name      = ppBlob.Name,
                    Progress  = new PullPaymentsModel.PullPaymentModel.ProgressModel()
                    {
                        CompletedPercent = (int)(totalCompleted / ppBlob.Limit * 100m),
                        AwaitingPercent  = (int)(totalAwaiting / ppBlob.Limit * 100m),
                        Awaiting         = totalAwaiting.RoundToSignificant(ni.Divisibility).ToString("C", nfi),
                        Completed        = totalCompleted.RoundToSignificant(ni.Divisibility).ToString("C", nfi),
                        Limit            = _currencyNameTable.DisplayFormatCurrency(ppBlob.Limit, ppBlob.Currency),
                        ResetIn          = period?.End is DateTimeOffset nr ? ZeroIfNegative(nr - now).TimeString() : null,
                        EndIn            = pp.EndDate is DateTimeOffset end ? ZeroIfNegative(end - now).TimeString() : null
                    }
                });
예제 #7
0
        public async Task <IActionResult> CreateApp(CreateAppViewModel vm)
        {
            var stores = await _AppService.GetOwnedStores(GetUserId());

            if (stores.Length == 0)
            {
                StatusMessage = new StatusMessageModel()
                {
                    Html =
                        $"Error: You need to create at least one store. <a href='{(Url.Action("CreateStore", "UserStores"))}'>Create store</a>",
                    Severity = StatusMessageModel.StatusSeverity.Error
                }.ToString();
                return(RedirectToAction(nameof(ListApps)));
            }
            var selectedStore = vm.SelectedStore;

            vm.SetStores(stores);
            vm.SelectedStore = selectedStore;

            if (!Enum.TryParse <AppType>(vm.SelectedAppType, out AppType appType))
            {
                ModelState.AddModelError(nameof(vm.SelectedAppType), "Invalid App Type");
            }

            if (!ModelState.IsValid)
            {
                return(View(vm));
            }

            if (!stores.Any(s => s.Id == selectedStore))
            {
                StatusMessage = "Error: You are not owner of this store";
                return(RedirectToAction(nameof(ListApps)));
            }
            var id = Encoders.Base58.EncodeData(RandomUtils.GetBytes(20));

            using (var ctx = _ContextFactory.CreateContext())
            {
                var appData = new AppData()
                {
                    Id = id
                };
                appData.StoreDataId = selectedStore;
                appData.Name        = vm.Name;
                appData.AppType     = appType.ToString();
                ctx.Apps.Add(appData);
                await ctx.SaveChangesAsync();
            }
            StatusMessage = "App successfully created";
            CreatedAppId  = id;

            switch (appType)
            {
            case AppType.PointOfSale:
                return(RedirectToAction(nameof(UpdatePointOfSale), new { appId = id }));

            case AppType.Crowdfund:
                return(RedirectToAction(nameof(UpdateCrowdfund), new { appId = id }));

            default:
                return(RedirectToAction(nameof(ListApps)));
            }
        }
예제 #8
0
        private async Task MigrateLighingAddressDatabaseMigration()
        {
            await using var ctx = _DBContextFactory.CreateContext();

            var lightningAddressSettings =
                await _Settings.GetSettingAsync <UILNURLController.LightningAddressSettings>(
                    nameof(UILNURLController.LightningAddressSettings));

            if (lightningAddressSettings is null)
            {
                return;
            }

            var storeids       = lightningAddressSettings.StoreToItemMap.Keys.ToArray();
            var existingStores = (await ctx.Stores.Where(data => storeids.Contains(data.Id)).Select(data => data.Id).ToArrayAsync()).ToHashSet();

            foreach (var storeMap in lightningAddressSettings.StoreToItemMap)
            {
                if (!existingStores.Contains(storeMap.Key))
                {
                    continue;
                }
                foreach (var storeitem in storeMap.Value)
                {
                    if (lightningAddressSettings.Items.TryGetValue(storeitem, out var val))
                    {
                        await _lightningAddressService.Set(
                            new LightningAddressData()
                        {
                            StoreDataId = storeMap.Key,
                            Username    = storeitem,
                            Blob        = new LightningAddressDataBlob()
                            {
                                Max          = val.Max,
                                Min          = val.Min,
                                CurrencyCode = val.CurrencyCode
                            }.SerializeBlob()
                        }, ctx);
                    }
                }
            }

            await ctx.SaveChangesAsync();

            await _Settings.UpdateSetting <object>(null, nameof(UILNURLController.LightningAddressSettings));
        }
예제 #9
0
 public async Task <List <ApplicationUserData> > GetUsersWithRoles()
 {
     await using var context = _applicationDbContextFactory.CreateContext();
     return(await(context.Users.Select(p => FromModel(p, p.UserRoles.Join(context.Roles, userRole => userRole.RoleId, role => role.Id,
                                                                          (userRole, role) => role.Name).ToArray()))).ToListAsync());
 }
예제 #10
0
 public async Task <List <LightningAddressData> > Get(LightningAddressQuery query)
 {
     await using var context = _applicationDbContextFactory.CreateContext();
     return(await GetCore(context, query));
 }
        public async Task <IActionResult> PullPayments(
            string storeId,
            PullPaymentState pullPaymentState,
            int skip         = 0,
            int count        = 50,
            string sortOrder = "desc"
            )
        {
            await using var ctx = _dbContextFactory.CreateContext();
            var now      = DateTimeOffset.UtcNow;
            var ppsQuery = ctx.PullPayments
                           .Include(data => data.Payouts)
                           .Where(p => p.StoreId == storeId);

            if (sortOrder != null)
            {
                switch (sortOrder)
                {
                case "desc":
                    ViewData["NextStartSortOrder"] = "asc";
                    ppsQuery = ppsQuery.OrderByDescending(p => p.StartDate);
                    break;

                case "asc":
                    ppsQuery = ppsQuery.OrderBy(p => p.StartDate);
                    ViewData["NextStartSortOrder"] = "desc";
                    break;
                }
            }

            var paymentMethods = await _payoutHandlers.GetSupportedPaymentMethods(HttpContext.GetStoreData());

            if (!paymentMethods.Any())
            {
                TempData.SetStatusMessageModel(new StatusMessageModel
                {
                    Message  = "You must enable at least one payment method before creating a pull payment.",
                    Severity = StatusMessageModel.StatusSeverity.Error
                });
                return(RedirectToAction(nameof(UIStoresController.GeneralSettings), "UIStores", new { storeId }));
            }

            var vm = this.ParseListQuery(new PullPaymentsModel
            {
                Skip        = skip,
                Count       = count,
                Total       = await ppsQuery.CountAsync(),
                ActiveState = pullPaymentState
            });

            switch (pullPaymentState)
            {
            case PullPaymentState.Active:
                ppsQuery = ppsQuery
                           .Where(
                    p => !p.Archived &&
                    (p.EndDate != null ? p.EndDate > DateTimeOffset.UtcNow : true) &&
                    p.StartDate <= DateTimeOffset.UtcNow
                    );
                break;

            case PullPaymentState.Archived:
                ppsQuery = ppsQuery.Where(p => p.Archived);
                break;

            case PullPaymentState.Expired:
                ppsQuery = ppsQuery.Where(p => DateTimeOffset.UtcNow > p.EndDate);
                break;

            case PullPaymentState.Future:
                ppsQuery = ppsQuery.Where(p => p.StartDate > DateTimeOffset.UtcNow);
                break;
            }

            var pps = (await ppsQuery
                       .Skip(vm.Skip)
                       .Take(vm.Count)
                       .ToListAsync()
                       );

            foreach (var pp in pps)
            {
                var totalCompleted = pp.Payouts.Where(p => (p.State == PayoutState.Completed ||
                                                            p.State == PayoutState.InProgress) && p.IsInPeriod(pp, now))
                                     .Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();
                var totalAwaiting = pp.Payouts.Where(p => (p.State == PayoutState.AwaitingPayment ||
                                                           p.State == PayoutState.AwaitingApproval) &&
                                                     p.IsInPeriod(pp, now)).Select(o => o.GetBlob(_jsonSerializerSettings).Amount).Sum();
                ;
                var ppBlob = pp.GetBlob();
                var ni     = _currencyNameTable.GetCurrencyData(ppBlob.Currency, true);
                var nfi    = _currencyNameTable.GetNumberFormatInfo(ppBlob.Currency, true);
                var period = pp.GetPeriod(now);
                vm.PullPayments.Add(new PullPaymentsModel.PullPaymentModel()
                {
                    StartDate = pp.StartDate,
                    EndDate   = pp.EndDate,
                    Id        = pp.Id,
                    Name      = ppBlob.Name,
                    Progress  = new PullPaymentsModel.PullPaymentModel.ProgressModel()
                    {
                        CompletedPercent = (int)(totalCompleted / ppBlob.Limit * 100m),
                        AwaitingPercent  = (int)(totalAwaiting / ppBlob.Limit * 100m),
                        Awaiting         = totalAwaiting.RoundToSignificant(ni.Divisibility).ToString("C", nfi),
                        Completed        = totalCompleted.RoundToSignificant(ni.Divisibility).ToString("C", nfi),
                        Limit            = _currencyNameTable.DisplayFormatCurrency(ppBlob.Limit, ppBlob.Currency),
                        ResetIn          = period?.End is DateTimeOffset nr ? ZeroIfNegative(nr - now).TimeString() : null,
                        EndIn            = pp.EndDate is DateTimeOffset end ? ZeroIfNegative(end - now).TimeString() : null,
                    },
예제 #12
0
 private async Task AddInitialUserBlob()
 {
     await using var ctx = _DBContextFactory.CreateContext();
     foreach (var user in await ctx.Users.AsQueryable().ToArrayAsync())
     {
         user.SetBlob(new UserBlob()
         {
             ShowInvoiceStatusChangeHint = true
         });
     }
     await ctx.SaveChangesAsync();
 }
예제 #13
0
    public async Task <StatusMessageModel> DoSpecificAction(string action, string[] payoutIds, string storeId)
    {
        switch (action)
        {
        case "mark-paid":
            await using (var context = _dbContextFactory.CreateContext())
            {
                var payouts = (await context.Payouts
                               .Include(p => p.PullPaymentData)
                               .Include(p => p.PullPaymentData.StoreData)
                               .Where(p => payoutIds.Contains(p.Id))
                               .Where(p => p.PullPaymentData.StoreId == storeId && !p.PullPaymentData.Archived && p.State == PayoutState.AwaitingPayment)
                               .ToListAsync()).Where(data =>
                                                     PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) &&
                                                     CanHandle(paymentMethodId))
                              .Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple => tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == false);
                foreach (var valueTuple in payouts)
                {
                    valueTuple.Item2.Accounted = true;
                    valueTuple.data.State      = PayoutState.InProgress;
                    SetProofBlob(valueTuple.data, valueTuple.Item2);
                }

                await context.SaveChangesAsync();
            }

            return(new StatusMessageModel()
            {
                Message = "Payout payments have been marked confirmed",
                Severity = StatusMessageModel.StatusSeverity.Success
            });

        case "reject-payment":
            await using (var context = _dbContextFactory.CreateContext())
            {
                var payouts = (await context.Payouts
                               .Include(p => p.PullPaymentData)
                               .Include(p => p.PullPaymentData.StoreData)
                               .Where(p => payoutIds.Contains(p.Id))
                               .Where(p => p.PullPaymentData.StoreId == storeId && !p.PullPaymentData.Archived && p.State == PayoutState.AwaitingPayment)
                               .ToListAsync()).Where(data =>
                                                     PaymentMethodId.TryParse(data.PaymentMethodId, out var paymentMethodId) &&
                                                     CanHandle(paymentMethodId))
                              .Select(data => (data, ParseProof(data) as PayoutTransactionOnChainBlob)).Where(tuple => tuple.Item2 != null && tuple.Item2.TransactionId != null && tuple.Item2.Accounted == true);
                foreach (var valueTuple in payouts)
                {
                    valueTuple.Item2.TransactionId = null;
                    SetProofBlob(valueTuple.data, valueTuple.Item2);
                }

                await context.SaveChangesAsync();
            }

            return(new StatusMessageModel()
            {
                Message = "Payout payments have been unmarked",
                Severity = StatusMessageModel.StatusSeverity.Success
            });
        }

        return(null);
    }
    private async Task UpdatePayoutsInProgress()
    {
        try
        {
            using var ctx = _dbContextFactory.CreateContext();
            var payouts = await ctx.Payouts
                          .Include(p => p.PullPaymentData)
                          .Where(p => p.State == PayoutState.InProgress)
                          .ToListAsync();

            foreach (var payout in payouts)
            {
                var proof      = ParseProof(payout) as PayoutTransactionOnChainBlob;
                var payoutBlob = payout.GetBlob(this._jsonSerializerSettings);
                if (proof is null || proof.Accounted is false)
                {
                    continue;
                }
                foreach (var txid in proof.Candidates.ToList())
                {
                    var explorer = _explorerClientProvider.GetExplorerClient(payout.GetPaymentMethodId().CryptoCode);
                    var tx       = await explorer.GetTransactionAsync(txid);

                    if (tx is null)
                    {
                        proof.Candidates.Remove(txid);
                    }
                    else if (tx.Confirmations >= payoutBlob.MinimumConfirmation)
                    {
                        payout.State        = PayoutState.Completed;
                        proof.TransactionId = tx.TransactionHash;
                        payout.Destination  = null;
                        break;
                    }
                    else
                    {
                        var rebroadcasted = await explorer.BroadcastAsync(tx.Transaction);

                        if (rebroadcasted.RPCCode == RPCErrorCode.RPC_TRANSACTION_ERROR ||
                            rebroadcasted.RPCCode == RPCErrorCode.RPC_TRANSACTION_REJECTED)
                        {
                            proof.Candidates.Remove(txid);
                        }
                        else
                        {
                            payout.State        = PayoutState.InProgress;
                            proof.TransactionId = tx.TransactionHash;
                            continue;
                        }
                    }
                }

                if (proof.TransactionId is null && !proof.Candidates.Contains(proof.TransactionId))
                {
                    proof.TransactionId = null;
                }

                if (proof.Candidates.Count == 0)
                {
                    payout.State = PayoutState.AwaitingPayment;
                }
                else if (proof.TransactionId is null)
                {
                    proof.TransactionId = proof.Candidates.First();
                }

                if (payout.State == PayoutState.Completed)
                {
                    proof.Candidates = null;
                }
                SetProofBlob(payout, proof);
            }

            await ctx.SaveChangesAsync();
        }
        catch (Exception ex)
        {
            Logs.PayServer.LogWarning(ex, "Error while processing an update in the pull payment hosted service");
        }
    }
예제 #15
0
        public async Task <StoreData> FindStore(string storeId)
        {
            if (storeId == null)
            {
                return(null);
            }
            using (var ctx = _ContextFactory.CreateContext())
            {
                var result = await ctx.FindAsync <StoreData>(storeId).ConfigureAwait(false);

                return(result);
            }
        }
예제 #16
0
        /// <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)
        {
            await using var context = _applicationDbContextFactory.CreateContext();
            var invoice = await context.Invoices.FindAsync(invoiceId);

            if (invoice == null)
            {
                return(null);
            }
            InvoiceEntity         invoiceEntity        = invoice.GetBlob(_btcPayNetworkProvider);
            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 = InvoiceRepository.ToBytes(invoiceEntity, network);
            }
            PaymentData data = new PaymentData
            {
                Id            = paymentData.GetPaymentId(),
                Blob          = InvoiceRepository.ToBytes(entity, entity.Network),
                InvoiceDataId = invoiceId,
                Accounted     = accounted
            };

            await context.Payments.AddAsync(data);

            InvoiceRepository.AddToTextSearch(context, invoice, paymentData.GetSearchTerms());
            var alreadyExists = false;

            try
            {
                await context.SaveChangesAsync().ConfigureAwait(false);
            }
            catch (DbUpdateException) { alreadyExists = true; }

            if (alreadyExists)
            {
                return(null);
            }

            if (paymentData.PaymentConfirmed(entity, invoiceEntity.SpeedPolicy))
            {
                _eventAggregator.Publish(new InvoiceEvent(invoiceEntity, InvoiceEvent.PaymentSettled)
                {
                    Payment = entity
                });
            }
            return(entity);
        }
예제 #17
0
        public async Task <bool> RemovePendingInvoice(string invoiceId)
        {
            Logs.PayServer.LogInformation($"Remove pending invoice {invoiceId}");
            using (var ctx = _ContextFactory.CreateContext())
            {
                ctx.PendingInvoices.Remove(new PendingInvoiceData()
                {
                    Id = invoiceId
                });
                try
                {
                    await ctx.SaveChangesAsync();

                    return(true);
                }
                catch (DbUpdateException) { return(false); }
            }
        }
예제 #18
0
        // In the past, if a server was considered local network, then we would disable TLS checks.
        // Now we don't do it anymore, as we have an explicit flag (DisableCertificateCheck) to control the behavior.
        // But we need to migrate old users that relied on the behavior before.
        private async Task MigrateEmailServerDisableTLSCerts()
        {
            await using var ctx = _DBContextFactory.CreateContext();
            var serverEmailSettings = await _Settings.GetSettingAsync <Services.Mails.EmailSettings>();

            if (serverEmailSettings?.Server is String server)
            {
                serverEmailSettings.DisableCertificateCheck = Extensions.IsLocalNetwork(server);
                if (serverEmailSettings.DisableCertificateCheck)
                {
                    await _Settings.UpdateSetting(serverEmailSettings);
                }
            }
            var stores = await ctx.Stores.ToArrayAsync();

            foreach (var store in stores)
            {
                var storeBlob = store.GetStoreBlob();
                if (storeBlob.EmailSettings?.Server is String storeServer)
                {
                    storeBlob.EmailSettings.DisableCertificateCheck = Extensions.IsLocalNetwork(storeServer);
                    if (storeBlob.EmailSettings.DisableCertificateCheck)
                    {
                        store.SetStoreBlob(storeBlob);
                    }
                }
            }
            await ctx.SaveChangesAsync();
        }