Esempio n. 1
0
        public void Can_Authorize_And_Then_Later_Capture_A_Payment()
        {
            var creditCardMethod = Provider.GetPaymentGatewayMethodByPaymentCode("CreditCard");

            Assert.NotNull(creditCardMethod);

            var ccEntry = new CreditCardFormData()
            {
                CreditCardType = "VISA",
                CardholderName = "Alex Lindgren",
                CardNumber     = "4012888888881881",
                CardCode       = "111",
                ExpireMonth    = "09",
                ExpireYear     = "15"
            };

            var authorizes = creditCardMethod.AuthorizePayment(_invoice, ccEntry.AsProcessorArgumentCollection());

            Assert.IsTrue(authorizes.Payment.Success, "authorize call failed");
            Assert.AreNotEqual(Core.Constants.DefaultKeys.InvoiceStatus.Paid, _invoice.InvoiceStatusKey, "invoice is marked as paid and is only authorized");

            //// Act
            var authorizedPayment = authorizes.Payment.Result;

            var result = creditCardMethod.CapturePayment(_invoice, authorizedPayment, _invoice.Total, new ProcessorArgumentCollection());


            //// Assert
            Assert.NotNull(result);
            Assert.IsTrue(result.Payment.Success);
            var payment = result.Payment.Result;

            Assert.IsFalse(_invoice.IsDirty());
            Assert.AreEqual(Core.Constants.DefaultKeys.InvoiceStatus.Paid, _invoice.InvoiceStatusKey);
        }
Esempio n. 2
0
        public void Can_Authorize_A_Payment()
        {
            //// Arrange
            var creditCardMethod = Provider.GetPaymentGatewayMethodByPaymentCode("CreditCard");

            Assert.NotNull(creditCardMethod);

            var ccEntry = new CreditCardFormData()
            {
                CreditCardType = "VISA",
                CardholderName = "Alex Lindgren",
                CardNumber     = "4012888888881881",
                CardCode       = "111",
                ExpireMonth    = "09",
                ExpireYear     = "15"
            };

            //// Act
            var result = creditCardMethod.AuthorizePayment(_invoice, ccEntry.AsProcessorArgumentCollection());

            //// Assert
            Assert.NotNull(result);
            Assert.IsTrue(result.Payment.Success);
            var payment = result.Payment.Result;
        }
Esempio n. 3
0
        public void Can_Authorize_A_Payment()
        {
            //// Arrange
            var creditCardMethod = Provider.GetPaymentGatewayMethodByPaymentCode("CreditCard");

            Assert.NotNull(creditCardMethod);

            var ccEntry = new CreditCardFormData()
            {
                CreditCardType = "VISA",
                CardholderName = "Rusty Swayne",
                CardNumber     = "4111111111111111",
                CardCode       = "111",
                ExpireMonth    = "09",
                ExpireYear     = "15",
                CustomerIp     = "10.0.0.15"
            };

            //// Act
            var result = creditCardMethod.AuthorizePayment(_invoice, ccEntry.AsProcessorArgumentCollection());

            //// Assert
            Assert.NotNull(result);
            Assert.IsTrue(result.Payment.Success);
            var payment = result.Payment.Result;

            Console.WriteLine(payment.ExtendedData.GetValue(Constants.ExtendedDataKeys.AuthorizationTransactionCode));
            Console.WriteLine(payment.ExtendedData.GetValue(Constants.ExtendedDataKeys.AuthorizationTransactionResult));
            Console.WriteLine(payment.ExtendedData.GetValue(Constants.ExtendedDataKeys.AvsResult));
        }
Esempio n. 4
0
        public void Can_AuthorizeAndCapture_A_Payment()
        {
            //// Arrange
            var creditCardMethod = Provider.GetPaymentGatewayMethodByPaymentCode("CreditCard");

            Assert.NotNull(creditCardMethod);

            var ccEntry = new CreditCardFormData()
            {
                CreditCardType = "VISA",
                CardholderName = "Alex Lindgren",
                CardNumber     = "4012888888881881",
                CardCode       = "111",
                ExpireMonth    = "09",
                ExpireYear     = "15"
            };

            //// Act
            var result = creditCardMethod.AuthorizeCapturePayment(_invoice, _invoice.Total, ccEntry.AsProcessorArgumentCollection());

            //// Assert
            Assert.NotNull(result);
            Assert.IsTrue(result.Payment.Success);
            var payment = result.Payment.Result;

            Assert.IsFalse(_invoice.IsDirty());
            Assert.AreEqual(Core.Constants.DefaultKeys.InvoiceStatus.Paid, _invoice.InvoiceStatusKey);
        }
Esempio n. 5
0
        public void Can_AuthFail_A_Payment()
        {
            //// Arrange
            var creditCardMethod = Provider.GetPaymentGatewayMethodByPaymentCode("CreditCard");

            Assert.NotNull(creditCardMethod);

            var ccEntry = new CreditCardFormData()
            {
                CreditCardType = "VISA",
                CardholderName = "Alex Lindgren",
                CardNumber     = "1234123412341234",
                CardCode       = "111",
                ExpireMonth    = "09",
                ExpireYear     = "15"
            };

            //// Act
            var result = creditCardMethod.AuthorizePayment(_invoice, ccEntry.AsProcessorArgumentCollection());

            //// Assert
            Assert.NotNull(result);
            Assert.IsFalse(result.Payment.Success);
            Assert.IsTrue(result.Payment.Exception.Message == "Your card number is incorrect.");
        }
        /// <summary>
        /// Gets a single use token that can be used in place of a credit card details.
        /// The token can be used once for creating a new charge.
        /// </summary>
        /// <param name="creditCard"></param>
        /// <param name="address"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public static string GetCardToken(CreditCardFormData creditCard, IAddress address, StripeProcessorSettings settings)
        {
            var requestParams = new NameValueCollection();

            requestParams.Add("card[number]", creditCard.CardNumber);
            requestParams.Add("card[exp_month]", creditCard.ExpireMonth);
            requestParams.Add("card[exp_year]", creditCard.ExpireYear);
            requestParams.Add("card[cvc]", creditCard.CardCode);
            requestParams.Add("card[name]", creditCard.CardholderName);

            if (address != null)
            {
                requestParams.Add("card[address_line1]", address.Address1);
                requestParams.Add("card[address_line2]", address.Address2);
                requestParams.Add("card[address_city]", address.Locality);
                if (!string.IsNullOrEmpty(address.Region))
                {
                    requestParams.Add("card[address_state]", address.Region);
                }
                requestParams.Add("card[address_zip]", address.PostalCode);
                if (!string.IsNullOrEmpty(address.CountryCode))
                {
                    requestParams.Add("card[address_country]", address.CountryCode);
                }
            }

            string postData =
                requestParams.AllKeys.Aggregate("",
                                                (current, key) => current + (key + "=" + HttpUtility.UrlEncode(requestParams[key]) + "&"))
                .TrimEnd('&');

            // https://stripe.com/docs/api#create_card_token
            var    response    = StripeHelper.MakeStripeApiRequest("https://api.stripe.com/v1/tokens", "POST", requestParams, settings);
            string apiResponse = null;

            using (var reader = new StreamReader(response.GetResponseStream()))
            {
                apiResponse = reader.ReadToEnd();
            }
            JObject responseJson = JObject.Parse(apiResponse);

            switch (response.StatusCode)
            {
            case HttpStatusCode.OK:     // 200
                return((string)responseJson["id"]);

            default:

                throw new Exception("Stripe error");
            }
        }
Esempio n. 7
0
        /// <summary>
        ///     Processes the Authorize and AuthorizeAndCapture transactions
        /// </summary>
        /// <param name="invoice">The <see cref="IInvoice" /> to be paid</param>
        /// <param name="payment">The <see cref="IPayment" /> record</param>
        /// <param name="transactionMode">Authorize or AuthorizeAndCapture</param>
        /// <param name="amount">The money amount to be processed</param>
        /// <param name="creditCard">The <see cref="CreditCardFormData" /></param>
        /// <returns>The <see cref="IPaymentResult" /></returns>
        public IPaymentResult ProcessPayment(IInvoice invoice, IPayment payment, TransactionMode transactionMode,
                                             decimal amount, CreditCardFormData creditCard)
        {
            if (!IsValidCurrencyCode(invoice.CurrencyCode()))
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception("Invalid currency")), invoice,
                                         false));
            }

            // The minimum amount is $0.50 (or equivalent in charge currency).
            // Test that the payment meets the minimum amount (for USD only).
            if (invoice.CurrencyCode() == "USD")
            {
                if (amount < 0.5m)
                {
                    return
                        (new PaymentResult(
                             Attempt <IPayment> .Fail(payment, new Exception("Invalid amount (less than 0.50 USD)")),
                             invoice, false));
                }
            }
            else
            {
                if (amount < 1)
                {
                    return
                        (new PaymentResult(
                             Attempt <IPayment> .Fail(payment,
                                                      new Exception("Invalid amount (less than 1 " + invoice.CurrencyCode() + ")")),
                             invoice, false));
                }
            }

            var requestParams = StripeHelper.PreparePostDataForProcessPayment(invoice.GetBillingAddress(), transactionMode,
                                                                              ConvertAmount(invoice, amount), invoice.CurrencyCode(), creditCard, invoice.PrefixedInvoiceNumber(),
                                                                              string.Format("Full invoice #{0}", invoice.PrefixedInvoiceNumber()));

            // https://stripe.com/docs/api#create_charge
            try
            {
                var response = StripeHelper.MakeStripeApiRequest("https://api.stripe.com/v1/charges", "POST", requestParams, _settings);
                return(GetProcessPaymentResult(invoice, payment, response));
            }
            catch (WebException ex)
            {
                return(GetProcessPaymentResult(invoice, payment, (HttpWebResponse)ex.Response));
            }
        }
        public static NameValueCollection PreparePostDataForProcessPayment(IAddress billingAddress,
                                                                           TransactionMode transactionMode,
                                                                           string amount, string currency, CreditCardFormData creditCard, string invoiceNumber, string description)
        {
            var requestParams = new NameValueCollection();

            requestParams.Add("amount", amount);
            requestParams.Add("currency", currency);
            if (transactionMode == TransactionMode.Authorize)
            {
                requestParams.Add("capture", "false");
            }

            if (!String.IsNullOrEmpty(creditCard.StripeCustomerId))
            {
                requestParams.Add("customer", creditCard.StripeCustomerId);
                if (!String.IsNullOrEmpty(creditCard.StripeCardId))
                {
                    requestParams.Add("card", creditCard.StripeCardId);
                }
            }
            else
            {
                if (!String.IsNullOrEmpty(creditCard.StripeCardToken))
                {
                    requestParams.Add("card", creditCard.StripeCardToken);
                }
                else
                {
                    requestParams.Add("card[number]", creditCard.CardNumber);
                    requestParams.Add("card[exp_month]", creditCard.ExpireMonth);
                    requestParams.Add("card[exp_year]", creditCard.ExpireYear);
                    requestParams.Add("card[cvc]", creditCard.CardCode);
                    requestParams.Add("card[name]", creditCard.CardholderName);

                    //requestParams.Add("receipt_email", address.Email); // note: this will send receipt email - maybe there should be a setting controlling if this is passed or not. Email could also be added to metadata
                    requestParams.Add("card[address_line1]", billingAddress.Address1);
                    requestParams.Add("card[address_line2]", billingAddress.Address2);
                    requestParams.Add("card[address_city]", billingAddress.Locality);
                    if (!string.IsNullOrEmpty(billingAddress.Region))
                    {
                        requestParams.Add("card[address_state]", billingAddress.Region);
                    }
                    requestParams.Add("card[address_zip]", billingAddress.PostalCode);
                    if (!string.IsNullOrEmpty(billingAddress.CountryCode))
                    {
                        requestParams.Add("card[address_country]", billingAddress.CountryCode);
                    }
                }
            }


            requestParams.Add("metadata[invoice_number]", invoiceNumber);
            requestParams.Add("description", description);

            string postData =
                requestParams.AllKeys.Aggregate("",
                                                (current, key) => current + (key + "=" + HttpUtility.UrlEncode(requestParams[key]) + "&"))
                .TrimEnd('&');

            return(requestParams);
        }
Esempio n. 9
0
        /// <summary>
        /// Processes the Authorize and AuthorizeAndCapture transactions
        /// </summary>
        /// <param name="invoice">The <see cref="IInvoice"/> to be paid</param>
        /// <param name="payment">The <see cref="IPayment"/> record</param>
        /// <param name="transactionMode">Authorize or AuthorizeAndCapture</param>
        /// <param name="amount">The money amount to be processed</param>
        /// <param name="creditCard">The <see cref="CreditCardFormData"/></param>
        /// <returns>The <see cref="IPaymentResult"/></returns>
        public IPaymentResult ProcessPayment(IInvoice invoice, IPayment payment, TransactionMode transactionMode, decimal amount, CreditCardFormData creditCard)
        {
            var address = invoice.GetBillingAddress();

            var names = creditCard.CardholderName.Split(' ');

            // Declare a response
            Paymentech.Response response;

            // Create an authorize transaction
            var transaction = new Transaction(RequestType.NEW_ORDER_TRANSACTION);

            // Populate the required fields for the given transaction type. You can use’
            // the Paymentech Transaction Appendix to help you populate the transaction’

            transaction["OrbitalConnectionUsername"] = _settings.Username;
            transaction["OrbitalConnectionPassword"] = _settings.Password;

            /*
             * Message Types
             * MO – Mail Order transaction
             * RC – Recurring Payment
             * EC– eCommerce transaction
             * IV – IVR [PINLess Debit Only]
             */
            transaction["IndustryType"] = "EC";

            /*
             * Message Types
             * A – Authorization request
             * AC – Authorization and Mark for Capture
             * FC – Force-Capture request
             * R – Refund request
             */
            transaction["MessageType"] = transactionMode == TransactionMode.Authorize ? "A" : "AC";

            transaction["MerchantID"] = _settings.MerchantId;
            transaction["BIN"]        = _settings.Bin;

            // Credit Card Number
            transaction["AccountNum"] = creditCard.CardNumber.Replace(" ", "").Replace("-", "").Replace("|", "");

            transaction["OrderID"] = invoice.InvoiceNumber.ToString(CultureInfo.InstalledUICulture);

            transaction["Amount"] = string.Format("{0:0}", amount * 100);
            // Expiration date
            var creditCardExpMonth = creditCard.ExpireMonth;
            var creditCardExpYear  = creditCard.ExpireYear.Length > 2
                ? creditCard.ExpireYear.Substring(2, 2)
                : creditCard.ExpireYear;

            transaction["Exp"] = creditCardExpMonth.PadLeft(2) + creditCardExpYear;

            transaction["AVSname"]        = address.Name;
            transaction["AVSaddress1"]    = address.Address1;
            transaction["AVSaddress2"]    = address.Address2;
            transaction["AVScity"]        = address.Locality;
            transaction["AVSstate"]       = address.Region;
            transaction["AVSzip"]         = address.PostalCode;
            transaction["AVScountryCode"] = address.CountryCode;
            transaction["CardSecVal"]     = creditCard.CardCode;

            transaction["TraceNumber"] = invoice.InvoiceNumber.ToString();

            if (string.IsNullOrEmpty(creditCard.CreditCardType))
            {
                creditCard.CreditCardType = GetCreditCardType(creditCard.CardNumber);
            }

            if (creditCard.CreditCardType.ToLower().Contains("visa") || creditCard.CreditCardType.ToLower().Contains("chase"))
            {
                transaction["CAVV"] = creditCard.AuthenticationVerification;

                // If no value for creditCard.CardCode, then CardSecValInd cannot be 1.  Send 2 or 9 instead
                if (string.IsNullOrEmpty(creditCard.CardCode))
                {
                    transaction["CardSecValInd"] = "9";
                }
                else
                {
                    transaction["CardSecValInd"] = "1";
                }
            }
            else if (creditCard.CreditCardType.ToLower().Contains("mastercard"))
            {
                transaction["AAV"]           = creditCard.AuthenticationVerification;
                transaction["CardSecValInd"] = "";
            }
            transaction["AuthenticationECIInd"] = creditCard.AuthenticationVerificationEci;

            /*
             * CardSecValInd
             * 1 - Value is Present
             * 2 - Value on card but illegible
             * 9 - Cardholder states data not available
             */
            // Only send if ChaseNet, Visa and Discover transactions
            // transaction["CardSecValInd"] = "1";

            /*
             * CardSecValInd
             * A – Auto Generate the CustomerRefNum
             * S – Use CustomerRefNum Element
             */

            // profile management will not be supported, do not send CustomerProfileFromOrderInd
            //transaction["CustomerProfileFromOrderInd"] = "A";

            /*
             * CustomerProfileOrderOverrideInd
             * NO No mapping to order data
             * OI Use <CustomerRefNum> for <OrderID> and <ECOrderNum> or <MailOrderNum>
             * OD Use <CustomerReferNum> for <Comments>
             * OA Use <CustomerRefNum> for <OrderID> and <Comments>
             */
            transaction["CustomerProfileOrderOverrideInd"] = "NO";

            transaction["Comments"] = invoice.InvoiceNumber.ToString(CultureInfo.InstalledUICulture);

            response = transaction.Process();

            // API Error
            if (response == null)
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception("Chase Paymentech unknown error")), invoice, false));
            }

            string approvalStatus = "";

            if (response.XML != null)
            {
                var xml = XDocument.Parse(response.MaskedXML);
                if (xml.Descendants("ApprovalStatus").FirstOrDefault() != null)
                {
                    approvalStatus = xml.Descendants("ApprovalStatus").First().Value;
                }
            }


            if (response.Error)
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Error {0}", response))), invoice, false));
            }
            if (response.Declined)
            {
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizeDeclinedResult, string.Format("Declined ({0} : {1})", response.ResponseCode, response.Message));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.TransactionReferenceNumber, response.TxRefNum);
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizationTransactionCode, string.Format("{0},{1},{2}", response.AuthCode, response.ResponseCode, approvalStatus));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AvsResult, response.AVSRespCode);
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.Cvv2Result, string.Format("{0},{1}", response.CVV2RespCode, response.CVV2ResponseCode));
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Declined ({0} : {1})", response.ResponseCode, response.Message))), invoice, false));
            }
            if (response.Approved)
            {
                var txRefIdx = "";
                if (response.XML != null)
                {
                    var xml = XDocument.Parse(response.MaskedXML);
                    txRefIdx = xml.Descendants("TxRefIdx").First().Value;
                }

                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.TransactionReferenceNumber, response.TxRefNum);
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.TransactionReferenceIndex, txRefIdx);
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizationTransactionCode, string.Format("{0},{1},{2}", response.AuthCode, response.ResponseCode, approvalStatus));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AvsResult, response.AVSRespCode);
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.Cvv2Result, string.Format("{0},{1}", response.CVV2RespCode, response.CVV2ResponseCode));

                payment.Authorized = true;
                if (transactionMode == TransactionMode.AuthorizeAndCapture)
                {
                    payment.Collected = true;
                }
                return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, true));
            }

            return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Error {0}", response))), invoice, false));
        }
Esempio n. 10
0
        /// <summary>
        ///     Processes the Authorize and AuthorizeAndCapture transactions
        /// </summary>
        /// <param name="invoice">The <see cref="IInvoice" /> to be paid</param>
        /// <param name="payment">The <see cref="IPayment" /> record</param>
        /// <param name="transactionMode">Authorize or AuthorizeAndCapture</param>
        /// <param name="amount">The money amount to be processed</param>
        /// <param name="creditCard">The <see cref="CreditCardFormData" /></param>
        /// <returns>The <see cref="IPaymentResult" /></returns>
        public IPaymentResult ProcessPayment(IInvoice invoice, IPayment payment, TransactionMode transactionMode,
                                             decimal amount, CreditCardFormData creditCard)
        {
            if (!IsValidCurrencyCode(invoice.CurrencyCode()))
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception("Invalid currency")), invoice,
                                         false));
            }

            // The minimum amount is $0.50 (or equivalent in charge currency).
            // Test that the payment meets the minimum amount (for USD only).
            if (invoice.CurrencyCode() == "USD")
            {
                if (amount < 0.5m)
                {
                    return
                        (new PaymentResult(
                             Attempt <IPayment> .Fail(payment, new Exception("Invalid amount (less than 0.50 USD)")),
                             invoice, false));
                }
            }
            else
            {
                if (amount < 1)
                {
                    return
                        (new PaymentResult(
                             Attempt <IPayment> .Fail(payment,
                                                      new Exception("Invalid amount (less than 1 " + invoice.CurrencyCode() + ")")),
                             invoice, false));
                }
            }

            var requestParams = new NameValueCollection();

            requestParams.Add("amount", ConvertAmount(invoice, amount));
            requestParams.Add("currency", invoice.CurrencyCode());
            if (transactionMode == TransactionMode.Authorize)
            {
                requestParams.Add("capture", "false");
            }
            requestParams.Add("card[number]", creditCard.CardNumber);
            requestParams.Add("card[exp_month]", creditCard.ExpireMonth);
            requestParams.Add("card[exp_year]", creditCard.ExpireYear);
            requestParams.Add("card[cvc]", creditCard.CardCode);
            requestParams.Add("card[name]", creditCard.CardholderName);

            // Billing address
            IAddress address = invoice.GetBillingAddress();

            //requestParams.Add("receipt_email", address.Email); // note: this will send receipt email - maybe there should be a setting controlling if this is passed or not. Email could also be added to metadata
            requestParams.Add("card[address_line1]", address.Address1);
            requestParams.Add("card[address_line2]", address.Address2);
            requestParams.Add("card[address_city]", address.Locality);
            if (!string.IsNullOrEmpty(address.Region))
            {
                requestParams.Add("card[address_state]", address.Region);
            }
            requestParams.Add("card[address_zip]", address.PostalCode);
            if (!string.IsNullOrEmpty(address.CountryCode))
            {
                requestParams.Add("card[address_country]", address.CountryCode);
            }
            requestParams.Add("metadata[invoice_number]", invoice.PrefixedInvoiceNumber());
            requestParams.Add("description", string.Format("Full invoice #{0}", invoice.PrefixedInvoiceNumber()));

            string postData =
                requestParams.AllKeys.Aggregate("",
                                                (current, key) => current + (key + "=" + HttpUtility.UrlEncode(requestParams[key]) + "&"))
                .TrimEnd('&');

            // https://stripe.com/docs/api#create_charge
            try
            {
                var response = MakeStripeApiRequest("https://api.stripe.com/v1/charges", "POST", requestParams);
                return(GetProcessPaymentResult(invoice, payment, response));
            }
            catch (WebException ex)
            {
                return(GetProcessPaymentResult(invoice, payment, (HttpWebResponse)ex.Response));
            }
        }
        /// <summary>
        /// Processes the Authorize and AuthorizeAndCapture transactions
        /// </summary>
        /// <param name="invoice">The <see cref="IInvoice"/> to be paid</param>
        /// <param name="payment">The <see cref="IPayment"/> record</param>
        /// <param name="transactionMode">Authorize or AuthorizeAndCapture</param>
        /// <param name="amount">The money amount to be processed</param>
        /// <param name="creditCard">The <see cref="CreditCardFormData"/></param>
        /// <returns>The <see cref="IPaymentResult"/></returns>
        public IPaymentResult ProcessPayment(IInvoice invoice, IPayment payment, TransactionMode transactionMode, decimal amount, CreditCardFormData creditCard)
        {
            var address = invoice.GetBillingAddress();

            var form = GetInitialRequestForm(invoice.CurrencyCode());

            var names = creditCard.CardholderName.Split(' ');

            form.Add("x_type",
                     transactionMode == TransactionMode.Authorize ?
                     "AUTH_ONLY" : "AUTH_CAPTURE"
                     );

            // Credit card information
            form.Add("x_card_num", creditCard.CardNumber);
            form.Add("x_exp_date", creditCard.ExpireMonth.PadLeft(2) + creditCard.ExpireYear);
            form.Add("x_card_code", creditCard.CardCode);
            form.Add("x_customer_ip", creditCard.CustomerIp);

            // Billing address
            form.Add("x_first_name", names.Count() > 1 ? names[0] : creditCard.CardholderName);
            form.Add("x_last_name", names.Count() > 1 ? names[1] : string.Empty);
            form.Add("x_email", address.Email);
            if (!string.IsNullOrEmpty(address.Organization))
            {
                form.Add("x_company", address.Organization);
            }
            form.Add("x_address", address.Address1);
            form.Add("x_city", address.Locality);
            if (!string.IsNullOrEmpty(address.Region))
            {
                form.Add("x_state", address.Region);
            }
            form.Add("x_zip", address.PostalCode);
            if (!string.IsNullOrEmpty(address.CountryCode))
            {
                form.Add("x_country", address.CountryCode);
            }

            // Invoice information
            form.Add("x_amount", amount.ToString("0.00", CultureInfo.InstalledUICulture));

            // maximum length 20 chars
            form.Add("x_invoice_num", invoice.PrefixedInvoiceNumber());
            form.Add("x_description", string.Format("Full invoice #{0}", invoice.PrefixedInvoiceNumber()));

            var reply = GetAuthorizeNetReply(form);

            // API Error
            if (string.IsNullOrEmpty(reply))
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception("Authorize.NET unknown error")), invoice, false));
            }

            var fields = reply.Split('|');

            switch (fields[0])
            {
            case "3":
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Error {0}", reply))), invoice, false));

            case "2":
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizeDeclinedResult, string.Format("Declined ({0} : {1})", fields[2], fields[3]));
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Declined ({0} : {1})", fields[2], fields[3]))), invoice, false));

            case "1":
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizationTransactionCode, string.Format("{0},{1}", fields[6], fields[4]));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizationTransactionResult, string.Format("Approved ({0}: {1})", fields[2], fields[3]));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AvsResult, fields[5]);
                payment.Authorized = true;
                if (transactionMode == TransactionMode.AuthorizeAndCapture)
                {
                    payment.Collected = true;
                }
                return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, true));
            }

            return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Error {0}", reply))), invoice, false));
        }
        /// <summary>
        /// Processes the Authorize and AuthorizeAndCapture transactions
        /// </summary>
        /// <param name="invoice">The <see cref="IInvoice"/> to be paid</param>
        /// <param name="payment">The <see cref="IPayment"/> record</param>
        /// <param name="transactionMode">Authorize or AuthorizeAndCapture</param>
        /// <param name="amount">The money amount to be processed</param>
        /// <param name="creditCard">The <see cref="CreditCardFormData"/></param>
        /// <returns>The <see cref="IPaymentResult"/></returns>
        public IPaymentResult ProcessPayment(IInvoice invoice, IPayment payment, TransactionMode transactionMode, decimal amount, CreditCardFormData creditCard)
        {
            var address = invoice.GetBillingAddress();

            var names = creditCard.CardholderName.Split(' ');

            // Declare a response
            Paymentech.Response response;

            // Create an authorize transaction
            var transaction = new Transaction(RequestType.NEW_ORDER_TRANSACTION);

            // Populate the required fields for the given transaction type. You can use’
            // the Paymentech Transaction Appendix to help you populate the transaction’

            /*
             * Message Types
             * MO – Mail Order transaction
             * RC – Recurring Payment
             * EC– eCommerce transaction
             * IV – IVR [PINLess Debit Only]
             */
            transaction["IndustryType"] = "EC";

            /*
             * Message Types
             * A – Authorization request
             * AC – Authorization and Mark for Capture
             * FC – Force-Capture request
             * R – Refund request
             */
            transaction["MessageType"] = transactionMode == TransactionMode.Authorize ? "A" : "AC";

            transaction["MerchantID"] = "041756";
            transaction["BIN"]        = "000001";


            // Credit Card Number
            transaction["AccountNum"] = creditCard.CardNumber;

            transaction["OrderID"] = invoice.InvoiceNumber.ToString(CultureInfo.InstalledUICulture);

            transaction["Amount"] = amount.ToString("0.00", CultureInfo.InstalledUICulture);

            // Expiration date
            transaction["Exp"] = creditCard.ExpireMonth.PadLeft(2) + creditCard.ExpireYear;

            transaction["AVSname"]        = address.Name;
            transaction["AVSaddress1"]    = address.Address1;
            transaction["AVSaddress2"]    = address.Address2;
            transaction["AVScity"]        = address.Locality;
            transaction["AVSstate"]       = address.Region;
            transaction["AVSzip"]         = address.PostalCode;
            transaction["AVScountryCode"] = address.CountryCode;
            transaction["CardSecVal"]     = creditCard.CardCode;

            /*
             * CardSecValInd
             * 1 - Value is Present
             * 2 - Value on card but illegible
             * 9 - Cardholder states data not available
             */
            transaction["CardSecValInd"] = "1";

            /*
             * CardSecValInd
             * A – Auto Generate the CustomerRefNum
             * S – Use CustomerRefNum Element
             */
            transaction["CustomerProfileFromOrderInd"] = "A";

            /*
             * CustomerProfileOrderOverrideInd
             * NO No mapping to order data
             * OI Use <CustomerRefNum> for <OrderID> and <ECOrderNum> or <MailOrderNum>
             * OD Use <CustomerReferNum> for <Comments>
             * OA Use <CustomerRefNum> for <OrderID> and <Comments>
             */
            transaction["CustomerProfileOrderOverrideInd"] = "NO";

            transaction["Comments"] = invoice.InvoiceNumber.ToString(CultureInfo.InstalledUICulture);

            response = transaction.Process();

            // API Error
            if (response == null)
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception("Chase Paymentech unknown error")), invoice, false));
            }


            if (response.Error)
            {
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Error {0}", response))), invoice, false));
            }
            if (response.Declined)
            {
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizeDeclinedResult, string.Format("Declined ({0} : {1})", response.ResponseCode, response.Message));
                return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Declined ({0} : {1})", response.ResponseCode, response.Message))), invoice, false));
            }
            if (response.Approved)
            {
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.TransactionReferenceNumber, string.Format("Approved ({0})", response.TxRefNum));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AuthorizationTransactionCode, string.Format("{0},{1}", response.ResponseCode));
                payment.ExtendedData.SetValue(Constants.ExtendedDataKeys.AvsResult, response.AVSRespCode);
                payment.Authorized = true;
                if (transactionMode == TransactionMode.AuthorizeAndCapture)
                {
                    payment.Collected = true;
                }
                return(new PaymentResult(Attempt <IPayment> .Succeed(payment), invoice, true));
            }

            return(new PaymentResult(Attempt <IPayment> .Fail(payment, new Exception(string.Format("Error {0}", response))), invoice, false));
        }