//Done the Vipps payment
        private async Task <int> VippsCapturePayment(string token, string orderId)
        {
            var queryString = HttpUtility.ParseQueryString(string.Empty);

            Client.DefaultRequestHeaders.Add("Authorization", token);
            Client.DefaultRequestHeaders.Add("X-Request-Id", orderId);
            Client.DefaultRequestHeaders.Add("X-TimeStamp", Format.NorwayDateTimeNow().ToString());
            Client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", VippsParameter["Ocp-Apim-Subscription-Key"]);

            var uri = VippsParameter["vippsBaseUrl"] + "/ecomm/v2/payments/" + orderId + "/capture?" + queryString;
            HttpResponseMessage response;

            var vippsPayment = new VippsPayment()
            {
                merchantInfo = new merchantInfo(),
                transaction  = new transaction()
                {
                    transactionText = "transaction test" // ToDo :: Change the text to be description
                },

                customerInfo = null,
            };

            byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(vippsPayment));

            using (var content = new ByteArrayContent(byteData))
            {
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = Client.PostAsync(uri, content).Result;
                var responseString = await response.Content.ReadAsStringAsync();

                return((int)response.StatusCode);
            }
        }
        private void CheckAndModifyOrders(string userId)
        {
            var orders = _context.InitiatedOrders.Where(x => x.UserId == userId)
                         .Where(x => x.PaymentMethod == EnumList.PaymentMethod.Vipps)
                         .Where(x => x.Status == EnumList.OrderStatus.Initiated || x.Status == EnumList.OrderStatus.ActionRequired).ToList();

            var token       = VippsAccessToken().Result;
            var accessToken = "Bearer " + token;

            Client_Check.DefaultRequestHeaders.Add("Authorization", accessToken);
            Client_Check.DefaultRequestHeaders.Add("X-TimeStamp", Format.NorwayDateTimeNow().ToString());
            Client_Check.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", VippsParameter["Ocp-Apim-Subscription-Key"]);


            foreach (var order in orders)
            {
                var uri = VippsParameter["vippsBaseUrl"] + "/ecomm/v2/payments/" + order.Id + "/details";
                HttpResponseMessage response;

                var vippsPayment = new VippsPayment()
                {
                    merchantInfo = new merchantInfo(),
                    transaction  = new transaction()
                    {
                        transactionText = ""
                    },

                    customerInfo = null,
                };

                byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(vippsPayment));

                var fullResult = "NONE";
                using (var content = new ByteArrayContent(byteData))
                {
                    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    response   = Client_Check.GetAsync(uri).Result;
                    fullResult = response.Content.ReadAsStringAsync().Result;
                }



                try
                {
                    var history        = JObject.Parse(fullResult).SelectToken("transactionLogHistory");
                    var finalOperation = history.First["operation"].ToString();


                    Enum.TryParse(finalOperation, out EnumList.VippsPaymentStatus operation);


                    switch (operation)
                    {
                    case EnumList.VippsPaymentStatus.INITIATE:
                    case EnumList.VippsPaymentStatus.REGISTER:
                        if (order.Created.AddHours(1) < Format.NorwayDateTimeNow())
                        {
                            order.Status = EnumList.OrderStatus.Canceled;
                            _context.Update(order);
                            _context.SaveChanges();
                        }
                        continue;

                    case EnumList.VippsPaymentStatus.RESERVE:
                        //Important :: The payment is done but the process not completed --> Return true to show it to the user
                        order.Status = EnumList.OrderStatus.ActionRequired;
                        _context.Update(order);
                        _context.SaveChanges();
                        continue;

                    case EnumList.VippsPaymentStatus.CAPTURE:
                    case EnumList.VippsPaymentStatus.SALE:
                        //The money is paid and the order is completed in this case --> Set the order to be done the return false to remove it from view
                        order.Status = EnumList.OrderStatus.Completed;
                        _context.Update(order);
                        _context.SaveChanges();
                        continue;

                    case EnumList.VippsPaymentStatus.REJECTED:
                    case EnumList.VippsPaymentStatus.VOID:
                    case EnumList.VippsPaymentStatus.FAILED:
                    case EnumList.VippsPaymentStatus.CANCEL:
                    case EnumList.VippsPaymentStatus.INVALID:     //The order is not exist (STRIPE Case)
                        //All those cases the money has not paid or returned so no action required, no need to hold the order in records
                        order.Status = EnumList.OrderStatus.Failed;
                        _context.Update(order);
                        _context.SaveChanges();
                        continue;

                    case EnumList.VippsPaymentStatus.REFUND:
                        order.Status = EnumList.OrderStatus.Canceled;
                        _context.Update(order);
                        _context.SaveChanges();
                        continue;


                    default:
                        order.Status = EnumList.OrderStatus.Failed;
                        _context.Update(order);
                        _context.SaveChanges();
                        continue;
                    }
                }
                catch (Exception e)
                {
                    //ToDo :: Order exists in my website but not in Vipps (This case can be stripe for example)
                    order.Status = EnumList.OrderStatus.Failed;
                    _context.Update(order);
                    _context.SaveChanges();
                }
            }
        }
        public async Task <IActionResult> VippsRefund(string paymentId, string orderId, decimal amount)
        {
            var payment = _context.Payments.Find(paymentId);

            if (payment == null)
            {
                return(NotFound("Payment id not found"));
            }

            var queryString = HttpUtility.ParseQueryString(string.Empty);

            var accessToken = VippsAccessToken().Result;

            Client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            Client.DefaultRequestHeaders.Add("X-Request-Id", orderId);
            Client.DefaultRequestHeaders.Add("X-TimeStamp", Format.NorwayDateTimeNow().ToString());
            Client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", VippsParameter["Ocp-Apim-Subscription-Key"]);

            var uri = VippsParameter["vippsBaseUrl"] + "/ecomm/v2/payments/" + orderId + "/refund?" + queryString;
            HttpResponseMessage response;

            var vippsPayment = new VippsPayment()
            {
                merchantInfo = new merchantInfo(),
                transaction  = new transaction()
                {
                    amount          = (int)amount * 100,
                    transactionText = "Refund payment: " + paymentId + " - amount: " + amount
                },
                customerInfo = null,
            };


            byte[] byteData      = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(vippsPayment));
            var    processStatus = 0;

            using (var content = new ByteArrayContent(byteData))
            {
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = await Client.PostAsync(uri, content);

                var responseString = response.Content.ReadAsStringAsync().Result;
                processStatus = (int)response.StatusCode;
            }

            if (processStatus != 200)
            {
                return(BadRequest("The process failed!"));
            }

            payment.ExtraDescription = "Refunded: " + amount;
            payment.RefundedAt       = Format.NorwayDateTimeNow();
            payment.Refunded         = true;


            _context.Update(payment);
            _context.SaveChanges();


            var relatedInvoice = _context.Invoices.SingleOrDefault(x => x.PaymentId == paymentId);

            if (relatedInvoice == null)
            {
                return(Ok());
            }
            relatedInvoice.Paid     = false;
            relatedInvoice.Canceled = true;
            _context.Update(relatedInvoice);
            _context.SaveChanges();


            return(Ok());
        }
        public async Task <IActionResult> CreateVipps(string courseId, EnumList.PaymentReason reason, [Bind("AuthCookies,Ip,DeviceType,OperatingSystem")] UserDevice device, bool payAllNow, int invoiceNumber)
        {
            var invoice = _paymentService.GetInvoice(invoiceNumber);
            var user    = _context.Users.Find(_access.GetUserId(User));


            if (user == null)
            {
                return(BadRequest(new{ result = EnumList.PaymentResult.Failed, message = "error", reason = reason, url = Url.Action("PaymentResult", "Payment") }));
            }


            var     orderId         = "";
            var     transactionText = "";
            decimal amountToPay     = 0;



            //Determine amount and description
            switch (reason)
            {
            case EnumList.PaymentReason.Register:
                //Check if course null
                var course = _courseService.GetCourse(courseId);
                if (course == null)
                {
                    return(BadRequest(new{ userId = user.Id, result = EnumList.PaymentResult.Failed, message = "error", reason = reason, url = Url.Action("PaymentResult", "Payment") }));
                }

                //Get on register invoice
                var registerInvoice = _paymentService.CreateOnRegisterInvoices(courseId, user)
                                      .SingleOrDefault(x => x.Reason == EnumList.InvoiceReason.Registration);

                //Determine the amount user wants to pay now
                if (payAllNow)
                {
                    amountToPay = course.Price;
                }
                else
                {
                    amountToPay = registerInvoice?.Amount ?? 0;
                }

                transactionText = $"{course.Subject}--{course.Code}";

                orderId = $"{course.Id.Split("-")[0]}-{user.Id.Split("-")[0]}-{Guid.NewGuid().ToString().Split("-")[0]}";
                break;



            case EnumList.PaymentReason.Invoice:
                //Check if invoice is null
                if (invoice == null)
                {
                    return(BadRequest(new{ userId = user.Id, result = EnumList.PaymentResult.Failed, message = "error", reason = reason, url = Url.Action("PaymentResult", "Payment") }));
                }

                if (string.IsNullOrEmpty(courseId))
                {
                    courseId = invoice.CourseId;
                }
                amountToPay     = invoice.CurrentAmount;
                transactionText = $"Faktura{invoiceNumber}-KID{invoice.CIDNumber}";
                orderId         =
                    $"{invoiceNumber}-{invoice.CIDNumber}-{Guid.NewGuid().ToString().Split("-")[0]}";
                break;



            case EnumList.PaymentReason.Donate:
            case EnumList.PaymentReason.Empty:
            case EnumList.PaymentReason.Other:
            default:
                return(BadRequest(new{ userId = user.Id, result = EnumList.PaymentResult.Failed, message = "error", courseId = courseId, invoiceNumber = invoice.Number, reason = reason, url = Url.Action("PaymentResult", "Payment") }));
            }



            if (amountToPay <= 0)
            {
                return(BadRequest(new{ userId = user.Id, result = EnumList.PaymentResult.Failed, message = "error", courseId = courseId, invoiceNumber = invoice.Number, reason = reason, url = Url.Action("PaymentResult", "Payment") }));
            }

            var order = new InitiatedOrder()
            {
                User        = user, Reason = reason, CourseId = courseId, InvoiceNumber = invoiceNumber, Ip = device.Ip,
                Amount      = amountToPay, PayAllNow = payAllNow, Id = orderId, DeviceType = device.DeviceType,
                AuthCookies = device.AuthCookies, OperatingSystem = device.OperatingSystem, Status = EnumList.OrderStatus.Initiated, PaymentMethod = EnumList.PaymentMethod.Vipps
            };
            await _context.AddAsync(order);

            await _context.SaveChangesAsync();



            var accessToken = VippsAccessToken().Result;

            var queryString = HttpUtility.ParseQueryString(string.Empty);

            Client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
            Client.DefaultRequestHeaders.Add("X-TimeStamp", Format.NorwayDateTimeNow().ToString());
            Client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", VippsParameter["Ocp-Apim-Subscription-Key"]);
            var uri = VippsParameter["vippsBaseUrl"] + "/ecomm/v2/payments?" + queryString;

            HttpResponseMessage response;



            var vippsPayment = new VippsPayment()
            {
                transaction = new transaction()
                {
                    amount          = (int)amountToPay * 100,
                    orderId         = orderId,
                    transactionText = transactionText
                },
                customerInfo = new customerInfo()
                {
                    mobileNumber = $"48059521", // ToDo :: Change this number to user.PhoneNumber on Production
                }
            };

//            _config.GetSection("liveWebsite").Value
            vippsPayment.merchantInfo.fallBack =
                StaticInformation.FullWebsite + "/VippsCallBack?" +
                "orderId=" + orderId +
                "&token=" + accessToken;

//            vippsPayment.merchantInfo.callbackPrefix = vippsPayment.merchantInfo.fallBack;
//            if (device.DeviceType == EnumList.DeviceType.Mobile)
//            {
//                vippsPayment.merchantInfo.isApp = true;
//            }

            var byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(vippsPayment));


            using (var content = new ByteArrayContent(byteData))
            {
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                response = Client.PostAsync(uri, content).Result;
                var     responseString = response.Content.ReadAsStringAsync().Result;
                JObject parseResponse  = JObject.Parse(responseString);
                var     url            = parseResponse["url"];


                //Run Task to give the payment 5 minutes to cancel if not completed, then return
//                Task.Factory.StartNew(CheckVippsPayment(orderId));
//                Task.Factory.StartNew( () => CheckVippsPayment(orderId, "Bearer "+accessToken), CancellationToken.None,
//                    TaskCreationOptions.LongRunning,
//                    TaskScheduler.Default);


                return(Ok(url));
            }
        }