public override void HandleOrderStateChangeNotification(
            string requestXml,
            OrderStateChangeNotification notification)
        {
            GoogleCheckoutLog gLog = new GoogleCheckoutLog();

            Guid orderGuid = GoogleCheckoutLog.GetCartGuidFromOrderNumber(notification.googleordernumber);

            gLog.RawResponse = requestXml;
            gLog.NotificationType = "OrderStateChangeNotification";
            gLog.ProviderName = "WebStoreGCheckoutNotificationHandlerProvider";
            gLog.SerialNumber = notification.serialnumber;
            gLog.OrderNumber = notification.googleordernumber;
            gLog.FinanceState = notification.newfinancialorderstate.ToString();
            gLog.FullfillState = notification.newfulfillmentorderstate.ToString();
            gLog.GTimestamp = notification.timestamp;
            gLog.AvsResponse = notification.reason;
            gLog.CartGuid = orderGuid;
            gLog.Save();

            if (orderGuid == Guid.Empty) return;

            Order order = new Order(orderGuid);
            if (order.OrderGuid != orderGuid) return;

            Store store = new Store(order.StoreGuid);
            if (store.Guid != order.StoreGuid) return;

            gLog.SiteGuid = store.SiteGuid;
            gLog.UserGuid = order.UserGuid;
            gLog.CartGuid = order.OrderGuid;
            gLog.StoreGuid = order.StoreGuid;
            gLog.Save();

            if (notification.newfinancialorderstate == FinancialOrderState.CHARGED)
            {
                order.StatusGuid = OrderStatus.OrderStatusFulfillableGuid;
                order.Save();

                if (!order.HasShippingProducts())
                {
                    // order only has download products so tell google the order is fulfilled

                    try
                    {
                        CommerceConfiguration commerceConfig = SiteUtils.GetCommerceConfig();

                        string gEvironment;
                        if (commerceConfig.GoogleEnvironment == GCheckout.EnvironmentType.Sandbox)
                        {
                            gEvironment = "Sandbox";
                        }
                        else
                        {
                            gEvironment = "Production";
                        }

                        GCheckout.OrderProcessing.DeliverOrderRequest fulfillNotification
                            = new GCheckout.OrderProcessing.DeliverOrderRequest(
                                commerceConfig.GoogleMerchantID,
                                commerceConfig.GoogleMerchantKey,
                                gEvironment,
                                notification.googleordernumber);

                        fulfillNotification.Send();

                        StoreHelper.ConfirmOrder(store, order);
                        PayPalLog.DeleteByCart(order.OrderGuid);

                        log.Info("Sent DeliverOrderRequest to google api for google order " + notification.googleordernumber);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex);
                    }
                }

            }
        }
        /// <summary>
        /// return true if the transaction was processed with no problems
        /// </summary>
        /// <param name="context"></param>
        /// <param name="transactionId"></param>
        /// <param name="orderId"></param>
        /// <param name="grossAmount"></param>
        /// <param name="standardCheckoutLog"></param>
        /// <returns></returns>
        public override bool HandleRequest(
            string transactionId,
            NameValueCollection form,
            PayPalLog standardCheckoutLog)
        {
            bool result = false;

            if (standardCheckoutLog.SerializedObject.Length == 0) { return result; }

            Cart cart = (Cart)SerializationHelper.DeserializeFromString(typeof(Cart), standardCheckoutLog.SerializedObject);

            Store store = new Store(cart.StoreGuid);
            SiteSettings siteSettings = new SiteSettings(store.SiteGuid);

            bool debugPayPal = WebConfigSettings.DebugPayPal;

            //mc_gross=5.00
            //&address_status=confirmed
            //&item_number1=d28a6bed-7e51-4f18-a893-77b4d5665a64
            //&payer_id=zzzzzz
            //&tax=0.00
            //&address_street=nnnn
            //&payment_date=10%3A08%3A08+Jul+29%2C+2008+PDT
            //&payment_status=Completed
            //&charset=windows-1252
            //&address_zip=92843
            //&mc_shipping=0.00
            //&mc_handling=0.00
            //&first_name=zz
            //&mc_fee=0.45
            //&address_country_code=US
            //&address_name=zzzz
            //&notify_version=2.4
            //&custom=d9ef5324-2201-4749-b06a-9bba7a9dce61
            //&payer_status=verified
            //&business=sales%40mojoportal.com
            //&address_country=United+States
            //&num_cart_items=1
            //&mc_handling1=0.00
            //&address_city=nnnn
            //&verify_sign=
            //&payer_email=zzzzzz
            //&mc_shipping1=0.00
            //&tax1=0.00
            //&txn_id=81Y88484JA1416221
            //&payment_type=instant
            //&payer_business_name=EBShoes
            //&last_name=Ngo
            //&address_state=CA
            //&item_name1=Buy+Joe+a+Beer
            //&receiver_email=sales%40mojoportal.com
            //&payment_fee=0.45
            //&quantity1=1
            //&receiver_id=nnnn
            //&txn_type=cart
            //&mc_gross_1=5.00
            //&mc_currency=USD
            //&residence_country=US
            //&payment_gross=5.00

            string firstName = string.Empty;
            if (form["first_name"] != null)
            {
                firstName = form["first_name"].ToString();
            }

            string lastName = string.Empty;
            if (form["last_name"] != null)
            {
                lastName = form["last_name"].ToString();
            }

            string paymentStatus = string.Empty;
            if (form["payment_status"] != null)
            {
                paymentStatus = form["payment_status"].ToString();
            }

            string payerEmail = string.Empty;
            if (form["payer_email"] != null)
            {
                payerEmail = form["payer_email"].ToString();
            }

            string paymentGross = string.Empty;
            if (form["mc_gross"] != null)
            {
                paymentGross = form["mc_gross"].ToString();
            }

            string payPalFee = string.Empty;
            if (form["mc_fee"] != null)
            {
                payPalFee = form["mc_fee"].ToString();
            }

            string payPalTax = string.Empty;
            if (form["tax"] != null)
            {
                payPalTax = form["tax"].ToString();
            }

            string payPalShipping = string.Empty;
            if (form["mc_shipping"] != null)
            {
                payPalShipping = form["mc_shipping"].ToString();
            }

            string currencyUsed = string.Empty;
            if (form["mc_currency"] != null)
            {
                currencyUsed = form["mc_currency"].ToString();
            }

            string pendingReason = string.Empty;
            if (form["pending_reason"] != null)
            {
                pendingReason = form["pending_reason"].ToString();
            }

            string reasonCode = string.Empty;
            if (form["reason_code"] != null)
            {
                reasonCode = form["reason_code"].ToString();
            }

            string paymentType = string.Empty;
            if (form["txn_type"] != null)
            {
                paymentType = form["txn_type"].ToString();
            }

            string payPalSettlement = "0";
            if (form["settle_amount"] != null)
            {
                payPalSettlement = form["settle_amount"].ToString();
            }

            string customerAddress = string.Empty;
            if (form["address_street"] != null)
            {
                customerAddress = form["address_street"].ToString();
            }

            string customerCity = string.Empty;
            if (form["address_city"] != null)
            {
                customerCity = form["address_city"].ToString();
            }

            string customerState = string.Empty;
            if (form["address_state"] != null)
            {
                customerState = form["address_state"].ToString();
            }

            string customerPostalCode = string.Empty;
            if (form["address_zip"] != null)
            {
                customerPostalCode = form["address_zip"].ToString();
            }

            string customerCountry = string.Empty;
            if (form["address_country"] != null)
            {
                customerCountry = form["address_country"].ToString();
            }

            string customerPhone = string.Empty;
            if (form["contact_phone"] != null)
            {
                customerPhone = form["contact_phone"].ToString();
            }

            string customerBusinessName = string.Empty;
            if (form["payer_business_name"] != null)
            {
                customerBusinessName = form["payer_business_name"].ToString();
            }

            // TODO: we need to store this somewhere on the cart/order
            // its the message the user enters in special instructions on paypal checkout
            string customerMemo = string.Empty;
            if (form["memo"] != null)
            {
                customerMemo = form["memo"].ToString();
            }

            if (debugPayPal) { log.Info("PayPal currencyUsed was " + currencyUsed); }

            //Regardless of the specified currency, the format will have decimal point
            //with exactly two digits to the right and an optional thousands separator to the left,
            //which must be a comma; for example, EUR 2.000,00 must be specified as 2000.00 or 2,000.00
            // So we want to parse it with US Culture

            CultureInfo currencyCulture = new CultureInfo("en-US");
            //if (currencyUsed.Length > 0)
            //{
            //    currencyCulture = ResourceHelper.GetCurrencyCulture(currencyUsed);
            //}
            //else
            //{
            //    //Currency currency = new Currency(store.DefaultCurrencyId);
            //    //currencyCulture = ResourceHelper.GetCurrencyCulture(currency.Code);
            //    Currency currency = siteSettings.GetCurrency();
            //    currencyCulture = ResourceHelper.GetCurrencyCulture(currency.Code);
            //    currencyUsed = currency.Code;
            //}

            //if (debugPayPal) { log.Info("PayPal final currency culture was " + currencyUsed); }

            decimal grossAmount = 0;
            decimal.TryParse(paymentGross, NumberStyles.Currency, currencyCulture, out grossAmount);
            decimal feeAmount = 0;
            decimal.TryParse(payPalFee, NumberStyles.Currency, currencyCulture, out feeAmount);
            decimal taxAmount = 0;
            decimal.TryParse(payPalTax, NumberStyles.Currency, currencyCulture, out taxAmount);
            decimal shippingAmount = 0;
            decimal.TryParse(payPalShipping, NumberStyles.Currency, currencyCulture, out shippingAmount);
            decimal settleAmount = 0;
            decimal.TryParse(payPalSettlement, NumberStyles.Currency, currencyCulture, out settleAmount);

            if (debugPayPal)
            {
                log.Info("PayPal paymentGross was " + paymentGross + " which was parsed as " + grossAmount.ToString());
                log.Info("PayPal payPalFee was " + payPalFee + " which was parsed as " + feeAmount.ToString());
                log.Info("PayPal payPalTax was " + payPalTax + " which was parsed as " + taxAmount.ToString());
                log.Info("PayPal payPalShipping was " + payPalShipping + " which was parsed as " + shippingAmount.ToString());
                log.Info("PayPal payPalSettlement was " + payPalSettlement + " which was parsed as " + settleAmount.ToString());

            }

            PayPalLog payPalLog = new PayPalLog();
            payPalLog.PDTProviderName = standardCheckoutLog.PDTProviderName;
            payPalLog.IPNProviderName = standardCheckoutLog.IPNProviderName;
            payPalLog.ReturnUrl = standardCheckoutLog.ReturnUrl;
            payPalLog.ProviderName = standardCheckoutLog.ProviderName;
            payPalLog.SiteGuid = standardCheckoutLog.SiteGuid;
            payPalLog.StoreGuid = standardCheckoutLog.StoreGuid;
            payPalLog.UserGuid = standardCheckoutLog.UserGuid;
            payPalLog.ApiVersion = standardCheckoutLog.ApiVersion;
            payPalLog.CartGuid = standardCheckoutLog.CartGuid;
            payPalLog.SerializedObject = standardCheckoutLog.SerializedObject;
            payPalLog.CartTotal = grossAmount;
            payPalLog.PayPalAmt = feeAmount;
            if (settleAmount > 0)
            {
                payPalLog.SettleAmt = settleAmount;
            }
            else
            {
                payPalLog.SettleAmt = (grossAmount - feeAmount);
            }
            payPalLog.TaxAmt = taxAmount;
            payPalLog.CurrencyCode = currencyUsed;
            payPalLog.TransactionId = transactionId;
            payPalLog.RawResponse = form.ToString();
            payPalLog.Response = "IPNSuccess";
            payPalLog.RequestType = "IPN";
            payPalLog.PayerId = payerEmail;
            payPalLog.PaymentType = paymentType;
            payPalLog.PaymentStatus = paymentStatus;
            payPalLog.PendingReason = pendingReason;
            payPalLog.ReasonCode = reasonCode;
            payPalLog.Save();

            // see if this cart has already been proceesed
            Order existingOrder = new Order(cart.CartGuid);
            // order already exists
            if (existingOrder.OrderGuid != Guid.Empty)
            {
                // lookup order status if needed make it fullfillable
                // then redirect to order detail page
                if (existingOrder.StatusGuid == OrderStatus.OrderStatusReceivedGuid)
                {
                    if (paymentStatus == "Completed")
                    {
                        existingOrder.StatusGuid = OrderStatus.OrderStatusFulfillableGuid;

                        existingOrder.Save();

                        try
                        {
                            StoreHelper.ConfirmOrder(store, existingOrder);
                            GoogleCheckoutLog.DeleteByCart(existingOrder.OrderGuid);
                        }
                        catch (Exception ex)
                        {
                            log.Error("error sending confirmation email", ex);
                        }
                    }

                }

                result = true;

                payPalLog.ReasonCode = "existing order found";
                payPalLog.Save();

                return result;
            }

            // if we get here the cart has not yet been processed into an order
            cart.DeSerializeCartOffers();

            Guid orderStatus;
            if (paymentStatus == "Completed")
            {
                orderStatus = OrderStatus.OrderStatusFulfillableGuid;
            }
            else
            {
                orderStatus = OrderStatus.OrderStatusReceivedGuid;
            }

            // update the order with customer shipping info
            cart.OrderInfo.DeliveryCompany = customerBusinessName;
            cart.OrderInfo.DeliveryAddress1 = customerAddress;

            cart.OrderInfo.DeliveryCity = customerCity;
            cart.OrderInfo.DeliveryFirstName = firstName;
            cart.OrderInfo.DeliveryLastName = lastName;
            cart.OrderInfo.DeliveryPostalCode = customerPostalCode;
            cart.OrderInfo.DeliveryState = customerState;
            cart.OrderInfo.DeliveryCountry = customerCountry;

            if (customerPhone.Length > 0)
            {
                cart.OrderInfo.CustomerTelephoneDay = customerPhone;
            }

            if (payerEmail.Length > 0)
            {
                cart.OrderInfo.CustomerEmail = payerEmail;
            }

            cart.CopyShippingToBilling();
            cart.CopyShippingToCustomer();
            cart.TaxTotal = taxAmount;
            cart.OrderTotal = grossAmount;
            if (shippingAmount > 0)
            {
                cart.ShippingTotal = shippingAmount;
            }

            StoreHelper.EnsureUserForOrder(cart);

            cart.Save();

            cart.SerializeCartOffers();
            payPalLog.SerializedObject = SerializationHelper.SerializeToString(cart);
            payPalLog.Save();

            Order order = Order.CreateOrder(
                store,
                cart,
                transactionId,
                transactionId,
                string.Empty,
                currencyUsed,
                "PayPal",
                orderStatus);

            if (orderStatus == OrderStatus.OrderStatusFulfillableGuid)
            {
                try
                {
                    StoreHelper.ConfirmOrder(store, order);
                    GoogleCheckoutLog.DeleteByCart(order.OrderGuid);
                }
                catch (Exception ex)
                {
                    log.Error("error sending confirmation email", ex);
                }
            }

            if (orderStatus == OrderStatus.OrderStatusReceivedGuid)
            {
                StoreHelper.ConfirmOrderReceived(store, order);
            }

            result = true;

            return result;
        }
Пример #3
0
        public static Order CreateOrder(
            Store store,
            Cart cart, 
            string gatewayRawResponse,
            string gatewayTransactionId,
            string gatewayApprovalCode,
            string currencyCode,
            string paymentMethod,
            Guid orderStatusGuid)
        {
            Order order = new Order(cart.CartGuid);

            order.billingAddress1 = cart.OrderInfo.BillingAddress1;
            order.billingAddress2 = cart.OrderInfo.BillingAddress2;
            order.billingCity = cart.OrderInfo.BillingCity;
            order.billingCompany = cart.OrderInfo.BillingCompany;
            order.billingCountry = cart.OrderInfo.BillingCountry;
            order.billingFirstName = cart.OrderInfo.BillingFirstName;
            order.billingLastName = cart.OrderInfo.BillingLastName;
            order.billingPostalCode = cart.OrderInfo.BillingPostalCode;
            order.billingState = cart.OrderInfo.BillingState;
            order.billingSuburb = cart.OrderInfo.BillingSuburb;

            order.completed = cart.OrderInfo.Completed;
            order.completedFromIP = cart.OrderInfo.CompletedFromIP;
            order.created = DateTime.UtcNow;
            order.createdFromIP = cart.OrderInfo.CompletedFromIP;

            order.customerAddressLine1 = cart.OrderInfo.CustomerAddressLine1;
            order.customerAddressLine2 = cart.OrderInfo.CustomerAddressLine2;
            order.customerCity = cart.OrderInfo.CustomerCity;
            order.customerCompany = cart.OrderInfo.CustomerCompany;
            order.customerCountry = cart.OrderInfo.CustomerCountry;
            order.customerEmail = cart.OrderInfo.CustomerEmail;
            order.customerEmailVerified = cart.OrderInfo.CustomerEmailVerified;
            order.customerFirstName = cart.OrderInfo.CustomerFirstName;
            order.customerLastName = cart.OrderInfo.CustomerLastName;
            order.customerPostalCode = cart.OrderInfo.CustomerPostalCode;
            order.customerState = cart.OrderInfo.CustomerState;
            order.customerSuburb = cart.OrderInfo.CustomerSuburb;
            order.customerTelephoneDay = cart.OrderInfo.CustomerTelephoneDay;
            order.customerTelephoneNight = cart.OrderInfo.CustomerTelephoneNight;

            order.deliveryAddress1 = cart.OrderInfo.DeliveryAddress1;
            order.deliveryAddress2 = cart.OrderInfo.DeliveryAddress2;
            order.deliveryCity = cart.OrderInfo.DeliveryCity;
            order.deliveryCompany = cart.OrderInfo.DeliveryCompany;
            order.deliveryCountry = cart.OrderInfo.DeliveryCountry;
            order.deliveryFirstName = cart.OrderInfo.DeliveryFirstName;
            order.deliveryLastName = cart.OrderInfo.DeliveryLastName;
            order.deliveryPostalCode = cart.OrderInfo.DeliveryPostalCode;
            order.deliveryState = cart.OrderInfo.DeliveryState;
            order.deliverySuburb = cart.OrderInfo.DeliverySuburb;

            order.gatewayAuthCode = gatewayApprovalCode;
            order.gatewayRawResponse = gatewayRawResponse;
            order.gatewayTransID = gatewayTransactionId;

            order.lastModified = DateTime.UtcNow;
            order.lastUserActivity = cart.LastUserActivity;

            order.orderGuid = cart.CartGuid;

            order.OrderTotal = cart.OrderTotal;
            order.statusGuid = orderStatusGuid;

            order.storeGuid = cart.StoreGuid;
            order.clerkGuid = cart.ClerkGuid;
            order.subTotal = cart.SubTotal;
            order.taxTotal = cart.TaxTotal;
            order.discount = cart.Discount;
            order.shippingTotal = cart.ShippingTotal;
            order.taxZoneGuid = cart.OrderInfo.TaxZoneGuid;
            order.userGuid = cart.UserGuid;
            order.discountCodesCsv = cart.DiscountCodesCsv;
            order.customData = cart.CustomData;

            order.Save();

            // TODO: need to add this in insert so we don't have to save 2x
            order.paymentMethod = paymentMethod;
            order.Save();

            foreach (CartOffer cartOffer in cart.CartOffers)
            {
                OrderOffer orderOffer = new OrderOffer();
                orderOffer.AddedToCart = cartOffer.AddedToCart;
                //orderOffer.CurrencyGuid = cartOffer.CurrencyGuid;
                orderOffer.OfferGuid = cartOffer.OfferGuid;
                orderOffer.OfferPrice = cartOffer.OfferPrice;
                orderOffer.OrderGuid = order.OrderGuid;
                //orderOffer.PriceGuid = cartOffer.PriceGuid;
                orderOffer.Quantity = cartOffer.Quantity;
                orderOffer.TaxClassGuid = cartOffer.TaxClassGuid;
                orderOffer.Save();

                Collection<OfferProduct> offerProducts
                    = OfferProduct.GetbyOffer(orderOffer.OfferGuid);

                foreach (OfferProduct offerProduct in offerProducts)
                {
                    OrderOfferProduct orderProduct = new OrderOfferProduct();
                    orderProduct.Created = DateTime.UtcNow;
                    orderProduct.FullfillTermsGuid = offerProduct.FullFillTermsGuid;
                    orderProduct.FullfillType = offerProduct.FullfillType;
                    orderProduct.OfferGuid = offerProduct.OfferGuid;
                    orderProduct.OrderGuid = order.OrderGuid;
                    orderProduct.ProductGuid = offerProduct.ProductGuid;
                    orderProduct.Save();

                    if (
                        (offerProduct.FullfillType
                        == (byte)FulfillmentType.Download)
                        && (offerProduct.FullFillTermsGuid != Guid.Empty)
                        )
                    {
                        // create download fullfillment ticket
                        FullfillDownloadTerms downloadTerms
                            = new FullfillDownloadTerms(offerProduct.FullFillTermsGuid);

                        FullfillDownloadTicket downloadTicket = new FullfillDownloadTicket();
                        downloadTicket.CountAfterDownload = downloadTerms.CountAfterDownload;
                        downloadTicket.DownloadsAllowed = downloadTerms.DownloadsAllowed;
                        downloadTicket.ExpireAfterDays = downloadTerms.ExpireAfterDays;
                        downloadTicket.FullfillTermsGuid = offerProduct.FullFillTermsGuid;
                        downloadTicket.OrderGuid = order.OrderGuid;
                        downloadTicket.ProductGuid = offerProduct.ProductGuid;
                        downloadTicket.PurchaseTime = order.Completed;
                        downloadTicket.StoreGuid = order.StoreGuid;
                        downloadTicket.UserGuid = order.UserGuid;
                        downloadTicket.Save();

                    }
                }

            }

            if (order.DiscountCodesCsv.Length > 0)
            {
                List<WebStore.Business.Discount> discountList = WebStore.Business.Discount.GetValidDiscounts(store.ModuleGuid, cart, cart.DiscountCodesCsv);
                foreach (WebStore.Business.Discount d in discountList)
                {
                    d.UseCount += 1;
                    d.Save();
                    // TODO: Discount log

                }
            }

            Cart.Delete(cart.CartGuid);

            return order;
        }
        public override string HandleRequestAndReturnUrlForRedirect(
            string rawResponse,
            StringDictionary pdtItems,
            string transactionId,
            PayPalLog standardCheckoutLog)
        {
            string redirectUrl = string.Empty;

            if (standardCheckoutLog.SerializedObject.Length == 0) { return redirectUrl; }

            Cart cart = (Cart)SerializationHelper.DeserializeFromString(typeof(Cart), standardCheckoutLog.SerializedObject);

            Store store = new Store(cart.StoreGuid);

            bool debugPayPal = WebConfigSettings.DebugPayPal;

            string firstName = string.Empty;
            string lastName = string.Empty;
            string paymentStatus = string.Empty;
            string payerEmail = string.Empty;
            string currencyUsed = string.Empty;
            string paymentGross = string.Empty;
            string payPalFee = string.Empty;
            string payPalTax = string.Empty;
            string payPalShipping = string.Empty;
            string payPalSettlement = string.Empty;
            string pendingReason = string.Empty;
            string reasonCode = string.Empty;
            string paymentType = string.Empty;

            string customerAddress = string.Empty;
            string customerCity = string.Empty;
            string customerState = string.Empty;
            string customerPostalCode = string.Empty;
            string customerCountry = string.Empty;
            string customerPhone = string.Empty;
            string customerBusinessName = string.Empty;
            string customerMemo = string.Empty;

            if (pdtItems.ContainsKey("first_name"))
            {
                firstName = pdtItems["first_name"];
            }

            if (pdtItems.ContainsKey("last_name"))
            {
                lastName = pdtItems["last_name"];
            }

            if (pdtItems.ContainsKey("payment_status"))
            {
                paymentStatus = pdtItems["payment_status"];
            }

            if (pdtItems.ContainsKey("payer_email"))
            {
                payerEmail = pdtItems["payer_email"];
            }

            if (pdtItems.ContainsKey("mc_gross"))
            {
                paymentGross = pdtItems["mc_gross"];
            }

            if (pdtItems.ContainsKey("mc_fee"))
            {
                payPalFee = pdtItems["mc_fee"];
            }

            if (pdtItems.ContainsKey("tax"))
            {
                payPalTax = pdtItems["tax"];
            }

            if (pdtItems.ContainsKey("shipping"))
            {
                payPalShipping = pdtItems["shipping"];
            }

            if (pdtItems.ContainsKey("mc_currency"))
            {
                currencyUsed = pdtItems["mc_currency"];
            }

            if (pdtItems.ContainsKey("pending_reason"))
            {
                pendingReason = pdtItems["pending_reason"];
            }

            if (pdtItems.ContainsKey("reason_code"))
            {
                reasonCode = pdtItems["reason_code"];
            }

            if (pdtItems.ContainsKey("txn_type"))
            {
                paymentType = pdtItems["txn_type"];
            }

            if (pdtItems.ContainsKey("settle_amount"))
            {
                payPalSettlement = pdtItems["settle_amount"];
            }

            if (pdtItems.ContainsKey("address_street"))
            {
                customerAddress = pdtItems["address_street"];
            }

            if (pdtItems.ContainsKey("address_city"))
            {
                customerCity = pdtItems["address_city"];
            }

            if (pdtItems.ContainsKey("address_state"))
            {
                customerState = pdtItems["address_state"];
            }

            if (pdtItems.ContainsKey("address_zip"))
            {
                customerPostalCode = pdtItems["address_zip"];
            }

            if (pdtItems.ContainsKey("address_country"))
            {
                customerCountry = pdtItems["address_country"];
            }

            if (pdtItems.ContainsKey("contact_phone"))
            {
                customerPhone = pdtItems["contact_phone"];
            }

            if (pdtItems.ContainsKey("payer_business_name"))
            {
                customerBusinessName = pdtItems["payer_business_name"];
            }

            // TODO: we need to store this somewhere on the cart/order
            // its the message the user enters in special instructions on paypal checkout
            if (pdtItems.ContainsKey("memo"))
            {
                customerMemo = pdtItems["memo"];
            }

            //Regardless of the specified currency, the format will have decimal point
            //with exactly two digits to the right and an optional thousands separator to the left,
            //which must be a comma; for example, EUR 2.000,00 must be specified as 2000.00 or 2,000.00
            // So we want to parse it with US Culture

            CultureInfo currencyCulture = new CultureInfo("en-US");
            //if (currencyUsed.Length > 0)
            //{
            //    currencyCulture = ResourceHelper.GetCurrencyCulture(currencyUsed);
            //    if (debugPayPal) { log.Info("PayPal currencyUsed was " + currencyUsed); }
            //}
            //else
            //{
            //    SiteSettings siteSettings = new SiteSettings(store.SiteGuid);
            //    //Currency currency = new Currency(store.DefaultCurrencyId);
            //    //currencyCulture = ResourceHelper.GetCurrencyCulture(currency.Code);
            //    Currency currency = siteSettings.GetCurrency();
            //    currencyCulture = ResourceHelper.GetCurrencyCulture(currency.Code);
            //    currencyUsed = currency.Code;
            //}

            if (debugPayPal) { log.Info("PayPal rawResponse was " + rawResponse); }

            if (debugPayPal) { log.Info("PayPal final currency culture was " + currencyUsed); }

            decimal grossAmount = 0;
            decimal.TryParse(paymentGross, NumberStyles.Currency, currencyCulture, out grossAmount);

            decimal feeAmount = 0;
            decimal.TryParse(payPalFee, NumberStyles.Currency, currencyCulture, out feeAmount);

            decimal taxAmount = 0;
            decimal.TryParse(payPalTax, NumberStyles.Currency, currencyCulture, out taxAmount);

            decimal shippingAmount = 0;
            decimal.TryParse(payPalShipping, NumberStyles.Currency, currencyCulture, out shippingAmount);

            decimal settleAmount = 0;
            decimal.TryParse(payPalSettlement, NumberStyles.Currency, currencyCulture, out settleAmount);

            if (debugPayPal)
            {
                log.Info("PayPal paymentGross was " + paymentGross + " which was parsed as " + grossAmount.ToString());
                log.Info("PayPal payPalFee was " + payPalFee + " which was parsed as " + feeAmount.ToString());
                log.Info("PayPal payPalTax was " + payPalTax + " which was parsed as " + taxAmount.ToString());
                log.Info("PayPal payPalShipping was " + payPalShipping + " which was parsed as " + shippingAmount.ToString());
                log.Info("PayPal payPalSettlement was " + payPalSettlement + " which was parsed as " + settleAmount.ToString());

            }

            PayPalLog payPalLog = new PayPalLog();
            payPalLog.PDTProviderName = standardCheckoutLog.PDTProviderName;
            payPalLog.IPNProviderName = standardCheckoutLog.IPNProviderName;
            payPalLog.ReturnUrl = standardCheckoutLog.ReturnUrl;
            payPalLog.ProviderName = standardCheckoutLog.ProviderName;
            payPalLog.SiteGuid = standardCheckoutLog.SiteGuid;
            payPalLog.StoreGuid = standardCheckoutLog.StoreGuid;
            payPalLog.UserGuid = standardCheckoutLog.UserGuid;
            payPalLog.ApiVersion = standardCheckoutLog.ApiVersion;
            payPalLog.CartGuid = standardCheckoutLog.CartGuid;
            payPalLog.SerializedObject = standardCheckoutLog.SerializedObject;
            payPalLog.CartTotal = standardCheckoutLog.CartTotal;
            payPalLog.PayPalAmt = grossAmount;
            payPalLog.FeeAmt = feeAmount;
            if (settleAmount > 0)
            {
                payPalLog.SettleAmt = settleAmount;
            }
            else
            {
                payPalLog.SettleAmt = (grossAmount - feeAmount);
            }
            payPalLog.TaxAmt = taxAmount;
            payPalLog.CurrencyCode = currencyUsed;
            payPalLog.TransactionId = transactionId;
            payPalLog.RawResponse = rawResponse;
            payPalLog.Response = "PDTSuccess";
            payPalLog.RequestType = "PDT";
            payPalLog.PayerId = payerEmail;
            payPalLog.PaymentType = paymentType;
            payPalLog.PaymentStatus = paymentStatus;
            payPalLog.PendingReason = pendingReason;
            payPalLog.ReasonCode = reasonCode;
            payPalLog.Save();

            // see if this cart has already been proceesed
            Order existingOrder = new Order(cart.CartGuid);
            // order already exists
            if (existingOrder.OrderGuid != Guid.Empty)
            {
                // lookup order status if needed make it fullfillable
                // then redirect to order detail page
                if (existingOrder.StatusGuid == OrderStatus.OrderStatusReceivedGuid)
                {
                    if (paymentStatus == "Completed")
                    {
                        existingOrder.StatusGuid = OrderStatus.OrderStatusFulfillableGuid;
                        existingOrder.Save();
                        try
                        {
                            StoreHelper.ConfirmOrder(store, existingOrder);
                            GoogleCheckoutLog.DeleteByCart(existingOrder.OrderGuid);
                        }
                        catch (Exception ex)
                        {
                            log.Error("error sending confirmation email", ex);
                        }
                    }

                }

                // this was set in Checkout.aspx and should return to order detail page
                if (standardCheckoutLog.ReturnUrl.Length > 0)
                {
                    redirectUrl = standardCheckoutLog.ReturnUrl;
                }

                payPalLog.ReasonCode = "existing order found";
                payPalLog.Save();

                return redirectUrl;
            }

            // if we get here the cart has not yet been processed into an order
            cart.DeSerializeCartOffers();

            Guid orderStatus;
            if (paymentStatus == "Completed")
            {
                orderStatus = OrderStatus.OrderStatusFulfillableGuid;
            }
            else
            {
                orderStatus = OrderStatus.OrderStatusReceivedGuid;
            }

            // update the order with customer shipping info
            cart.OrderInfo.DeliveryCompany = customerBusinessName;
            cart.OrderInfo.DeliveryAddress1 = customerAddress;

            cart.OrderInfo.DeliveryCity = customerCity;
            cart.OrderInfo.DeliveryFirstName = firstName;
            cart.OrderInfo.DeliveryLastName = lastName;
            cart.OrderInfo.DeliveryPostalCode = customerPostalCode;
            cart.OrderInfo.DeliveryState = customerState;
            cart.OrderInfo.DeliveryCountry = customerCountry;

            if (customerPhone.Length > 0)
            {
                cart.OrderInfo.CustomerTelephoneDay = customerPhone;
            }

            if (payerEmail.Length > 0)
            {
                cart.OrderInfo.CustomerEmail = payerEmail;
            }

            cart.CopyShippingToBilling();
            cart.CopyShippingToCustomer();
            cart.TaxTotal = taxAmount;
            cart.OrderTotal = grossAmount;
            if (shippingAmount > 0)
            {
                cart.ShippingTotal = shippingAmount;
            }

            StoreHelper.EnsureUserForOrder(cart);

            cart.Save();

            cart.SerializeCartOffers();
            payPalLog.SerializedObject = SerializationHelper.SerializeToString(cart);
            payPalLog.Save();

            Order order = Order.CreateOrder(
                store,
                cart,
                transactionId,
                transactionId,
                string.Empty,
                currencyUsed,
                "PayPal",
                orderStatus);

            if (standardCheckoutLog.ReturnUrl.Length > 0)
            {
                redirectUrl = standardCheckoutLog.ReturnUrl;
            }

            if (orderStatus == OrderStatus.OrderStatusFulfillableGuid)
            {
                try
                {
                    StoreHelper.ConfirmOrder(store, order);
                    GoogleCheckoutLog.DeleteByCart(order.OrderGuid);
                }
                catch (Exception ex)
                {
                    log.Error("error sending confirmation email", ex);
                }
            }

            if (orderStatus == OrderStatus.OrderStatusReceivedGuid)
            {
                if ((paymentStatus == "Pending") && (pendingReason == "echeck"))
                {
                    StoreHelper.ConfirmOrderReceived(store, existingOrder, true);
                }
            }

            return redirectUrl;
        }