public async Task <TransactionResult> ChargeAsync(
            string cardNumber,
            string cardExpMonth,
            string cardExpYear,
            decimal baseAmount,
            decimal?taxAmount       = null,
            decimal?shippingAmount  = null,
            decimal?surchargeAmount = null,
            decimal?tipAmount       = null,
            AVSType avs             = AVSType.Bypass,
            string billingAddress   = null,
            string billingZipCode   = null,
            bool cvv                   = false,
            string cardCvv             = null,
            string invoiceNumber       = null,
            string purchaseOrderNumber = null,
            string note                = null)
        {
            var requestPayload = new StringBuilder();

            requestPayload.Append("action=CHARGE");
            requestPayload.AppendFormat("&cardNumber={0}", cardNumber.Replace("-", "").Replace(" ", ""));
            requestPayload.AppendFormat("&cardExpMonth={0}", cardExpMonth);
            requestPayload.AppendFormat("&cardExpYear={0}", cardExpYear);

            return(await ExecuteTransactionAsync(
                       requestPayload,
                       baseAmount,
                       taxAmount,
                       shippingAmount,
                       surchargeAmount,
                       tipAmount,
                       avs,
                       billingAddress,
                       billingZipCode,
                       cvv,
                       cardCvv,
                       invoiceNumber,
                       purchaseOrderNumber,
                       note));
        }
        public async Task <TransactionResult> ReChargeAsync(
            string destinationTerminalId,
            string previousTransactionId,
            decimal baseAmount,
            decimal?taxAmount       = null,
            decimal?shippingAmount  = null,
            decimal?surchargeAmount = null,
            decimal?tipAmount       = null,
            AVSType avs             = AVSType.Bypass,
            string billingAddress   = null,
            string billingZipCode   = null,
            bool cvv                   = false,
            string cardCvv             = null,
            string invoiceNumber       = null,
            string purchaseOrderNumber = null,
            string note                = null)
        {
            var requestPayload = new StringBuilder();

            requestPayload.Append("action=CHARGE");
            requestPayload.AppendFormat("&transactionId={0}", previousTransactionId);
            requestPayload.AppendFormat("&terminalId={0}", destinationTerminalId);

            return(await ExecuteTransactionAsync(
                       requestPayload,
                       baseAmount,
                       taxAmount,
                       shippingAmount,
                       surchargeAmount,
                       tipAmount,
                       avs,
                       billingAddress,
                       billingZipCode,
                       cvv,
                       cardCvv,
                       invoiceNumber,
                       purchaseOrderNumber,
                       note));
        }
        private async Task <TransactionResult> ExecuteTransactionAsync(
            StringBuilder requestPayload,
            decimal baseAmount,
            decimal?taxAmount       = null,
            decimal?shippingAmount  = null,
            decimal?surchargeAmount = null,
            decimal?tipAmount       = null,
            AVSType avs             = AVSType.Bypass,
            string billingAddress   = null,
            string billingZipCode   = null,
            bool cvv                   = false,
            string cardCvv             = null,
            string invoiceNumber       = null,
            string purchaseOrderNumber = null,
            string note                = null)
        {
            requestPayload.AppendFormat("&amountBase={0}", baseAmount.ToCurrency(addCommas: false));

            if (taxAmount.HasValue)
            {
                requestPayload.AppendFormat("&amountTax={0}", taxAmount.Value.ToCurrency(addCommas: false));
            }
            if (shippingAmount.HasValue)
            {
                requestPayload.AppendFormat("&amountShipping={0}", shippingAmount.Value.ToCurrency(addCommas: false));
            }
            if (surchargeAmount.HasValue)
            {
                requestPayload.AppendFormat("&amountSurcharge={0}", surchargeAmount.Value.ToCurrency(addCommas: false));
            }
            if (tipAmount.HasValue)
            {
                requestPayload.AppendFormat("&amountTip={0}", tipAmount.Value.ToCurrency(addCommas: false));
            }

            requestPayload.AppendFormat("&avs={0}", avs.ToString().ToUpper());
            if (!String.IsNullOrEmpty(billingAddress))
            {
                requestPayload.AppendFormat("&billingAddress={0}", billingAddress);
            }
            if (!String.IsNullOrEmpty(billingZipCode))
            {
                requestPayload.AppendFormat("&billingZip={0}", billingZipCode);
            }

            requestPayload.AppendFormat("&cvv={0}", cvv.ToOnOff().ToUpper());
            if (cvv)
            {
                requestPayload.AppendFormat("&cardCvv={0}", cardCvv);
            }

            if (!String.IsNullOrEmpty(invoiceNumber))
            {
                requestPayload.AppendFormat("&invoiceNumber={0}", invoiceNumber);
            }
            if (!String.IsNullOrEmpty(purchaseOrderNumber))
            {
                requestPayload.AppendFormat("&purchaseOrderNumber={0}", purchaseOrderNumber);
            }
            if (!String.IsNullOrEmpty(note))
            {
                requestPayload.AppendFormat("&note={0}", note);
            }

            var apiEndPoint = "/transactions";
            var response    = await SendRequestAsync(apiEndPoint, "POST", requestPayload.ToString());

            var result = JsonConvert.DeserializeObject <TransactionResult>(response);

            return(ValidateTransactionResult(result));
        }