Exemple #1
0
        /// <summary>
        /// Tests that use this method must be ignored when run in an automated environment because executing an order
        /// will require approval via the executed payment's approval_url.
        /// </summary>
        /// <returns></returns>
        private Order GetExecutedPaymentOrder(PayPal.APIContext apiContext)
        {
            var pay = PaymentTest.CreatePaymentOrder();
            var paymentExecution = PaymentExecutionTest.GetPaymentExecution();

            paymentExecution.payer_id = pay.id;
            paymentExecution.transactions[0].amount.details = null;
            var executedPayment = pay.Execute(apiContext, paymentExecution);
            var orderId         = executedPayment.transactions[0].related_resources[0].order.id;

            return(Order.Get(apiContext, orderId));
        }
        } // End of the payex_confirmation method

        #endregion

        #region PayPal payment

        /// <summary>
        /// Create a paypal payment
        /// </summary>
        public ActionResult CreatePayPalPayment(Order order, List<OrderRow> orderRows, Domain domain, KeyStringList tt)
        {
            // Create the string to return
            string error_message = "";

            // Get the currency
            Currency currency = Currency.GetOneById(order.currency_code);

            // Get the webshop settings
            KeyStringList webshopSettings = WebshopSetting.GetAllFromCache();

            // Get credentials
            string paypalClientId = webshopSettings.Get("PAYPAL-CLIENT-ID");
            string paypalClientSecret = webshopSettings.Get("PAYPAL-CLIENT-SECRET");
            string paypalMode = webshopSettings.Get("PAYPAL-MODE");
            Dictionary<string, string> config = new Dictionary<string, string> { { "mode", paypalMode } };

            // Create a payment variable
            PayPal.Api.Payments.Payment createdPayment = null;

            try
            {
                // Create the credential token
                PayPal.OAuthTokenCredential tokenCredential = new PayPal.OAuthTokenCredential(paypalClientId, paypalClientSecret, config);

                // Create the api context
                PayPal.APIContext paypalContext = new PayPal.APIContext(tokenCredential.GetAccessToken());
                paypalContext.Config = config;

                // Create the amount details
                decimal subTotal = order.net_sum + order.rounding_sum - order.gift_cards_amount;
                PayPal.Api.Payments.Details amountDetails = new PayPal.Api.Payments.Details();
                amountDetails.subtotal = subTotal.ToString("F2", CultureInfo.InvariantCulture);
                amountDetails.tax = order.vat_sum.ToString("F2", CultureInfo.InvariantCulture);

                // Create the amount
                decimal totalAmount = order.total_sum - order.gift_cards_amount;
                PayPal.Api.Payments.Amount amount = new PayPal.Api.Payments.Amount();
                amount.total = totalAmount.ToString("F2", CultureInfo.InvariantCulture);
                amount.currency = order.currency_code;
                amount.details = amountDetails;

                // Create a transaction
                PayPal.Api.Payments.Transaction transaction = new PayPal.Api.Payments.Transaction();
                transaction.item_list = new PayPal.Api.Payments.ItemList();
                transaction.item_list.items = new List<PayPal.Api.Payments.Item>(10);

                // Add order rows to the transaction
                for (int i = 0; i < orderRows.Count; i++)
                {
                    // Create a new item
                    PayPal.Api.Payments.Item item = new PayPal.Api.Payments.Item();
                    item.sku = orderRows[i].product_code.Length > 50 ? orderRows[i].product_code.Substring(0, 50) : orderRows[i].product_code;
                    item.name = orderRows[i].product_name.Length > 100 ? orderRows[i].product_name.Substring(0, 50) : orderRows[i].product_name;
                    item.price = orderRows[i].unit_price.ToString("F2", CultureInfo.InvariantCulture);
                    item.quantity = Convert.ToInt32(orderRows[i].quantity).ToString();
                    item.currency = order.currency_code;

                    // Add the item to the list
                    transaction.item_list.items.Add(item);
                }

                // Add the rounding
                if(order.rounding_sum != 0)
                {
                    PayPal.Api.Payments.Item roundingItem = new PayPal.Api.Payments.Item();
                    roundingItem.sku = "rd";
                    roundingItem.name = tt.Get("rounding");
                    roundingItem.price = order.rounding_sum.ToString("F2", CultureInfo.InvariantCulture);
                    roundingItem.quantity = "1";
                    roundingItem.currency = order.currency_code;
                    transaction.item_list.items.Add(roundingItem);
                }

                // Add the gift cards amount
                if (order.gift_cards_amount > 0)
                {
                    decimal giftCardAmount = order.gift_cards_amount * -1;
                    PayPal.Api.Payments.Item giftCardsItem = new PayPal.Api.Payments.Item();
                    giftCardsItem.sku = "gc";
                    giftCardsItem.name = tt.Get("gift_cards");
                    giftCardsItem.price = giftCardAmount.ToString("F2", CultureInfo.InvariantCulture);
                    giftCardsItem.quantity = "1";
                    giftCardsItem.currency = order.currency_code;
                    transaction.item_list.items.Add(giftCardsItem);
                }
                
                // Set the transaction amount
                transaction.amount = amount;
                List<PayPal.Api.Payments.Transaction> transactions = new List<PayPal.Api.Payments.Transaction>();
                transactions.Add(transaction);

                // Create the payer
                PayPal.Api.Payments.Payer payer = new PayPal.Api.Payments.Payer();
                payer.payment_method = "paypal";

                // Create redirect urls
                string hostUrl = Request.Url.Host;
                PayPal.Api.Payments.RedirectUrls redirectUrls = new PayPal.Api.Payments.RedirectUrls();
                redirectUrls.return_url = domain.web_address + "/order/paypal_confirmation/" + order.id;
                redirectUrls.cancel_url = domain.web_address + "/order/confirmation/" + order.id;

                // Create the payment
                PayPal.Api.Payments.Payment payment = new PayPal.Api.Payments.Payment();
                payment.intent = "sale";
                payment.payer = payer;
                payment.redirect_urls = redirectUrls;
                payment.transactions = transactions;

                // Create the payment
                createdPayment = payment.Create(paypalContext);

            }
            catch (Exception ex)
            {
                error_message = ex.Message;
            }

            // Check if there is any errors in the payment
            if (createdPayment != null)
            {
                // Save the paypal payment id
                Order.SetPaymentToken(order.id, createdPayment.id);

                // Get the link
                string link = "";
                foreach(PayPal.Api.Payments.Links url in createdPayment.links)
                {
                    if (url.rel == "approval_url")
                    {
                        link = url.href;
                        break;
                    }
                }

                // Redirect the user to the paypal page
                return Redirect(link);
            }
            else
            {
                // Redirect the user to the order confirmation page
                return RedirectToAction("confirmation", "order", new { id = order.id });
            }

        } // End of the CreatePayPalPayment method
        public ActionResult paypal_confirmation(Int32 id = 0)
        {
            // Get the payer id
            string payerId = "";
            if (Request.Params["PayerID"] != null)
            {
                payerId = Server.UrlDecode(Request.Params["PayerID"]);
            }

            // Get the order
            Order order = Order.GetOneById(id);

            // Make sure that the order not is null
            if(order == null)
            {
                // Redirect the user to the order confirmation page
                return RedirectToAction("index", "home");
            }

            // Get the webshop settings
            KeyStringList webshopSettings = WebshopSetting.GetAllFromCache();

            // Get credentials
            string paypalClientId = webshopSettings.Get("PAYPAL-CLIENT-ID");
            string paypalClientSecret = webshopSettings.Get("PAYPAL-CLIENT-SECRET");
            string paypalMode = webshopSettings.Get("PAYPAL-MODE");
            Dictionary<string, string> config = new Dictionary<string, string> { { "mode", paypalMode } };

            // Create a error message
            string error_message = "";

            // Create a payment variable
            PayPal.Api.Payments.Payment createdPayment = null;

            try
            {
                // Create the credential token
                PayPal.OAuthTokenCredential tokenCredential = new PayPal.OAuthTokenCredential(paypalClientId, paypalClientSecret, config);

                // Create the api context
                PayPal.APIContext paypalContext = new PayPal.APIContext(tokenCredential.GetAccessToken());
                paypalContext.Config = config;

                // Get the payment
                PayPal.Api.Payments.Payment payment = PayPal.Api.Payments.Payment.Get(paypalContext, order.payment_token);

                // Create the payment excecution
                PayPal.Api.Payments.PaymentExecution paymentExecution = new PayPal.Api.Payments.PaymentExecution();
                paymentExecution.payer_id = payerId;
                paypalContext.HTTPHeaders = null;

                // Excecute the payment
                createdPayment = payment.Execute(paypalContext, paymentExecution);

            }
            catch (Exception ex)
            {
                error_message = ex.Message;
            }

            // Check if the created payment is different from null
            if (createdPayment != null && createdPayment.state == "approved")
            {
                // Get the sale id
                List<PayPal.Api.Payments.RelatedResources> resources = createdPayment.transactions[0].related_resources;

                // Save the paypal sale id
                Order.SetPaymentToken(order.id, resources[0].sale.id);

                // Update the order status
                Order.UpdatePaymentStatus(order.id, "payment_status_paid");

                // Add customer files
                CustomerFile.AddCustomerFiles(order);
            }

            // Redirect the user to the order confirmation page
            return RedirectToAction("confirmation", "order", new { id = id });

        } // End of the paypal_confirmation method
Exemple #4
0
        } // End of the UpdatePaymentStatus method

        /// <summary>
        /// Respond to an updated order status
        /// </summary>
        /// <param name="order"></param>
        /// <param name="paymentOption"></param>
        /// <param name="orderStatus"></param>
        /// <returns></returns>
        private string UpdateOrderStatus(Order order, PaymentOption paymentOption, string orderStatus)
        {
            // Create the string to return
            string error_message = "";

            // Get the current domain
            Domain domain = Tools.GetCurrentDomain();

            // Get webshop settings
            KeyStringList webshopSettings = WebshopSetting.GetAllFromCache();

            // Check the order status
            if (orderStatus == "order_status_delivered")
            {
                if(paymentOption.connection == 102) // Payson invoice
                {
                    // Get credentials
                    string paysonEmail = webshopSettings.Get("PAYSON-EMAIL");
                    string userId = webshopSettings.Get("PAYSON-AGENT-ID");
                    string md5Key = webshopSettings.Get("PAYSON-MD5-KEY");
                    bool paysonTest = false;
                    bool.TryParse(webshopSettings.Get("PAYSON-TEST"), out paysonTest);

                    // Create the api
                    PaysonIntegration.PaysonApi paysonApi = new PaysonIntegration.PaysonApi(userId, md5Key, null, paysonTest);

                    // Update the order
                    PaysonIntegration.Data.PaymentUpdateData paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.ShipOrder);
                    PaysonIntegration.Response.PaymentUpdateResponse paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData);

                    // Check if the response is successful
                    if (paymentUpdateResponse != null && paymentUpdateResponse.Success == false)
                    {
                        // Set error messages
                        foreach (string key in paymentUpdateResponse.ErrorMessages)
                        {
                            error_message += "&#149; " + "Payson: " + paymentUpdateResponse.ErrorMessages[key] + "<br/>";
                        }
                    }
                }
                else if(paymentOption.connection == 301) // Svea invoice
                {
                    // Get the order rows
                    List<OrderRow> orderRows = OrderRow.GetByOrderId(order.id);

                    // Create the payment configuration
                    SveaSettings sveaConfiguration = new SveaSettings();

                    // Create the order builder
                    Webpay.Integration.CSharp.Order.Handle.DeliverOrderBuilder inoviceBuilder = Webpay.Integration.CSharp.WebpayConnection.DeliverOrder(sveaConfiguration);

                    // Add order rows
                    for (int i = 0; i < orderRows.Count; i++)
                    {
                        // Get the unit
                        Unit unit = Unit.GetOneById(orderRows[i].unit_id, domain.back_end_language);

                        // Create an order item
                        Webpay.Integration.CSharp.Order.Row.OrderRowBuilder orderItem = new Webpay.Integration.CSharp.Order.Row.OrderRowBuilder();
                        orderItem.SetArticleNumber(orderRows[i].product_code);
                        orderItem.SetName(orderRows[i].product_name);
                        orderItem.SetQuantity(orderRows[i].quantity);
                        orderItem.SetUnit(unit.unit_code);
                        orderItem.SetAmountExVat(orderRows[i].unit_price);
                        orderItem.SetVatPercent(orderRows[i].vat_percent * 100);

                        // Add the order item
                        inoviceBuilder.AddOrderRow(orderItem);
                    }

                    // Get the order id
                    Int64 sveaOrderId = 0;
                    Int64.TryParse(order.payment_token, out sveaOrderId);

                    // Set invoice values
                    inoviceBuilder.SetOrderId(sveaOrderId);
                    inoviceBuilder.SetNumberOfCreditDays(15);
                    inoviceBuilder.SetInvoiceDistributionType(Webpay.Integration.CSharp.Util.Constant.InvoiceDistributionType.POST);
                    inoviceBuilder.SetCountryCode(SveaSettings.GetSveaCountryCode(order.country_code));

                    // Make the request to send the invoice
                    Webpay.Integration.CSharp.WebpayWS.DeliverOrderEuResponse deliverOrderResponse = inoviceBuilder.DeliverInvoiceOrder().DoRequest();
                    
                    // Check if the response is successful
                    if (deliverOrderResponse.Accepted == false)
                    {
                        // Set error messages
                        error_message += "&#149; " + "Svea code: " + deliverOrderResponse.ResultCode.ToString() + "<br/>";
                        error_message += "&#149; " + "Svea message: " + deliverOrderResponse.ErrorMessage + "<br/>";
                    }
                }
                else if (paymentOption.connection >= 400 && paymentOption.connection <= 499) // Payex
                {
                    // Check the transaction
                    Dictionary<string, string> payexResponse = PayExManager.CheckTransaction(order, webshopSettings);

                    // Get response variables
                    string error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : "";
                    string description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : "";
                    string parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : "";
                    string transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : "";
                    string transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : "";

                    // Check if the response was successful
                    if (error_code.ToUpper() == "OK")
                    {
                        if(transaction_status == "3") // Authorize
                        {
                            // Capture the transaction
                            payexResponse = PayExManager.CaptureTransaction(order);

                            // Get response variables
                            error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : "";
                            description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : "";
                            parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : "";
                            transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : "";
                            transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : "";
                            string transaction_number_original = payexResponse.ContainsKey("transaction_number_original") == true ? payexResponse["transaction_number_original"] : "";

                            if(error_code.ToUpper() != "OK" || transaction_status != "6")
                            {
                                // Set error messages
                                error_message += "&#149; " + "Payex code: " + error_code + "<br/>";
                                error_message += "&#149; " + "Payex message: " + description + "<br/>";
                                error_message += "&#149; " + "Payex parameter: " + parameter_name + "<br/>";
                                error_message += "&#149; " + "Payex status: " + transaction_status + "<br/>";
                                error_message += "&#149; " + "Payex number (original): " + transaction_number + "<br/>";
                            }
                            else
                            {
                                // Update the transaction number for the order
                                Order.SetPaymentToken(order.id, transaction_number);
                            }
                        }
                    }
                    else
                    {
                        // Set error messages
                        error_message += "&#149; " + "Payex code: " + error_code + "<br/>";
                        error_message += "&#149; " + "Payex message: " + description + "<br/>";
                        error_message += "&#149; " + "Payex parameter: " + parameter_name + "<br/>";
                        error_message += "&#149; " + "Payex status: " + transaction_status + "<br/>";
                        error_message += "&#149; " + "Payex number: " + transaction_number + "<br/>";
                    }
                }
            }
            else if (orderStatus == "order_status_cancelled")
            {
                if(paymentOption.connection >= 100 && paymentOption.connection <= 199) // Payson
                {
                    // Get credentials
                    string paysonEmail = webshopSettings.Get("PAYSON-EMAIL");
                    string userId = webshopSettings.Get("PAYSON-AGENT-ID");
                    string md5Key = webshopSettings.Get("PAYSON-MD5-KEY");
                    bool paysonTest = false;
                    bool.TryParse(webshopSettings.Get("PAYSON-TEST"), out paysonTest);

                    // Create the api
                    PaysonIntegration.PaysonApi paysonApi = new PaysonIntegration.PaysonApi(userId, md5Key, null, paysonTest);

                    // Get details about the payment status
                    PaysonIntegration.Response.PaymentDetailsResponse paysonResponse = paysonApi.MakePaymentDetailsRequest(new PaysonIntegration.Data.PaymentDetailsData(order.payment_token));

                    // Get the type and status of the payment
                    PaysonIntegration.Utils.PaymentType? paymentType = paysonResponse.PaymentDetails.PaymentType;
                    PaysonIntegration.Utils.PaymentStatus? paymentStatus = paysonResponse.PaymentDetails.PaymentStatus;
                    PaysonIntegration.Utils.InvoiceStatus? invoiceStatus = paysonResponse.PaymentDetails.InvoiceStatus;

                    // Payment update
                    PaysonIntegration.Data.PaymentUpdateData paymentUpdateData = null;
                    PaysonIntegration.Response.PaymentUpdateResponse paymentUpdateResponse = null;

                    if (paymentType == PaysonIntegration.Utils.PaymentType.Direct && paymentStatus == PaysonIntegration.Utils.PaymentStatus.Completed)
                    {
                        // Refund the payment
                        paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.Refund);
                        paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData);
                    }
                    else if (paymentType == PaysonIntegration.Utils.PaymentType.Invoice && invoiceStatus == PaysonIntegration.Utils.InvoiceStatus.OrderCreated)
                    {
                        // Cancel the order
                        paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.CancelOrder);
                        paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData);
                    }
                    else if (paymentType == PaysonIntegration.Utils.PaymentType.Invoice && (invoiceStatus == PaysonIntegration.Utils.InvoiceStatus.Shipped 
                        || invoiceStatus == PaysonIntegration.Utils.InvoiceStatus.Done))
                    {
                        // Credit the order
                        paymentUpdateData = new PaysonIntegration.Data.PaymentUpdateData(order.payment_token, PaysonIntegration.Utils.PaymentUpdateAction.CreditOrder);
                        paymentUpdateResponse = paysonApi.MakePaymentUpdateRequest(paymentUpdateData);
                    }

                    // Check if there was any errors
                    if (paymentUpdateResponse != null && paymentUpdateResponse.Success == false)
                    {
                        // Set error messages
                        foreach (string key in paymentUpdateResponse.ErrorMessages)
                        {
                            error_message += "&#149; " + "Payson: " + paymentUpdateResponse.ErrorMessages[key] + "<br/>";
                        }
                    }
                }
                else if(paymentOption.connection == 201) // PayPal
                {
                    // Get credentials
                    string paypalClientId = webshopSettings.Get("PAYPAL-CLIENT-ID");
                    string paypalClientSecret = webshopSettings.Get("PAYPAL-CLIENT-SECRET");
                    string paypalMode = webshopSettings.Get("PAYPAL-MODE");
                    Dictionary<string, string> config = new Dictionary<string, string> { { "mode", paypalMode } };

                    try
                    {
                        // Create the credential token
                        PayPal.OAuthTokenCredential tokenCredential = new PayPal.OAuthTokenCredential(paypalClientId, paypalClientSecret, config);

                        // Create the api context
                        PayPal.APIContext paypalContext = new PayPal.APIContext(tokenCredential.GetAccessToken());
                        paypalContext.Config = config;

                        // Look up the sale
                        PayPal.Api.Payments.Sale sale = PayPal.Api.Payments.Sale.Get(paypalContext, order.payment_token);

                        if (sale.state == "completed")
                        {
                            // Refund the payment
                            paypalContext.HTTPHeaders = null;
                            PayPal.Api.Payments.Refund refund = sale.Refund(paypalContext, new PayPal.Api.Payments.Refund());

                            if(refund.state != "completed")
                            {
                                error_message += "&#149; " + "PayPal: " + refund.state;
                            }
                        }
                        else
                        {
                            error_message += "&#149; " + "PayPal: " + sale.state;
                        }
                    }
                    catch (Exception ex)
                    {
                        error_message += "&#149; PayPal: " + ex.Message;
                    }
                }
                else if(paymentOption.connection == 301) // Svea invoice
                {
                    // Create the payment configuration
                    SveaSettings sveaConfiguration = new SveaSettings();

                    // Get the order id
                    Int64 sveaOrderId = 0;
                    Int64.TryParse(order.payment_token, out sveaOrderId);

                    // Cancel the order
                    Webpay.Integration.CSharp.Order.Handle.CloseOrderBuilder closeOrder = Webpay.Integration.CSharp.WebpayConnection.CloseOrder(sveaConfiguration);
                    closeOrder.SetOrderId(sveaOrderId);
                    closeOrder.SetCountryCode(SveaSettings.GetSveaCountryCode(order.country_code));
                    Webpay.Integration.CSharp.WebpayWS.CloseOrderEuResponse closeOrderResponse = closeOrder.CloseInvoiceOrder().DoRequest();

                    // Check if the response is successful
                    if (closeOrderResponse.Accepted == false)
                    {
                        // Set error messages
                        error_message += "&#149; " + "Svea code: " + closeOrderResponse.ResultCode.ToString() + "<br/>";
                        error_message += "&#149; " + "Svea message: " + closeOrderResponse.ErrorMessage + "<br/>";
                    }
                }
                else if(paymentOption.connection >= 400 && paymentOption.connection <= 499) // Payex
                {
                    // Check the transaction
                    Dictionary<string, string> payexResponse = PayExManager.CheckTransaction(order, webshopSettings);

                    // Get response variables
                    string error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : "";
                    string description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : "";
                    string parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : "";
                    string transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : "";
                    string transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : "";

                    // Check if the response was successful
                    if(error_code.ToUpper() == "OK")
                    {
                        // Check if we should cancel or credit the order
                        if(transaction_status == "3") // Authorize
                        {
                            // Cancel the transaction
                            payexResponse = PayExManager.CancelTransaction(order, webshopSettings);

                            // Get response variables
                            error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : "";
                            description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : "";
                            parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : "";
                            transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : "";
                            transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : "";

                            if(error_code.ToUpper() != "OK" || transaction_status != "4")
                            {
                                // Set error messages
                                error_message += "&#149; " + "Payex code: " + error_code + "<br/>";
                                error_message += "&#149; " + "Payex message: " + description + "<br/>";
                                error_message += "&#149; " + "Payex parameter: " + parameter_name + "<br/>";
                                error_message += "&#149; " + "Payex status: " + transaction_status + "<br/>";
                                error_message += "&#149; " + "Payex number: " + transaction_number + "<br/>";
                            }
                        }
                        else if(transaction_status == "0" || transaction_status == "6") // Sale or capture
                        {
                            // Get the order rows
                            List<OrderRow> orderRows = OrderRow.GetByOrderId(order.id);

                            // Credit the transaction
                            payexResponse = PayExManager.CreditTransaction(order, orderRows, webshopSettings);

                            // Get response variables
                            error_code = payexResponse.ContainsKey("error_code") == true ? payexResponse["error_code"] : "";
                            description = payexResponse.ContainsKey("description") == true ? payexResponse["description"] : "";
                            parameter_name = payexResponse.ContainsKey("parameter_name") == true ? payexResponse["parameter_name"] : "";
                            transaction_status = payexResponse.ContainsKey("transaction_status") == true ? payexResponse["transaction_status"] : "";
                            transaction_number = payexResponse.ContainsKey("transaction_number") == true ? payexResponse["transaction_number"] : "";

                            if (error_code.ToUpper() != "OK" || transaction_status != "2")
                            {
                                // Set error messages
                                error_message += "&#149; " + "Payex code: " + error_code + "<br/>";
                                error_message += "&#149; " + "Payex message: " + description + "<br/>";
                                error_message += "&#149; " + "Payex parameter: " + parameter_name + "<br/>";
                                error_message += "&#149; " + "Payex status: " + transaction_status + "<br/>";
                                error_message += "&#149; " + "Payex number: " + transaction_number + "<br/>";
                            }
                        }
                    }
                    else
                    {
                        // Set error messages
                        error_message += "&#149; " + "Payex code: " + error_code + "<br/>";
                        error_message += "&#149; " + "Payex message: " + description + "<br/>";
                        error_message += "&#149; " + "Payex parameter: " + parameter_name + "<br/>";
                        error_message += "&#149; " + "Payex status: " + transaction_status + "<br/>";
                        error_message += "&#149; " + "Payex number: " + transaction_number + "<br/>";
                    }
                }
            }

            // Return the error message
            return error_message;

        } // End of the UpdateOrderStatus method
        private Int32 AndNowItIsTimeToTalkToPayPal(Int32 productCost,
                                                   String productDescription,
                                                   String yourname,
                                               out String redirect_approvalUrlFromCreatedPayment)
        {
            // ................................
            //   Miscellaneous Error Messages from PayPal ... *****  "debug_id" is NOT a constant, examples:  "67f86e19d300d",  "36f998b61c785"
            String response_VALIDATION_ERROR =
            "{\"name\":\"VALIDATION_ERROR\",\"details\":[{\"field\":\"transactions[0].amount\",\"issue\":\"Required field missing\"}],\"message\":\"Invalid request - see details\",\"information_link\":\"https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR\",\"debug_id\":\"";
            Int32  response_VALIDATION_ERROR_Length = response_VALIDATION_ERROR.Length;
            // https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR
            // VALIDATION_ERROR
            // Invalid request                                - see details
            // There was a validation issue with your request - see details
            // ==> https://developer.paypal.com/webapps/developer/docs/api/#validation-issues

            // ................................
            String response_INTERNAL_SERVICE_ERROR =
                 "{\"name\":\"INTERNAL_SERVICE_ERROR\",\"message\":\"An internal service error has occurred\",\"information_link\":\"https://developer.paypal.com/webapps/developer/docs/api/#INTERNAL_SERVICE_ERROR\",\"debug_id\":\"";
            Int32  response_INTERNAL_SERVICE_ERROR_Length = response_INTERNAL_SERVICE_ERROR.Length;
            // https://developer.paypal.com/webapps/developer/docs/api/#INTERNAL_SERVICE_ERROR
            // INTERNAL_SERVICE_ERROR
            // An internal service error has occurred
            // Resend the request at another time. If this error continues,
            //      contact PayPal Merchant Technical Support.
            //      https://developer.paypal.com/webapps/developer/support

            // ................................
            Int32 payPalSuccessLevel = 999; // 999 =. unknown
            redirect_approvalUrlFromCreatedPayment = String.Empty;

            // THINGS WE NEED TO USE THE PAYPAL REST API
            String argumentsPlusPayPalClentID = "AU ... 6G"; // todo   ... your PayPal REST API SDK user ID
            String argumentsPlusPayPalSecret  = "EA ... -f"; // todo   ... your PayPal REST API SDK PASSWORD
            //          String payPalRestApiEndpoint      = "api.sandbox.paypal.com"; // For TESTING !!!
                                           // = "api.paypal.com";         // For LIVE    !!!
            // ................................
            Dictionary<String, String> sdkConfig = new Dictionary<String, String>();
            sdkConfig.Add("mode", "sandbox");
            // ................................
            // POTENTIAL POINT OF FAILURE
            // example:  "Exception in HttpConnection Execute: Invalid HTTP response The operation has timed out"
            String oAuthAccessTokenForPayPal = String.Empty; // scope outside of try/catch
            try
            {
                oAuthAccessTokenForPayPal
                    = new PayPal
                          .OAuthTokenCredential(argumentsPlusPayPalClentID,
                                                argumentsPlusPayPalSecret,
                                                sdkConfig).GetAccessToken();
            }                                          // .GetAccessToken takes us over to PayPal
            catch (Exception)
            {
                throw;  // todo ... make this code more robust
            }
            // ................................
            // We're back from PayPal with our access token.
            PayPal.APIContext apiContext // use the "Bearer" token from PayPal
                = new PayPal.APIContext(oAuthAccessTokenForPayPal);
            apiContext.Config = sdkConfig;
            // ................................
            PayPal.Api.Payments.Amount argumentsPlusPayPalPaymentAmount
                = new PayPal.Api.Payments.Amount();
            // https://developer.paypal.com/docs/classic/api/currency_codes/
            argumentsPlusPayPalPaymentAmount.currency = "GBP"; // UK Pound Sterling; "USD" for US$
            argumentsPlusPayPalPaymentAmount.total = productCost.ToString();
            // ................................
            String description = String.Empty; // 127 character maximum length
            description        = productDescription + " "
                               + DateTime.Now.ToLongDateString()
                               + " -- " + DateTime.Now.ToLongTimeString()
                               + " -- " + productCost + " U.K. pounds"
                               + " -- Thank you " + yourname
                               + " for your purchase.";
            // ................................
            // borrowed code from:  http://msdn.microsoft.com/en-us/library/xwewhkd1(v=vs.110).aspx
            // Regex.Replace Method (String, String)
            // ...  match ALL one or more white-space characters in our description text,
            //      replace EACH instance found with just one space.
            System.Text.RegularExpressions.Regex regexPattern
                        = new System.Text.RegularExpressions.Regex(@"\s+");
            description = regexPattern.Replace(description, " ");
            //  PayPal's HTML will drop extra whilespace, so we do not send any extra whitespace.
            // ................................
            PayPal.Api.Payments.Transaction argumentsSale
                = new PayPal.Api.Payments.Transaction();
            if (description.Length > 127) description = description.Substring(0, 127);
                                       // allow no more that 127 characters (PayPal's Limit)
            argumentsSale.description                 = description;
            argumentsSale.amount = argumentsPlusPayPalPaymentAmount;
            // ................................
            List<PayPal.Api.Payments.Transaction> transactionList
                = new List<PayPal.Api.Payments.Transaction>();
            transactionList.Add(argumentsSale);
            // ................................
            PayPal.Api.Payments.Payer argumentBuyer
                = new PayPal.Api.Payments.Payer();
            // The payment method "paypal" lets the customer choose
            // whether to pay us using a PayPal account
            // or to pay us with their credit card as a PayPal guest.
            argumentBuyer.payment_method        = "paypal";
            // ................................
            // Note:  we need some way to connect PayPal's response
            //        back to our customer ... TIMTOWTDI
            Guid reconnectToOurBuyer = Guid.NewGuid();
            PayPal.Api.Payments.RedirectUrls redirUrls
                = new PayPal.Api.Payments.RedirectUrls();
            String cancelURL = "http://localhost:53326/home/argumentsnotsold/"
                             + reconnectToOurBuyer.ToString("N");  // customer changes her/his mind
            String returnURL = "http://localhost:53326/home/argumentssold/"
                             + reconnectToOurBuyer.ToString("N");  // Hurrah!  A sale!
            redirUrls.cancel_url = cancelURL;
            redirUrls.return_url = returnURL;
            // ................................
            // Next, we create a Payment object to send to PayPal
            PayPal.Api.Payments.Payment getInvoiceFromPayPal = new PayPal.Api.Payments.Payment();
            getInvoiceFromPayPal.intent        = "sale";
            getInvoiceFromPayPal.payer         = argumentBuyer;
            getInvoiceFromPayPal.transactions  = transactionList;
            getInvoiceFromPayPal.redirect_urls = redirUrls;
            // ................................

            PayPal.Api.Payments.Payment createdInvoice = null; // scope outside of try/catch
            try
            {
                // the next line can fail, for example:  http://paradigmmentors.net//files/code/argumentsPlus/500_internal_Server_Error_catch.txt
                createdInvoice = getInvoiceFromPayPal.Create(apiContext); //  <==
                // SUCCESSFUL CREATION
                // we must persist createdInvoice.id (the Payment.id value)
                payPalSuccessLevel = 100; // successful
                SavePayPalInvoice(reconnectToOurBuyer, createdInvoice);
            }

            catch (PayPal.Exception.ConnectionException connectionExceptionPayPal)
             {
                 payPalSuccessLevel = 111;
                if(String.Compare(connectionExceptionPayPal.Message,
                    "Invalid HTTP response The remote server returned an error: (400) Bad Request.")
                   == 0)
                {
                    payPalSuccessLevel += 10000;
                    if(String.Compare(connectionExceptionPayPal.Response.Substring(0, response_VALIDATION_ERROR_Length),
                                      response_VALIDATION_ERROR) == 0)
                    {
                        // todo Take appropriate action
                    }
                    else
                    {
                        payPalSuccessLevel += 20000;
                        // todo Take appropriate action
                    }
                }
                else if(String.Compare(connectionExceptionPayPal.Message,
                    "Invalid HTTP response The remote server returned an error: (500) Internal Server Error.")
                   == 0)
                {
                    payPalSuccessLevel = 500;
                    if (String.Compare(connectionExceptionPayPal.Response.Substring(0, response_INTERNAL_SERVICE_ERROR_Length),
                                       response_INTERNAL_SERVICE_ERROR) == 0)
                    {
                        payPalSuccessLevel += 30000;
                        // todo Take appropriate action
                    }
                    else
                    {
                        payPalSuccessLevel += 40000;
                        // todo Take appropriate action
                    }
                }
                else
                {
                    payPalSuccessLevel = 666;
                    // todo Take appropriate action
                }
            //              throw;        // todo complete
            }
            catch (PayPal.Exception.PayPalException paypalException)
            {
                if (String.Compare(paypalException.Message,
                    "Exception in HttpConnection Execute: Invalid HTTP response The remote server returned an error: (500) Internal Server Error.")
                   == 0)
                {   // the "may" be an inner exception
                    payPalSuccessLevel = 777;
                    if (paypalException.InnerException != null) // we take a chance that the InnerException is PayPal.Exception.ConnectionException
                    {
                        try
                        {
                            PayPal.Exception.ConnectionException payPalInnerException = (PayPal.Exception.ConnectionException)paypalException.InnerException;
                            if (String.Compare(payPalInnerException.Response.Substring(0, response_INTERNAL_SERVICE_ERROR_Length),
                   response_INTERNAL_SERVICE_ERROR) == 0)
                            {
                                payPalSuccessLevel = 30777;       // fine tune our error code
                                // todo Take appropriate action
                            }
                            else
                            {
                                payPalSuccessLevel = 40777;       // fine tune our error code
                                // todo Take appropriate action
                            }
                        }
                        catch (Exception)
                        {
                            payPalSuccessLevel = 50777;           // fine tune our error code
                            // we probably guessed wrong
                            // todo ........... handle appropriately
                        }
                    }
                }
                else
                {
                    payPalSuccessLevel = 888;
                    // todo Take appropriate action
                }
                //              throw;        // todo complete
            }
            catch (Exception genericException)  // todo complete
            {
                // example causes:
                // (a) "No connection string named 'ArgumentPlusContext'
                //      could be found in the application config file."
                // (b) "Directory lookup for the file
                //      c:\argumentsPlus\argumentClinic.mdf\" failed
                //      with the operating system error
                //      The system cannot find the file specified.
                //         CREATE DATABASE failed.
                payPalSuccessLevel = 2222;
                // todo Take appropriate action
            }

            // ................................
            Boolean approval_url_found = false;
            if(payPalSuccessLevel == 100)
            {
                List<PayPal.Api.Payments.Links> linksFromCreatedPayment = createdInvoice.links;
                foreach (PayPal.Api.Payments.Links rel_approval in linksFromCreatedPayment)
                {
                    if (rel_approval.rel.ToLower().Equals("approval_url"))
                    {
                        redirect_approvalUrlFromCreatedPayment = Server.UrlDecode(rel_approval.href);
                        approval_url_found = true;
                        break;
                    }
                }
                if (!approval_url_found) payPalSuccessLevel = 69;
            }
            return payPalSuccessLevel;
        }
        public ActionResult ArgumentsSold(String id,      // your ID
                                          String token,   // PayPal token
                                          String PayerID)
        {
            String payment_id                   = String.Empty;
            String executeUrlFromCreatedPayment = String.Empty;
            // ................................
            //  ======>      // THINGS WE NEED TO USE THE PAYPAL REST API
            //  ======>      String argumentsPlusPayPalClentID = " ... your user ID for Arguments Plus ...";
            //  ======>      String argumentsPlusPayPalSecret  = " ... this is YOUR PASSWORD ...";
            String argumentsPlusPayPalClentID = "AU ... 6G"; // todo   ... your PayPal REST API SDK user ID
            String argumentsPlusPayPalSecret  = "EA ... -f"; // todo   ... your PayPal REST API SDK PASSWORD
            //  ======>      String payPalRestApiEndpoint      = "api.sandbox.paypal.com"; // For TESTING !!!
            //  ======>                                     // = "api.paypal.com";         // For LIVE    !!!
            Dictionary<String, String> sdkConfig = new Dictionary<String, String>();
            sdkConfig.Add("mode", "sandbox");
            // ................................
            // POTENTIAL POINT OF FAILURE
            // example:  "Exception in HttpConnection Execute: Invalid HTTP response The operation has timed out"
            String oAuthAccessTokenForPayPal = String.Empty; // scope outside of try/catch
            try
            {
                oAuthAccessTokenForPayPal = new PayPal.OAuthTokenCredential(argumentsPlusPayPalClentID,
                                                                            argumentsPlusPayPalSecret,
                                                                            sdkConfig).GetAccessToken();
            }                                                                      // .GetAccessToken takes us over to PayPal
            catch (Exception)
            {
                throw;  // todo ... make this code more robust
            }
            // ................................
            PayPal.APIContext apiContext = new PayPal.APIContext(oAuthAccessTokenForPayPal);
            apiContext.Config = sdkConfig;
            // ................................
            // id is our Guid for reconnecting to our customer's invoice
            PayPal.Api.Payments.Payment createdInvoice
                       = GetSavedPayPalInvoice(id);
            // ................................
            // now we convert the approved invoice into an actual payment
            PayPal.Api.Payments.Payment payment
                       = new PayPal.Api.Payments.Payment();
            payment.id = createdInvoice.id; // use the previously returned "invoice" identifier

            PayPal.Api.Payments.PaymentExecution askPayPalForMoney = new PayPal.Api.Payments.PaymentExecution();
            askPayPalForMoney.payer_id = PayerID; // from Query string ==> ?token=EC-3LN850372M719842K&PayerID=JJT6YSAZSFJTC
            PayPal.Api.Payments.Payment paidInvoice = null;  // scope outside of try/catch
            try
            {   //  an APPROVED PAYMENT morphs into a SALE !!!!!!!!!!!!!!!!!!!!!
                paidInvoice = payment.Execute(apiContext, askPayPalForMoney);  // off to PayPal
               		        // Here, if all has gone well, we're just right back from PayPal
                // and the money for the above invoice is now in our PayPal Merchant Account.
                ViewBag.PaidInvoice = paidInvoice;
             	}
            catch (PayPal.Exception.ConnectionException connectionExceptionPayPal)
            {
                if (String.Compare(connectionExceptionPayPal.Message,
                    "Invalid HTTP response The remote server returned an error: (400) Bad Request.")
                   == 0)
                {
                    String response_PAYMENT_STATE_INVALID =
                             "{\"name\":\"PAYMENT_STATE_INVALID\",\"message\":\"This request is invalid due to the current state of the payment\",\"information_link\":\"https://developer.paypal.com/webapps/developer/docs/api/#PAYMENT_STATE_INVALID\",\"debug_id\":\"";
                    Int32  response_PAYMENT_STATE_INVALID_Length = response_PAYMENT_STATE_INVALID.Length;
                    if (String.Compare(connectionExceptionPayPal.Response.Substring(0,response_PAYMENT_STATE_INVALID_Length),
                                       response_PAYMENT_STATE_INVALID) == 0)
                    {
                        // todo Take appropriate action
                    }
                    else
                    {
                        // todo Take appropriate action
                    }
                }
                else
                {
                    // todo Take appropriate action
                }
                throw;        // todo complete this code ... for PRODUCTION, more robustness is a must!
            }
             	catch (Exception generalExceptionGettingMoney)
             	{
             		throw;  // todo ... deal with this error appropriately ("throw" is not appropriate)
             	}
            // ................................
            // PayPal has provided data -- we capture as much or as little as when require.
            // We can save the PayPal data and/or display it on our web page, et cetera.
            // Remember:  respect your customers' privacy.  Protect their data.

            String payment_state    = String.Empty;       // N.B.:  this is NOT the province/state/region
            payment_state           = paidInvoice.state;  // Possible Values:  pending, approved
            ViewBag.Payment_State   = payment_state;

            String payment_intent   = String.Empty;
            payment_intent          = paidInvoice.intent;  // Expected Value:  "sale"
            ViewBag.Payment_Intent  = payment_intent;

            String payment_method   = String.Empty;
            payment_method          = paidInvoice.payer.payment_method;  // Expected Value:  "paypal"
            ViewBag.Payment_Method  = payment_method;

            String parent_payment = String.Empty;
            parent_payment          = paidInvoice.transactions[0].related_resources[0].sale.parent_payment;
            ViewBag.Parent_Payment  = parent_payment;

            String update_time      = String.Empty;
            update_time             = paidInvoice.update_time; // "2014-02-05T04:06:39Z"     string
            ViewBag.Update_Time     = update_time;

            String create_time      = String.Empty;
            create_time             = paidInvoice.create_time; // "2014-02-05T04:06:39Z"     string
            ViewBag.Create_Time     = create_time;

            // ................................
            String payPal_email_address  = String.Empty;  //  paidInvoice::email  "*****@*****.**"  string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.email))
                payPal_email_address     = paidInvoice.payer.payer_info.email;
            ViewBag.PayPal_Email_Address = payPal_email_address;

            String payPal_first_name     = String.Empty;  //  paidInvoice::first_name	"gerry"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.first_name))
                payPal_first_name        = paidInvoice.payer.payer_info.first_name;
            ViewBag.PayPal_First_Name    = payPal_first_name;

            String payPal_last_name      = String.Empty;  //  paidInvoice::last_name	"lowry"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.last_name))
                payPal_last_name         = paidInvoice.payer.payer_info.last_name;
            ViewBag.PayPal_Last_Name     = payPal_last_name;

            String payPal_phone  = String.Empty;  //  paidInvoice::phone null string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.phone))
                payPal_phone     = paidInvoice.payer.payer_info.phone;
            ViewBag.PayPal_Phone = payPal_phone;

            String payPal_city = String.Empty;  //  paidInvoice::city	"SAN Jose"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.city))
                payPal_city    = paidInvoice.payer.payer_info.shipping_address.city;
            ViewBag.City       = payPal_city;

            String payPal_country_code  = String.Empty;  //  paidInvoice::country_code	"US"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.country_code))
                payPal_country_code     = paidInvoice.payer.payer_info.shipping_address.country_code;
            ViewBag.PayPal_Country_Code = payPal_country_code;

            String payPal_address_line1  = String.Empty;  //  paidInvoice::line1	"1 Main St"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.line1))
                payPal_address_line1     = paidInvoice.payer.payer_info.shipping_address.line1;
            ViewBag.PayPal_Address_Line1 = payPal_address_line1;

            String payPal_address_line2  = String.Empty;  //  paidInvoice::line2	null	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.line2))
                payPal_address_line2     = paidInvoice.payer.payer_info.shipping_address.line2;
            ViewBag.PayPal_Address_Line2 = payPal_address_line2;

            String payPal_postal_code  = String.Empty;  //  paidInvoice::postal_code	"95131"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.postal_code))
                payPal_postal_code     = paidInvoice.payer.payer_info.shipping_address.postal_code;
            ViewBag.PayPal_Postal_Code = payPal_postal_code;

            String payPal_address_state  = String.Empty;  //  paidInvoice::state	"CA"	string
            if (!String.IsNullOrWhiteSpace(paidInvoice.payer.payer_info.shipping_address.state))
                payPal_address_state     = paidInvoice.payer.payer_info.shipping_address.state;
            ViewBag.PayPal_Address_State = payPal_address_state;

            // ................................
            String payPal_transaction_amount_total  = String.Empty;  //  paidInvoice::transation[0].amount" string
            if (!String.IsNullOrWhiteSpace(paidInvoice.transactions[0].amount.total))
                payPal_transaction_amount_total     = paidInvoice.transactions[0].amount.total;
            ViewBag.PayPal_Transaction_Amount_Total = payPal_transaction_amount_total;

            String payPal_transaction_amount_currency  = String.Empty;  //  paidInvoice::transation[0].amount" string
            if (!String.IsNullOrWhiteSpace(paidInvoice.transactions[0].amount.total))
                payPal_transaction_amount_currency     = paidInvoice.transactions[0].amount.currency;
            ViewBag.PayPal_Transaction_Amount_Currency = payPal_transaction_amount_currency;

            String payPal_transaction_descripition = String.Empty;  //  paidInvoice::transation[0].amount" string
            if (!String.IsNullOrWhiteSpace(paidInvoice.transactions[0].amount.total))
                payPal_transaction_descripition = paidInvoice.transactions[0].description;
            ViewBag.PayPal_Transaction_Description = payPal_transaction_descripition;
            // ................................
            return View();
        }