コード例 #1
0
        private async Task <HttpResponseMessage> SendNotification(BitPayInvoicePaymentNotificationEventWrapper notification, CancellationToken cancellationToken)
        {
            var request = new HttpRequestMessage();

            request.Method = HttpMethod.Post;

            var notificationString = NBitcoin.JsonConverters.Serializer.ToString(notification);
            var jobj = JObject.Parse(notificationString);

            if (notification.ExtendedNotification)
            {
                jobj.Remove("extendedNotification");
                jobj.Remove("notificationURL"); notificationString = jobj.ToString();
            }
            else
            {
                notificationString = jobj["data"].ToString();
            }

            request.RequestUri = new Uri(notification.NotificationURL, UriKind.Absolute);
            request.Content    = new StringContent(notificationString, UTF8, "application/json");
            var response = await Enqueue(notification.Data.Id, async() =>
            {
                using (CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
                {
                    cts.CancelAfter(TimeSpan.FromMinutes(1.0));
                    return(await _Client.SendAsync(request, cts.Token));
                }
            });

            return(response);
        }
コード例 #2
0
        async Task Notify(InvoiceEntity invoice, InvoiceEvent invoiceEvent, bool extendedNotification)
        {
            var dto          = invoice.EntityToDTO();
            var notification = new BitPayInvoicePaymentNotificationEventWrapper()
            {
                Data = new InvoicePaymentNotification()
                {
                    Id              = dto.Id,
                    Currency        = dto.Currency,
                    CurrentTime     = dto.CurrentTime,
                    ExceptionStatus = dto.ExceptionStatus,
                    ExpirationTime  = dto.ExpirationTime,
                    InvoiceTime     = dto.InvoiceTime,
                    PosData         = dto.PosData,
                    Price           = dto.Price,
                    Status          = dto.Status,
                    BuyerFields     = invoice.RefundMail == null ? null : new Newtonsoft.Json.Linq.JObject()
                    {
                        new JProperty("buyerEmail", invoice.RefundMail)
                    },
                    PaymentSubtotals = dto.PaymentSubtotals,
                    PaymentTotals    = dto.PaymentTotals,
                    AmountPaid       = dto.AmountPaid,
                    ExchangeRates    = dto.ExchangeRates,
                    OrderId          = dto.OrderId
                },
                Event = new BitPayInvoicePaymentNotificationEvent()
                {
                    Code = invoiceEvent.EventCode,
                    Name = invoiceEvent.Name
                },
                ExtendedNotification = extendedNotification,
                NotificationURL      = invoice.NotificationURL?.AbsoluteUri
            };

            // For lightning network payments, paid, confirmed and completed come all at once.
            // So despite the event is "paid" or "confirmed" the Status of the invoice is technically complete
            // This confuse loggers who think their endpoint get duplicated events
            // So here, we just override the status expressed by the notification
            if (invoiceEvent.Name == InvoiceEvent.Confirmed)
            {
                notification.Data.Status = InvoiceState.ToString(InvoiceStatus.Confirmed);
            }
            if (invoiceEvent.Name == InvoiceEvent.PaidInFull)
            {
                notification.Data.Status = InvoiceState.ToString(InvoiceStatus.Paid);
            }
            //////////////////

            // We keep backward compatibility with bitpay by passing BTC info to the notification
            // we don't pass other info, as it is a bad idea to use IPN data for logic processing (can be faked)
            var btcCryptoInfo = dto.CryptoInfo.FirstOrDefault(c => c.GetpaymentMethodId() == new PaymentMethodId("BTC", Payments.PaymentTypes.BTCLike));

            if (btcCryptoInfo != null)
            {
#pragma warning disable CS0618
                notification.Data.Rate     = dto.Rate;
                notification.Data.Url      = dto.Url;
                notification.Data.BTCDue   = dto.BTCDue;
                notification.Data.BTCPaid  = dto.BTCPaid;
                notification.Data.BTCPrice = dto.BTCPrice;
#pragma warning restore CS0618
            }

            if (invoiceEvent.Name != InvoiceEvent.Expired && !String.IsNullOrEmpty(invoice.NotificationEmail))
            {
                var json  = NBitcoin.JsonConverters.Serializer.ToString(notification);
                var store = await _StoreRepository.FindStore(invoice.StoreId);

                var storeName = store.StoreName ?? "BTCPay Server";
                var emailBody = $"Store: {storeName}<br>" +
                                $"Invoice ID: {notification.Data.Id}<br>" +
                                $"Status: {notification.Data.Status}<br>" +
                                $"Amount: {notification.Data.Price} {notification.Data.Currency}<br>" +
                                $"<br><details><summary>Details</summary><pre>{json}</pre></details>";

                _EmailSenderFactory.GetEmailSender(invoice.StoreId).SendEmail(
                    invoice.NotificationEmail,
                    $"{storeName} Invoice Notification - ${invoice.StoreId}",
                    emailBody);
            }

            if (invoice.NotificationURL != null)
            {
                var invoiceStr = NBitcoin.JsonConverters.Serializer.ToString(new ScheduledJob()
                {
                    TryCount = 0, Notification = notification
                });
                _JobClient.Schedule((cancellation) => NotifyHttp(invoiceStr, cancellation), TimeSpan.Zero);
            }
        }