public void TestAlternateTaxTables() {
      CheckoutShoppingCartRequest request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

      //Ensure the factory works as expected
      AlternateTaxTable ohio1 = new AlternateTaxTable("ohio");
      request.AlternateTaxTables.Add(ohio1);
      AlternateTaxTable ohio2 = request.AlternateTaxTables["ohio"];
      AlternateTaxTable ohio3 = new AlternateTaxTable("ohio", true);

      //Ensure that two Tax tables with the same name are not the same reference
      Assert.AreSame(ohio1, ohio2);
      Assert.IsFalse(object.ReferenceEquals(ohio1, ohio3));
      //Assert.AreEqual(ohio1, ohio3);

      //Now add some rules to the item
      ohio1.AddStateTaxRule("OH", .02);

      //Make sure we can add an item to the cart.
      ShoppingCartItem item = request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1, ohio1);

      try {
        request.AddItem("Item 2", "Cool Candy 2", 2.00M, 1, ohio3);
        Assert.Fail("An exception should have been thrown when we tried to add an item that has a new Tax Reference");
      }
      catch (Exception) {

      }

      //Now this should work fine.
      request.AddItem("Item 3", "Cool Candy 3", string.Empty, 2.00M, 1, ohio2);

      //you could create this as an IShoppingCartItem or ShoppingCartItem
      IShoppingCartItem newItem = new ShoppingCartItem("Item 2", "Cool Candy 2", string.Empty, 2.00M, 2, AlternateTaxTable.Empty, "This is a test of a string of private data");
      //now decide to change your mind on the quantity and price
      newItem.Price = 20;
      newItem.Quantity = 4;

      request.AddItem(newItem);

      //Console.WriteLine("private data:" + newItem.MerchantPrivateItemData);

      Assert.AreEqual("This is a test of a string of private data", newItem.MerchantPrivateItemData);

      //now change the private data string and compare again.
      newItem.MerchantPrivateItemData = "This is a new String";
      Assert.AreEqual("This is a new String", newItem.MerchantPrivateItemData);

      //now change the private data string and compare again.
      newItem.MerchantPrivateItemData = string.Empty;
      Assert.AreEqual(string.Empty, newItem.MerchantPrivateItemData);

      Assert.AreEqual(1, ohio1.RuleCount);

      DigitalItem emailDigitalItem = new DigitalItem();
      request.AddItem("Email Digital Item", "Cool DigitalItem", 2.00m, 1, emailDigitalItem);

      DigitalItem urlDigitalItem = new DigitalItem(new Uri("http://www.google.com/download.aspx?myitem=1"), "Url Description for item");
      request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, urlDigitalItem);

      DigitalItem keyDigitalItem = new DigitalItem("24-235-sdf-123541-53", "Key Description for item");
      request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, keyDigitalItem);

      DigitalItem keyUrlItem = new DigitalItem("24-235-sdf-123541-53", "http://www.google.com/download.aspx?myitem=1", "Url/Key Description for item");
      request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, keyUrlItem);

      //lets make sure we can add 2 different flat rate shipping amounts

      request.AddFlatRateShippingMethod("UPS Ground", 5);
      request.AddFlatRateShippingMethod("UPS 2 Day Air", 25);
      request.AddFlatRateShippingMethod("Test", 12, new ShippingRestrictions());

      //You can't mix shipping methods
      try {
        request.AddMerchantCalculatedShippingMethod("Test", 12.95m);
        Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
      }
      catch {
      }

      //lets try adding a Carrier Calculated Shipping Type

      //this should fail because the city is empty
      try {
        request.AddShippingPackage("failedpackage", string.Empty, "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);
        Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
      }
      catch {
      }

      //The first thing that needs to be done for carrier calculated shipping is we must set the FOB address.
      request.AddShippingPackage("main", "Cleveland", "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);

      //this should fail because two packages exist
      try {
        request.AddShippingPackage("failedpackage", "Cleveland", "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);
        Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
      }
      catch {
      }

      try {
        request.AddShippingPackage("main", "Cleveland", "OH", "44114");
        Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
      }
      catch {
      }

      //The next thing we will do is add a Fedex Home Package.
      //We will set the default to 3.99, the Pickup to Regular Pickup, the additional fixed charge to 1.29 and the discount to 2.5%
      CarrierCalculatedShippingOption option
        = request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Home_Delivery, 3.99m, CarrierPickup.REGULAR_PICKUP, 1.29m, -2.5);
      option.AdditionalVariableChargePercent = 0; //make sure we can set it back to 0;
      option.AdditionalFixedCharge = 0;

      Assert.AreEqual(option.StatedShippingType, ShippingType.Fedex_Home_Delivery);
      Assert.AreEqual(option.Price, 3.99m);

      Assert.AreEqual(option.AdditionalVariableChargePercent, 0);
      Assert.AreEqual(option.AdditionalFixedCharge, 0);

      try {
        option.AdditionalFixedCharge = -1;
        Assert.Fail("Additional charge must be >= 0");
      }
      catch {
      }

      option.AdditionalVariableChargePercent = 2; //make sure we can set it back to 0;
      option.AdditionalFixedCharge = 3;

      Assert.AreEqual(option.AdditionalVariableChargePercent, 2);
      Assert.AreEqual(option.AdditionalFixedCharge, 3);

      //this should fail
      try {
        request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Home_Delivery, 3.99m, CarrierPickup.REGULAR_PICKUP, 1.29m, -2.5);
        Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
      }
      catch {

      }

      //verify the rounding works
      CarrierCalculatedShippingOption ccso = request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Ground, 1.993m);
      Assert.AreEqual(1.99m, ccso.Price);
      ccso.Price = 1.975m;
      Assert.AreEqual(1.98m, ccso.Price);
      request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Second_Day, 9.99m, CarrierPickup.REGULAR_PICKUP, 2.34m, -24.5);

      //Ensure we are able to create the cart xml

      byte[] cart = request.GetXml();

      //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

      //test to see if the item can desialize
      Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));
    }
        public void TestAlternateTaxTables()
        {
            CheckoutShoppingCartRequest request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            //Ensure the factory works as expected
            AlternateTaxTable ohio1 = new AlternateTaxTable("ohio");

            request.AlternateTaxTables.Add(ohio1);
            AlternateTaxTable ohio2 = request.AlternateTaxTables["ohio"];
            AlternateTaxTable ohio3 = new AlternateTaxTable("ohio", true);

            //Ensure that two Tax tables with the same name are not the same reference
            Assert.AreSame(ohio1, ohio2);
            Assert.IsFalse(object.ReferenceEquals(ohio1, ohio3));
            //Assert.AreEqual(ohio1, ohio3);

            //Now add some rules to the item
            ohio1.AddStateTaxRule("OH", .02);

            //Make sure we can add an item to the cart.
            ShoppingCartItem item = request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1, ohio1);

            try {
                request.AddItem("Item 2", "Cool Candy 2", 2.00M, 1, ohio3);
                Assert.Fail("An exception should have been thrown when we tried to add an item that has a new Tax Reference");
            }
            catch (Exception) {
            }

            //Now this should work fine.
            request.AddItem("Item 3", "Cool Candy 3", string.Empty, 2.00M, 1, ohio2);

            //you could create this as an IShoppingCartItem or ShoppingCartItem
            IShoppingCartItem newItem = new ShoppingCartItem("Item 2", "Cool Candy 2", string.Empty, 2.00M, 2, AlternateTaxTable.Empty, "This is a test of a string of private data");

            //now decide to change your mind on the quantity and price
            newItem.Price    = 20;
            newItem.Quantity = 4;

            request.AddItem(newItem);

            //Console.WriteLine("private data:" + newItem.MerchantPrivateItemData);

            Assert.AreEqual("This is a test of a string of private data", newItem.MerchantPrivateItemData);

            //now change the private data string and compare again.
            newItem.MerchantPrivateItemData = "This is a new String";
            Assert.AreEqual("This is a new String", newItem.MerchantPrivateItemData);

            //now change the private data string and compare again.
            newItem.MerchantPrivateItemData = string.Empty;
            Assert.AreEqual(string.Empty, newItem.MerchantPrivateItemData);

            Assert.AreEqual(1, ohio1.RuleCount);

            DigitalItem emailDigitalItem = new DigitalItem();

            request.AddItem("Email Digital Item", "Cool DigitalItem", 2.00m, 1, emailDigitalItem);

            DigitalItem urlDigitalItem = new DigitalItem(new Uri("http://www.google.com/download.aspx?myitem=1"), "Url Description for item");

            request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, urlDigitalItem);

            DigitalItem keyDigitalItem = new DigitalItem("24-235-sdf-123541-53", "Key Description for item");

            request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, keyDigitalItem);

            DigitalItem keyUrlItem = new DigitalItem("24-235-sdf-123541-53", "http://www.google.com/download.aspx?myitem=1", "Url/Key Description for item");

            request.AddItem("Url Digital Item", "Cool Url DigitalItem", 2.00m, 1, keyUrlItem);

            //lets make sure we can add 2 different flat rate shipping amounts

            request.AddFlatRateShippingMethod("UPS Ground", 5);
            request.AddFlatRateShippingMethod("UPS 2 Day Air", 25);
            request.AddFlatRateShippingMethod("Test", 12, new ShippingRestrictions());

            //You can't mix shipping methods
            try {
                request.AddMerchantCalculatedShippingMethod("Test", 12.95m);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //lets try adding a Carrier Calculated Shipping Type

            //this should fail because the city is empty
            try {
                request.AddShippingPackage("failedpackage", string.Empty, "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //The first thing that needs to be done for carrier calculated shipping is we must set the FOB address.
            request.AddShippingPackage("main", "Cleveland", "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);

            //this should fail because two packages exist
            try {
                request.AddShippingPackage("failedpackage", "Cleveland", "OH", "44114", DeliveryAddressCategory.COMMERCIAL, 2, 3, 4);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            try {
                request.AddShippingPackage("main", "Cleveland", "OH", "44114");
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //The next thing we will do is add a Fedex Home Package.
            //We will set the default to 3.99, the Pickup to Regular Pickup, the additional fixed charge to 1.29 and the discount to 2.5%
            CarrierCalculatedShippingOption option
                = request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Home_Delivery, 3.99m, CarrierPickup.REGULAR_PICKUP, 1.29m, -2.5);

            option.AdditionalVariableChargePercent = 0; //make sure we can set it back to 0;
            option.AdditionalFixedCharge           = 0;

            Assert.AreEqual(option.StatedShippingType, ShippingType.Fedex_Home_Delivery);
            Assert.AreEqual(option.Price, 3.99m);

            Assert.AreEqual(option.AdditionalVariableChargePercent, 0);
            Assert.AreEqual(option.AdditionalFixedCharge, 0);

            try {
                option.AdditionalFixedCharge = -1;
                Assert.Fail("Additional charge must be >= 0");
            }
            catch {
            }

            option.AdditionalVariableChargePercent = 2; //make sure we can set it back to 0;
            option.AdditionalFixedCharge           = 3;

            Assert.AreEqual(option.AdditionalVariableChargePercent, 2);
            Assert.AreEqual(option.AdditionalFixedCharge, 3);

            //this should fail
            try {
                request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Home_Delivery, 3.99m, CarrierPickup.REGULAR_PICKUP, 1.29m, -2.5);
                Assert.Fail("AddCarrierCalculatedShippingOption should not allow duplicates.");
            }
            catch {
            }

            //verify the rounding works
            CarrierCalculatedShippingOption ccso = request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Ground, 1.993m);

            Assert.AreEqual(1.99m, ccso.Price);
            ccso.Price = 1.975m;
            Assert.AreEqual(1.98m, ccso.Price);
            request.AddCarrierCalculatedShippingOption(ShippingType.Fedex_Second_Day, 9.99m, CarrierPickup.REGULAR_PICKUP, 2.34m, -24.5);

            //Ensure we are able to create the cart xml

            byte[] cart = request.GetXml();

            //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

            //test to see if the item can desialize
            Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));
        }
        protected void GCheckoutButton_Click(object sender, ImageClickEventArgs e)
        {
            if (_BasketGrid != null)
            {
                //First Save the updated Basket
                AbleCommerce.Code.BasketHelper.SaveBasket(_BasketGrid);
            }

            GCheckoutButton.Currency = AbleContext.Current.Store.BaseCurrency.ISOCode;
            CheckoutShoppingCartRequest Req = GCheckoutButton.CreateRequest();

            System.Xml.XmlDocument tempDoc = new System.Xml.XmlDocument();

            Basket basket = AbleContext.Current.User.Basket;

            // Add a "BasketId" node.
            System.Xml.XmlNode tempNode2 = tempDoc.CreateElement("BasketId");
            tempNode2.InnerText = basket.Id.ToString();
            Req.AddMerchantPrivateDataNode(tempNode2);

            tempNode2           = tempDoc.CreateElement("BasketContentHash");
            tempNode2.InnerText = GetBasketContentHash(basket);
            Req.AddMerchantPrivateDataNode(tempNode2);

            // We just created this structure on the order level:
            // <merchant-private-data>
            //   <BasketId xmlns="">xxxxxx</BasketId>
            // </merchant-private-data>

            // Now we are going to add the basket items.
            XmlNode[] itemPrivateData;
            foreach (BasketItem item in basket.Items)
            {
                switch (item.OrderItemType)
                {
                case OrderItemType.Product:
                    itemPrivateData = BuildPrivateData(item);
                    bool isDigitalContent = item.Product == null ? false : item.Product.IsDigitalGood;
                    if (isDigitalContent)
                    {
                        Req.AddItem(AcHelper.SanitizeText(item.Name), AcHelper.SanitizeText(item.Product.Description), (Decimal)item.Price, item.Quantity, isDigitalContent, AcHelper.SanitizeText(string.Format("The download will be available from your {0} order receipt once payment is processed.", AbleContext.Current.Store.Name)), itemPrivateData);
                    }
                    else
                    {
                        Req.AddItem(AcHelper.SanitizeText(item.Name), AcHelper.SanitizeText(item.Product.Description), (Decimal)item.Price, item.Quantity, itemPrivateData);
                    }
                    break;

                case OrderItemType.Charge:
                    itemPrivateData = BuildPrivateData(item);
                    Req.AddItem(AcHelper.SanitizeText(item.Name), "Charge", (Decimal)item.Price, item.Quantity, itemPrivateData);
                    break;

                case OrderItemType.Credit:
                    itemPrivateData = BuildPrivateData(item);
                    Req.AddItem(AcHelper.SanitizeText(item.Name), "Credit", (Decimal)item.Price, item.Quantity, itemPrivateData);
                    break;

                case OrderItemType.GiftWrap:
                    itemPrivateData = BuildPrivateData(item);
                    Req.AddItem(AcHelper.SanitizeText(item.Name), "Gift Wrapping", (Decimal)item.Price, item.Quantity, itemPrivateData);
                    break;

                case OrderItemType.Coupon:     //on callback as well
                    itemPrivateData = BuildPrivateData(item);
                    Req.AddItem(AcHelper.SanitizeText(item.Name), "Your coupon has been applied.", (Decimal)item.Price, item.Quantity, itemPrivateData);
                    break;

                case OrderItemType.Discount:
                    itemPrivateData = BuildPrivateData(item);
                    Req.AddItem(AcHelper.SanitizeText(item.Name), "Discount", (Decimal)item.Price, item.Quantity, itemPrivateData);
                    break;

                case OrderItemType.GiftCertificate:     //on callback
                    break;

                case OrderItemType.Handling:     //on callback
                    break;

                case OrderItemType.Shipping:     //on callback
                    break;

                case OrderItemType.Tax:     //on callback
                    break;
                }
            }

            //setup other settings
            Req.AcceptMerchantCoupons          = GCheckoutButton.GatewayInstance.CouponsEnabled;
            Req.AcceptMerchantGiftCertificates = GCheckoutButton.GatewayInstance.GiftCertificatesEnabled;
            //Req.CartExpiration = expirationDate;
            string storeDomain  = UrlHelper.GetDomainFromUrl(AbleContext.Current.Store.StoreUrl);
            string storeBaseUrl = "http://" + storeDomain;

            Req.ContinueShoppingUrl   = storeBaseUrl + this.ResolveUrl("~/Default.aspx");
            Req.EditCartUrl           = storeBaseUrl + this.ResolveUrl("~/Basket.aspx");
            Req.MerchantCalculatedTax = true;
            //add at least one tax rule
            Req.AddZipTaxRule("99999", 0F, false);
            string storeBaseSecureUrl = AbleContext.Current.Store.Settings.SSLEnabled ? storeBaseUrl.Replace("http://", "https://") : storeBaseUrl;

            Req.MerchantCalculationsUrl = storeBaseSecureUrl + this.ResolveUrl("~/Checkout/Google/MerchantCalc.ashx");
            Req.PlatformID = 769150108975916;
            Req.RequestBuyerPhoneNumber = true;
            Req.SetExpirationMinutesFromNow(GCheckoutButton.GatewayInstance.ExpirationMinutes);

            //add ship methods
            IList <ShipMethod>   shipMethods      = ShipMethodDataSource.LoadAll();
            List <string>        shipMethodsAdded = new List <string>();
            string               shipMethName;
            decimal              basketTotal      = basket.Items.TotalPrice();
            decimal              defaultRate      = GCheckoutButton.GatewayInstance.DefaultShipRate;
            ShippingRestrictions shipRestrictions = new ShippingRestrictions();

            shipRestrictions.AddAllowedWorldArea();

            foreach (ShipMethod shipMethod in shipMethods)
            {
                if (!shipMethod.Name.Equals("Unknown(GoogleCheckout)") &&
                    (shipMethod.MinPurchase <= 0 || shipMethod.MinPurchase <= basketTotal))
                {
                    //add all other shipmethods as merchant calculated irrespective of whether they
                    //are applicable or not. It will be determined on call-back
                    //GoogleCheckout does not allow to mix merchant calculated shipping methods with other methods
                    if (shipMethod.ShipMethodType == ShipMethodType.FlatRate)
                    {
                        defaultRate = GetFlatShipRate(shipMethod);
                    }
                    else
                    {
                        defaultRate = GCheckoutButton.GatewayInstance.DefaultShipRate;
                    }
                    shipMethName = BuildShipMethodName(shipMethod, shipMethodsAdded);
                    Req.AddMerchantCalculatedShippingMethod(shipMethName, defaultRate, shipRestrictions, shipRestrictions);
                    shipMethodsAdded.Add(shipMethName.ToLowerInvariant());
                }
            }

            GCheckoutResponse Resp = Req.Send();

            if (Resp.IsGood)
            {
                Response.Redirect(Resp.RedirectUrl, true);
            }
            else
            {
                DataList msgList;
                if (_WarningMessageList != null)
                {
                    msgList = _WarningMessageList;
                }
                else
                {
                    msgList            = GCWarningMessageList;
                    phWarnings.Visible = true;
                }
                if (msgList != null)
                {
                    List <string> googleMessages = new List <string>();
                    googleMessages.Add("Google Checkout Failed.");
                    googleMessages.Add("Google Checkout Response.IsGood = " + Resp.IsGood);
                    googleMessages.Add("Google Checkout Error Message = " + Resp.ErrorMessage);
                    msgList.DataSource = googleMessages;
                    msgList.DataBind();
                }
            }
        }
        public void TestExamples()
        {
            CheckoutShoppingCartRequest request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            //Make sure we can add an item to the cart.
            request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1);

            request.AddStateTaxRule("CT", .06, true);

            byte[] cart = request.GetXml();

            //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

            //test to see if the item can desialize
            Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));


            //example 2

            request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            //Make sure we can add an item to the cart.
            request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1);

            request.AddStateTaxRule("CT", .06, true);
            request.AddStateTaxRule("MD", .05, false);

            cart = request.GetXml();

            //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

            //test to see if the item can desialize
            Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));

            //example 2a

            request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            //Make sure we can add an item to the cart.
            request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1);

            cart = request.GetXml();

            //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

            //test to see if the item can desialize
            Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));


            //example 3

            request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);

            //Make sure we can add an item to the cart.
            request.AddItem("Item 1", "Cool Candy 1", 2.00M, 1);

            request.AddZipTaxRule("100*", 0.08375, false);
            request.AddStateTaxRule("NY", 0.0400, true);

            //this should be an invalid format
            try {
                request.AddZipTaxRule("255333", .05, true);
                Assert.Fail("255333 should not be a correct zip code format");
            }
            catch {
            }

            cart = request.GetXml();

            //Console.WriteLine(EncodeHelper.Utf8BytesToString(cart));

            //test to see if the item can desialize
            Assert.IsNotNull(GCheckout.Util.EncodeHelper.Deserialize(cart));

            request.AddMerchantCalculatedShippingMethod("Test 1", 12.11m);
            request.AddMerchantCalculatedShippingMethod("Test 2", 4.95m, new ShippingRestrictions());
            request.AddMerchantCalculatedShippingMethod("Test 3", 5.95m, new ShippingRestrictions());
            request.AddMerchantCalculatedShippingMethod("MerchantCalc", 12.95m, new ShippingRestrictions(), new ShippingRestrictions());

            //create a pickup shipping method
            request = new CheckoutShoppingCartRequest(MERCHANT_ID, MERCHANT_KEY, EnvironmentType.Sandbox, "USD", 120);
            request.AddPickupShippingMethod("Name", 4.95m);
            request.AddCountryTaxRule(GCheckout.AutoGen.USAreas.ALL, .05, true);
            request.AddWorldAreaTaxRule(.02, true);
            //Tax Canada at 5%
            request.AddPostalAreaTaxRule("CA", .05, true);

            //Tax all cities that start with L4L at 7%
            request.AddPostalAreaTaxRule("CA", "L4L*", .07, true);

            XmlDocument doc = new XmlDocument();

            doc.LoadXml("<data />");
            request.AddMerchantPrivateDataNode(doc.DocumentElement);

            //we must pass in a valid node
            try {
                request.AddMerchantPrivateDataNode(null);
                Assert.Fail("Null can't be sent to AddMerchantPrivateDataNode.");
            }
            catch {
            }
        }