Exemplo n.º 1
0
        public async Task UpdatePayments(List <PaymentEntity> payments)
        {
            if (payments.Count == 0)
            {
                return;
            }
            await using var context = _applicationDbContextFactory.CreateContext();
            var paymentsDict = payments
                               .Select(entity => (entity, entity.GetCryptoPaymentData()))
                               .ToDictionary(tuple => tuple.Item2.GetPaymentId());
            var paymentIds = paymentsDict.Keys.ToArray();
            var dbPayments = await context.Payments
                             .Include(data => data.InvoiceData)
                             .Where(data => paymentIds.Contains(data.Id)).ToDictionaryAsync(data => data.Id);

            var eventsToSend = new List <InvoiceEvent>();

            foreach (KeyValuePair <string, (PaymentEntity entity, CryptoPaymentData)> payment in paymentsDict)
            {
                var dbPayment       = dbPayments[payment.Key];
                var invBlob         = dbPayment.InvoiceData.GetBlob(_btcPayNetworkProvider);
                var dbPaymentEntity = dbPayment.GetBlob(_btcPayNetworkProvider);
                var wasConfirmed    = dbPayment.GetBlob(_btcPayNetworkProvider).GetCryptoPaymentData()
                                      .PaymentConfirmed(dbPaymentEntity, invBlob.SpeedPolicy);
                if (!wasConfirmed && payment.Value.Item2.PaymentConfirmed(payment.Value.entity, invBlob.SpeedPolicy))
                {
                    eventsToSend.Add(new InvoiceEvent(invBlob, InvoiceEvent.PaymentSettled)
                    {
                        Payment = payment.Value.entity
                    });
                }

                dbPayment.Accounted = payment.Value.entity.Accounted;
                dbPayment.Blob      = InvoiceRepository.ToBytes(payment.Value.entity, payment.Value.entity.Network);
            }
            await context.SaveChangesAsync().ConfigureAwait(false);

            eventsToSend.ForEach(_eventAggregator.Publish);
        }
Exemplo n.º 2
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);
        }