/// <summary>
        /// Mock validator that checks the passed in credentials against hard-coded values.
        /// Not for production use!
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static bool ValidateRequestCredentials(NVPCodec data)
        {
            bool validated = false;

            // Our hard-coded authentication values:
            string APIUsername = "******";
            string APIPassword = "******";
            string APISignature = "ABCDEFGHIJKLMNOP1234567890";

            if (data[NVPProperties.Properties.USER] == APIUsername &&
                data[NVPProperties.Properties.PWD] == APIPassword &&
                data[NVPProperties.Properties.SIGNATURE] == APISignature)
            {
                validated = true;
            }

            return validated;
        }
        /// <summary>
        /// Authorize the requested payment amount (first step).
        /// </summary>
        /// <param name="data"></param>
        /// <param name="transactionId"></param>
        /// <returns></returns>
        public static bool AuthorizePayment(NVPCodec data, ref string token)
        {
            bool status = false;

            // TODO: Match up the token in the data parameter to the stored token from the
            // payment authorization step.

            // TODO: Write output to a log file.
            Debug.WriteLine("Authorizing payment amount: " + data[NVPProperties.Properties.PAYMENTREQUEST_AMT]);

            // Generate an Id for this transaction.
            token = new Randomizer().GetRandomString(16);
            status = true;

            Debug.WriteLine("Authorization token: " + token);

            return status;
        }
        public ActionResult Review(CheckoutViewModel data)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    NVPAPICaller gatewayCaller = new NVPAPICaller();

                    string token = "";
                    NVPCodec decoder = new NVPCodec();

                    // Call the gateway payment authorization API:
                    bool ret = gatewayCaller.DoCheckoutAuth(data.Order, ref token, ref decoder);

                    // If authorizaton is successful:
                    if (ret)
                    {
                        // Hydrate a new Order model from our OrderViewModel.
                        var myOrder = Mapper.Map<Data.Models.Order>(data.Order);
                        // Timestamp with a UTC date.
                        myOrder.OrderDate = DateTime.UtcNow;

                        // Get DB context.
                        ProductContext _db = new ProductContext();

                        // Add order to DB.
                        _db.Orders.Add(myOrder);
                        _db.SaveChanges();

                        // Get the shopping cart items and process them.
                        using (ShoppingCartActions usersShoppingCart = new ShoppingCartActions(cartId))
                        {
                            List<CartItem> myOrderList = usersShoppingCart.GetCartItems();

                            // Add OrderDetail information to the DB for each product purchased.
                            for (int i = 0; i < myOrderList.Count; i++)
                            {
                                // Create a new OrderDetail object.
                                var myOrderDetail = new OrderDetail();
                                myOrderDetail.OrderId = myOrder.OrderId;
                                myOrderDetail.ProductId = myOrderList[i].ProductId;
                                myOrderDetail.Quantity = myOrderList[i].Quantity;
                                myOrderDetail.UnitPrice = myOrderList[i].Product.UnitPrice;

                                // Add OrderDetail to DB.
                                _db.OrderDetails.Add(myOrderDetail);
                                _db.SaveChanges();
                            }

                            // Set OrderId.
                            Session["currentOrderId"] = myOrder.OrderId;
                            Session["Token"] = token;

                            // Report successful event to Application Insights.
                            var eventProperties = new Dictionary<string, string>();
                            eventProperties.Add("CustomerEmail", data.Order.Email);
                            eventProperties.Add("NumberOfItems", myOrderList.Count.ToString());
                            eventProperties.Add("OrderTotal", data.Order.Total.ToString("C2"));
                            eventProperties.Add("OrderId", myOrder.OrderId.ToString());
                            TelemetryHelper.TrackEvent("SuccessfulPaymentAuth", eventProperties);

                            data.Order.OrderId = myOrder.OrderId;
                            if (data.Order.CreditCardNumber.Length > 4)
                            {
                                // Only show the last 4 digits of the credit card number:
                                data.Order.CreditCardNumber = "xxxxxxxxxxx" + data.Order.CreditCardNumber.Substring(data.Order.CreditCardNumber.Length - 4);
                            }
                        }
                    }
                    else
                    {
                        var error = gatewayCaller.PopulateGatewayErrorModel(decoder);

                        // Report failed event to Application Insights.
                        Exception ex = new Exception(error.ToString());
                        ex.Source = "Contoso.Apps.SportsLeague.Web.CheckoutController.cs";
                        TelemetryHelper.TrackException(ex);

                        // Redirect to the checkout error view:
                        return RedirectToAction("Error", error);
                    }
                }
                catch (WebException wex)
                {
                    ExceptionUtility.LogException(wex, "CheckoutController.cs Complete Action");

                    var error = new CheckoutErrorViewModel
                    {
                        ErrorCode = wex.Message
                    };

                    if (wex.Response != null && wex.Response.GetType() == typeof(HttpWebResponse))
                    {
                        // Extract the response body from the WebException's HttpWebResponse:
                        error.LongMessage = ((HttpWebResponse)wex.Response).StatusDescription;
                    }

                    // Redirect to the checkout error view:
                    return RedirectToAction("Error", error);
                }
                catch (Exception ex)
                {
                    ExceptionUtility.LogException(ex, "CheckoutController.cs Review Action");

                    var error = new CheckoutErrorViewModel
                    {
                        ErrorCode = ex.Message
                    };

                    // Redirect to the checkout error view:
                    return RedirectToAction("Error", error);
                }
            }

            return View(data);
        }
        public async Task<ActionResult> Complete(OrderViewModel order)
        {
            try
            {
                // TODO: Complete the payment processing via the gateway and update the order...
                NVPAPICaller gatewayCaller = new NVPAPICaller();

                string token = "";
                string finalPaymentAmount = "";
                NVPCodec decoder = new NVPCodec();

                token = Session["token"].ToString();
                //PayerID = Session["payerId"].ToString();
                //finalPaymentAmount = Session["payment_amt"].ToString();
                finalPaymentAmount = order.Total.ToString("C2");

                bool ret = gatewayCaller.DoCheckoutPayment(finalPaymentAmount, token, ref decoder);
                if (ret)
                {
                    // Retrieve PayPal confirmation value.
                    string PaymentConfirmation = decoder[NVPProperties.Properties.TRANSACTIONID].ToString();
                    order.PaymentTransactionId = PaymentConfirmation;


                    ProductContext _db = new ProductContext();
                    // Get the current order id.
                    int currentOrderId = -1;
                    if (Session["currentOrderId"] != null && Session["currentOrderId"].ToString() != string.Empty)
                    {
                        currentOrderId = Convert.ToInt32(Session["currentOrderID"]);
                    }
                    Order myCurrentOrder;
                    if (currentOrderId >= 0)
                    {
                        // Get the order based on order id.
                        myCurrentOrder = _db.Orders.Single(o => o.OrderId == currentOrderId);
                        // Update the order to reflect payment has been completed.
                        myCurrentOrder.PaymentTransactionId = PaymentConfirmation;
                        // Save to DB.
                        _db.SaveChanges();

                        // Queue up a receipt generation request, asynchronously.
                        await new AzureQueueHelper().QueueReceiptRequest(currentOrderId);

                        // Report successful event to Application Insights.
                        var eventProperties = new Dictionary<string, string>();
                        eventProperties.Add("CustomerEmail", order.Email);
                        eventProperties.Add("OrderTotal", finalPaymentAmount);
                        eventProperties.Add("PaymentTransactionId", PaymentConfirmation);
                        TelemetryHelper.TrackEvent("OrderCompleted", eventProperties);
                    }

                    // Clear shopping cart.
                    using (ShoppingCartActions usersShoppingCart =
                        new ShoppingCartActions(cartId))
                    {
                        usersShoppingCart.EmptyCart();
                    }

                    // Clear order id.
                    Session["currentOrderId"] = string.Empty;
                }
                else
                {
                    var error = gatewayCaller.PopulateGatewayErrorModel(decoder);

                    // Report failed event to Application Insights.
                    Exception ex = new Exception(error.ToString());
                    ex.Source = "Contoso.Apps.SportsLeague.Web.CheckoutController.cs";
                    TelemetryHelper.TrackException(ex);

                    // Redirect to the checkout error view:
                    return RedirectToAction("Error", error);
                }
            }
            catch (WebException wex)
            {
                ExceptionUtility.LogException(wex, "CheckoutController.cs Complete Action");

                var error = new CheckoutErrorViewModel
                {
                    ErrorCode = wex.Message
                };

                if (wex.Response != null && wex.Response.GetType() == typeof(HttpWebResponse))
                {
                    // Extract the response body from the WebException's HttpWebResponse:
                    error.LongMessage = ((HttpWebResponse)wex.Response).StatusDescription;
                }

                // Redirect to the checkout error view:
                return RedirectToAction("Error", error);
            }
            catch (Exception ex)
            {
                ExceptionUtility.LogException(ex, "CheckoutController.cs Complete Action");

                var error = new CheckoutErrorViewModel
                {
                    ErrorCode = ex.Message
                };

                // Redirect to the checkout error view:
                return RedirectToAction("Error", error);
            }

            return View(order);
        }
        public HttpResponseMessage PerformAction([FromBody] string data)
        {
            string response = string.Empty;
            HttpResponseMessage resp = new HttpResponseMessage();
            var encoder = new NVPCodec();

            try
            {
                // Deserialize the string data into a key value pair collection.
                var decoder = new NVPCodec();
                decoder.Decode(data);

                // Perform mock validation:
                var isAuthorized = ProcessorMethods.ValidateRequestCredentials(decoder);

                if (isAuthorized)
                {
                    // Determine which method is being called:
                    string method = decoder[NVPProperties.Properties.METHOD];
                    if (!string.IsNullOrWhiteSpace(method))
                    {
                        if (method.ToLower().Trim() == NVPProperties.Methods.AuthorizePayment.ToLower())
                        {
                            // Conduct the payment authorization (first step).
                            string token = string.Empty;
                            var status = ProcessorMethods.AuthorizePayment(decoder, ref token);

                            if (status)
                            {
                                // Success!
                                encoder[NVPProperties.Properties.ACK] = "success";
                                encoder[NVPProperties.Properties.TOKEN] = token;
                            }
                        }
                        else if (method.ToLower().Trim() == NVPProperties.Methods.ProcessPayment.ToLower())
                        {
                            // Conduct a final processing of the payment.
                            string transactionId = string.Empty;
                            var status = ProcessorMethods.ProcessPayment(decoder, ref transactionId);

                            if (status)
                            {
                                // Success!
                                encoder[NVPProperties.Properties.ACK] = "success";
                                encoder[NVPProperties.Properties.TRANSACTIONID] = transactionId;
                            }
                        }
                        else
                        {
                            // Invalid method requested. Throw implementation error.
                            throw new InvalidOperationException("The specified transaction method was invalid.");
                        }
                    }
                }
                else
                {
                    // Throw unauthorized response.
                    resp.StatusCode = HttpStatusCode.Unauthorized;
                    resp.Content = new StringContent("You are unauthorized to use this API. Check your credentials and try again.", Encoding.UTF8, "text/plain");
                    return resp;
                }
            }
            catch (Exception ex)
            {
                // TODO: Log exception; catch other exception types first
                encoder[NVPProperties.Properties.ERRORCODE] = ex.Source;
                encoder[NVPProperties.Properties.LONGMESSAGE] = ex.Message;
                encoder[NVPProperties.Properties.ACK] = "failure";
            }
            finally
            {
                // Serialize our response.
                response = encoder.Encode();
            }

            resp.StatusCode = HttpStatusCode.OK;
            resp.Content = new StringContent(response, Encoding.UTF8, "text/plain");
            return resp;
        }