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));
            }
        }
        public IActionResult Index(EnumList.PaymentReason reason, string courseId, int invoiceNumber)
        {
            //Shared variable
            var vm = new PaymentViewModel
            {
                Reason   = reason, Course = new Course(), Address = new Address(), Student = new ApplicationUser(),
                Invoices = new List <MatterixInvoice>()
            };
            var course = _courseService.GetCourse(courseId);

            var student = _context.Users.Find(_access.GetUserId(User));
            var address = _context.Addresses.SingleOrDefault(x => x.UserId == student.Id);

            if (student == null || address == null)
            {
                return(RedirectToAction("Error", "Home"));
            }

            vm.Student = student;
            vm.Address = address;

            //Determine payment reason
            switch (reason)
            {
            case EnumList.PaymentReason.Register:
                if (course == null || !course.IsAvailable())
                {
                    return(RedirectToAction("Error", "Home"));
                }

                //User already has access to the course
                if (_access.CourseViewAccess(User, courseId))
                {
                    return(RedirectToAction("CourseArea", "Course", new { courseId }));
                }

                ViewBag.AltCourse = "";
                if (course.Ended)
                {
                    var altCourse = _context.Courses.ToList().Where(x =>
                                                                    !x.Ended && x.IsAvailable()).SingleOrDefault(x => string.Equals(x.Subject.Replace(" ", ""), course.Subject.Replace(" ", ""), StringComparison.CurrentCultureIgnoreCase));

                    if (altCourse != null)
                    {
                        ViewBag.AltCourse = altCourse.Id;
                    }
                }

                //ToDo :: Check Max Student - If not, return

                if (!student.SignedStudentAgreement)
                {
                    return(RedirectToAction("StudentAgreement", "Instructions", new { returnUrl = courseId }));
                }

                //ToDo :: Check Student Agreement - if not, return
                //ToDo :: Check Installment Available -- If not, continue with preventing installment


                vm.Course = course;

                var registerInvoices = _paymentService.CreateOnRegisterInvoices(courseId, student);

                vm.InvoiceToPay = registerInvoices.SingleOrDefault(x => x.Reason == EnumList.InvoiceReason.Registration);
                vm.Invoices     = registerInvoices.Where(x => x.Reason != EnumList.InvoiceReason.Registration).OrderBy(x => x.OriginalDueDate).ToList();
                return(View(vm));



            case EnumList.PaymentReason.Invoice:
                var invoice = _paymentService.GetInvoice(invoiceNumber);
                if (invoice == null || !invoice.ActiveInvoice())
                {
                    return(RedirectToAction("Error", "Home"));
                }

                vm.Course = _courseService.GetCourse(invoice.CourseId) ?? new Course();
                //ToDo :: Check any increment for the invoice here _PaymentService.InvoiceFullAmount
                vm.InvoiceToPay = invoice;
                return(View(vm));


            case EnumList.PaymentReason.Empty:
            case EnumList.PaymentReason.Donate:
            case EnumList.PaymentReason.Other:
            default:
                return(RedirectToAction("Error", "Home"));
            }
        }