/// <summary>
        /// Charges the specified order.
        /// </summary>
        /// <param name="order">The order.</param>
        /// <returns></returns>
        internal Transaction Charge(Order order)
        {
            /*
             * Minimum Requirements
             * x_version
             * x_login
             * x_tran_key
             * x_type
             * x_amount
             * x_card_num
             * x_exp_date
             * x_trans_id**
             * x_auth_code**
             */

            StringBuilder sb       = new StringBuilder();
            string        postData = string.Empty;
            Currency      currency = new Currency();

            #region Order Info

            #region Best Practice Fields

            GetBestPracticeFields(sb, AuthorizeNetTransactionType.AUTH_CAPTURE);

            #endregion

            sb.AppendFormat("&x_customer_ip={0}", HttpUtility.UrlEncode(order.IPAddress));
            sb.AppendFormat("&x_invoice_num={0}", HttpUtility.UrlEncode(order.OrderNumber));
            sb.AppendFormat("&x_amount={0}", HttpUtility.UrlEncode(GetFormattedAmount(currency, order.Total).ToString()));
            sb.AppendFormat("&x_freight={0}", HttpUtility.UrlEncode(GetFormattedAmount(currency, order.ShippingAmount).ToString()));
            sb.AppendFormat("&x_tax={0}", HttpUtility.UrlEncode(GetFormattedAmount(currency, order.TaxTotal).ToString()));

            #endregion

            #region Billing Info
            if (order.BillingAddress != null)
            {
                sb.AppendFormat("&x_email={0}", HttpUtility.UrlEncode(order.BillingAddress.Email));
                sb.AppendFormat("&x_phone={0}", HttpUtility.UrlEncode(order.BillingAddress.Phone));
                sb.AppendFormat("&x_first_name={0}", HttpUtility.UrlEncode(order.BillingAddress.FirstName));
                sb.AppendFormat("&x_last_name={0}", HttpUtility.UrlEncode(order.BillingAddress.LastName));
                sb.AppendFormat("&x_address={0}", HttpUtility.UrlEncode(order.BillingAddress.Address1));
                sb.AppendFormat("&x_city={0}", HttpUtility.UrlEncode(order.BillingAddress.City));
                sb.AppendFormat("&x_state={0}", HttpUtility.UrlEncode(order.BillingAddress.StateOrRegion));
                sb.AppendFormat("&x_zip={0}", HttpUtility.UrlEncode(order.BillingAddress.PostalCode));
                sb.AppendFormat("&x_country={0}", HttpUtility.UrlEncode(order.BillingAddress.Country));
            }

            #endregion

            #region Shipping Info

            if (order.ShippingAddress != null)
            {
                sb.AppendFormat("&x_ship_to_first_name={0}", HttpUtility.UrlEncode(order.ShippingAddress.FirstName));
                sb.AppendFormat("&x_ship_to_last_name={0}", HttpUtility.UrlEncode(order.ShippingAddress.LastName));
                sb.AppendFormat("&x_ship_to_address={0}", HttpUtility.UrlEncode(order.ShippingAddress.Address1));
                sb.AppendFormat("&x_ship_to_city={0}", HttpUtility.UrlEncode(order.ShippingAddress.City));
                sb.AppendFormat("&x_ship_to_state={0}", HttpUtility.UrlEncode(order.ShippingAddress.StateOrRegion));
                sb.AppendFormat("&x_ship_to_zip={0}", HttpUtility.UrlEncode(order.ShippingAddress.PostalCode));
                sb.AppendFormat("&x_ship_to_country={0}", HttpUtility.UrlEncode(order.ShippingAddress.Country));
            }

            #endregion

            #region Line Items

            AppendLineItems(order, sb, currency);

            #endregion

            #region Credit Card Info

            //x_exp_date
            //x_card_num
            //x_card_code

            string expDate = string.Empty;
            if (order.CreditCardExpirationMonth < 10)
            {
                expDate = "0" + order.CreditCardExpirationMonth.ToString();
            }
            else
            {
                expDate = order.CreditCardExpirationMonth.ToString();
            }
            if (order.CreditCardExpirationYear > 99)
            {
                expDate += order.CreditCardExpirationYear.ToString().Substring(2, 2);
            }
            else
            {
                expDate += order.CreditCardExpirationYear.ToString();
            }
            sb.AppendFormat("&x_exp_date={0}", HttpUtility.UrlEncode(expDate));
            sb.AppendFormat("&x_card_num={0}", HttpUtility.UrlEncode(order.CreditCardNumber));
            sb.AppendFormat("&x_card_code={0}", HttpUtility.UrlEncode(order.CreditCardSecurityNumber));
            //If the charge fails the first time thru, then we will have some data populated, so we need to try to remove it first
            if (order.ExtendedProperties.Contains("Validator"))
            {
                order.ExtendedProperties.Remove("Validator");
            }
            if (order.ExtendedProperties.Contains("ExpDate"))
            {
                order.ExtendedProperties.Remove("ExpDate");
            }
            //now, add them back in
            order.ExtendedProperties.Add("Validator", order.CreditCardNumber.ToString().Substring((order.CreditCardNumber.Length - 4)));
            order.ExtendedProperties.Add("ExpDate", expDate);
            order.AdditionalProperties = order.ExtendedProperties.ToXml();
            order.Save("System");

            #endregion

            #region Charge It

            //postData = HttpUtility.UrlEncode(sb.ToString());
            postData = sb.ToString();
            string response = CoreUtility.SendRequestByPost(AuthorizeServiceUtility.GetAuthorizeServiceEndpoint(this.IsLive), postData);

            #endregion

            #region Check it and Build up the Transaction

            string[] output = response.Split('|');

            int counter = 1;//Start @ 1 to keep in sync with docs
            System.Collections.Hashtable vars = new System.Collections.Hashtable();

            foreach (string var in output)
            {
                vars.Add(counter, var);
                counter += 1;
            }

            Transaction transaction  = null;
            string      responseCode = vars[1].ToString();
            if ((responseCode == "2") || (responseCode == "3"))
            {
                throw new AuthorizeNetServiceException(vars[4].ToString());
            }
            else
            {
                transaction         = new Transaction();
                transaction.OrderId = order.OrderId;
                transaction.TransactionTypeDescriptorId = (int)TransactionType.Charge;
                transaction.PaymentMethod        = order.CreditCardType.ToString();
                transaction.GatewayName          = AUTHORIZENET;
                transaction.GatewayResponse      = vars[1].ToString();
                transaction.GatewayTransactionId = vars[7].ToString();
                transaction.AVSCode  = vars[6].ToString();
                transaction.CVV2Code = vars[39].ToString();
                decimal grossAmount = 0.00M;
                bool    isParsed    = decimal.TryParse(vars[10].ToString(), out grossAmount);
                transaction.GrossAmount     = grossAmount;
                transaction.TransactionDate = DateTime.Now;
                transaction.Save("System");
            }

            #endregion
            return(transaction);
        }
        /// <summary>
        /// Refunds the specified order.
        /// </summary>
        /// <param name="order">The order.</param>
        /// <returns></returns>
        internal Transaction Refund(Transaction transaction, Order order)
        {
            StringBuilder sb       = new StringBuilder();
            string        postData = string.Empty;
            Currency      currency = new Currency();

            #region Best Practice Fields

            GetBestPracticeFields(sb, AuthorizeNetTransactionType.CREDIT);

            #endregion

            #region Refund Fields

            sb.AppendFormat("&x_trans_id={0}", HttpUtility.UrlEncode(transaction.GatewayTransactionId));
            //We need to get the parent order because it has the ExtendedProperty we need.
            //TODO: CMC - If we keep the full info, it needs to be encrypted.
            Order parentOrder = new Order(transaction.OrderId);
            sb.AppendFormat("&x_card_num={0}", HttpUtility.UrlEncode(parentOrder.ExtendedProperties["Validator"].ToString())); //.Substring((parentOrder.ExtendedProperties["AuthorizeNetRefundValidator"].ToString().Length - 4))));
            sb.AppendFormat("&x_exp_date={0}", HttpUtility.UrlEncode(parentOrder.ExtendedProperties["ExpDate"].ToString()));
            //sb.AppendFormat("&x_card_code={0}", HttpUtility.UrlEncode(parentOrder.ExtendedProperties["SecNum"].ToString()));
            sb.AppendFormat("&x_amount={0}", HttpUtility.UrlEncode(GetFormattedAmount(currency, order.Total).ToString()));

            #endregion

            #region Line Items

            AppendLineItems(order, sb, currency);
            //foreach (OrderItem orderItem in order.OrderItemCollection) {
            //  //Sku, Name, Description, Quantity, Unit Price, Taxable
            //  sb.AppendFormat("&x_line_item={0}<|>{1}<|>{2}<|>{3}<|>{4}<|>{5}", HttpUtility.UrlEncode(orderItem.Sku), HttpUtility.UrlEncode(orderItem.Name), HttpUtility.UrlEncode(orderItem.Attributes), HttpUtility.UrlEncode(orderItem.Quantity.ToString()), HttpUtility.UrlEncode(GetFormattedAmount(currency, orderItem.PricePaid).ToString()), HttpUtility.UrlEncode("TRUE"));
            //}

            #endregion

            #region Refund it

            postData = sb.ToString();
            string response = CoreUtility.SendRequestByPost(AuthorizeServiceUtility.GetAuthorizeServiceEndpoint(this.IsLive), postData);

            #endregion

            #region Check it and Build up the Transaction

            string[] output = response.Split('|');

            int counter = 1;//Start @ 1 to keep in sync with docs
            System.Collections.Hashtable vars = new System.Collections.Hashtable();

            foreach (string var in output)
            {
                vars.Add(counter, var);
                counter += 1;
            }

            Transaction refundTransaction = null;
            string      responseCode      = vars[1].ToString();
            if ((responseCode == "2") || (responseCode == "3"))
            {
                throw new AuthorizeNetServiceException(vars[4].ToString());// + " :: " + postData);
            }
            else
            {
                refundTransaction         = new Transaction();
                refundTransaction.OrderId = transaction.OrderId;
                refundTransaction.TransactionTypeDescriptorId = (int)TransactionType.Refund;
                refundTransaction.PaymentMethod        = transaction.PaymentMethod;
                refundTransaction.GatewayName          = AUTHORIZENET;
                refundTransaction.GatewayResponse      = vars[1].ToString();
                refundTransaction.GatewayTransactionId = vars[7].ToString();
                refundTransaction.AVSCode  = vars[6].ToString();
                refundTransaction.CVV2Code = vars[39].ToString();
                decimal grossAmount = 0.00M;
                bool    isParsed    = decimal.TryParse(vars[10].ToString(), out grossAmount);
                refundTransaction.GrossAmount     = grossAmount;
                refundTransaction.TransactionDate = DateTime.Now;
            }

            #endregion

            return(refundTransaction);
        }