public int?GetOrderIdForTransactionToken(string payPalToken)
        {
            PaymentTransaction paymentTransaction = PaymentTransaction.GetMostRecentByTransactionId(payPalToken);

            if (paymentTransaction != null)
            {
                return(paymentTransaction.OrderId);
            }
            return(null);
        }
        public override PaymentStatusName ProcessOffsitePaymentResponse(Order order, HttpRequest request)
        {
            //---- Need to validate the incoming request with PayPal so we know it's authentic
            Dictionary <string, string> requestParams = HttpHelper.DecodeParamsFromHttpRequest(request);
            string requestDataString = HttpHelper.EncodeVarsForHttpPostString(requestParams);

            // send our modified request back to PayPal for validation
            string          postData       = requestDataString + "&cmd=_notify-validate";
            HttpWebResponse payPalResponse = HttpHelper.HttpPost(ProviderUrl, postData);

            string payPalResponseString = HttpHelper.WebResponseToString(payPalResponse);

            // Parse response into some variables
            NameValueCollection fields = request.Params;
            string paymentStatus       = fields["payment_status"];
            string transactionId       = fields["txn_id"];
            string receiverEmail       = fields["receiver_email"];
            string businessEmail       = fields["business"];

            int?    orderId              = WA.Parser.ToInt(fields["custom"]);
            decimal?paymentAmount        = WA.Parser.ToDecimal(fields["mc_gross"]); // amount before PayPal fee is subtracted
            decimal?payPalTransactionFee = WA.Parser.ToDecimal(fields["mc_fee"]);
            decimal shippingAmount       = WA.Parser.ToDecimal(fields["mc_shipping"]).GetValueOrDefault(0);
            decimal handlingAmount       = WA.Parser.ToDecimal(fields["mc_handling"]).GetValueOrDefault(0);
            decimal taxAmount            = WA.Parser.ToDecimal(fields["tax"]).GetValueOrDefault(0);

            string firstName = fields["first_name"] ?? "";
            string lastName  = fields["last_name"] ?? "";
            string email     = fields["payer_email"] ?? "";
            string phone     = fields["contact_phone"] ?? "";

            string shipName        = fields["address_name"] ?? "";
            string shipAddress1    = fields["address_street"] ?? "";
            string shipCity        = fields["address_city"] ?? "";
            string shipRegion      = fields["address_state"] ?? "";
            string shipPostalCode  = fields["address_zip"] ?? "";
            string shipCountryCode = fields["address_country_code"] ?? "";

            PaymentStatusName paymentStatusName = order.PaymentStatus;
            bool isValidReceiverEmail           = (receiverEmail == EmailAddress) || (businessEmail == EmailAddress);

            PaymentTransaction newTransaction = new PaymentTransaction();

            newTransaction.OrderId              = orderId;
            newTransaction.PaymentProviderId    = this.ProviderId;
            newTransaction.GatewayUrl           = ProviderUrl;
            newTransaction.GatewayTransactionId = transactionId;
            newTransaction.GatewayResponse      = paymentStatus;
            newTransaction.GatewayDebugResponse = requestDataString;
            newTransaction.Amount = paymentAmount;

            if (payPalResponseString != "VERIFIED")
            {
                newTransaction.GatewayError = "Invalid/Unknown response or response could not be validated as authentic";
                newTransaction.Save();

                return(PaymentStatusName.ProviderError);
            }
            if (!isValidReceiverEmail)
            {
                newTransaction.GatewayError = "Receiver Email does not match PayPal Account";
                newTransaction.Save();

                return(PaymentStatusName.ProviderError);
            }

            //Order pendingOrder = Order.GetOrder(orderId);
            if (payPalResponseString == "VERIFIED")
            {
                // check if we have already processed this transaction successfully
                // we might already have processed the IPN callback, and the user clicks "return to store"
                // which would trigger another transaction
                PaymentTransaction priorTransaction = PaymentTransaction.GetMostRecentByTransactionId(transactionId);
                if (priorTransaction != null && priorTransaction.OrderId == orderId)
                {
                    // we have a duplicate transaction, we should NOT process this new one
                    return(order.PaymentStatus);
                }

                //check the payment_status is Completed
                bool paymentStatusComplete = (paymentStatus.ToLower() == "completed");

                if (paymentAmount.GetValueOrDefault(-1) < order.Total.Value)
                {
                    newTransaction.GatewayError = string.Format("Payment amount does not match Order Total. Order total {0:N2}. Payment amount {1:N2}", order.Total, paymentAmount);
                    newTransaction.Save();
                    return(PaymentStatusName.ProviderError);
                }

                //if (paymentStatusComplete && paymentAmountMatches && receiverEmailMatches)
                if (paymentStatusComplete)
                {
                    newTransaction.GatewayResponse = "Verified Payment Completed";
                    if (request.RawUrl.Contains("PayPalIpnHandler.aspx"))
                    {
                        newTransaction.GatewayResponse += " via IPN";
                    }
                    else if (request.RawUrl.Contains("Checkout-Complete.aspx"))
                    {
                        newTransaction.GatewayResponse += " via return button from PayPal";
                    }
                    paymentStatusName = PaymentStatusName.Completed;

                    //---- Update the Order
                    order.CustomerFirstName = firstName;
                    order.CustomerLastName  = lastName;
                    order.CustomerEmail     = email;

                    order.ShipRecipientName = shipName;
                    order.ShipAddress1      = shipAddress1;
                    //order.ShipAddress2 = shipAddress2;
                    order.ShipCity        = shipCity;
                    order.ShipRegion      = shipRegion;
                    order.ShipPostalCode  = shipPostalCode;
                    order.ShipCountryCode = shipCountryCode;
                    order.ShipTelephone   = phone;

                    order.BillAddress1 = shipAddress1;
                    //order.BillAddress2 = shipAddress2;
                    order.BillCity        = shipCity;
                    order.BillRegion      = shipRegion;
                    order.BillPostalCode  = shipPostalCode;
                    order.BillCountryCode = shipCountryCode;
                    order.BillTelephone   = phone;

                    // PayPal 'paymentAmount' is the total amount paid by customer
                    // so we need to do some basic math to get the other order amounts...
                    order.ShippingAmount = shippingAmount + handlingAmount;
                    order.TaxAmount      = taxAmount;
                    order.SubTotal       = paymentAmount - (order.ShippingAmount + order.TaxAmount);
                    order.Total          = paymentAmount;

                    order.Save();
                }
                newTransaction.Save();
            }

            return(paymentStatusName);
        }