svn commit: r780306 - in /ofbiz/trunk/specialpurpose/googlecheckout: config/ data/ entitydef/ src/org/ofbiz/googlecheckout/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r780306 - in /ofbiz/trunk/specialpurpose/googlecheckout: config/ data/ entitydef/ src/org/ofbiz/googlecheckout/

jaz-3
Author: jaz
Date: Sat May 30 17:47:08 2009
New Revision: 780306

URL: http://svn.apache.org/viewvc?rev=780306&view=rev
Log:
implemented data driven configuration for google checkout; basic configuration now is configured using the GoogleConfiguration entity. Allowing each product store to have completely different settings. Moved the the static URLs to a new properties file which will remain if/when the old code is deprecated.

Added:
    ofbiz/trunk/specialpurpose/googlecheckout/config/google-checkout.properties
Modified:
    ofbiz/trunk/specialpurpose/googlecheckout/config/googleCheckout.properties
    ofbiz/trunk/specialpurpose/googlecheckout/data/GoogleCheckoutTypeData.xml
    ofbiz/trunk/specialpurpose/googlecheckout/entitydef/entitymodel.xml
    ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutHelper.java
    ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutResponseEvents.java
    ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleRequestServices.java

Added: ofbiz/trunk/specialpurpose/googlecheckout/config/google-checkout.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/config/google-checkout.properties?rev=780306&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/config/google-checkout.properties (added)
+++ ofbiz/trunk/specialpurpose/googlecheckout/config/google-checkout.properties Sat May 30 17:47:08 2009
@@ -0,0 +1,35 @@
+#####################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#####################################################################
+
+# These are static configuration variable which could easily be hard coded.
+# However, in case they ever do change they should be easy to modify so
+# they are configured here.
+
+# Production server URL
+production.root.url = https://checkout.google.com/api/checkout/v2
+
+# Sandbox server URL
+sandbox.root.url = https://sandbox.google.com/checkout/api/checkout/v2
+
+# Request Commands
+merchant.checkout.command = merchantCheckout
+checkout.command = checkout
+request.command = request
+diagnose.command = diagnose
+

Modified: ofbiz/trunk/specialpurpose/googlecheckout/config/googleCheckout.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/config/googleCheckout.properties?rev=780306&r1=780305&r2=780306&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/config/googleCheckout.properties (original)
+++ ofbiz/trunk/specialpurpose/googlecheckout/config/googleCheckout.properties Sat May 30 17:47:08 2009
@@ -56,19 +56,3 @@
 checkout = /checkout
 request = /request
 diagnose = /diagnose
-
-### Notification API and Order Processing API URLs -- NOTE: we should migrate the above urls to build upon these instead
-
-# use Sandbox or Production
-environment.mode = Sandbox
-
-production.root.url = https://checkout.google.com/api/checkout/v2
-sandbox.root.url = https://sandbox.google.com/checkout/api/checkout/v2
-
-merchant.checkout.command = merchantCheckout
-checkout.command = checkout
-request.command = request
-
-
-
-

Modified: ofbiz/trunk/specialpurpose/googlecheckout/data/GoogleCheckoutTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/data/GoogleCheckoutTypeData.xml?rev=780306&r1=780305&r2=780306&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/data/GoogleCheckoutTypeData.xml (original)
+++ ofbiz/trunk/specialpurpose/googlecheckout/data/GoogleCheckoutTypeData.xml Sat May 30 17:47:08 2009
@@ -23,6 +23,10 @@
     <PaymentMethodType description="Google Checkout" paymentMethodTypeId="EXT_GOOGLE_CHECKOUT"/>
     <WebSite webSiteId="GOOGLECHECKOUT" siteName="Google Checkout Application" visualThemeSetId="BACKOFFICE"/>
     
+    <EnumerationType description="Google Environment Types" enumTypeId="GOOGLE_ENV_TYPE" hasTable="N" parentTypeId=""/>
+    <Enumeration description="Sandbox" enumCode="SANDBOX" enumId="GOOGLE_SANDBOX" sequenceId="01" enumTypeId="GOOGLE_ENV_TYPE"/>
+    <Enumeration description="Production" enumCode="PRODUCTION" enumId="GOOGLE_PRODUCTION" sequenceId="02" enumTypeId="GOOGLE_ENV_TYPE"/>
+    
     <EnumerationType description="Google Checkout Ship Types" enumTypeId="GOOGLE_SHIP_TYPE" hasTable="N" parentTypeId=""/>
     <Enumeration description="Flat Rate Shipping" enumCode="FLAT_RATE" enumId="GOOGLE_FLAT_RATE" sequenceId="01" enumTypeId="GOOGLE_SHIP_TYPE"/>
     <Enumeration description="Merchant Calculated Shipping" enumCode="MERCHANT_CALC" enumId="GOOGLE_MERCHANT_CALC" sequenceId="02" enumTypeId="GOOGLE_SHIP_TYPE"/>

Modified: ofbiz/trunk/specialpurpose/googlecheckout/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/entitydef/entitymodel.xml?rev=780306&r1=780305&r2=780306&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/specialpurpose/googlecheckout/entitydef/entitymodel.xml Sat May 30 17:47:08 2009
@@ -40,28 +40,40 @@
     <!-- ========================================================= -->
     <!-- org.ofbiz.googlecheckout.config -->
     <!-- ========================================================= -->
-    <!--
+  
     <entity entity-name="GoogleConfiguration"
             package-name="org.ofbiz.googlecheckout.config"
             title="Google Checkout Configuration">
-      <field name="merchantId" type="id-ne"></field>
-      <field name="merchantKey" type="value"></field>
-      <field name="environment" type="name"></field>
-      <field name="productStoreId" type="id-ne"></field>
-      <field name="webSiteId" type="id"></field>
-      <field name="prodCatalogId" type="id"></field>        
-      <prim-key field="merchantId"/>      
-      <relation type="one" fk-name="GCC_PROD_STORE" rel-entity-name="ProductStore">
-        <key-map field-name="productStoreId"/>
-      </relation>
-      <relation type="one" fk-name="GCC_WEBSITE" rel-entity-name="WebSite">
-        <key-map field-name="webSiteId"/>
-      </relation>
-      <relation type="one" fk-name="GCC_PROD_CAT" rel-entity-name="ProdCatalog">
-        <key-map field-name="prodCatalogId"/>
-      </relation>      
+        <field name="productStoreId" type="id-ne"></field>
+        <field name="merchantId" type="value"></field>
+        <field name="merchantKey" type="value"></field>
+        <field name="envEnumId" type="id-ne"></field>        
+        <field name="webSiteId" type="id-ne"></field>
+        <field name="prodCatalogId" type="id-ne"></field>
+        <field name="currencyUomId" type="id-ne"></field>
+        <field name="requestAuthDetails" type="indicator"></field>
+        <field name="requestPhone" type="indicator"></field>
+        <field name="sendPromoItems" type="indicator"></field>
+        <field name="errorOnBadItem" type="indicator"></field>
+        <field name="acceptCoupons" type="indicator"></field>
+        <field name="acceptGiftCerts" type="indicator"></field>      
+        <prim-key field="productStoreId"/>      
+        <relation type="one" fk-name="GCC_PROD_STORE" rel-entity-name="ProductStore">
+            <key-map field-name="productStoreId"/>
+        </relation>
+        <relation type="one" fk-name="GCC_ENV_ENUM" rel-entity-name="Enumeration">
+            <key-map field-name="envEnumId" rel-field-name="enumId"/>
+        </relation>
+        <relation type="one" fk-name="GCC_WEBSITE" rel-entity-name="WebSite">
+            <key-map field-name="webSiteId"/>
+        </relation>
+        <relation type="one" fk-name="GCC_PROD_CAT" rel-entity-name="ProdCatalog">
+            <key-map field-name="prodCatalogId"/>
+        </relation>  
+        <relation type="one" fk-name="GCC_CUOM" rel-entity-name="Uom">
+            <key-map field-name="currencyUomId" rel-field-name="uomId"/>
+        </relation>    
     </entity>
-    -->
     
     <!-- ========================================================= -->
     <!-- org.ofbiz.googlecheckout.shipping -->
@@ -70,27 +82,27 @@
     <entity entity-name="GoogleShippingMethods"
             package-name="org.ofbiz.googlecheckout.shipping"
             title="Google Shipping Method Config">
-      <field name="shipmentMethodName" type="id-ne"></field>
-      <field name="productStoreId" type="id-ne"></field>
-      <field name="amount" type="currency-amount"></field>
-      <field name="additionalAmount" type="currency-amount"></field>
-      <field name="additionalPercent" type="fixed-point"></field>
-      <field name="methodTypeEnumId" type="id-ne"></field>
-      <field name="carrierPartyId" type="id-ne"></field>
-      <field name="shipmentMethodTypeId" type="id-ne"></field>      
-      <prim-key field="shipmentMethodName"/>
-      <prim-key field="productStoreId"/>
-      <relation type="one" fk-name="GSM_PROD_STORE" rel-entity-name="ProductStore">
-        <key-map field-name="productStoreId"/>
-      </relation>
-      <relation type="one" fk-name="GSM_TYPE_ENUM" rel-entity-name="Enumeration">
-        <key-map field-name="methodTypeEnumId" rel-field-name="enumId"/>
-      </relation>
-      <relation type="one" fk-name="GSM_CARRIER_PARTY" rel-entity-name="Party">
-        <key-map field-name="carrierPartyId" rel-field-name="partyId"/>
-      </relation>
-      <relation type="one" fk-name="GSM_SHIPMETH_TYPE" rel-entity-name="ShipmentMethodType">
-        <key-map field-name="shipmentMethodTypeId"/>
-      </relation>
+        <field name="shipmentMethodName" type="id-ne"></field>
+        <field name="productStoreId" type="id-ne"></field>
+        <field name="amount" type="currency-amount"></field>
+        <field name="additionalAmount" type="currency-amount"></field>
+        <field name="additionalPercent" type="fixed-point"></field>
+        <field name="methodTypeEnumId" type="id-ne"></field>
+        <field name="carrierPartyId" type="id-ne"></field>
+        <field name="shipmentMethodTypeId" type="id-ne"></field>      
+        <prim-key field="shipmentMethodName"/>
+        <prim-key field="productStoreId"/>
+        <relation type="one" fk-name="GSM_PROD_STORE" rel-entity-name="ProductStore">
+            <key-map field-name="productStoreId"/>
+        </relation>
+        <relation type="one" fk-name="GSM_TYPE_ENUM" rel-entity-name="Enumeration">
+            <key-map field-name="methodTypeEnumId" rel-field-name="enumId"/>
+        </relation>
+        <relation type="one" fk-name="GSM_CARRIER_PARTY" rel-entity-name="Party">
+            <key-map field-name="carrierPartyId" rel-field-name="partyId"/>
+        </relation>
+        <relation type="one" fk-name="GSM_SHIPMETH_TYPE" rel-entity-name="ShipmentMethodType">
+            <key-map field-name="shipmentMethodTypeId"/>
+        </relation>
     </entity>
 </entitymodel>
\ No newline at end of file

Modified: ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutHelper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutHelper.java?rev=780306&r1=780305&r2=780306&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutHelper.java (original)
+++ ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutHelper.java Sat May 30 17:47:08 2009
@@ -63,8 +63,7 @@
 
 public class GoogleCheckoutHelper {
 
-    private static final String module = GoogleCheckoutHelper.class.getName();
-    private static final boolean errorOnUnknownItem = true; // set to false to simply ignore the item
+    private static final String module = GoogleCheckoutHelper.class.getName();    
     
     public static final String SALES_CHANNEL = "GC_SALES_CHANNEL";
     public static final String ORDER_TYPE = "SALES_ORDER";
@@ -158,7 +157,7 @@
     }
     
     @SuppressWarnings("unchecked")
-    public void createOrder(NewOrderNotification info, String productStoreId, String websiteId, String currencyUom, Locale locale) throws GeneralException {
+    public void createOrder(NewOrderNotification info, String productStoreId, Locale locale) throws GeneralException {
         // get the google order number
         String externalId = info.getGoogleOrderNumber();
 
@@ -170,11 +169,23 @@
             return;
         }
 
+        // get the config object
+        GenericValue googleCfg = GoogleRequestServices.getGoogleConfiguration(delegator, productStoreId);
+        if (googleCfg == null) {
+            throw new GeneralException("No google configuration found for product store : " + productStoreId);
+        }
+        
+        String websiteId = googleCfg.getString("webSiteId");
+        String currencyUom = googleCfg.getString("currencyUomId");
+        String prodCatalogId = googleCfg.getString("prodCatalogId");
+        boolean errorOnUnknownItem = googleCfg.get("errorOnBadItem") != null &&
+            "Y".equalsIgnoreCase(googleCfg.getString("errorOnBadItem")) ? true : false;
+        
         // Initialize the shopping cart
-        ShoppingCart cart = new ShoppingCart(delegator, productStoreId, websiteId, locale, currencyUom);
+        ShoppingCart cart = new ShoppingCart(delegator, productStoreId, websiteId, locale, currencyUom);          
         cart.setUserLogin(system, dispatcher);
         cart.setOrderType(ORDER_TYPE);
-        cart.setChannelType(SALES_CHANNEL);
+        cart.setChannelType(SALES_CHANNEL);        
         //cart.setOrderDate(UtilDateTime.toTimestamp(info.getTimestamp().()));
         cart.setExternalId(externalId);
 
@@ -218,7 +229,7 @@
         Collection<Item> items = info.getShoppingCart().getItems();
         for (Item item : items) {
             try {
-                addItem(cart, item, null, 0);
+                addItem(cart, item, prodCatalogId, 0);
             } catch (ItemNotFoundException e) {                
                 Debug.logWarning(e, "Item was not found : " + item.getMerchantItemId(), module);
                 // throwing this exception tell google the order failed; it will continue to retry  
@@ -262,7 +273,7 @@
         }        
     }
 
-    protected void addItem(ShoppingCart cart, Item item, String productCatalogId, int groupIdx) throws GeneralException {
+    protected void addItem(ShoppingCart cart, Item item, String prodCatalogId, int groupIdx) throws GeneralException {
         String productId = item.getMerchantItemId();
         BigDecimal qty = new BigDecimal(item.getQuantity());
         BigDecimal price = new BigDecimal(item.getUnitPriceAmount());
@@ -271,7 +282,7 @@
         HashMap<Object, Object> attrs = new HashMap<Object, Object>();
         attrs.put("shipGroup", groupIdx);
 
-        int idx = cart.addItemToEnd(productId, null, qty, null, null, attrs, productCatalogId, null, dispatcher, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE);
+        int idx = cart.addItemToEnd(productId, null, qty, null, null, attrs, prodCatalogId, null, dispatcher, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE);
         ShoppingCartItem cartItem = cart.findCartItem(idx);
         cartItem.setQuantity(qty, dispatcher, cart, true, false);
 

Modified: ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutResponseEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutResponseEvents.java?rev=780306&r1=780305&r2=780306&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutResponseEvents.java (original)
+++ ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleCheckoutResponseEvents.java Sat May 30 17:47:08 2009
@@ -20,17 +20,12 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.Locale;
-
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.GeneralException;
-import org.ofbiz.base.util.UtilMisc;
 import org.ofbiz.entity.GenericDelegator;
-import org.ofbiz.entity.GenericEntityException;
-import org.ofbiz.entity.GenericValue;
 import org.ofbiz.product.store.ProductStoreWorker;
 import org.ofbiz.service.LocalDispatcher;
 import org.w3c.dom.Document;
@@ -72,10 +67,10 @@
             String nodeValue = document.getDocumentElement().getNodeName();
             if ("new-order-notification".equals(nodeValue)) {
                 // handle create new order
-                NewOrderNotification info = new NewOrderNotification(document);
+                NewOrderNotification info = new NewOrderNotification(document);              
                 String serialNumber = info.getSerialNumber();
                 try {
-                    helper.createOrder(info, getProductStoreId(request), getWebsiteId(request), getCurrencyUom(request), getLocale(request));
+                    helper.createOrder(info, ProductStoreWorker.getProductStoreId(request), ProductStoreWorker.getStoreLocale(request));
                     sendResponse(response, serialNumber, false);
                 } catch (GeneralException e) {
                     Debug.logError(e, module);
@@ -175,46 +170,5 @@
                 out.close();
             }
         }
-    }
-    
-    private static String getWebsiteId(HttpServletRequest request) {
-        return (String) request.getSession().getAttribute("webSiteId");
-    }
-    
-    private static String getProductStoreId(HttpServletRequest request) {
-        return ProductStoreWorker.getProductStoreId(request);
-    }
-    
-    private static String getCurrencyUom(HttpServletRequest request) {
-        GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
-        String productStoreId = getProductStoreId(request);
-        GenericValue productStore = null;
-        try {
-            productStore = delegator.findOne("ProductStore", true, "productStoreId", productStoreId);
-        } catch (GenericEntityException e) {
-            Debug.logError(e, module);
-        }
-        if (productStore != null) {
-            return productStore.getString("defaultCurrencyUomId");
-        }
-        return null;
-    }
-    
-    private static Locale getLocale(HttpServletRequest request) {
-        GenericDelegator delegator = (GenericDelegator) request.getAttribute("delegator");
-        String productStoreId = getProductStoreId(request);
-        GenericValue productStore = null;
-        try {
-            productStore = delegator.findOne("ProductStore", true, "productStoreId", productStoreId);
-        } catch (GenericEntityException e) {
-            Debug.logError(e, module);
-        }
-        if (productStore != null) {
-            String localeStr = productStore.getString("defaultLocaleString");
-            if (localeStr != null) {
-                return UtilMisc.parseLocale(localeStr);
-            }
-        }
-        return null;
-    }
+    }                        
 }

Modified: ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleRequestServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleRequestServices.java?rev=780306&r1=780305&r2=780306&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleRequestServices.java (original)
+++ ofbiz/trunk/specialpurpose/googlecheckout/src/org/ofbiz/googlecheckout/GoogleRequestServices.java Sat May 30 17:47:08 2009
@@ -19,7 +19,6 @@
 
 package org.ofbiz.googlecheckout;
 
-import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -63,7 +62,8 @@
         ShoppingCart cart = (ShoppingCart) context.get("shoppingCart");
         String productStoreId = cart.getProductStoreId();
         GenericDelegator delegator = dctx.getDelegator();
-        MerchantInfo mInfo = getMerchantInfo();
+        GenericValue googleCfg = getGoogleConfiguration(delegator, productStoreId);
+        MerchantInfo mInfo = getMerchantInfo(delegator, productStoreId);
         if (mInfo == null) {
             Debug.logError("Invalid Google Chechout Merchant settings, check your configuration!", module);
             return ServiceUtil.returnError("Google checkout configuration error");
@@ -71,23 +71,36 @@
         
         // the checkout request object
         CheckoutShoppingCartRequest req = new CheckoutShoppingCartRequest(mInfo, 300);
-        req.setRequestInitialAuthDetails(true); // send the auth notification
+        String requestAuthStr = googleCfg.getString("requestAuthDetails");
+        if (requestAuthStr == null) {
+            requestAuthStr = "Y";
+        }
+        boolean requestAuth = "Y".equalsIgnoreCase(requestAuthStr) ? true : false;
+        req.setRequestInitialAuthDetails(requestAuth); // send the auth notification
+        
+        String sendPromoItemStr = googleCfg.getString("sendPromoItems");
+        if (sendPromoItemStr == null) {
+            sendPromoItemStr = "Y";
+        }
+        boolean sendPromoItems = "Y".equalsIgnoreCase(sendPromoItemStr) ? true : false;
         
         // add the items
         List<ShoppingCartItem> items = cart.items();
-        for (ShoppingCartItem item : items) {                        
-            Item i = new Item();            
-            i.setItemName(item.getName());
-            i.setItemDescription(item.getDescription());
-            i.setMerchantItemId(item.getProductId());
-            i.setQuantity(item.getQuantity().intValue());
-            i.setUnitPriceAmount(item.getBasePrice().floatValue());
-            i.setUnitPriceCurrency(cart.getCurrency());            
-            //i.setItemWeight(item.getWeight().floatValue()); // must convert weight to Lb
-            if (!item.taxApplies()) {
-                i.setTaxTableSelector("tax_exempt");
+        for (ShoppingCartItem item : items) {
+            if (!item.getIsPromo() || sendPromoItems) {
+                Item i = new Item();            
+                i.setItemName(item.getName());
+                i.setItemDescription(item.getDescription());
+                i.setMerchantItemId(item.getProductId());
+                i.setQuantity(item.getQuantity().intValue());
+                i.setUnitPriceAmount(item.getBasePrice().floatValue());
+                i.setUnitPriceCurrency(cart.getCurrency());            
+                //i.setItemWeight(item.getWeight().floatValue()); // must convert weight to Lb
+                if (!item.taxApplies()) {
+                    i.setTaxTableSelector("tax_exempt");
+                }
+                req.addItem(i);
             }
-            req.addItem(i);
         }
                         
         // flow support URLs
@@ -154,9 +167,31 @@
         }
         
         // merchant stuff
-        //req.setAcceptMerchantCoupons(false); // disable coupons through google
-        //req.setAcceptMerchantGiftCertificates(false); // disable gift certs through google
-        req.setRequestBuyerPhoneNumber(true);
+        String acceptCouponStr = googleCfg.getString("acceptCoupons");
+        if (acceptCouponStr == null) {
+            acceptCouponStr = "N";
+        }
+        boolean acceptCoupons = "Y".equalsIgnoreCase(acceptCouponStr) ? true : false;
+                
+        String acceptCertStr = googleCfg.getString("acceptGiftCerts");
+        if (acceptCertStr == null) {
+            acceptCertStr = "N";
+        }
+        boolean acceptGiftCerts = "Y".equalsIgnoreCase(acceptCertStr) ? true : false;
+        
+        if (acceptCoupons || acceptGiftCerts) {
+            req.setAcceptMerchantCoupons(acceptCoupons);
+            req.setAcceptMerchantGiftCertificates(acceptGiftCerts);
+            
+            // TODO: merchant calc support needs to be implemented if these are ever TRUE
+        }
+        
+        String requestPhoneStr = googleCfg.getString("requestPhone");
+        if (requestPhoneStr == null) {
+            requestPhoneStr = "Y";
+        }
+        boolean requestPhone = "Y".equalsIgnoreCase(requestPhoneStr) ? true : false;                        
+        req.setRequestBuyerPhoneNumber(requestPhone);
         
         // send the request
         CheckoutResponse resp = null;
@@ -185,7 +220,7 @@
         String orderId = (String) context.get("orderId");
         GenericValue order = findGoogleOrder(delegator, orderId);
         if (order != null) {
-            MerchantInfo mInfo = getMerchantInfo();
+            MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
             if (mInfo != null) {
                 String externalId = order.getString("externalId");                
                 AddMerchantOrderNumberRequest aor = new AddMerchantOrderNumberRequest(mInfo, externalId, orderId);
@@ -205,7 +240,7 @@
         String orderId = (String) context.get("orderId");
         GenericValue order = findGoogleOrder(delegator, orderId);
         if (order != null) {
-            MerchantInfo mInfo = getMerchantInfo();
+            MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
             if (mInfo != null) {
                 String externalId = order.getString("externalId");
                 AuthorizeOrderRequest aor = new AuthorizeOrderRequest(mInfo, externalId);
@@ -226,7 +261,7 @@
         String orderId = (String) context.get("orderId");
         GenericValue order = findGoogleOrder(delegator, orderId);
         if (order != null) {
-            MerchantInfo mInfo = getMerchantInfo();
+            MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
             if (mInfo != null) {
                 String externalId = order.getString("externalId");
                 Double amountToCharge = (Double) context.get("captureAmount");
@@ -258,15 +293,13 @@
     
     public static Map<String, Object> sendShipRequest(DispatchContext dctx, Map<String, ? extends Object> context) {
         GenericDelegator delegator = dctx.getDelegator();
-        String shipmentId = (String) context.get("shipmentId");
-        MerchantInfo mInfo = getMerchantInfo();
-        if (mInfo != null) {
-            try {
-                sendItemsShipped(delegator, shipmentId, mInfo);
-            } catch (GeneralException e) {
-                // TODO: handle the error
-            }
-        }                
+        String shipmentId = (String) context.get("shipmentId");                
+        try {
+            sendItemsShipped(delegator, shipmentId);
+        } catch (GeneralException e) {
+            // TODO: handle the error
+        }
+        
         return ServiceUtil.returnSuccess();
     }
     
@@ -275,7 +308,7 @@
         String orderId = (String) context.get("orderId");
         GenericValue order = findGoogleOrder(delegator, orderId);
         if (order != null) {
-            MerchantInfo mInfo = getMerchantInfo();
+            MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
             if (mInfo != null) {
                 String externalId = order.getString("externalId");                
                 CancelOrderRequest cor = new CancelOrderRequest(mInfo, externalId, "Order Cancelled", ""); // TODO: configure the reason and comment
@@ -304,7 +337,7 @@
             }
             
             if (orderItem != null) {
-                MerchantInfo mInfo = getMerchantInfo();
+                MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
                 if (mInfo != null) {
                     String externalId = order.getString("externalId");                    
                     CancelItemsRequest cir = new CancelItemsRequest(mInfo, externalId, "Item Cancelled", ""); // TODO: configure the reason and comment
@@ -326,7 +359,7 @@
         String orderId = (String) context.get("orderId");
         GenericValue order = findGoogleOrder(delegator, orderId);
         if (order != null) {
-            MerchantInfo mInfo = getMerchantInfo();
+            MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
             if (mInfo != null) {
                 String externalId = order.getString("externalId");                
                 ArchiveOrderRequest aor = new ArchiveOrderRequest(mInfo, externalId);
@@ -346,7 +379,7 @@
         String orderId = (String) context.get("orderId");
         GenericValue order = findGoogleOrder(delegator, orderId);
         if (order != null) {
-            MerchantInfo mInfo = getMerchantInfo();
+            MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
             if (mInfo != null) {
                 String externalId = order.getString("externalId");
                 UnarchiveOrderRequest uor = new UnarchiveOrderRequest(mInfo, externalId);
@@ -373,7 +406,7 @@
         return ServiceUtil.returnSuccess();        
     }    
     
-    private static void sendItemsShipped(GenericDelegator delegator, String shipmentId, MerchantInfo mInfo) throws GeneralException {
+    private static void sendItemsShipped(GenericDelegator delegator, String shipmentId) throws GeneralException {
         List<GenericValue> issued = delegator.findByAnd("ItemIssuance", UtilMisc.toMap("shipmentId", shipmentId));
         if (issued != null && issued.size() > 0) {
             for (GenericValue issue : issued) {
@@ -384,6 +417,12 @@
                 GenericValue order = findGoogleOrder(delegator, orderId);
                                 
                 if (order != null) {
+                    MerchantInfo mInfo = getMerchantInfo(delegator, getProductStoreFromOrder(order));
+                    if (mInfo == null) {
+                        Debug.logInfo("Cannot find Google MerchantInfo for Order #" + orderId, module);
+                        continue;
+                    }
+                    
                     String externalId = order.getString("externalId");
                     
                     // locate the shipment package content record
@@ -414,6 +453,8 @@
                                     try {
                                         ShipItemsRequest isr = new ShipItemsRequest(mInfo, externalId);
                                         isr.addItemShippingInformation(productId, carrier, track);
+                                        Debug.logInfo("Sending item shipped notification: " + productId + " / " + carrier + " / " + track, module);
+                                        Debug.logInfo("Using merchantInfo : " + mInfo.getMerchantId() + " #" + externalId, module);
                                         isr.send();
                                     } catch (CheckoutException e) {
                                         Debug.logError(e, module);
@@ -446,40 +487,82 @@
         
         return null;
     }
-                          
-    public static MerchantInfo getMerchantInfo() {
+    
+    public static String getProductStoreFromShipment(GenericDelegator delegator, String shipmentId) {
+        GenericValue shipment = null;
+        try {
+            shipment = delegator.findOne("Shipment", false, "shipmentId", shipmentId);
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+        }
+        if (shipment != null) {
+            String orderId = shipment.getString("primaryOrderId");
+            return getProductStoreFromOrder(findGoogleOrder(delegator, orderId));
+        }
+        return null;
+    }
+    
+    public static String getProductStoreFromOrder(GenericValue order) {
+        if  (order != null) {
+            return order.getString("productStoreId");
+        }
+        return null;
+    }
+    
+    public static GenericValue getGoogleConfiguration(GenericDelegator delegator, String productStoreId) {
+        if (productStoreId == null) return null;
+        GenericValue config = null;
+        try {
+            config = delegator.findOne("GoogleConfiguration", true, "productStoreId", productStoreId);
+        } catch (GenericEntityException e) {
+            Debug.logError(e, module);
+        }
+        return config;
+    }
+    
+    public static MerchantInfo getMerchantInfo(GenericDelegator delegator, String productStoreId) {
+        // google configuration
+        GenericValue config = getGoogleConfiguration(delegator, productStoreId);
+        if (config == null) {
+            Debug.logError("No google configuration found for product store ID : " + productStoreId, module);
+            return null;
+        }
+        
         // merchant information
-        String merchantId = UtilProperties.getPropertyValue("googleCheckout.properties", "merchantId");
-        String merchantKey = UtilProperties.getPropertyValue("googleCheckout.properties", "merchantKey");
-        String environment = UtilProperties.getPropertyValue("googleCheckout.properties", "environment.mode", "Sandbox");
-        String currencyCode = "USD";
+        String merchantId = config.getString("merchantId");
+        String merchantKey = config.getString("merchantKey");
+        String envEnumId = config.getString("envEnumId");
+        String currencyCode = config.getString("currencyUomId");
         
         if (UtilValidate.isEmpty(merchantId) || UtilValidate.isEmpty(merchantKey)) {
             return null;
         }
         
         // base URLs
-        String productionRoot = UtilProperties.getPropertyValue("googleCheckout.properties", "production.root.url");
-        String sandboxRoot = UtilProperties.getPropertyValue("googleCheckout.properties", "sandbox.root.url");
+        String productionRoot = UtilProperties.getPropertyValue("google-checkout.properties", "production.root.url");
+        String sandboxRoot = UtilProperties.getPropertyValue("google-checkout.properties", "sandbox.root.url");
         
         // command strings
-        String merchantCheckoutCommand = UtilProperties.getPropertyValue("googleCheckout.properties", "merchant.checkout.command", "merchantCheckout");
-        String checkoutCommand = UtilProperties.getPropertyValue("googleCheckout.properties", "checkout.command", "checkout");        
-        String requestCommand = UtilProperties.getPropertyValue("googleCheckout.properties", "request.command", "request");
+        String merchantCheckoutCommand = UtilProperties.getPropertyValue("google-checkout.properties", "merchant.checkout.command", "merchantCheckout");
+        String checkoutCommand = UtilProperties.getPropertyValue("google-checkout.properties", "checkout.command", "checkout");        
+        String requestCommand = UtilProperties.getPropertyValue("google-checkout.properties", "request.command", "request");
 
+        String environment = null;
         String checkoutUrl = "";
         String merchantCheckoutUrl = "";
         String requestUrl = "";
 
         // build the URLs based on the Environment type
-        if (EnvironmentType.Sandbox.equals(environment)) {
+        if ("GOOGLE_SANDBOX".equals(envEnumId)) {
             merchantCheckoutUrl = sandboxRoot + "/" + merchantCheckoutCommand + "/Merchant/" + merchantId;
             checkoutUrl = sandboxRoot + "/" + checkoutCommand + "/Merchant/" + merchantId;            
             requestUrl = sandboxRoot + "/" + requestCommand + "/Merchant/" + merchantId;
-        } else if (EnvironmentType.Production.equals(environment)) {
+            environment = EnvironmentType.Sandbox;
+        } else if ("GOOGLE_PRODUCTION".equals(envEnumId)) {
             merchantCheckoutUrl = productionRoot + "/" + merchantCheckoutCommand + "/Merchant/" + merchantId;
             checkoutUrl = productionRoot + "/" + checkoutCommand + "/Merchant/" + merchantId;            
             requestUrl = productionRoot + "/" + requestCommand + "/Merchant/" + merchantId;
+            environment = EnvironmentType.Production;
         } else {
             Debug.logError("Environment must be one of " + EnvironmentType.Sandbox + " or " + EnvironmentType.Production + ".", module);
             return null;