public ActionResult AdyenDefaultCardCheckOut(string destinationUrl, AdyenCardPaymentModels model, string bookingNo, decimal bookingAmt)
        {
            if (model == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            NameValueCollection formData = new NameValueCollection();
            string AdyenMethod2POSTURL   = Core.GetAppSettingValueEnhanced("AdyenMethod2POSTURL");

            if (!string.IsNullOrEmpty(bookingNo))
            {
                formData.Add("AppId", "2");
                formData.Add("AmountValue", model.PaymentAmount.ToString().Replace(".", ""));
                formData.Add("AmountCurrency", model.Currency);
                formData.Add("ProdDesc", "MayFlower Booking Payment - " + model.SuperPNRNo);
                formData.Add("ShopperReference", model.SuperPNRID + " - " + model.SuperPNRNo);
                formData.Add("ShopperEmail", model.UserEmail);
                formData.Add("ShopperIP", Mayflower.General.Utilities.GetClientIP);
                formData.Add("ResponseURL", destinationUrl);
            }

            string postURL = AdyenMethod2POSTURL;
            string strForm = PreparePOSTForm(postURL, formData);

            return(Content(strForm));
        }
        public ActionResult AdyenCheckOut(string destinationUrl, AdyenCardPaymentModels model, NameValueCollection fc)
        {
            string isAdyenTesting = Core.GetAppSettingValueEnhanced("AdyenTesting");
            bool   isTestingAcc   = bool.TryParse(isAdyenTesting, out isTestingAcc) ? isTestingAcc : isTestingAcc;

            if (model == null)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            NameValueCollection formData = new NameValueCollection();
            string AdyenPOSTURL          = Core.GetAppSettingValueEnhanced("AdyenPOSTURL");

            if (!string.IsNullOrEmpty(model.SuperPNRNo))
            {
                //formData.Add("number", model.CardNumber.Replace("-", ""));
                //formData.Add("holderName", model.CardHolderName);
                //formData.Add("expiryMonth", model.ExpiryMonth.ToString());// expected two digit
                //formData.Add("expiryYear", model.ExpiryYear.ToString());
                //formData.Add("cvc", model.CVV.ToString());
                //formData.Add("generationtime", model.GenerationTime);
                formData.Add("adyen-encrypted-data", fc["adyen-encrypted-data"]);

                /*foreach (var item in fc.AllKeys)
                 * {
                 *  formData.Add(item, fc[item]);
                 * }*/

                formData.Add("ShopperReference", model.SuperPNRID + " - " + model.SuperPNRNo);
                formData.Add("ShopperEmail", model.ShopperEmail);
                formData.Add("AmountValue", isTestingAcc ? "500" : model.PaymentAmount.ToString().Replace(".", ""));
                formData.Add("AmountCurrency", model.Currency);
                formData.Add("ProdDesc", "MayFlower Booking Payment - " + model.SuperPNRNo);
                formData.Add("AppId", "2");
                formData.Add("ShopperIP", Mayflower.General.Utilities.GetClientIP);
                formData.Add("ResponseURL", destinationUrl);
                // Refer to Appendix I.pdf
                //formData.Add("PaymentId", paymentId);

                // Ref No only allow 20 char.
                //formData.Add("Amount", isTestingAcc ? "1.00" : payment.PaymentAmount.ToString("n2"));
            }

            string postURL = AdyenPOSTURL;
            string strForm = AdyenPreparePOSTForm(postURL, formData);

            return(Content(strForm));
        }
        public static AdyenCardPaymentModels PopulateAdyenPaymentSubmitModel(int bookingId, string destinationUrl, string bookingNo, string currencyCode, decimal totalAmount, string userEmail, CreditCard model)
        {
            AdyenCardPaymentModels adyenPaymentSubmitModel = new AdyenCardPaymentModels();

            adyenPaymentSubmitModel.SuperPNRID       = bookingId;
            adyenPaymentSubmitModel.SuperPNRNo       = bookingNo;
            adyenPaymentSubmitModel.CardNumber       = model.CreditCardNo;
            adyenPaymentSubmitModel.CardHolderName   = model.CardholderName;
            adyenPaymentSubmitModel.ExpiryMonth      = model.ExpMonths.ToString("00");
            adyenPaymentSubmitModel.ExpiryYear       = model.ExpYear;
            adyenPaymentSubmitModel.CVV              = model.CVC;
            adyenPaymentSubmitModel.GenerationTime   = model.GenerationTime;
            adyenPaymentSubmitModel.AppId            = "2";
            adyenPaymentSubmitModel.Currency         = currencyCode;
            adyenPaymentSubmitModel.PaymentAmount    = string.Join("", (totalAmount * 100).ToString("0.####").Where(char.IsDigit));
            adyenPaymentSubmitModel.ProdDesc         = "MayFlower Booking Payment - " + bookingNo;
            adyenPaymentSubmitModel.ShopperReference = bookingNo;
            adyenPaymentSubmitModel.ShopperEmail     = userEmail;
            adyenPaymentSubmitModel.ShopperIP        = Mayflower.General.Utilities.GetClientIP;
            adyenPaymentSubmitModel.ResponseURL      = destinationUrl;

            return(adyenPaymentSubmitModel);
        }
        public async Task <ActionResult> Checkout(PaymentCheckout payment, string paymentID = null)
        {
            string _pMethod = payment.PaymentMethod?.ToLower();

            if (_pMethod != null && _pMethod.Contains("adyen"))
            {
                // Reflection get credit card property to remove model validation
                var ccModel = typeof(Alphareds.Module.Model.CreditCard);

                foreach (var item in ccModel.GetProperties())
                {
                    // Remove model validtion
                    ModelState[item.Name]?.Errors.Clear();
                }
            }

            // If member not verify email, block place booking.
            if (User.Identity.IsAuthenticated && !CustomPrincipal.IsProfileActive && !CustomPrincipal.IsAgent)
            {
                ModelState.AddModelError("Error", "Please verify your account first, before place order.");
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Account inactive."));
            }

            string _paymentInfo = null;

            Cryptography.AES.TryDecrypt(paymentID, out _paymentInfo);

            var _superPNR = db.SuperPNRs.FirstOrDefault(x => x.SuperPNRID.ToString() == _paymentInfo);

            // Check model error before postback
            if (!ModelState.IsValid)
            {
                if (_superPNR.MainProductType == ProductTypes.Flight)
                {
                    return(RedirectToAction("OrderHistory", "Flight", new { tripid, bookingID = _superPNR.SuperPNRNo, status = "payment-fail" }));
                }
                else if (_superPNR.MainProductType == ProductTypes.Hotel)
                {
                    return(RedirectToAction("OrderHistory", "Hotel", new { tripid, confirmid = _superPNR.SuperPNRNo, status = "payment-fail" }));
                }
                else
                {
                    return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Product Undefined."));
                }
            }

            var    _paymentList    = _superPNR.GetAllPaymentRecords();
            string paymentCurrency = "MYR";

            _superPNR.LoadPaymentDetailList(true, paymentCurrency);
            var paymentDtlList = _superPNR.PaymentDetailsList.FirstOrDefault(); // take converted rate, only one result

            SqlCommand command = new SqlCommand();

            // Can pass in user preferred currency code into ChkCreditAmtRemin, with optional parameter
            // Use this method to handle multi currency code in different order issues.
            decimal            creditUserAvail     = MemberServiceController.ChkCreditAmtRemain.ByUserId(CustomPrincipal.UserId, CustomPrincipal.UserTypeCode, command, paymentCurrency);
            decimal            cashWalletUserAvail = MemberServiceController.GetUserCashCredit(CustomPrincipal.UserId, command);
            CheckoutController checkoutCtl         = new CheckoutController(ControllerContext);

            decimal thisBookUsableAmt = checkoutCtl.CalcTravelCreditUsable(paymentDtlList.TotalPendingAmount, creditUserAvail, cashWalletUserAvail, DiscountType.TC);

            if (creditUserAvail >= thisBookUsableAmt && payment.UseCredit && (paymentDtlList.TotalPendingAmount <= thisBookUsableAmt))
            {
                payment.PaymentMethod = CustomPrincipal.IsAgent ? "AC" : "SC";
            }

            payment = new PaymentCheckout
            {
                AvailableCredit      = creditUserAvail,
                CreditUsed           = payment.UseCredit ? thisBookUsableAmt : 0m,
                PaymentMethod        = string.IsNullOrWhiteSpace(payment.PaymentMethod) ? CustomPrincipal.IsAgent ? "AC" : "SC" : payment.PaymentMethod,
                Policy               = payment.Policy,
                TnC                  = payment.TnC,
                UseCredit            = payment.UseCredit,
                CreditCard           = payment.CreditCard,
                CreditTerm           = CustomPrincipal.CreditTerm,
                PaymentCurrencyCode  = paymentDtlList.CurrencyCode,
                GrandTotalForPayment = paymentDtlList.TotalPendingAmount
            };

            PromoCodeFunctions  promoCodeFunctions          = new PromoCodeFunctions(_superPNR._MainPromoID, db);
            decimal             ttlOrderUsedTCAmountUseable = payment.CreditUsed;
            decimal             ttlTCAmtUsed         = 0m;
            List <PaymentOrder> paymentOrderToInsert = new List <PaymentOrder>();

            foreach (var _orderId in paymentDtlList.OrdersPendingPayment)
            {
                var _orders = _superPNR.SuperPNROrders.FirstOrDefault(x => x.OrderID == _orderId);

                #region Insert/Update Processing Fee
                var           feeChargeOrder = _orders.FeeChargeOrders.FirstOrDefault();
                ProcessingFee pf             = new ProcessingFee(payment.PaymentMethod, _orders.PendingPaymentAmt, _superPNR.MainProductType, promoCodeFunctions, paymentCurrency);

                var latestFeeCharge = new FeeChargeOrder
                {
                    OrderID         = _orders.OrderID,
                    CreatedByID     = _superPNR.CreatedByID,
                    CurrencyCode    = _orders.CurrencyCode,
                    FeeChargeAmount = pf.Amt,
                    FeeCode         = string.IsNullOrWhiteSpace(pf.FeeCode) ? payment.PaymentMethod : pf.FeeCode,
                    TaxCode         = string.IsNullOrWhiteSpace(pf.TaxCode) ? "ES" : pf.TaxCode,
                    TaxAmount       = pf.GST,
                    ModifiedByID    = CurrentUserID,
                    SuperPNROrder   = _orders,
                };

                if (feeChargeOrder == null)
                {
                    _orders.FeeChargeOrders.Add(latestFeeCharge); // for model calculation
                    PaymentServiceController.InsertFeeChargeOrder(latestFeeCharge, command);
                }
                else
                {
                    // For model calculation only
                    feeChargeOrder.CurrencyCode    = _orders.CurrencyCode;
                    feeChargeOrder.FeeChargeAmount = pf.Amt;
                    feeChargeOrder.FeeCode         = string.IsNullOrWhiteSpace(pf.FeeCode) ? payment.PaymentMethod : pf.FeeCode;
                    feeChargeOrder.TaxCode         = string.IsNullOrWhiteSpace(pf.TaxCode) ? "ES" : pf.TaxCode;
                    feeChargeOrder.TaxAmount       = pf.GST;

                    PaymentServiceController.UpdateFeeChargeOrder(latestFeeCharge, command);
                }
                #endregion

                if (payment != null && payment.UseCredit && payment.CreditUsed > 0 && (payment.PaymentMethod != "SC" && payment.PaymentMethod != "AC"))
                {
                    decimal _thisTransAmt      = _orders.PendingPaymentAmt;
                    decimal _thisTransUseTCAmt = ttlOrderUsedTCAmountUseable;
                    bool    usedAllTC          = ttlTCAmtUsed == payment.CreditUsed;

                    if (ttlOrderUsedTCAmountUseable > _thisTransAmt && !usedAllTC)
                    {
                        _thisTransUseTCAmt = _thisTransAmt;
                    }

                    if (ttlOrderUsedTCAmountUseable > 0 && !usedAllTC)
                    {
                        ttlOrderUsedTCAmountUseable -= _thisTransUseTCAmt;
                        ttlTCAmtUsed += _thisTransUseTCAmt;

                        PaymentOrder tcPaymentOrder = new PaymentOrder
                        {
                            OrderID             = _orders.OrderID,
                            PaymentDate         = DateTime.Now,
                            PaymentMethodCode   = CustomPrincipal.IsAgent ? "AC" : "SC",
                            PaymentStatusCode   = "PEND",
                            CurrencyCode        = _orders.CurrencyCode,
                            PaymentAmount       = _thisTransUseTCAmt,
                            ImagePath           = string.Empty,
                            Ipay88RefNo         = string.Empty,
                            Ipay88TransactionID = string.Empty,
                            CreatedByID         = CurrentUserID,
                            ModifiedByID        = CurrentUserID
                        };

                        paymentOrderToInsert.Add(tcPaymentOrder);

                        // Update SuperPNR Order indicated is Credit Used.
                        _orders.CreditAmount += _thisTransUseTCAmt;
                        _orders.IsCreditUsed  = _orders.CreditAmount > 0;
                        HotelServiceController.UpdateSuperPNROrder(_orders, command);
                    }
                }
                else
                {
                    // Update SuperPNR Order indicated is Credit Used.
                    _orders.CreditAmount = _orders.PaymentOrders.Where(x => (x.PaymentMethodCode == "AC" || x.PaymentMethodCode == "SC") && x.PaymentStatusCode == "PAID").Sum(s => s.PaymentAmount);
                    _orders.IsCreditUsed = _orders.CreditAmount > 0;
                    HotelServiceController.UpdateSuperPNROrder(_orders, command);
                }

                decimal paymentPrepareToInsert = paymentOrderToInsert.Where(x => x.OrderID == _orders.OrderID).Sum(s => s.PaymentAmount);

                if (paymentPrepareToInsert < _orders.PendingPaymentAmt)
                {
                    PaymentOrder normalPayment = new PaymentOrder
                    {
                        OrderID             = _orders.OrderID,
                        PaymentDate         = DateTime.Now,
                        PaymentMethodCode   = payment.PaymentMethod,
                        PaymentStatusCode   = "PEND",
                        CurrencyCode        = _orders.CurrencyCode,
                        PaymentAmount       = _orders.PendingPaymentAmt - paymentPrepareToInsert,
                        ImagePath           = string.Empty,
                        Ipay88RefNo         = string.Empty,
                        Ipay88TransactionID = string.Empty,
                        CreatedByID         = CurrentUserID,
                        ModifiedByID        = CurrentUserID
                    };

                    paymentOrderToInsert.Add(normalPayment);
                }
            }

            decimal    ttlAmtPOSTGateway    = paymentOrderToInsert.Where(x => x.PaymentMethodCode != "SC" && x.PaymentMethodCode != "AC").Sum(s => s.PaymentAmount);
            List <int> paymentOrderInserted = new List <int>();

            #region Insert SupperPNROrders records into DB
            try
            {
                foreach (var paymentRecord in paymentOrderToInsert)
                {
                    paymentOrderInserted.Add(PaymentServiceController.InsertPaymentOrder(paymentRecord, command));
                }

                #region Payment Gateway Redirect
                _superPNR.GetContactPerson();
                var contactPerson             = _superPNR.ContactPerson;
                PaymentSubmitModels iPayModel = PaymentController.PopulatePaymentSubmitModel(DateTime.Now, _superPNR.SuperPNRID, _superPNR.SuperPNRNo, paymentCurrency, ttlAmtPOSTGateway, payment.PaymentMethod, contactPerson.Phone1, contactPerson.Email, contactPerson.FullName);

                // Save transaction before redirect
                command.Transaction.Commit();

                string clientIP              = HttpContext.Request.UserHostAddress;
                string paymentMethod         = payment.PaymentMethod.ToUpper();
                string token                 = _superPNR.SuperPNRID.ToString() + "," + _superPNR.SuperPNRNo;
                string encToken              = General.CustomizeBaseEncoding.CodeBase64(token);
                string encPaymentOrderIDList = Cryptography.AES.Encrypt(paymentOrderInserted.JoinToString(","));

                FormCollection             form = new FormCollection();
                adyenCaptureResponseModels captureResponseModels2 = new adyenCaptureResponseModels();
                iPayCaptureResponseModels  captureResponseModels  = new iPayCaptureResponseModels
                {
                    Status = "1", Amount = iPayModel.PaymentAmount, TransId = ""
                };

                switch (payment.PaymentMethod.ToLower())
                {
                case "sc":
                    form.Add("Status", captureResponseModels.Status);
                    form.Add("Amount", captureResponseModels.Amount.ToString("n2"));

                    return(await checkoutCtl.PaymentCheckOut(form, captureResponseModels, captureResponseModels2, encToken, tripid, encPaymentOrderIDList, true));

                case "ac":
                    form.Add("Status", captureResponseModels.Status);
                    form.Add("Amount", captureResponseModels.Amount.ToString("n2"));

                    return(await checkoutCtl.PaymentCheckOut(form, captureResponseModels, captureResponseModels2, encToken, tripid, encPaymentOrderIDList, true));

                case "ipacc":
                    return(iPay88CheckOut(Url.Action("PaymentCheckOut", "Checkout", new { token = encToken, tripid, paymentOdToken = encPaymentOrderIDList, fromRepay = true }, Request.Url.Scheme), iPayModel, true));

                case "ipafpx":
                    return(iPay88CheckOut(Url.Action("PaymentCheckOut", "Checkout", new { token = encToken, tripid, paymentOdToken = encPaymentOrderIDList, fromRepay = true }, Request.Url.Scheme), iPayModel));

                case "adyenc":
                    AdyenCardPaymentModels adyenModel = PaymentController.PopulateAdyenPaymentSubmitModel(_superPNR.SuperPNRID, Request.Url.Scheme, _superPNR.SuperPNRNo, paymentCurrency, ttlAmtPOSTGateway, contactPerson.Email, payment.CreditCard);
                    return(AdyenCheckOut(Url.Action("PaymentCheckOut", "Checkout", new { token = encToken, tripid, paymentOdToken = encPaymentOrderIDList, fromRepay = true }, Request.Url.Scheme), adyenModel, Request.Form));

                default:
                    ModelState.AddModelError("Error", "Payment Method Not Found.");
                    break;
                }

                #endregion
            }
            catch (Exception ex)
            {
                // Insert payment record failed.
                command?.Transaction?.Rollback();

                // Handle redirect back to OrderHistory Page
                ViewBag.PaymentDetails = payment;
                ModelState.AddModelError("Error", "Unexpected error occured, please try again later.");

                string errorMsg = $"Insert Payment Order record failed on OrderHistory repayment.";
                logger.Fatal(ex, errorMsg);

                if (_superPNR.MainProductType == ProductTypes.Flight)
                {
                    return(RedirectToAction("OrderHistory", "Flight", new { tripid, bookingID = _superPNR.SuperPNRNo, status = "payment-fail" }));
                }
                else if (_superPNR.MainProductType == ProductTypes.Hotel)
                {
                    return(RedirectToAction("OrderHistory", "Hotel", new { tripid, confirmid = _superPNR.SuperPNRNo, status = "payment-fail" }));
                }
                else
                {
                    return(new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Product Undefined."));
                }
            }
            #endregion

            return(null);
        }