public async Task <IActionResult> PaymentConnect(string id)
        {
            var factor = await _context.Factors.Include(x => x.FactorItems).FirstOrDefaultAsync(x => x.Id == id);

            if (factor == null)
            {
                return(RedirectToAction("Error", "Home"));
            }

            if (factor.FactorItems == null || factor.FactorItems.Count == 0)
            {
                ModelState.AddModelError(String.Empty, "خطا در محاسبه مبلغ فاکتور");
                return(View(factor));
            }

            if (factor.TotalPrice == 0)
            {
                ModelState.AddModelError("AmountError", "مبلغ نمی تواند خالی باشد. لطفا مبلغی را بیشتر از 100 تومان وارد نمایید.");
                return(View(factor));
            }

            _context.Factors.Update(factor);
            await _context.SaveChangesAsync();

            var schoolNmae  = _context.Settings.FirstOrDefault().SchoolName;
            var callbackUrl = $"https://{Request.Host}/Payment/{nameof(PaymentVerify)}/{factor.Id}";
            var description = "پرداخت شهریه مدرسه " + schoolNmae;

            try
            {
                string M_Code   = _context.Settings.FirstOrDefault().MerchentCode;
                var    response = ZarinPalPayment.Request(M_Code, factor.TotalPrice, description, callbackUrl);

                // if there is an error show this page again
                if (response.Status == 100)
                {
                    Response.Redirect(ZarinPalPayment.GetPaymentGatewayUrl(response.Authority));
                }
                else
                {
                    ModelState.AddModelError(String.Empty, $"خطا در پرداخت. کد خطا: {response.Status} ");
                }
            }
            catch (Exception e)
            {
                ModelState.AddModelError(String.Empty, "خطا در پرداخت. کد خطا: عدم اتصال به درگاه ");
            }

            return(View(factor));
        }
        public async Task <IActionResult> PaymentVerify(string id)
        {
            var collection = HttpUtility.ParseQueryString(HttpContext.Request.QueryString.Value);
            var status     = collection["Status"];

            var factor = await _context.Factors.FirstOrDefaultAsync(x => x.Id == id);

            if (factor == null)
            {
                return(RedirectToAction(nameof(FailedPayment), new { error = "خطا در تایید فاکتور" }));
            }

            var user = await _userManager.GetUserAsync(HttpContext.User);

            user = _context.Users.Where(x => x.Id == user.Id).Include(x => x.Students).FirstOrDefault();
            if (user == null)
            {
                return(RedirectToAction(nameof(FailedPayment), new { factorCode = factor.FactorCode, error = "خطا در تایید کاربر" }));
            }

            if (status != "OK")
            {
                var failStatus = await _context.Statuses.FirstOrDefaultAsync(x => x.Title == "پرداخت نشده");

                if (failStatus == null)
                {
                    failStatus = new Status
                    {
                        Title = "پرداخت نشده"
                    };

                    await _context.Statuses.AddAsync(failStatus);

                    await _context.SaveChangesAsync();
                }

                var order = new Order
                {
                    Description       = user.UserName,
                    TransactionNumber = collection["Authority"].TrimStart('0'),
                    StatusId          = failStatus.Id,
                    TransactionDate   = DateTime.UtcNow,
                    //IssueCode = 0,
                    FactorId          = factor.Id,
                    TransactionStatus = false
                };

                await _context.Orders.AddAsync(order);

                await _context.SaveChangesAsync();

                return(RedirectToAction(nameof(FailedPayment), new { factorCode = factor.FactorCode, error = "خطا در پرداخت" }));
            }

            var authority = collection["Authority"];

            TempData["FactorCode"] = factor.FactorCode;

            if (factor.TotalPrice == 0)
            {
                return(RedirectToAction(nameof(FailedPayment), new { factorCode = factor.FactorCode, error = "خطا در مبلغ درست پرداختی" }));
            }

            string M_Code = _context.Settings.FirstOrDefault().MerchentCode;

            var verificationResponse = ZarinPalPayment.Verify(M_Code, factor.TotalPrice, authority);

            if (!verificationResponse.IsSuccess)
            {
                var failStatus = await _context.Statuses.FirstOrDefaultAsync(x => x.Title == "پرداخت نشده");

                if (failStatus == null)
                {
                    failStatus = new Status
                    {
                        Title = "پرداخت نشده"
                    };

                    await _context.Statuses.AddAsync(failStatus);

                    await _context.SaveChangesAsync();
                }

                var order = new Order
                {
                    Description       = user.UserName,
                    TransactionNumber = verificationResponse.RefId,
                    StatusId          = failStatus.Id,
                    TransactionDate   = DateTime.UtcNow,
                    //IssueCode = 0,
                    FactorId          = factor.Id,
                    TransactionStatus = false
                };

                await _context.Orders.AddAsync(order);

                await _context.SaveChangesAsync();

                return(RedirectToAction(nameof(FailedPayment), new { factorCode = factor.FactorCode, error = "خطا در تایید پرداخت" }));
            }

            //string dateTimes = Helper.GetPersianDateText(DateTime.Now);

            var statuses = await _context.Statuses.FirstOrDefaultAsync(x => x.Title == "پرداخت شده	");

            if (statuses == null)
            {
                statuses = new Status
                {
                    Title = "پرداخت شده	"
                };

                await _context.Statuses.AddAsync(statuses);

                await _context.SaveChangesAsync();
            }

            await using (var transaction = await _context.Database.BeginTransactionAsync())
            {
                try
                {
                    var order = new Order
                    {
                        Description       = user.UserName,
                        TransactionNumber = verificationResponse.RefId,
                        StatusId          = statuses.Id,
                        TransactionDate   = DateTime.UtcNow,
                        //IssueCode = 1,
                        FactorId          = factor.Id,
                        TransactionStatus = true
                    };

                    await _context.Orders.AddAsync(order);

                    factor.IsPaid = true;
                    _context.Factors.Update(factor);

                    HttpContext.Session.Remove("CartItems");

                    var factorItems = await _context.FactorItems.Where(x => x.FactorId == factor.Id).ToListAsync();

                    var products = await _context.Costs.Where(x => factorItems.Select(y => y.CostId).Contains(x.Id)).ToListAsync();

                    foreach (var factorItem in factorItems)
                    {
                        var product = products.FirstOrDefault(x => x.Id == factorItem.CostId);

                        //if (product != null)
                        //{
                        //	product.Inventory -= factorItem.UnitCount;

                        //	if (product.Inventory < 0)
                        //	{
                        //		product.Inventory = 0;
                        //	}

                        //	_context.Products.Update(product);
                        //}
                    }

                    await _context.SaveChangesAsync();

                    await transaction.CommitAsync();
                }
                catch (Exception ex)
                {
                    await transaction.RollbackAsync();

                    return(RedirectToAction(nameof(FailedPayment), new { factorCode = factor.FactorCode, error = ex.Message }));
                }
            }
            var    schoolName  = _context.Settings.FirstOrDefault().SchoolName;
            var    student     = _context.Students.Where(x => x.IdUser == user.Id).FirstOrDefault();
            string studentName = student.FirstName + " " + student.LastName;

            student.isDone = true;
            _context.Update(student);
            await _context.SaveChangesAsync();


            await _smsSender.SendSmsAsync(user.UserName, SmsTypes.SchoolPaymentDone, factor.FactorCode, schoolName, studentName);

            return(RedirectToAction(nameof(SuccessfulPayment), new { factorCode = factor.FactorCode }));
        }