com.salesmanager.core.business.modules.integration.shipping.impl.UPSShippingQuote.java Source code

Java tutorial

Introduction

Here is the source code for com.salesmanager.core.business.modules.integration.shipping.impl.UPSShippingQuote.java

Source

package com.salesmanager.core.business.modules.integration.shipping.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.apache.commons.digester.Digester;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.salesmanager.core.business.utils.DataUtils;
import com.salesmanager.core.model.common.Delivery;
import com.salesmanager.core.model.merchant.MerchantStore;
import com.salesmanager.core.model.reference.country.Country;
import com.salesmanager.core.model.shipping.PackageDetails;
import com.salesmanager.core.model.shipping.ShippingConfiguration;
import com.salesmanager.core.model.shipping.ShippingOption;
import com.salesmanager.core.model.shipping.ShippingOrigin;
import com.salesmanager.core.model.shipping.ShippingQuote;
import com.salesmanager.core.model.system.CustomIntegrationConfiguration;
import com.salesmanager.core.model.system.IntegrationConfiguration;
import com.salesmanager.core.model.system.IntegrationModule;
import com.salesmanager.core.model.system.ModuleConfig;
import com.salesmanager.core.modules.integration.IntegrationException;
import com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule;

/**
 * Integrates with UPS online API
 * @author casams1
 *
 */
public class UPSShippingQuote implements ShippingQuoteModule {

    private static final Logger LOGGER = LoggerFactory.getLogger(UPSShippingQuote.class);

    @Override
    public void validateModuleConfiguration(IntegrationConfiguration integrationConfiguration, MerchantStore store)
            throws IntegrationException {

        List<String> errorFields = null;

        //validate integrationKeys['accessKey']
        Map<String, String> keys = integrationConfiguration.getIntegrationKeys();
        if (keys == null || StringUtils.isBlank(keys.get("accessKey"))) {
            errorFields = new ArrayList<String>();
            errorFields.add("accessKey");
        }

        if (keys == null || StringUtils.isBlank(keys.get("userId"))) {
            errorFields = new ArrayList<String>();
            errorFields.add("userId");
        }

        if (keys == null || StringUtils.isBlank(keys.get("password"))) {
            errorFields = new ArrayList<String>();
            errorFields.add("password");
        }

        //validate at least one integrationOptions['packages']
        Map<String, List<String>> options = integrationConfiguration.getIntegrationOptions();
        if (options == null) {
            errorFields = new ArrayList<String>();
            errorFields.add("packages");
        }

        List<String> packages = options.get("packages");
        if (packages == null || packages.size() == 0) {
            if (errorFields == null) {
                errorFields = new ArrayList<String>();
            }
            errorFields.add("packages");
        }

        /*      List<String> services = options.get("services");
              if(services==null || services.size()==0) {
                 if(errorFields==null) {
        errorFields = new ArrayList<String>();
                 }
                 errorFields.add("services");
              }
                  
              if(services!=null && services.size()>3) {
                 if(errorFields==null) {
        errorFields = new ArrayList<String>();
                 }
                 errorFields.add("services");
              }*/

        if (errorFields != null) {
            IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
            ex.setErrorFields(errorFields);
            throw ex;

        }

    }

    @Override
    public List<ShippingOption> getShippingQuotes(ShippingQuote shippingQuote, List<PackageDetails> packages,
            BigDecimal orderTotal, Delivery delivery, ShippingOrigin origin, MerchantStore store,
            IntegrationConfiguration configuration, IntegrationModule module,
            ShippingConfiguration shippingConfiguration, Locale locale) throws IntegrationException {

        Validate.notNull(configuration, "IntegrationConfiguration must not be null for USPS shipping module");

        if (StringUtils.isBlank(delivery.getPostalCode())) {
            return null;
        }

        BigDecimal total = orderTotal;

        if (packages == null) {
            return null;
        }

        List<ShippingOption> options = null;

        // only applies to Canada and US
        Country country = delivery.getCountry();

        if (!(country.getIsoCode().equals("US") || country.getIsoCode().equals("CA"))) {
            return null;
            //throw new IntegrationException("UPS Not configured for shipping in country " + country.getIsoCode());
        }

        // supports en and fr
        String language = locale.getLanguage();
        if (!language.equals(Locale.FRENCH.getLanguage()) && !language.equals(Locale.ENGLISH.getLanguage())) {
            language = Locale.ENGLISH.getLanguage();
        }

        String pack = configuration.getIntegrationOptions().get("packages").get(0);
        Map<String, String> keys = configuration.getIntegrationKeys();

        String accessKey = keys.get("accessKey");
        String userId = keys.get("userId");
        String password = keys.get("password");

        String host = null;
        String protocol = null;
        String port = null;
        String url = null;

        StringBuilder xmlbuffer = new StringBuilder();
        HttpPost httppost = null;
        BufferedReader reader = null;

        try {
            String env = configuration.getEnvironment();

            Set<String> regions = module.getRegionsSet();
            if (!regions.contains(store.getCountry().getIsoCode())) {
                throw new IntegrationException("Can't use the service for store country code ");
            }

            Map<String, ModuleConfig> moduleConfigsMap = module.getModuleConfigs();
            for (String key : moduleConfigsMap.keySet()) {

                ModuleConfig moduleConfig = (ModuleConfig) moduleConfigsMap.get(key);
                if (moduleConfig.getEnv().equals(env)) {
                    host = moduleConfig.getHost();
                    protocol = moduleConfig.getScheme();
                    port = moduleConfig.getPort();
                    url = moduleConfig.getUri();
                }
            }

            StringBuilder xmlreqbuffer = new StringBuilder();
            xmlreqbuffer.append("<?xml version=\"1.0\"?>");
            xmlreqbuffer.append("<AccessRequest>");
            xmlreqbuffer.append("<AccessLicenseNumber>");
            xmlreqbuffer.append(accessKey);
            xmlreqbuffer.append("</AccessLicenseNumber>");
            xmlreqbuffer.append("<UserId>");
            xmlreqbuffer.append(userId);
            xmlreqbuffer.append("</UserId>");
            xmlreqbuffer.append("<Password>");
            xmlreqbuffer.append(password);
            xmlreqbuffer.append("</Password>");
            xmlreqbuffer.append("</AccessRequest>");

            String xmlhead = xmlreqbuffer.toString();

            String weightCode = store.getWeightunitcode();
            String measureCode = store.getSeizeunitcode();

            if (weightCode.equals("KG")) {
                weightCode = "KGS";
            } else {
                weightCode = "LBS";
            }

            String xml = "<?xml version=\"1.0\"?><RatingServiceSelectionRequest><Request><TransactionReference><CustomerContext>Shopizer</CustomerContext><XpciVersion>1.0001</XpciVersion></TransactionReference><RequestAction>Rate</RequestAction><RequestOption>Shop</RequestOption></Request>";
            StringBuffer xmldatabuffer = new StringBuffer();

            /**
             * <Shipment>
             * 
             * <Shipper> <Address> <City></City>
             * <StateProvinceCode>QC</StateProvinceCode>
             * <CountryCode>CA</CountryCode> <PostalCode></PostalCode>
             * </Address> </Shipper>
             * 
             * <ShipTo> <Address> <City>Redwood Shores</City>
             * <StateProvinceCode>CA</StateProvinceCode>
             * <CountryCode>US</CountryCode> <PostalCode></PostalCode>
             * <ResidentialAddressIndicator/> </Address> </ShipTo>
             * 
             * <Package> <PackagingType> <Code>21</Code> </PackagingType>
             * <PackageWeight> <UnitOfMeasurement> <Code>LBS</Code>
             * </UnitOfMeasurement> <Weight>1.1</Weight> </PackageWeight>
             * <PackageServiceOptions> <InsuredValue>
             * <CurrencyCode>CAD</CurrencyCode>
             * <MonetaryValue>100</MonetaryValue> </InsuredValue>
             * </PackageServiceOptions> </Package>
             * 
             * 
             * </Shipment>
             * 
             * <CustomerClassification> <Code>03</Code>
             * </CustomerClassification> </RatingServiceSelectionRequest>
             * **/

            /**Map countriesMap = (Map) RefCache.getAllcountriesmap(LanguageUtil
                  .getLanguageNumberCode(locale.getLanguage()));
            Map zonesMap = (Map) RefCache.getAllZonesmap(LanguageUtil
                  .getLanguageNumberCode(locale.getLanguage()));
                
            Country storeCountry = (Country) countriesMap.get(store
                  .getCountry());
                
            Country customerCountry = (Country) countriesMap.get(customer
                  .getCustomerCountryId());
                
            int sZone = -1;
            try {
               sZone = Integer.parseInt(store.getZone());
            } catch (Exception e) {
               // TODO: handle exception
            }
                
            Zone storeZone = (Zone) zonesMap.get(sZone);
            Zone customerZone = (Zone) zonesMap.get(customer
                  .getCustomerZoneId());**/

            xmldatabuffer.append("<PickupType><Code>03</Code></PickupType>");
            // xmldatabuffer.append("<Description>Daily Pickup</Description>");
            xmldatabuffer.append("<Shipment><Shipper>");
            xmldatabuffer.append("<Address>");
            xmldatabuffer.append("<City>");
            xmldatabuffer.append(store.getStorecity());
            xmldatabuffer.append("</City>");
            // if(!StringUtils.isBlank(store.getStorestateprovince())) {
            if (store.getZone() != null) {
                xmldatabuffer.append("<StateProvinceCode>");
                xmldatabuffer.append(store.getZone().getCode());// zone code
                xmldatabuffer.append("</StateProvinceCode>");
            }
            xmldatabuffer.append("<CountryCode>");
            xmldatabuffer.append(store.getCountry().getIsoCode());
            xmldatabuffer.append("</CountryCode>");
            xmldatabuffer.append("<PostalCode>");
            xmldatabuffer.append(DataUtils.trimPostalCode(store.getStorepostalcode()));
            xmldatabuffer.append("</PostalCode></Address></Shipper>");

            // ship to
            xmldatabuffer.append("<ShipTo>");
            xmldatabuffer.append("<Address>");
            xmldatabuffer.append("<City>");
            xmldatabuffer.append(delivery.getCity());
            xmldatabuffer.append("</City>");
            // if(!StringUtils.isBlank(customer.getCustomerState())) {
            if (delivery.getZone() != null) {
                xmldatabuffer.append("<StateProvinceCode>");
                xmldatabuffer.append(delivery.getZone().getCode());// zone code
                xmldatabuffer.append("</StateProvinceCode>");
            }
            xmldatabuffer.append("<CountryCode>");
            xmldatabuffer.append(delivery.getCountry().getIsoCode());
            xmldatabuffer.append("</CountryCode>");
            xmldatabuffer.append("<PostalCode>");
            xmldatabuffer.append(DataUtils.trimPostalCode(delivery.getPostalCode()));
            xmldatabuffer.append("</PostalCode></Address></ShipTo>");
            // xmldatabuffer.append("<Service><Code>11</Code></Service>");//TODO service codes (next day ...)

            for (PackageDetails packageDetail : packages) {

                xmldatabuffer.append("<Package>");
                xmldatabuffer.append("<PackagingType>");
                xmldatabuffer.append("<Code>");
                xmldatabuffer.append(pack);
                xmldatabuffer.append("</Code>");
                xmldatabuffer.append("</PackagingType>");

                // weight
                xmldatabuffer.append("<PackageWeight>");
                xmldatabuffer.append("<UnitOfMeasurement>");
                xmldatabuffer.append("<Code>");
                xmldatabuffer.append(weightCode);
                xmldatabuffer.append("</Code>");
                xmldatabuffer.append("</UnitOfMeasurement>");
                xmldatabuffer.append("<Weight>");
                xmldatabuffer.append(
                        new BigDecimal(packageDetail.getShippingWeight()).setScale(1, BigDecimal.ROUND_HALF_UP));
                xmldatabuffer.append("</Weight>");
                xmldatabuffer.append("</PackageWeight>");

                // dimension
                xmldatabuffer.append("<Dimensions>");
                xmldatabuffer.append("<UnitOfMeasurement>");
                xmldatabuffer.append("<Code>");
                xmldatabuffer.append(measureCode);
                xmldatabuffer.append("</Code>");
                xmldatabuffer.append("</UnitOfMeasurement>");
                xmldatabuffer.append("<Length>");
                xmldatabuffer.append(
                        new BigDecimal(packageDetail.getShippingLength()).setScale(2, BigDecimal.ROUND_HALF_UP));
                xmldatabuffer.append("</Length>");
                xmldatabuffer.append("<Width>");
                xmldatabuffer.append(
                        new BigDecimal(packageDetail.getShippingWidth()).setScale(2, BigDecimal.ROUND_HALF_UP));
                xmldatabuffer.append("</Width>");
                xmldatabuffer.append("<Height>");
                xmldatabuffer.append(
                        new BigDecimal(packageDetail.getShippingHeight()).setScale(2, BigDecimal.ROUND_HALF_UP));
                xmldatabuffer.append("</Height>");
                xmldatabuffer.append("</Dimensions>");
                xmldatabuffer.append("</Package>");

            }

            xmldatabuffer.append("</Shipment>");
            xmldatabuffer.append("</RatingServiceSelectionRequest>");

            xmlbuffer.append(xmlhead).append(xml).append(xmldatabuffer.toString());

            LOGGER.debug("UPS QUOTE REQUEST " + xmlbuffer.toString());

            CloseableHttpClient httpclient = HttpClients.createDefault();
            //HttpClient client = new HttpClient();
            httppost = new HttpPost(protocol + "://" + host + ":" + port + url);

            StringEntity entity = new StringEntity(xmlbuffer.toString(), ContentType.APPLICATION_ATOM_XML);

            //RequestEntity entity = new StringRequestEntity(
            //      xmlbuffer.toString(), "text/plain", "UTF-8");
            httppost.setEntity(entity);

            // Create a custom response handler
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {

                @Override
                public String handleResponse(final HttpResponse response)
                        throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        LOGGER.error("Communication Error with ups quote " + status);
                        throw new ClientProtocolException("UPS quote communication error " + status);
                    }
                }

            };

            String data = httpclient.execute(httppost, responseHandler);

            //int result = response.getStatusLine().getStatusCode();
            //int result = client.executeMethod(httppost);
            /*         if (result != 200) {
                        LOGGER.error("Communication Error with ups quote " + result + " "
              + protocol + "://" + host + ":" + port + url);
                        throw new Exception("UPS quote communication error " + result);
                     }*/

            LOGGER.debug("ups quote response " + data);

            UPSParsedElements parsed = new UPSParsedElements();

            Digester digester = new Digester();
            digester.push(parsed);
            digester.addCallMethod("RatingServiceSelectionResponse/Response/Error", "setErrorCode", 0);
            digester.addCallMethod("RatingServiceSelectionResponse/Response/ErrorDescriprion", "setError", 0);
            digester.addCallMethod("RatingServiceSelectionResponse/Response/ResponseStatusCode", "setStatusCode",
                    0);
            digester.addCallMethod("RatingServiceSelectionResponse/Response/ResponseStatusDescription",
                    "setStatusMessage", 0);
            digester.addCallMethod("RatingServiceSelectionResponse/Response/Error/ErrorDescription", "setError", 0);

            digester.addObjectCreate("RatingServiceSelectionResponse/RatedShipment", ShippingOption.class);
            // digester.addSetProperties(
            // "RatingServiceSelectionResponse/RatedShipment", "sequence",
            // "optionId" );
            digester.addCallMethod("RatingServiceSelectionResponse/RatedShipment/Service/Code", "setOptionId", 0);
            digester.addCallMethod("RatingServiceSelectionResponse/RatedShipment/TotalCharges/MonetaryValue",
                    "setOptionPriceText", 0);
            //digester
            //      .addCallMethod(
            //            "RatingServiceSelectionResponse/RatedShipment/TotalCharges/CurrencyCode",
            //            "setCurrency", 0);
            digester.addCallMethod("RatingServiceSelectionResponse/RatedShipment/Service/Code", "setOptionCode", 0);
            digester.addCallMethod("RatingServiceSelectionResponse/RatedShipment/GuaranteedDaysToDelivery",
                    "setEstimatedNumberOfDays", 0);
            digester.addSetNext("RatingServiceSelectionResponse/RatedShipment", "addOption");

            // <?xml
            // version="1.0"?><AddressValidationResponse><Response><TransactionReference><CustomerContext>SalesManager
            // Data</CustomerContext><XpciVersion>1.0</XpciVersion></TransactionReference><ResponseStatusCode>0</ResponseStatusCode><ResponseStatusDescription>Failure</ResponseStatusDescription><Error><ErrorSeverity>Hard</ErrorSeverity><ErrorCode>10002</ErrorCode><ErrorDescription>The
            // XML document is well formed but the document is not
            // valid</ErrorDescription><ErrorLocation><ErrorLocationElementName>AddressValidationRequest</ErrorLocationElementName></ErrorLocation></Error></Response></AddressValidationResponse>

            Reader xmlreader = new StringReader(data);

            digester.parse(xmlreader);

            if (!StringUtils.isBlank(parsed.getErrorCode())) {

                LOGGER.error(
                        "Can't process UPS statusCode=" + parsed.getErrorCode() + " message= " + parsed.getError());
                throw new IntegrationException(parsed.getError());
            }
            if (!StringUtils.isBlank(parsed.getStatusCode()) && !parsed.getStatusCode().equals("1")) {

                throw new IntegrationException(parsed.getError());
            }

            if (parsed.getOptions() == null || parsed.getOptions().size() == 0) {

                throw new IntegrationException("No shipping options available for the configuration");
            }

            /*String carrier = getShippingMethodDescription(locale);
            // cost is in CAD, need to do conversion
                
                
            boolean requiresCurrencyConversion = false; String storeCurrency
             = store.getCurrency();
            if(!storeCurrency.equals(Constants.CURRENCY_CODE_CAD)) {
             requiresCurrencyConversion = true; }
                 
                
            LabelUtil labelUtil = LabelUtil.getInstance();
            Map serviceMap = com.salesmanager.core.util.ShippingUtil
                  .buildServiceMap("upsxml", locale);
                
            *//** Details on whit RT quote information to display **//*
                                                                      MerchantConfiguration rtdetails = config
                                                                      .getMerchantConfiguration(ShippingConstants.MODULE_SHIPPING_DISPLAY_REALTIME_QUOTES);
                                                                      int displayQuoteDeliveryTime = ShippingConstants.NO_DISPLAY_RT_QUOTE_TIME;
                                                                          
                                                                          
                                                                      if (rtdetails != null) {
                                                                          
                                                                      if (!StringUtils.isBlank(rtdetails.getConfigurationValue1())) {// display
                                                                      // or
                                                                      // not
                                                                      // quotes
                                                                      try {
                                                                      displayQuoteDeliveryTime = Integer.parseInt(rtdetails
                                                                      .getConfigurationValue1());
                                                                          
                                                                      } catch (Exception e) {
                                                                      log.error("Display quote is not an integer value ["
                                                                      + rtdetails.getConfigurationValue1() + "]");
                                                                      }
                                                                      }
                                                                      }*/

            List<ShippingOption> shippingOptions = parsed.getOptions();

            if (shippingOptions != null) {

                Map<String, String> details = module.getDetails();

                for (ShippingOption option : shippingOptions) {

                    String name = details.get(option.getOptionCode());
                    option.setOptionName(name);
                    if (option.getOptionPrice() == null) {
                        String priceText = option.getOptionPriceText();
                        if (StringUtils.isBlank(priceText)) {
                            throw new IntegrationException("Price text is null for option " + name);
                        }

                        try {
                            BigDecimal price = new BigDecimal(priceText);
                            option.setOptionPrice(price);
                        } catch (Exception e) {
                            throw new IntegrationException("Can't convert to numeric price " + priceText);
                        }

                    }

                }

            }

            /*         if (options != null) {
                
                        Map selectedintlservices = (Map) config
              .getConfiguration("service-global-upsxml");
                
                        Iterator i = options.iterator();
                        while (i.hasNext()) {
                           ShippingOption option = (ShippingOption) i.next();
                           // option.setCurrency(store.getCurrency());
                           StringBuffer description = new StringBuffer();
                
                           String code = option.getOptionCode();
                           option.setOptionCode(code);
                           // get description
                           String label = (String) serviceMap.get(code);
                           if (label == null) {
              log
                    .warn("UPSXML cannot find description for service code "
                          + code);
                           }
                
                           option.setOptionName(label);
                
                           description.append(option.getOptionName());
                           if (displayQuoteDeliveryTime == ShippingConstants.DISPLAY_RT_QUOTE_TIME) {
              if (!StringUtils.isBlank(option
                    .getEstimatedNumberOfDays())) {
                 description.append(" (").append(
                       option.getEstimatedNumberOfDays()).append(
                       " ").append(
                       labelUtil.getText(locale,
                             "label.generic.days.lowercase"))
                       .append(")");
              }
                           }
                           option.setDescription(description.toString());
                
                           // get currency
                           if (!option.getCurrency().equals(store.getCurrency())) {
              option.setOptionPrice(CurrencyUtil.convertToCurrency(
                    option.getOptionPrice(), option.getCurrency(),
                    store.getCurrency()));
                           }
                
                           if (!selectedintlservices.containsKey(option
                 .getOptionCode())) {
              if (returnColl == null) {
                 returnColl = new ArrayList();
              }
              returnColl.add(option);
              // options.remove(option);
                           }
                
                        }
                
                        if (options.size() == 0) {
                           LogMerchantUtil
                 .log(
                       store.getMerchantId(),
                       " none of the service code returned by UPS ["
                             + selectedintlservices
                                   .keySet()
                                   .toArray(
                                         new String[selectedintlservices
                                               .size()])
                             + "] for this shipping is in your selection list");
                        }
                     }*/

            return shippingOptions;

        } catch (Exception e1) {
            LOGGER.error("UPS quote error", e1);
            throw new IntegrationException(e1);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception ignore) {
                }
            }

            if (httppost != null) {
                httppost.releaseConnection();
            }
        }
    }

    @Override
    public CustomIntegrationConfiguration getCustomModuleConfiguration(MerchantStore store)
            throws IntegrationException {
        //nothing to do
        return null;
    }
}

class UPSParsedElements {

    private String statusCode;
    private String statusMessage;
    private String error = "";
    private String errorCode = "";
    private List<ShippingOption> options = new ArrayList<ShippingOption>();

    public void addOption(ShippingOption option) {
        options.add(option);
    }

    public List<ShippingOption> getOptions() {
        return options;
    }

    public String getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(String statusCode) {
        this.statusCode = statusCode;
    }

    public String getStatusMessage() {
        return statusMessage;
    }

    public void setStatusMessage(String statusMessage) {
        this.statusMessage = statusMessage;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

}