Example #1
0
        public async Task <IActionResult> CreateInvoice(string storeId, CreateInvoiceRequest request)
        {
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(NotFound());
            }

            if (request.Amount < 0.0m)
            {
                ModelState.AddModelError(nameof(request.Amount), "The amount should be 0 or more.");
            }

            if (string.IsNullOrEmpty(request.Currency))
            {
                ModelState.AddModelError(nameof(request.Currency), "Currency is required");
            }

            if (request.Checkout.PaymentMethods?.Any() is true)
            {
                for (int i = 0; i < request.Checkout.PaymentMethods.Length; i++)
                {
                    if (!PaymentMethodId.TryParse(request.Checkout.PaymentMethods[i], out _))
                    {
                        request.AddModelError(invoiceRequest => invoiceRequest.Checkout.PaymentMethods[i],
                                              "Invalid payment method", this);
                    }
                }
            }

            if (request.Checkout.Expiration != null && request.Checkout.Expiration < TimeSpan.FromSeconds(30.0))
            {
                request.AddModelError(invoiceRequest => invoiceRequest.Checkout.Expiration,
                                      "Expiration time must be at least 30 seconds", this);
            }

            if (request.Checkout.PaymentTolerance != null &&
                (request.Checkout.PaymentTolerance < 0 || request.Checkout.PaymentTolerance > 100))
            {
                request.AddModelError(invoiceRequest => invoiceRequest.Checkout.PaymentTolerance,
                                      "PaymentTolerance can only be between 0 and 100 percent", this);
            }

            if (!ModelState.IsValid)
            {
                return(this.CreateValidationError(ModelState));
            }

            try
            {
                var invoice = await _invoiceController.CreateInvoiceCoreRaw(request, store,
                                                                            Request.GetAbsoluteUri(""));

                return(Ok(ToModel(invoice)));
            }
            catch (BitpayHttpException e)
            {
                return(this.CreateAPIError(null, e.Message));
            }
        }
        public async Task <IActionResult> CreateInvoice(string storeId, CreateInvoiceRequest request)
        {
            var store = HttpContext.GetStoreData();

            if (store == null)
            {
                return(StoreNotFound());
            }

            if (request.Amount < 0.0m)
            {
                ModelState.AddModelError(nameof(request.Amount), "The amount should be 0 or more.");
            }

            if (string.IsNullOrEmpty(request.Currency))
            {
                ModelState.AddModelError(nameof(request.Currency), "Currency is required");
            }
            request.Checkout = request.Checkout ?? new CreateInvoiceRequest.CheckoutOptions();
            if (request.Checkout.PaymentMethods?.Any() is true)
            {
                for (int i = 0; i < request.Checkout.PaymentMethods.Length; i++)
                {
                    if (!PaymentMethodId.TryParse(request.Checkout.PaymentMethods[i], out _))
                    {
                        request.AddModelError(invoiceRequest => invoiceRequest.Checkout.PaymentMethods[i],
                                              "Invalid payment method", this);
                    }
                }
            }

            if (request.Checkout.Expiration != null && request.Checkout.Expiration < TimeSpan.FromSeconds(30.0))
            {
                request.AddModelError(invoiceRequest => invoiceRequest.Checkout.Expiration,
                                      "Expiration time must be at least 30 seconds", this);
            }

            if (request.Checkout.PaymentTolerance != null &&
                (request.Checkout.PaymentTolerance < 0 || request.Checkout.PaymentTolerance > 100))
            {
                request.AddModelError(invoiceRequest => invoiceRequest.Checkout.PaymentTolerance,
                                      "PaymentTolerance can only be between 0 and 100 percent", this);
            }

            if (request.Checkout.DefaultLanguage != null)
            {
                var lang = LanguageService.FindLanguage(request.Checkout.DefaultLanguage);
                if (lang == null)
                {
                    request.AddModelError(invoiceRequest => invoiceRequest.Checkout.DefaultLanguage,
                                          "The requested defaultLang does not exists, Browse the ~/misc/lang page of your BTCPay Server instance to see the list of supported languages.", this);
                }
                else
                {
                    // Ensure this is good case
                    request.Checkout.DefaultLanguage = lang.Code;
                }
            }

            if (!ModelState.IsValid)
            {
                return(this.CreateValidationError(ModelState));
            }

            try
            {
                var invoice = await _invoiceController.CreateInvoiceCoreRaw(request, store,
                                                                            Request.GetAbsoluteUri(""));

                return(Ok(ToModel(invoice)));
            }
            catch (BitpayHttpException e)
            {
                return(this.CreateAPIError(null, e.Message));
            }
        }
        public async Task <IActionResult> ShopifyInvoiceEndpoint(
            string storeId, string orderId, decimal amount, bool checkOnly = false)
        {
            var invoiceOrderId          = $"{ShopifyOrderMarkerHostedService.SHOPIFY_ORDER_ID_PREFIX}{orderId}";
            var matchedExistingInvoices = await _invoiceRepository.GetInvoices(new InvoiceQuery()
            {
                OrderId = new[] { invoiceOrderId }, StoreId = new[] { storeId }
            });

            matchedExistingInvoices = matchedExistingInvoices.Where(entity =>
                                                                    entity.GetInternalTags(ShopifyOrderMarkerHostedService.SHOPIFY_ORDER_ID_PREFIX)
                                                                    .Any(s => s == orderId))
                                      .ToArray();

            var firstInvoiceStillPending =
                matchedExistingInvoices.FirstOrDefault(entity =>
                                                       entity.GetInvoiceState().Status == InvoiceStatusLegacy.New);

            if (firstInvoiceStillPending != null)
            {
                return(Ok(new
                {
                    invoiceId = firstInvoiceStillPending.Id,
                    status = firstInvoiceStillPending.Status.ToString().ToLowerInvariant()
                }));
            }

            var firstInvoiceSettled =
                matchedExistingInvoices.LastOrDefault(entity =>
                                                      new[] { InvoiceStatusLegacy.Paid, InvoiceStatusLegacy.Complete, InvoiceStatusLegacy.Confirmed }
                                                      .Contains(
                                                          entity.GetInvoiceState().Status));

            var store = await _storeRepository.FindStore(storeId);

            var shopify             = store?.GetStoreBlob()?.GetShopifySettings();
            ShopifyApiClient client = null;
            ShopifyOrder     order  = null;

            if (shopify?.IntegratedAt.HasValue is true)
            {
                client = new ShopifyApiClient(_clientFactory, shopify.CreateShopifyApiCredentials());
                order  = await client.GetOrder(orderId);

                if (string.IsNullOrEmpty(order?.Id))
                {
                    return(NotFound());
                }
            }

            if (firstInvoiceSettled != null)
            {
                //if BTCPay was shut down before the tx managed to get registered on shopify, this will fix it on the next UI load in shopify
                if (client != null && order?.FinancialStatus == "pending" &&
                    firstInvoiceSettled.Status != InvoiceStatusLegacy.Paid)
                {
                    await new OrderTransactionRegisterLogic(client).Process(orderId, firstInvoiceSettled.Id,
                                                                            firstInvoiceSettled.Currency,
                                                                            firstInvoiceSettled.Price.ToString(CultureInfo.InvariantCulture), true);
                    order = await client.GetOrder(orderId);
                }

                if (order?.FinancialStatus != "pending" && order?.FinancialStatus != "partially_paid")
                {
                    return(Ok(new
                    {
                        invoiceId = firstInvoiceSettled.Id,
                        status = firstInvoiceSettled.Status.ToString().ToLowerInvariant()
                    }));
                }
            }

            if (checkOnly)
            {
                return(Ok());
            }

            if (shopify?.IntegratedAt.HasValue is true)
            {
                if (string.IsNullOrEmpty(order?.Id) ||
                    !new[] { "pending", "partially_paid" }.Contains(order.FinancialStatus))
                {
                    return(NotFound());
                }

                //we create the invoice at due amount provided from order page or full amount if due amount is bigger than order amount
                var invoice = await _invoiceController.CreateInvoiceCoreRaw(
                    new CreateInvoiceRequest()
                {
                    Amount   = amount < order.TotalPrice ? amount : order.TotalPrice,
                    Currency = order.Currency,
                    Metadata = new JObject {
                        ["orderId"] = invoiceOrderId
                    }
                }, store,
                    Request.GetAbsoluteUri(""), new List <string>() { invoiceOrderId });

                return(Ok(new { invoiceId = invoice.Id, status = invoice.Status.ToString().ToLowerInvariant() }));
            }

            return(NotFound());
        }