0001: /*
0002: * $Id: UpsServices.java,v 1.1 2003/08/18 18:45:49 jonesde Exp $
0003: *
0004: * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: */
0024: package org.ofbiz.shipment.thirdparty.ups;
0025:
0026: import java.io.File;
0027: import java.io.FileOutputStream;
0028: import java.io.IOException;
0029: import java.util.HashMap;
0030: import java.util.Iterator;
0031: import java.util.LinkedList;
0032: import java.util.List;
0033: import java.util.Map;
0034: import java.util.Set;
0035: import java.util.TreeSet;
0036:
0037: import javax.xml.parsers.ParserConfigurationException;
0038:
0039: import org.ofbiz.base.util.Base64;
0040: import org.ofbiz.base.util.Debug;
0041: import org.ofbiz.base.util.GeneralException;
0042: import org.ofbiz.base.util.HttpClient;
0043: import org.ofbiz.base.util.HttpClientException;
0044: import org.ofbiz.base.util.StringUtil;
0045: import org.ofbiz.base.util.UtilMisc;
0046: import org.ofbiz.base.util.UtilProperties;
0047: import org.ofbiz.base.util.UtilValidate;
0048: import org.ofbiz.base.util.UtilXml;
0049: import org.ofbiz.entity.GenericDelegator;
0050: import org.ofbiz.entity.GenericEntityException;
0051: import org.ofbiz.entity.GenericValue;
0052: import org.ofbiz.service.DispatchContext;
0053: import org.ofbiz.service.ServiceUtil;
0054: import org.w3c.dom.Document;
0055: import org.w3c.dom.Element;
0056: import org.xml.sax.SAXException;
0057:
0058: /**
0059: * UPS ShipmentServices
0060: *
0061: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0062: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0063: * @version $Revision: 1.1 $
0064: * @since 2.2
0065: */
0066: public class UpsServices {
0067:
0068: public final static String module = UpsServices.class.getName();
0069:
0070: public static Map unitsUpsToOfbiz = new HashMap();
0071: public static Map unitsOfbizToUps = new HashMap();
0072: static {
0073: unitsUpsToOfbiz.put("LBS", "WT_lb");
0074: unitsUpsToOfbiz.put("KGS", "WT_kg");
0075:
0076: Iterator unitsUpsToOfbizIter = unitsUpsToOfbiz.entrySet()
0077: .iterator();
0078: while (unitsUpsToOfbizIter.hasNext()) {
0079: Map.Entry entry = (Map.Entry) unitsUpsToOfbizIter.next();
0080: unitsOfbizToUps.put(entry.getValue(), entry.getKey());
0081: }
0082: }
0083:
0084: public static Map upsShipmentConfirm(DispatchContext dctx,
0085: Map context) {
0086: Map result = new HashMap();
0087: GenericDelegator delegator = dctx.getDelegator();
0088: String shipmentId = (String) context.get("shipmentId");
0089: String shipmentRouteSegmentId = (String) context
0090: .get("shipmentRouteSegmentId");
0091:
0092: boolean shipmentUpsSaveCertificationInfo = "true"
0093: .equals(UtilProperties.getPropertyValue("shipment",
0094: "shipment.ups.save.certification.info"));
0095: String shipmentUpsSaveCertificationPath = UtilProperties
0096: .getPropertyValue("shipment",
0097: "shipment.ups.save.certification.path");
0098: File shipmentUpsSaveCertificationFile = null;
0099: if (shipmentUpsSaveCertificationInfo) {
0100: shipmentUpsSaveCertificationFile = new File(
0101: shipmentUpsSaveCertificationPath);
0102: if (!shipmentUpsSaveCertificationFile.exists()) {
0103: shipmentUpsSaveCertificationFile.mkdirs();
0104: }
0105: }
0106:
0107: String shipmentConfirmResponseString = null;
0108:
0109: try {
0110: GenericValue shipment = delegator.findByPrimaryKey(
0111: "Shipment", UtilMisc
0112: .toMap("shipmentId", shipmentId));
0113: if (shipment == null) {
0114: return ServiceUtil
0115: .returnError("Shipment not found with ID "
0116: + shipmentId);
0117: }
0118: GenericValue shipmentRouteSegment = delegator
0119: .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
0120: .toMap("shipmentId", shipmentId,
0121: "shipmentRouteSegmentId",
0122: shipmentRouteSegmentId));
0123: if (shipmentRouteSegment == null) {
0124: return ServiceUtil
0125: .returnError("ShipmentRouteSegment not found with shipmentId "
0126: + shipmentId
0127: + " and shipmentRouteSegmentId "
0128: + shipmentRouteSegmentId);
0129: }
0130:
0131: if (!"UPS".equals(shipmentRouteSegment
0132: .getString("carrierPartyId"))) {
0133: return ServiceUtil
0134: .returnError("ERROR: The Carrier for ShipmentRouteSegment "
0135: + shipmentRouteSegmentId
0136: + " of Shipment "
0137: + shipmentId
0138: + ", is not UPS.");
0139: }
0140:
0141: // add ShipmentRouteSegment carrierServiceStatusId, check before all UPS services
0142: if (UtilValidate.isNotEmpty(shipmentRouteSegment
0143: .getString("carrierServiceStatusId"))
0144: && !"SHRSCS_NOT_STARTED"
0145: .equals(shipmentRouteSegment
0146: .getString("carrierServiceStatusId"))) {
0147: return ServiceUtil
0148: .returnError("ERROR: The Carrier Service Status for ShipmentRouteSegment "
0149: + shipmentRouteSegmentId
0150: + " of Shipment "
0151: + shipmentId
0152: + ", is ["
0153: + shipmentRouteSegment
0154: .getString("carrierServiceStatusId")
0155: + "], but must be not-set or [SHRSCS_NOT_STARTED] to perform the UPS Shipment Confirm operation.");
0156: }
0157:
0158: // Get Origin Info
0159: GenericValue originPostalAddress = shipmentRouteSegment
0160: .getRelatedOne("OriginPostalAddress");
0161: if (originPostalAddress == null) {
0162: return ServiceUtil
0163: .returnError("OriginPostalAddress not found for ShipmentRouteSegment with shipmentId "
0164: + shipmentId
0165: + " and shipmentRouteSegmentId "
0166: + shipmentRouteSegmentId);
0167: }
0168: GenericValue originTelecomNumber = shipmentRouteSegment
0169: .getRelatedOne("OriginTelecomNumber");
0170: if (originTelecomNumber == null) {
0171: return ServiceUtil
0172: .returnError("OriginTelecomNumber not found for ShipmentRouteSegment with shipmentId "
0173: + shipmentId
0174: + " and shipmentRouteSegmentId "
0175: + shipmentRouteSegmentId);
0176: }
0177: String originPhoneNumber = originTelecomNumber
0178: .getString("areaCode")
0179: + originTelecomNumber.getString("contactNumber");
0180: // don't put on country code if not specified or is the US country code (UPS wants it this way)
0181: if (UtilValidate.isNotEmpty(originTelecomNumber
0182: .getString("countryCode"))
0183: && !"001".equals(originTelecomNumber
0184: .getString("countryCode"))) {
0185: originPhoneNumber = originTelecomNumber
0186: .getString("countryCode")
0187: + originPhoneNumber;
0188: }
0189: originPhoneNumber = StringUtil.replaceString(
0190: originPhoneNumber, "-", "");
0191: originPhoneNumber = StringUtil.replaceString(
0192: originPhoneNumber, " ", "");
0193: // lookup the two letter country code (in the geoCode field)
0194: GenericValue originCountryGeo = originPostalAddress
0195: .getRelatedOne("CountryGeo");
0196: if (originCountryGeo == null) {
0197: return ServiceUtil
0198: .returnError("OriginCountryGeo not found for ShipmentRouteSegment with shipmentId "
0199: + shipmentId
0200: + " and shipmentRouteSegmentId "
0201: + shipmentRouteSegmentId);
0202: }
0203:
0204: // Get Dest Info
0205: GenericValue destPostalAddress = shipmentRouteSegment
0206: .getRelatedOne("DestPostalAddress");
0207: if (destPostalAddress == null) {
0208: return ServiceUtil
0209: .returnError("DestPostalAddress not found for ShipmentRouteSegment with shipmentId "
0210: + shipmentId
0211: + " and shipmentRouteSegmentId "
0212: + shipmentRouteSegmentId);
0213: }
0214:
0215: GenericValue destTelecomNumber = shipmentRouteSegment
0216: .getRelatedOne("DestTelecomNumber");
0217: if (destTelecomNumber == null) {
0218: String missingErrMsg = "DestTelecomNumber not found for ShipmentRouteSegment with shipmentId "
0219: + shipmentId
0220: + " and shipmentRouteSegmentId "
0221: + shipmentRouteSegmentId;
0222: Debug.logError(missingErrMsg, module);
0223: // for now we won't require the dest phone number, but is it required?
0224: //return ServiceUtil.returnError(missingErrMsg);
0225: }
0226: String destPhoneNumber = null;
0227: if (destTelecomNumber != null) {
0228: destPhoneNumber = destTelecomNumber
0229: .getString("areaCode")
0230: + destTelecomNumber.getString("contactNumber");
0231: // don't put on country code if not specified or is the US country code (UPS wants it this way)
0232: if (UtilValidate.isNotEmpty(destTelecomNumber
0233: .getString("countryCode"))
0234: && !"001".equals(destTelecomNumber
0235: .getString("countryCode"))) {
0236: destPhoneNumber = destTelecomNumber
0237: .getString("countryCode")
0238: + destPhoneNumber;
0239: }
0240: destPhoneNumber = StringUtil.replaceString(
0241: destPhoneNumber, "-", "");
0242: destPhoneNumber = StringUtil.replaceString(
0243: destPhoneNumber, " ", "");
0244: }
0245:
0246: // lookup the two letter country code (in the geoCode field)
0247: GenericValue destCountryGeo = destPostalAddress
0248: .getRelatedOne("CountryGeo");
0249: if (destCountryGeo == null) {
0250: return ServiceUtil
0251: .returnError("DestCountryGeo not found for ShipmentRouteSegment with shipmentId "
0252: + shipmentId
0253: + " and shipmentRouteSegmentId "
0254: + shipmentRouteSegmentId);
0255: }
0256:
0257: Map findCarrierShipmentMethodMap = UtilMisc.toMap(
0258: "partyId", shipmentRouteSegment
0259: .get("carrierPartyId"), "roleTypeId",
0260: "CARRIER", "shipmentMethodTypeId",
0261: shipmentRouteSegment.get("shipmentMethodTypeId"));
0262: GenericValue carrierShipmentMethod = delegator
0263: .findByPrimaryKey("CarrierShipmentMethod",
0264: findCarrierShipmentMethodMap);
0265: if (carrierShipmentMethod == null) {
0266: return ServiceUtil
0267: .returnError("CarrierShipmentMethod not found for ShipmentRouteSegment with shipmentId "
0268: + shipmentId
0269: + " and shipmentRouteSegmentId "
0270: + shipmentRouteSegmentId
0271: + "; partyId is "
0272: + shipmentRouteSegment
0273: .get("carrierPartyId")
0274: + " and shipmentMethodTypeId is "
0275: + shipmentRouteSegment
0276: .get("shipmentMethodTypeId"));
0277: }
0278:
0279: List shipmentPackageRouteSegs = shipmentRouteSegment
0280: .getRelated("ShipmentPackageRouteSeg", null,
0281: UtilMisc.toList("+shipmentPackageSeqId"));
0282: if (shipmentPackageRouteSegs == null
0283: || shipmentPackageRouteSegs.size() == 0) {
0284: return ServiceUtil
0285: .returnError("No ShipmentPackageRouteSegs (ie No Packages) found for ShipmentRouteSegment with shipmentId "
0286: + shipmentId
0287: + " and shipmentRouteSegmentId "
0288: + shipmentRouteSegmentId);
0289: }
0290:
0291: List itemIssuances = shipment.getRelated("ItemIssuance");
0292: Set orderIdSet = new TreeSet();
0293: Iterator itemIssuanceIter = itemIssuances.iterator();
0294: while (itemIssuanceIter.hasNext()) {
0295: GenericValue itemIssuance = (GenericValue) itemIssuanceIter
0296: .next();
0297: orderIdSet.add(itemIssuance.get("orderId"));
0298: }
0299: String ordersDescription = "";
0300: if (orderIdSet.size() > 1) {
0301: StringBuffer odBuf = new StringBuffer("Orders ");
0302: Iterator orderIdIter = orderIdSet.iterator();
0303: while (orderIdIter.hasNext()) {
0304: String orderId = (String) orderIdIter.next();
0305: odBuf.append(orderId);
0306: if (orderIdIter.hasNext()) {
0307: odBuf.append(", ");
0308: }
0309: }
0310: ordersDescription = odBuf.toString();
0311: } else if (orderIdSet.size() > 0) {
0312: ordersDescription = "Order "
0313: + (String) orderIdSet.iterator().next();
0314: }
0315:
0316: // Okay, start putting the XML together...
0317: Document shipmentConfirmRequestDoc = UtilXml
0318: .makeEmptyXmlDocument("ShipmentConfirmRequest");
0319: Element shipmentConfirmRequestElement = shipmentConfirmRequestDoc
0320: .getDocumentElement();
0321: shipmentConfirmRequestElement.setAttribute("xml:lang",
0322: "en-US");
0323:
0324: // Top Level Element: Request
0325: Element requestElement = UtilXml.addChildElement(
0326: shipmentConfirmRequestElement, "Request",
0327: shipmentConfirmRequestDoc);
0328:
0329: Element transactionReferenceElement = UtilXml
0330: .addChildElement(requestElement,
0331: "TransactionReference",
0332: shipmentConfirmRequestDoc);
0333: UtilXml.addChildElementValue(transactionReferenceElement,
0334: "CustomerContext", "Ship Confirm / nonvalidate",
0335: shipmentConfirmRequestDoc);
0336: UtilXml.addChildElementValue(transactionReferenceElement,
0337: "XpciVersion", "1.0001", shipmentConfirmRequestDoc);
0338:
0339: UtilXml.addChildElementValue(requestElement,
0340: "RequestAction", "ShipConfirm",
0341: shipmentConfirmRequestDoc);
0342: UtilXml.addChildElementValue(requestElement,
0343: "RequestOption", "nonvalidate",
0344: shipmentConfirmRequestDoc);
0345:
0346: // Top Level Element: LabelSpecification
0347: Element labelSpecificationElement = UtilXml
0348: .addChildElement(shipmentConfirmRequestElement,
0349: "LabelSpecification",
0350: shipmentConfirmRequestDoc);
0351:
0352: Element labelPrintMethodElement = UtilXml.addChildElement(
0353: labelSpecificationElement, "LabelPrintMethod",
0354: shipmentConfirmRequestDoc);
0355: UtilXml.addChildElementValue(labelPrintMethodElement,
0356: "Code", "GIF", shipmentConfirmRequestDoc);
0357:
0358: UtilXml.addChildElementValue(labelSpecificationElement,
0359: "HTTPUserAgent", "Mozilla/5.0",
0360: shipmentConfirmRequestDoc);
0361:
0362: Element labelImageFormatElement = UtilXml.addChildElement(
0363: labelSpecificationElement, "LabelImageFormat",
0364: shipmentConfirmRequestDoc);
0365: UtilXml.addChildElementValue(labelImageFormatElement,
0366: "Code", "GIF", shipmentConfirmRequestDoc);
0367:
0368: // Top Level Element: Shipment
0369: Element shipmentElement = UtilXml.addChildElement(
0370: shipmentConfirmRequestElement, "Shipment",
0371: shipmentConfirmRequestDoc);
0372: UtilXml.addChildElementValue(shipmentElement,
0373: "Description", "Goods for Shipment "
0374: + shipment.get("shipmentId") + " from "
0375: + ordersDescription,
0376: shipmentConfirmRequestDoc);
0377:
0378: // Child of Shipment: Shipper
0379: Element shipperElement = UtilXml.addChildElement(
0380: shipmentElement, "Shipper",
0381: shipmentConfirmRequestDoc);
0382: UtilXml.addChildElementValue(shipperElement, "Name",
0383: originPostalAddress.getString("toName"),
0384: shipmentConfirmRequestDoc);
0385: UtilXml.addChildElementValue(shipperElement,
0386: "AttentionName", originPostalAddress
0387: .getString("attnName"),
0388: shipmentConfirmRequestDoc);
0389: UtilXml.addChildElementValue(shipperElement, "PhoneNumber",
0390: originPhoneNumber, shipmentConfirmRequestDoc);
0391: UtilXml.addChildElementValue(shipperElement,
0392: "ShipperNumber", UtilProperties.getPropertyValue(
0393: "shipment", "shipment.ups.shipper.number"),
0394: shipmentConfirmRequestDoc);
0395:
0396: Element shipperAddressElement = UtilXml.addChildElement(
0397: shipperElement, "Address",
0398: shipmentConfirmRequestDoc);
0399: UtilXml.addChildElementValue(shipperAddressElement,
0400: "AddressLine1", originPostalAddress
0401: .getString("address1"),
0402: shipmentConfirmRequestDoc);
0403: if (UtilValidate.isNotEmpty(originPostalAddress
0404: .getString("address2"))) {
0405: UtilXml.addChildElementValue(shipperAddressElement,
0406: "AddressLine2", originPostalAddress
0407: .getString("address2"),
0408: shipmentConfirmRequestDoc);
0409: }
0410: //UtilXml.addChildElementValue(shipperAddressElement, "AddressLine3", "", shipmentConfirmRequestDoc);
0411: UtilXml.addChildElementValue(shipperAddressElement, "City",
0412: originPostalAddress.getString("city"),
0413: shipmentConfirmRequestDoc);
0414: UtilXml.addChildElementValue(shipperAddressElement,
0415: "StateProvinceCode", originPostalAddress
0416: .getString("stateProvinceGeoId"),
0417: shipmentConfirmRequestDoc);
0418: UtilXml.addChildElementValue(shipperAddressElement,
0419: "PostalCode", originPostalAddress
0420: .getString("postalCode"),
0421: shipmentConfirmRequestDoc);
0422: UtilXml.addChildElementValue(shipperAddressElement,
0423: "CountryCode", originCountryGeo
0424: .getString("geoCode"),
0425: shipmentConfirmRequestDoc);
0426: // How to determine this? Add to data model...? UtilXml.addChildElement(shipperAddressElement, "ResidentialAddress", shipmentConfirmRequestDoc);
0427:
0428: // Child of Shipment: ShipTo
0429: Element shipToElement = UtilXml.addChildElement(
0430: shipmentElement, "ShipTo",
0431: shipmentConfirmRequestDoc);
0432: UtilXml.addChildElementValue(shipToElement, "CompanyName",
0433: destPostalAddress.getString("toName"),
0434: shipmentConfirmRequestDoc);
0435: UtilXml.addChildElementValue(shipToElement,
0436: "AttentionName", destPostalAddress
0437: .getString("attnName"),
0438: shipmentConfirmRequestDoc);
0439: if (UtilValidate.isNotEmpty(destPhoneNumber)) {
0440: UtilXml.addChildElementValue(shipToElement,
0441: "PhoneNumber", destPhoneNumber,
0442: shipmentConfirmRequestDoc);
0443: }
0444: Element shipToAddressElement = UtilXml
0445: .addChildElement(shipToElement, "Address",
0446: shipmentConfirmRequestDoc);
0447: UtilXml.addChildElementValue(shipToAddressElement,
0448: "AddressLine1", destPostalAddress
0449: .getString("address1"),
0450: shipmentConfirmRequestDoc);
0451: if (UtilValidate.isNotEmpty(destPostalAddress
0452: .getString("address2"))) {
0453: UtilXml.addChildElementValue(shipToAddressElement,
0454: "AddressLine2", destPostalAddress
0455: .getString("address2"),
0456: shipmentConfirmRequestDoc);
0457: }
0458: //UtilXml.addChildElementValue(shipToAddressElement, "AddressLine3", "", shipmentConfirmRequestDoc);
0459: UtilXml.addChildElementValue(shipToAddressElement, "City",
0460: destPostalAddress.getString("city"),
0461: shipmentConfirmRequestDoc);
0462: UtilXml.addChildElementValue(shipToAddressElement,
0463: "StateProvinceCode", destPostalAddress
0464: .getString("stateProvinceGeoId"),
0465: shipmentConfirmRequestDoc);
0466: UtilXml.addChildElementValue(shipToAddressElement,
0467: "PostalCode", destPostalAddress
0468: .getString("postalCode"),
0469: shipmentConfirmRequestDoc);
0470: UtilXml.addChildElementValue(shipToAddressElement,
0471: "CountryCode", destCountryGeo.getString("geoCode"),
0472: shipmentConfirmRequestDoc);
0473:
0474: // Child of Shipment: ShipFrom
0475: Element shipFromElement = UtilXml.addChildElement(
0476: shipmentElement, "ShipFrom",
0477: shipmentConfirmRequestDoc);
0478: UtilXml.addChildElementValue(shipFromElement,
0479: "CompanyName", originPostalAddress
0480: .getString("toName"),
0481: shipmentConfirmRequestDoc);
0482: UtilXml.addChildElementValue(shipFromElement,
0483: "AttentionName", originPostalAddress
0484: .getString("attnName"),
0485: shipmentConfirmRequestDoc);
0486: UtilXml.addChildElementValue(shipFromElement,
0487: "PhoneNumber", originPhoneNumber,
0488: shipmentConfirmRequestDoc);
0489: Element shipFromAddressElement = UtilXml.addChildElement(
0490: shipFromElement, "Address",
0491: shipmentConfirmRequestDoc);
0492: UtilXml.addChildElementValue(shipFromAddressElement,
0493: "AddressLine1", originPostalAddress
0494: .getString("address1"),
0495: shipmentConfirmRequestDoc);
0496: if (UtilValidate.isNotEmpty(originPostalAddress
0497: .getString("address2"))) {
0498: UtilXml.addChildElementValue(shipFromAddressElement,
0499: "AddressLine2", originPostalAddress
0500: .getString("address2"),
0501: shipmentConfirmRequestDoc);
0502: }
0503: //UtilXml.addChildElementValue(shipFromAddressElement, "AddressLine3", "", shipmentConfirmRequestDoc);
0504: UtilXml.addChildElementValue(shipFromAddressElement,
0505: "City", originPostalAddress.getString("city"),
0506: shipmentConfirmRequestDoc);
0507: UtilXml.addChildElementValue(shipFromAddressElement,
0508: "StateProvinceCode", originPostalAddress
0509: .getString("stateProvinceGeoId"),
0510: shipmentConfirmRequestDoc);
0511: UtilXml.addChildElementValue(shipFromAddressElement,
0512: "PostalCode", originPostalAddress
0513: .getString("postalCode"),
0514: shipmentConfirmRequestDoc);
0515: UtilXml.addChildElementValue(shipFromAddressElement,
0516: "CountryCode", originCountryGeo
0517: .getString("geoCode"),
0518: shipmentConfirmRequestDoc);
0519:
0520: // Child of Shipment: PaymentInformation
0521: Element paymentInformationElement = UtilXml
0522: .addChildElement(shipmentElement,
0523: "PaymentInformation",
0524: shipmentConfirmRequestDoc);
0525: Element prepaidElement = UtilXml.addChildElement(
0526: paymentInformationElement, "Prepaid",
0527: shipmentConfirmRequestDoc);
0528: Element billShipperElement = UtilXml.addChildElement(
0529: prepaidElement, "BillShipper",
0530: shipmentConfirmRequestDoc);
0531: // fill in BillShipper AccountNumber element from properties file
0532: UtilXml
0533: .addChildElementValue(
0534: billShipperElement,
0535: "AccountNumber",
0536: UtilProperties
0537: .getPropertyValue("shipment",
0538: "shipment.ups.bill.shipper.account.number"),
0539: shipmentConfirmRequestDoc);
0540:
0541: // Child of Shipment: Service
0542: Element serviceElement = UtilXml.addChildElement(
0543: shipmentElement, "Service",
0544: shipmentConfirmRequestDoc);
0545: UtilXml.addChildElementValue(serviceElement, "Code",
0546: carrierShipmentMethod
0547: .getString("carrierServiceCode"),
0548: shipmentConfirmRequestDoc);
0549:
0550: // Child of Shipment: Package
0551: Iterator shipmentPackageRouteSegIter = shipmentPackageRouteSegs
0552: .iterator();
0553: while (shipmentPackageRouteSegIter.hasNext()) {
0554: GenericValue shipmentPackageRouteSeg = (GenericValue) shipmentPackageRouteSegIter
0555: .next();
0556: GenericValue shipmentPackage = shipmentPackageRouteSeg
0557: .getRelatedOne("ShipmentPackage");
0558: GenericValue shipmentBoxType = shipmentPackage
0559: .getRelatedOne("ShipmentBoxType");
0560: List carrierShipmentBoxTypes = shipmentPackage
0561: .getRelated("CarrierShipmentBoxType", UtilMisc
0562: .toMap("partyId", "UPS"), null);
0563: GenericValue carrierShipmentBoxType = null;
0564: if (carrierShipmentBoxTypes.size() > 0) {
0565: carrierShipmentBoxType = (GenericValue) carrierShipmentBoxTypes
0566: .get(0);
0567: }
0568:
0569: Element packageElement = UtilXml.addChildElement(
0570: shipmentElement, "Package",
0571: shipmentConfirmRequestDoc);
0572: Element packagingTypeElement = UtilXml.addChildElement(
0573: packageElement, "PackagingType",
0574: shipmentConfirmRequestDoc);
0575: if (carrierShipmentBoxType != null
0576: && carrierShipmentBoxType
0577: .get("packagingTypeCode") != null) {
0578: UtilXml.addChildElementValue(packagingTypeElement,
0579: "Code", carrierShipmentBoxType
0580: .getString("packagingTypeCode"),
0581: shipmentConfirmRequestDoc);
0582: } else {
0583: // default to "02", plain old Package
0584: UtilXml.addChildElementValue(packagingTypeElement,
0585: "Code", "02", shipmentConfirmRequestDoc);
0586: }
0587: if (shipmentBoxType != null) {
0588: Element dimensionsElement = UtilXml
0589: .addChildElement(packageElement,
0590: "Dimensions",
0591: shipmentConfirmRequestDoc);
0592: Element unitOfMeasurementElement = UtilXml
0593: .addChildElement(dimensionsElement,
0594: "UnitOfMeasurement",
0595: shipmentConfirmRequestDoc);
0596: GenericValue dimensionUom = shipmentBoxType
0597: .getRelatedOne("DimensionUom");
0598: if (dimensionUom != null) {
0599: UtilXml.addChildElementValue(
0600: unitOfMeasurementElement, "Code",
0601: dimensionUom.getString("abbreviation"),
0602: shipmentConfirmRequestDoc);
0603: } else {
0604: // I guess we'll default to inches...
0605: UtilXml.addChildElementValue(
0606: unitOfMeasurementElement, "Code", "IN",
0607: shipmentConfirmRequestDoc);
0608: }
0609: UtilXml.addChildElementValue(dimensionsElement,
0610: "Length", shipmentBoxType.get("boxLength")
0611: .toString(),
0612: shipmentConfirmRequestDoc);
0613: UtilXml.addChildElementValue(dimensionsElement,
0614: "Width", shipmentBoxType.get("boxWidth")
0615: .toString(),
0616: shipmentConfirmRequestDoc);
0617: UtilXml.addChildElementValue(dimensionsElement,
0618: "Height", shipmentBoxType.get("boxHeight")
0619: .toString(),
0620: shipmentConfirmRequestDoc);
0621: }
0622:
0623: Element packageWeightElement = UtilXml.addChildElement(
0624: packageElement, "PackageWeight",
0625: shipmentConfirmRequestDoc);
0626: Element packageWeightUnitOfMeasurementElement = UtilXml
0627: .addChildElement(packageElement,
0628: "UnitOfMeasurement",
0629: shipmentConfirmRequestDoc);
0630: String weightUomUps = (String) unitsOfbizToUps
0631: .get(shipmentPackage.get("weightUomId"));
0632: if (weightUomUps != null) {
0633: UtilXml.addChildElementValue(
0634: packageWeightUnitOfMeasurementElement,
0635: "Code", weightUomUps,
0636: shipmentConfirmRequestDoc);
0637: } else {
0638: // might as well default to LBS
0639: UtilXml.addChildElementValue(
0640: packageWeightUnitOfMeasurementElement,
0641: "Code", "LBS", shipmentConfirmRequestDoc);
0642: }
0643:
0644: if (shipmentPackage.getString("weight") == null) {
0645: return ServiceUtil
0646: .returnError("Weight value not found for ShipmentRouteSegment with shipmentId "
0647: + shipmentId
0648: + ", shipmentRouteSegmentId "
0649: + shipmentRouteSegmentId
0650: + ", and shipmentPackageSeqId "
0651: + shipmentPackage
0652: .getString("shipmentPackageSeqId"));
0653: }
0654: UtilXml.addChildElementValue(packageWeightElement,
0655: "Weight", shipmentPackage.getString("weight"),
0656: shipmentConfirmRequestDoc);
0657:
0658: Element referenceNumberElement = UtilXml
0659: .addChildElement(packageElement,
0660: "ReferenceNumber",
0661: shipmentConfirmRequestDoc);
0662: UtilXml.addChildElementValue(referenceNumberElement,
0663: "Code", "MK", shipmentConfirmRequestDoc);
0664: UtilXml.addChildElementValue(referenceNumberElement,
0665: "Value", shipmentPackage
0666: .getString("shipmentPackageSeqId"),
0667: shipmentConfirmRequestDoc);
0668:
0669: if (carrierShipmentBoxType != null
0670: && carrierShipmentBoxType.get("oversizeCode") != null) {
0671: UtilXml.addChildElementValue(packageElement,
0672: "OversizePackage", carrierShipmentBoxType
0673: .getString("oversizeCode"),
0674: shipmentConfirmRequestDoc);
0675: }
0676: }
0677:
0678: String shipmentConfirmRequestString = null;
0679: try {
0680: shipmentConfirmRequestString = UtilXml
0681: .writeXmlDocument(shipmentConfirmRequestDoc);
0682: } catch (IOException e) {
0683: String ioeErrMsg = "Error writing the ShipmentConfirmRequest XML Document to a String: "
0684: + e.toString();
0685: Debug.logError(e, ioeErrMsg, module);
0686: return ServiceUtil.returnError(ioeErrMsg);
0687: }
0688:
0689: // create AccessRequest XML doc
0690: Document accessRequestDocument = createAccessRequestDocument();
0691: String accessRequestString = null;
0692: try {
0693: accessRequestString = UtilXml
0694: .writeXmlDocument(accessRequestDocument);
0695: } catch (IOException e) {
0696: String ioeErrMsg = "Error writing the AccessRequest XML Document to a String: "
0697: + e.toString();
0698: Debug.logError(e, ioeErrMsg, module);
0699: return ServiceUtil.returnError(ioeErrMsg);
0700: }
0701:
0702: // connect to UPS server, send AccessRequest to auth
0703: // send ShipmentConfirmRequest String
0704: // get ShipmentConfirmResponse String back
0705: StringBuffer xmlString = new StringBuffer();
0706: // TODO: note that we may have to append <?xml version="1.0"?> before each string
0707: xmlString.append(accessRequestString);
0708: xmlString.append(shipmentConfirmRequestString);
0709:
0710: if (shipmentUpsSaveCertificationInfo) {
0711: String outFileName = shipmentUpsSaveCertificationPath
0712: + "/UpsShipmentConfirmRequest"
0713: + shipmentId
0714: + "_"
0715: + shipmentRouteSegment
0716: .getString("shipmentRouteSegmentId")
0717: + ".xml";
0718: try {
0719: FileOutputStream fileOut = new FileOutputStream(
0720: outFileName);
0721: fileOut.write(xmlString.toString().getBytes());
0722: fileOut.flush();
0723: fileOut.close();
0724: } catch (IOException e) {
0725: Debug.log(e, "Could not save UPS XML file: [[["
0726: + xmlString.toString() + "]]] to file: "
0727: + outFileName, module);
0728: }
0729: }
0730:
0731: try {
0732: shipmentConfirmResponseString = sendUpsRequest(
0733: "ShipConfirm", xmlString.toString());
0734: } catch (UpsConnectException e) {
0735: String uceErrMsg = "Error sending UPS request for UPS Service ShipConfirm: "
0736: + e.toString();
0737: Debug.logError(e, uceErrMsg, module);
0738: return ServiceUtil.returnError(uceErrMsg);
0739: }
0740:
0741: if (shipmentUpsSaveCertificationInfo) {
0742: String outFileName = shipmentUpsSaveCertificationPath
0743: + "/UpsShipmentConfirmResponse"
0744: + shipmentId
0745: + "_"
0746: + shipmentRouteSegment
0747: .getString("shipmentRouteSegmentId")
0748: + ".xml";
0749: try {
0750: FileOutputStream fileOut = new FileOutputStream(
0751: outFileName);
0752: fileOut.write(shipmentConfirmResponseString
0753: .getBytes());
0754: fileOut.flush();
0755: fileOut.close();
0756: } catch (IOException e) {
0757: Debug.log(e, "Could not save UPS XML file: [[["
0758: + xmlString.toString() + "]]] to file: "
0759: + outFileName, module);
0760: }
0761: }
0762:
0763: Document shipmentConfirmResponseDocument = null;
0764: try {
0765: shipmentConfirmResponseDocument = UtilXml
0766: .readXmlDocument(shipmentConfirmResponseString,
0767: false);
0768: } catch (SAXException e2) {
0769: String excErrMsg = "Error parsing the ShipmentConfirmResponse: "
0770: + e2.toString();
0771: Debug.logError(e2, excErrMsg, module);
0772: return ServiceUtil.returnError(excErrMsg);
0773: } catch (ParserConfigurationException e2) {
0774: String excErrMsg = "Error parsing the ShipmentConfirmResponse: "
0775: + e2.toString();
0776: Debug.logError(e2, excErrMsg, module);
0777: return ServiceUtil.returnError(excErrMsg);
0778: } catch (IOException e2) {
0779: String excErrMsg = "Error parsing the ShipmentConfirmResponse: "
0780: + e2.toString();
0781: Debug.logError(e2, excErrMsg, module);
0782: return ServiceUtil.returnError(excErrMsg);
0783: }
0784:
0785: return handleUpsShipmentConfirmResponse(
0786: shipmentConfirmResponseDocument,
0787: shipmentRouteSegment);
0788: } catch (GenericEntityException e) {
0789: Debug.logError(e, module);
0790: if (shipmentConfirmResponseString != null) {
0791: Debug.logError("Got XML ShipmentConfirmRespose: "
0792: + shipmentConfirmResponseString, module);
0793: return ServiceUtil.returnError(UtilMisc.toList(
0794: "Error reading or writing Shipment data for UPS Shipment Confirm: "
0795: + e.toString(),
0796: "A ShipmentConfirmRespose was received: "
0797: + shipmentConfirmResponseString));
0798: } else {
0799: return ServiceUtil
0800: .returnError("Error reading or writing Shipment data for UPS Shipment Confirm: "
0801: + e.toString());
0802: }
0803: }
0804: }
0805:
0806: public static Map handleUpsShipmentConfirmResponse(
0807: Document shipmentConfirmResponseDocument,
0808: GenericValue shipmentRouteSegment)
0809: throws GenericEntityException {
0810: // process ShipmentConfirmResponse, update data as needed
0811: Element shipmentConfirmResponseElement = shipmentConfirmResponseDocument
0812: .getDocumentElement();
0813:
0814: // handle Response element info
0815: Element responseElement = UtilXml.firstChildElement(
0816: shipmentConfirmResponseElement, "Response");
0817: Element responseTransactionReferenceElement = UtilXml
0818: .firstChildElement(responseElement,
0819: "TransactionReference");
0820: String responseTransactionReferenceCustomerContext = UtilXml
0821: .childElementValue(responseTransactionReferenceElement,
0822: "CustomerContext");
0823: String responseTransactionReferenceXpciVersion = UtilXml
0824: .childElementValue(responseTransactionReferenceElement,
0825: "XpciVersion");
0826:
0827: String responseStatusCode = UtilXml.childElementValue(
0828: responseElement, "ResponseStatusCode");
0829: String responseStatusDescription = UtilXml.childElementValue(
0830: responseElement, "ResponseStatusDescription");
0831: List errorList = new LinkedList();
0832: UpsServices.handleErrors(responseElement, errorList);
0833:
0834: if ("1".equals(responseStatusCode)) {
0835: // handle ShipmentCharges element info
0836: Element shipmentChargesElement = UtilXml.firstChildElement(
0837: shipmentConfirmResponseElement, "ShipmentCharges");
0838:
0839: Element transportationChargesElement = UtilXml
0840: .firstChildElement(shipmentChargesElement,
0841: "TransportationCharges");
0842: String transportationCurrencyCode = UtilXml
0843: .childElementValue(transportationChargesElement,
0844: "CurrencyCode");
0845: String transportationMonetaryValue = UtilXml
0846: .childElementValue(transportationChargesElement,
0847: "MonetaryValue");
0848:
0849: Element serviceOptionsChargesElement = UtilXml
0850: .firstChildElement(shipmentChargesElement,
0851: "ServiceOptionsCharges");
0852: String serviceOptionsCurrencyCode = UtilXml
0853: .childElementValue(serviceOptionsChargesElement,
0854: "CurrencyCode");
0855: String serviceOptionsMonetaryValue = UtilXml
0856: .childElementValue(serviceOptionsChargesElement,
0857: "MonetaryValue");
0858:
0859: Element totalChargesElement = UtilXml.firstChildElement(
0860: shipmentChargesElement, "TotalCharges");
0861: String totalCurrencyCode = UtilXml.childElementValue(
0862: totalChargesElement, "CurrencyCode");
0863: String totalMonetaryValue = UtilXml.childElementValue(
0864: totalChargesElement, "MonetaryValue");
0865:
0866: if (UtilValidate.isNotEmpty(totalCurrencyCode)) {
0867: if (UtilValidate.isEmpty(shipmentRouteSegment
0868: .getString("currencyUomId"))) {
0869: shipmentRouteSegment.set("currencyUomId",
0870: totalCurrencyCode);
0871: } else if (!totalCurrencyCode
0872: .equals(shipmentRouteSegment
0873: .getString("currencyUomId"))) {
0874: errorList
0875: .add("The Currency Unit of Measure returned ["
0876: + totalCurrencyCode
0877: + "] is not the same as the original ["
0878: + shipmentRouteSegment
0879: .getString("currencyUomId")
0880: + "], setting to the new one.");
0881: shipmentRouteSegment.set("currencyUomId",
0882: totalCurrencyCode);
0883: }
0884: }
0885:
0886: try {
0887: shipmentRouteSegment.set("actualTransportCost", Double
0888: .valueOf(transportationMonetaryValue));
0889: } catch (NumberFormatException e) {
0890: String excErrMsg = "Error parsing the transportationMonetaryValue ["
0891: + transportationMonetaryValue
0892: + "]: "
0893: + e.toString();
0894: Debug.logError(e, excErrMsg, module);
0895: errorList.add(excErrMsg);
0896: }
0897: try {
0898: shipmentRouteSegment.set("actualServiceCost", Double
0899: .valueOf(serviceOptionsMonetaryValue));
0900: } catch (NumberFormatException e) {
0901: String excErrMsg = "Error parsing the serviceOptionsMonetaryValue ["
0902: + serviceOptionsMonetaryValue
0903: + "]: "
0904: + e.toString();
0905: Debug.logError(e, excErrMsg, module);
0906: errorList.add(excErrMsg);
0907: }
0908: try {
0909: shipmentRouteSegment.set("actualCost", Double
0910: .valueOf(totalMonetaryValue));
0911: } catch (NumberFormatException e) {
0912: String excErrMsg = "Error parsing the totalMonetaryValue ["
0913: + totalMonetaryValue + "]: " + e.toString();
0914: Debug.logError(e, excErrMsg, module);
0915: errorList.add(excErrMsg);
0916: }
0917:
0918: // handle BillingWeight element info
0919: Element billingWeightElement = UtilXml.firstChildElement(
0920: shipmentConfirmResponseElement, "BillingWeight");
0921: Element billingWeightUnitOfMeasurementElement = UtilXml
0922: .firstChildElement(billingWeightElement,
0923: "UnitOfMeasurement");
0924: String billingWeightUnitOfMeasurement = UtilXml
0925: .childElementValue(
0926: billingWeightUnitOfMeasurementElement,
0927: "Code");
0928: String billingWeight = UtilXml.childElementValue(
0929: billingWeightElement, "Weight");
0930: try {
0931: shipmentRouteSegment.set("billingWeight", Double
0932: .valueOf(billingWeight));
0933: } catch (NumberFormatException e) {
0934: String excErrMsg = "Error parsing the billingWeight ["
0935: + billingWeight + "]: " + e.toString();
0936: Debug.logError(e, excErrMsg, module);
0937: errorList.add(excErrMsg);
0938: }
0939: shipmentRouteSegment
0940: .set("billingWeightUomId", unitsUpsToOfbiz
0941: .get(billingWeightUnitOfMeasurement));
0942:
0943: // store the ShipmentIdentificationNumber and ShipmentDigest
0944: String shipmentIdentificationNumber = UtilXml
0945: .childElementValue(shipmentConfirmResponseElement,
0946: "ShipmentIdentificationNumber");
0947: String shipmentDigest = UtilXml.childElementValue(
0948: shipmentConfirmResponseElement, "ShipmentDigest");
0949: shipmentRouteSegment.set("trackingIdNumber",
0950: shipmentIdentificationNumber);
0951: shipmentRouteSegment.set("trackingDigest", shipmentDigest);
0952:
0953: // set ShipmentRouteSegment carrierServiceStatusId after each UPS service applicable
0954: shipmentRouteSegment.put("carrierServiceStatusId",
0955: "SHRSCS_CONFIRMED");
0956:
0957: // write/store all modified value objects
0958: shipmentRouteSegment.store();
0959:
0960: // -=-=-=- Okay, now done with that, just return any extra info...
0961:
0962: StringBuffer successString = new StringBuffer(
0963: "The UPS ShipmentConfirm succeeded");
0964: if (errorList.size() > 0) {
0965: // this shouldn't happen much, but handle it anyway
0966: successString.append(", but the following occurred: ");
0967: Iterator errorListIter = errorList.iterator();
0968: while (errorListIter.hasNext()) {
0969: String errorMsg = (String) errorListIter.next();
0970: successString.append(errorMsg);
0971: if (errorListIter.hasNext()) {
0972: successString.append(", ");
0973: }
0974: }
0975: }
0976: return ServiceUtil.returnSuccess(successString.toString());
0977: } else {
0978: errorList.add(0, "The UPS ShipmentConfirm failed");
0979: return ServiceUtil.returnError(errorList);
0980: }
0981: }
0982:
0983: public static Map upsShipmentAccept(DispatchContext dctx,
0984: Map context) {
0985: Map result = new HashMap();
0986: GenericDelegator delegator = dctx.getDelegator();
0987: String shipmentId = (String) context.get("shipmentId");
0988: String shipmentRouteSegmentId = (String) context
0989: .get("shipmentRouteSegmentId");
0990:
0991: boolean shipmentUpsSaveCertificationInfo = "true"
0992: .equals(UtilProperties.getPropertyValue("shipment",
0993: "shipment.ups.save.certification.info"));
0994: String shipmentUpsSaveCertificationPath = UtilProperties
0995: .getPropertyValue("shipment",
0996: "shipment.ups.save.certification.path");
0997: File shipmentUpsSaveCertificationFile = null;
0998: if (shipmentUpsSaveCertificationInfo) {
0999: shipmentUpsSaveCertificationFile = new File(
1000: shipmentUpsSaveCertificationPath);
1001: if (!shipmentUpsSaveCertificationFile.exists()) {
1002: shipmentUpsSaveCertificationFile.mkdirs();
1003: }
1004: }
1005:
1006: String shipmentAcceptResponseString = null;
1007:
1008: try {
1009: GenericValue shipment = delegator.findByPrimaryKey(
1010: "Shipment", UtilMisc
1011: .toMap("shipmentId", shipmentId));
1012: GenericValue shipmentRouteSegment = delegator
1013: .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
1014: .toMap("shipmentId", shipmentId,
1015: "shipmentRouteSegmentId",
1016: shipmentRouteSegmentId));
1017:
1018: if (!"UPS".equals(shipmentRouteSegment
1019: .getString("carrierPartyId"))) {
1020: return ServiceUtil
1021: .returnError("ERROR: The Carrier for ShipmentRouteSegment "
1022: + shipmentRouteSegmentId
1023: + " of Shipment "
1024: + shipmentId
1025: + ", is not UPS.");
1026: }
1027:
1028: // add ShipmentRouteSegment carrierServiceStatusId, check before all UPS services
1029: if (!"SHRSCS_CONFIRMED".equals(shipmentRouteSegment
1030: .getString("carrierServiceStatusId"))) {
1031: return ServiceUtil
1032: .returnError("ERROR: The Carrier Service Status for ShipmentRouteSegment "
1033: + shipmentRouteSegmentId
1034: + " of Shipment "
1035: + shipmentId
1036: + ", is ["
1037: + shipmentRouteSegment
1038: .getString("carrierServiceStatusId")
1039: + "], but must be [SHRSCS_CONFIRMED] to perform the UPS Shipment Accept operation.");
1040: }
1041:
1042: List shipmentPackageRouteSegs = shipmentRouteSegment
1043: .getRelated("ShipmentPackageRouteSeg", null,
1044: UtilMisc.toList("+shipmentPackageSeqId"));
1045: if (shipmentPackageRouteSegs == null
1046: || shipmentPackageRouteSegs.size() == 0) {
1047: return ServiceUtil
1048: .returnError("No ShipmentPackageRouteSegs found for ShipmentRouteSegment with shipmentId "
1049: + shipmentId
1050: + " and shipmentRouteSegmentId "
1051: + shipmentRouteSegmentId);
1052: }
1053:
1054: if (UtilValidate.isEmpty(shipmentRouteSegment
1055: .getString("trackingDigest"))) {
1056: return ServiceUtil
1057: .returnError("ERROR: The trackingDigest was not set for this Route Segment, meaning that a UPS shipment confirm has not been done.");
1058: }
1059:
1060: Document shipmentAcceptRequestDoc = UtilXml
1061: .makeEmptyXmlDocument("ShipmentAcceptRequest");
1062: Element shipmentAcceptRequestElement = shipmentAcceptRequestDoc
1063: .getDocumentElement();
1064: shipmentAcceptRequestElement.setAttribute("xml:lang",
1065: "en-US");
1066:
1067: // Top Level Element: Request
1068: Element requestElement = UtilXml.addChildElement(
1069: shipmentAcceptRequestElement, "Request",
1070: shipmentAcceptRequestDoc);
1071:
1072: Element transactionReferenceElement = UtilXml
1073: .addChildElement(requestElement,
1074: "TransactionReference",
1075: shipmentAcceptRequestDoc);
1076: UtilXml.addChildElementValue(transactionReferenceElement,
1077: "CustomerContext", "ShipAccept / 01",
1078: shipmentAcceptRequestDoc);
1079: UtilXml.addChildElementValue(transactionReferenceElement,
1080: "XpciVersion", "1.0001", shipmentAcceptRequestDoc);
1081:
1082: UtilXml.addChildElementValue(requestElement,
1083: "RequestAction", "ShipAccept",
1084: shipmentAcceptRequestDoc);
1085: UtilXml.addChildElementValue(requestElement,
1086: "RequestOption", "01", shipmentAcceptRequestDoc);
1087:
1088: UtilXml.addChildElementValue(shipmentAcceptRequestElement,
1089: "ShipmentDigest", shipmentRouteSegment
1090: .getString("trackingDigest"),
1091: shipmentAcceptRequestDoc);
1092:
1093: String shipmentAcceptRequestString = null;
1094: try {
1095: shipmentAcceptRequestString = UtilXml
1096: .writeXmlDocument(shipmentAcceptRequestDoc);
1097: } catch (IOException e) {
1098: String ioeErrMsg = "Error writing the ShipmentAcceptRequest XML Document to a String: "
1099: + e.toString();
1100: Debug.logError(e, ioeErrMsg, module);
1101: return ServiceUtil.returnError(ioeErrMsg);
1102: }
1103:
1104: // create AccessRequest XML doc
1105: Document accessRequestDocument = createAccessRequestDocument();
1106: String accessRequestString = null;
1107: try {
1108: accessRequestString = UtilXml
1109: .writeXmlDocument(accessRequestDocument);
1110: } catch (IOException e) {
1111: String ioeErrMsg = "Error writing the AccessRequest XML Document to a String: "
1112: + e.toString();
1113: Debug.logError(e, ioeErrMsg, module);
1114: return ServiceUtil.returnError(ioeErrMsg);
1115: }
1116:
1117: // connect to UPS server, send AccessRequest to auth
1118: // send ShipmentConfirmRequest String
1119: // get ShipmentConfirmResponse String back
1120: StringBuffer xmlString = new StringBuffer();
1121: // TODO: note that we may have to append <?xml version="1.0"?> before each string
1122: xmlString.append(accessRequestString);
1123: xmlString.append(shipmentAcceptRequestString);
1124:
1125: if (shipmentUpsSaveCertificationInfo) {
1126: String outFileName = shipmentUpsSaveCertificationPath
1127: + "/UpsShipmentAcceptRequest"
1128: + shipmentId
1129: + "_"
1130: + shipmentRouteSegment
1131: .getString("shipmentRouteSegmentId")
1132: + ".xml";
1133: try {
1134: FileOutputStream fileOut = new FileOutputStream(
1135: outFileName);
1136: fileOut.write(xmlString.toString().getBytes());
1137: fileOut.flush();
1138: fileOut.close();
1139: } catch (IOException e) {
1140: Debug.log(e, "Could not save UPS XML file: [[["
1141: + xmlString.toString() + "]]] to file: "
1142: + outFileName, module);
1143: }
1144: }
1145:
1146: try {
1147: shipmentAcceptResponseString = sendUpsRequest(
1148: "ShipAccept", xmlString.toString());
1149: } catch (UpsConnectException e) {
1150: String uceErrMsg = "Error sending UPS request for UPS Service ShipAccept: "
1151: + e.toString();
1152: Debug.logError(e, uceErrMsg, module);
1153: return ServiceUtil.returnError(uceErrMsg);
1154: }
1155:
1156: if (shipmentUpsSaveCertificationInfo) {
1157: String outFileName = shipmentUpsSaveCertificationPath
1158: + "/UpsShipmentAcceptResponse"
1159: + shipmentId
1160: + "_"
1161: + shipmentRouteSegment
1162: .getString("shipmentRouteSegmentId")
1163: + ".xml";
1164: try {
1165: FileOutputStream fileOut = new FileOutputStream(
1166: outFileName);
1167: fileOut.write(shipmentAcceptResponseString
1168: .getBytes());
1169: fileOut.flush();
1170: fileOut.close();
1171: } catch (IOException e) {
1172: Debug.log(e, "Could not save UPS XML file: [[["
1173: + xmlString.toString() + "]]] to file: "
1174: + outFileName, module);
1175: }
1176: }
1177:
1178: Document shipmentAcceptResponseDocument = null;
1179: try {
1180: shipmentAcceptResponseDocument = UtilXml
1181: .readXmlDocument(shipmentAcceptResponseString,
1182: false);
1183: } catch (SAXException e2) {
1184: String excErrMsg = "Error parsing the ShipmentAcceptResponse: "
1185: + e2.toString();
1186: Debug.logError(e2, excErrMsg, module);
1187: return ServiceUtil.returnError(excErrMsg);
1188: } catch (ParserConfigurationException e2) {
1189: String excErrMsg = "Error parsing the ShipmentAcceptResponse: "
1190: + e2.toString();
1191: Debug.logError(e2, excErrMsg, module);
1192: return ServiceUtil.returnError(excErrMsg);
1193: } catch (IOException e2) {
1194: String excErrMsg = "Error parsing the ShipmentAcceptResponse: "
1195: + e2.toString();
1196: Debug.logError(e2, excErrMsg, module);
1197: return ServiceUtil.returnError(excErrMsg);
1198: }
1199:
1200: return handleUpsShipmentAcceptResponse(
1201: shipmentAcceptResponseDocument,
1202: shipmentRouteSegment, shipmentPackageRouteSegs);
1203: } catch (GenericEntityException e) {
1204: Debug.logError(e, module);
1205: return ServiceUtil
1206: .returnError("Error reading or writing Shipment data for UPS Shipment Accept: "
1207: + e.toString());
1208: }
1209: }
1210:
1211: public static Map handleUpsShipmentAcceptResponse(
1212: Document shipmentAcceptResponseDocument,
1213: GenericValue shipmentRouteSegment,
1214: List shipmentPackageRouteSegs)
1215: throws GenericEntityException {
1216: boolean shipmentUpsSaveCertificationInfo = "true"
1217: .equals(UtilProperties.getPropertyValue("shipment",
1218: "shipment.ups.save.certification.info"));
1219: String shipmentUpsSaveCertificationPath = UtilProperties
1220: .getPropertyValue("shipment",
1221: "shipment.ups.save.certification.path");
1222: File shipmentUpsSaveCertificationFile = null;
1223: if (shipmentUpsSaveCertificationInfo) {
1224: shipmentUpsSaveCertificationFile = new File(
1225: shipmentUpsSaveCertificationPath);
1226: if (!shipmentUpsSaveCertificationFile.exists()) {
1227: shipmentUpsSaveCertificationFile.mkdirs();
1228: }
1229: }
1230:
1231: // process ShipmentAcceptResponse, update data as needed
1232: Element shipmentAcceptResponseElement = shipmentAcceptResponseDocument
1233: .getDocumentElement();
1234:
1235: // handle Response element info
1236: Element responseElement = UtilXml.firstChildElement(
1237: shipmentAcceptResponseElement, "Response");
1238: Element responseTransactionReferenceElement = UtilXml
1239: .firstChildElement(responseElement,
1240: "TransactionReference");
1241: String responseTransactionReferenceCustomerContext = UtilXml
1242: .childElementValue(responseTransactionReferenceElement,
1243: "CustomerContext");
1244: String responseTransactionReferenceXpciVersion = UtilXml
1245: .childElementValue(responseTransactionReferenceElement,
1246: "XpciVersion");
1247:
1248: String responseStatusCode = UtilXml.childElementValue(
1249: responseElement, "ResponseStatusCode");
1250: String responseStatusDescription = UtilXml.childElementValue(
1251: responseElement, "ResponseStatusDescription");
1252: List errorList = new LinkedList();
1253: UpsServices.handleErrors(responseElement, errorList);
1254:
1255: if ("1".equals(responseStatusCode)) {
1256: Element shipmentResultsElement = UtilXml.firstChildElement(
1257: shipmentAcceptResponseElement, "ShipmentResults");
1258:
1259: // This information is returned in both the ShipmentConfirmResponse and
1260: //the ShipmentAcceptResponse. So, we'll go ahead and store it here again
1261: //and warn of changes or something...
1262:
1263: // handle ShipmentCharges element info
1264: Element shipmentChargesElement = UtilXml.firstChildElement(
1265: shipmentResultsElement, "ShipmentCharges");
1266:
1267: Element transportationChargesElement = UtilXml
1268: .firstChildElement(shipmentChargesElement,
1269: "TransportationCharges");
1270: String transportationCurrencyCode = UtilXml
1271: .childElementValue(transportationChargesElement,
1272: "CurrencyCode");
1273: String transportationMonetaryValue = UtilXml
1274: .childElementValue(transportationChargesElement,
1275: "MonetaryValue");
1276:
1277: Element serviceOptionsChargesElement = UtilXml
1278: .firstChildElement(shipmentChargesElement,
1279: "ServiceOptionsCharges");
1280: String serviceOptionsCurrencyCode = UtilXml
1281: .childElementValue(serviceOptionsChargesElement,
1282: "CurrencyCode");
1283: String serviceOptionsMonetaryValue = UtilXml
1284: .childElementValue(serviceOptionsChargesElement,
1285: "MonetaryValue");
1286:
1287: Element totalChargesElement = UtilXml.firstChildElement(
1288: shipmentChargesElement, "TotalCharges");
1289: String totalCurrencyCode = UtilXml.childElementValue(
1290: totalChargesElement, "CurrencyCode");
1291: String totalMonetaryValue = UtilXml.childElementValue(
1292: totalChargesElement, "MonetaryValue");
1293:
1294: if (UtilValidate.isNotEmpty(totalCurrencyCode)) {
1295: if (UtilValidate.isEmpty(shipmentRouteSegment
1296: .getString("currencyUomId"))) {
1297: shipmentRouteSegment.set("currencyUomId",
1298: totalCurrencyCode);
1299: } else if (!totalCurrencyCode
1300: .equals(shipmentRouteSegment
1301: .getString("currencyUomId"))) {
1302: errorList
1303: .add("The Currency Unit of Measure returned ["
1304: + totalCurrencyCode
1305: + "] is not the same as the original ["
1306: + shipmentRouteSegment
1307: .getString("currencyUomId")
1308: + "], setting to the new one.");
1309: shipmentRouteSegment.set("currencyUomId",
1310: totalCurrencyCode);
1311: }
1312: }
1313:
1314: try {
1315: shipmentRouteSegment.set("actualTransportCost", Double
1316: .valueOf(transportationMonetaryValue));
1317: } catch (NumberFormatException e) {
1318: String excErrMsg = "Error parsing the transportationMonetaryValue ["
1319: + transportationMonetaryValue
1320: + "]: "
1321: + e.toString();
1322: Debug.logError(e, excErrMsg, module);
1323: errorList.add(excErrMsg);
1324: }
1325: try {
1326: shipmentRouteSegment.set("actualServiceCost", Double
1327: .valueOf(serviceOptionsMonetaryValue));
1328: } catch (NumberFormatException e) {
1329: String excErrMsg = "Error parsing the serviceOptionsMonetaryValue ["
1330: + serviceOptionsMonetaryValue
1331: + "]: "
1332: + e.toString();
1333: Debug.logError(e, excErrMsg, module);
1334: errorList.add(excErrMsg);
1335: }
1336: try {
1337: shipmentRouteSegment.set("actualCost", Double
1338: .valueOf(totalMonetaryValue));
1339: } catch (NumberFormatException e) {
1340: String excErrMsg = "Error parsing the totalMonetaryValue ["
1341: + totalMonetaryValue + "]: " + e.toString();
1342: Debug.logError(e, excErrMsg, module);
1343: errorList.add(excErrMsg);
1344: }
1345:
1346: // handle BillingWeight element info
1347: Element billingWeightElement = UtilXml.firstChildElement(
1348: shipmentResultsElement, "BillingWeight");
1349: Element billingWeightUnitOfMeasurementElement = UtilXml
1350: .firstChildElement(billingWeightElement,
1351: "UnitOfMeasurement");
1352: String billingWeightUnitOfMeasurement = UtilXml
1353: .childElementValue(
1354: billingWeightUnitOfMeasurementElement,
1355: "Code");
1356: String billingWeight = UtilXml.childElementValue(
1357: billingWeightElement, "Weight");
1358: try {
1359: shipmentRouteSegment.set("billingWeight", Double
1360: .valueOf(billingWeight));
1361: } catch (NumberFormatException e) {
1362: String excErrMsg = "Error parsing the billingWeight ["
1363: + billingWeight + "]: " + e.toString();
1364: Debug.logError(e, excErrMsg, module);
1365: errorList.add(excErrMsg);
1366: }
1367: shipmentRouteSegment
1368: .set("billingWeightUomId", unitsUpsToOfbiz
1369: .get(billingWeightUnitOfMeasurement));
1370:
1371: // store the ShipmentIdentificationNumber and ShipmentDigest
1372: String shipmentIdentificationNumber = UtilXml
1373: .childElementValue(shipmentResultsElement,
1374: "ShipmentIdentificationNumber");
1375: // should compare to trackingIdNumber, should always be the same right?
1376: shipmentRouteSegment.set("trackingIdNumber",
1377: shipmentIdentificationNumber);
1378:
1379: // set ShipmentRouteSegment carrierServiceStatusId after each UPS service applicable
1380: shipmentRouteSegment.put("carrierServiceStatusId",
1381: "SHRSCS_ACCEPTED");
1382:
1383: // write/store modified value object
1384: shipmentRouteSegment.store();
1385:
1386: // now process the PackageResults elements
1387: List packageResultsElements = UtilXml.childElementList(
1388: shipmentResultsElement, "PackageResults");
1389: Iterator packageResultsElementIter = packageResultsElements
1390: .iterator();
1391: Iterator shipmentPackageRouteSegIter = shipmentPackageRouteSegs
1392: .iterator();
1393: while (packageResultsElementIter.hasNext()) {
1394: Element packageResultsElement = (Element) packageResultsElementIter
1395: .next();
1396:
1397: String trackingNumber = UtilXml.childElementValue(
1398: packageResultsElement, "TrackingNumber");
1399:
1400: Element packageServiceOptionsChargesElement = UtilXml
1401: .firstChildElement(packageResultsElement,
1402: "ServiceOptionsCharges");
1403: String packageServiceOptionsCurrencyCode = UtilXml
1404: .childElementValue(
1405: packageServiceOptionsChargesElement,
1406: "CurrencyCode");
1407: String packageServiceOptionsMonetaryValue = UtilXml
1408: .childElementValue(
1409: packageServiceOptionsChargesElement,
1410: "MonetaryValue");
1411:
1412: Element packageLabelImageElement = UtilXml
1413: .firstChildElement(packageResultsElement,
1414: "LabelImage");
1415: Element packageLabelImageFormatElement = UtilXml
1416: .firstChildElement(packageResultsElement,
1417: "LabelImageFormat");
1418: // will be EPL or GIF, should always be GIF since that is what we requested
1419: String packageLabelImageFormatCode = UtilXml
1420: .childElementValue(
1421: packageLabelImageFormatElement, "Code");
1422: String packageLabelImageFormatDescription = UtilXml
1423: .childElementValue(
1424: packageLabelImageFormatElement,
1425: "Description");
1426: String packageLabelGraphicImageString = UtilXml
1427: .childElementValue(packageLabelImageElement,
1428: "GraphicImage");
1429: String packageLabelInternationalSignatureGraphicImageString = UtilXml
1430: .childElementValue(packageLabelImageElement,
1431: "InternationalSignatureGraphicImage");
1432: String packageLabelHTMLImageString = UtilXml
1433: .childElementValue(packageLabelImageElement,
1434: "HTMLImage");
1435:
1436: if (!shipmentPackageRouteSegIter.hasNext()) {
1437: errorList
1438: .add("Error: More PackageResults were returned than there are Packages on this Shipment; the TrackingNumber is ["
1439: + trackingNumber
1440: + "], the ServiceOptionsCharges were "
1441: + packageServiceOptionsMonetaryValue
1442: + packageServiceOptionsCurrencyCode);
1443: // NOTE: if this happens much we should just create a new package to store all of the info...
1444: continue;
1445: }
1446:
1447: //NOTE: I guess they come back in the same order we sent them, so we'll get the packages in order and off we go...
1448: GenericValue shipmentPackageRouteSeg = (GenericValue) shipmentPackageRouteSegIter
1449: .next();
1450: shipmentPackageRouteSeg.set("trackingCode",
1451: trackingNumber);
1452: shipmentPackageRouteSeg.set("boxNumber", "");
1453: shipmentPackageRouteSeg.set("currencyUomId",
1454: packageServiceOptionsCurrencyCode);
1455: try {
1456: shipmentPackageRouteSeg
1457: .set(
1458: "packageServiceCost",
1459: Double
1460: .valueOf(packageServiceOptionsMonetaryValue));
1461: } catch (NumberFormatException e) {
1462: String excErrMsg = "Error parsing the packageServiceOptionsMonetaryValue ["
1463: + packageServiceOptionsMonetaryValue
1464: + "] for Package ["
1465: + shipmentPackageRouteSeg
1466: .getString("shipmentPackageSeqId")
1467: + "]: " + e.toString();
1468: Debug.logError(e, excErrMsg, module);
1469: errorList.add(excErrMsg);
1470: }
1471:
1472: byte[] labelImageBytes = null;
1473: if (packageLabelGraphicImageString != null) {
1474: labelImageBytes = Base64
1475: .base64Decode(packageLabelGraphicImageString
1476: .getBytes());
1477: shipmentPackageRouteSeg.setBytes("labelImage",
1478: labelImageBytes);
1479: }
1480: byte[] labelInternationalSignatureGraphicImageBytes = null;
1481: if (packageLabelInternationalSignatureGraphicImageString != null) {
1482: labelInternationalSignatureGraphicImageBytes = Base64
1483: .base64Decode(packageLabelInternationalSignatureGraphicImageString
1484: .getBytes());
1485: shipmentPackageRouteSeg
1486: .set("labelIntlSignImage",
1487: labelInternationalSignatureGraphicImageBytes);
1488: }
1489: String packageLabelHTMLImageStringDecoded = Base64
1490: .base64Decode(packageLabelHTMLImageString);
1491: shipmentPackageRouteSeg.set("labelHtml",
1492: packageLabelHTMLImageStringDecoded);
1493:
1494: if (shipmentUpsSaveCertificationInfo) {
1495: if (labelImageBytes != null) {
1496: String outFileName = shipmentUpsSaveCertificationPath
1497: + "/UpsShipmentLabelImage"
1498: + shipmentRouteSegment
1499: .getString("shipmentId")
1500: + "_"
1501: + shipmentRouteSegment
1502: .getString("shipmentRouteSegmentId")
1503: + "_"
1504: + shipmentPackageRouteSeg
1505: .getString("shipmentPackageSeqId")
1506: + ".gif";
1507: try {
1508: FileOutputStream fileOut = new FileOutputStream(
1509: outFileName);
1510: fileOut.write(labelImageBytes);
1511: fileOut.flush();
1512: fileOut.close();
1513: } catch (IOException e) {
1514: Debug
1515: .log(
1516: e,
1517: "Could not save UPS LabelImage GIF file: [[["
1518: + packageLabelGraphicImageString
1519: + "]]] to file: "
1520: + outFileName,
1521: module);
1522: }
1523: }
1524: if (labelInternationalSignatureGraphicImageBytes != null) {
1525: String outFileName = shipmentUpsSaveCertificationPath
1526: + "/UpsShipmentLabelIntlSignImage"
1527: + shipmentRouteSegment
1528: .getString("shipmentId")
1529: + "_"
1530: + shipmentRouteSegment
1531: .getString("shipmentRouteSegmentId")
1532: + "_"
1533: + shipmentPackageRouteSeg
1534: .getString("shipmentPackageSeqId")
1535: + ".gif";
1536: try {
1537: FileOutputStream fileOut = new FileOutputStream(
1538: outFileName);
1539: fileOut
1540: .write(labelInternationalSignatureGraphicImageBytes);
1541: fileOut.flush();
1542: fileOut.close();
1543: } catch (IOException e) {
1544: Debug
1545: .log(
1546: e,
1547: "Could not save UPS IntlSign LabelImage GIF file: [[["
1548: + packageLabelInternationalSignatureGraphicImageString
1549: + "]]] to file: "
1550: + outFileName,
1551: module);
1552: }
1553: }
1554: if (packageLabelHTMLImageStringDecoded != null) {
1555: String outFileName = shipmentUpsSaveCertificationPath
1556: + "/UpsShipmentLabelHTMLImage"
1557: + shipmentRouteSegment
1558: .getString("shipmentId")
1559: + "_"
1560: + shipmentRouteSegment
1561: .getString("shipmentRouteSegmentId")
1562: + "_"
1563: + shipmentPackageRouteSeg
1564: .getString("shipmentPackageSeqId")
1565: + ".html";
1566: try {
1567: FileOutputStream fileOut = new FileOutputStream(
1568: outFileName);
1569: fileOut
1570: .write(packageLabelHTMLImageStringDecoded
1571: .getBytes());
1572: fileOut.flush();
1573: fileOut.close();
1574: } catch (IOException e) {
1575: Debug
1576: .log(
1577: e,
1578: "Could not save UPS LabelImage HTML file: [[["
1579: + packageLabelHTMLImageStringDecoded
1580: + "]]] to file: "
1581: + outFileName,
1582: module);
1583: }
1584: }
1585: }
1586:
1587: shipmentPackageRouteSeg.store();
1588: }
1589:
1590: if (shipmentPackageRouteSegIter.hasNext()) {
1591: errorList
1592: .add("Error: There are more Packages on this Shipment than there were PackageResults returned from UPS");
1593: while (shipmentPackageRouteSegIter.hasNext()) {
1594: GenericValue shipmentPackageRouteSeg = (GenericValue) shipmentPackageRouteSegIter
1595: .next();
1596: errorList
1597: .add("Error: No PackageResults were returned for the Package ["
1598: + shipmentPackageRouteSeg
1599: .getString("shipmentPackageSeqId")
1600: + "]");
1601: }
1602: }
1603:
1604: // -=-=-=- Okay, now done with that, just return any extra info...
1605: StringBuffer successString = new StringBuffer(
1606: "The UPS ShipmentAccept succeeded");
1607: if (errorList.size() > 0) {
1608: // this shouldn't happen much, but handle it anyway
1609: successString.append(", but the following occurred: ");
1610: Iterator errorListIter = errorList.iterator();
1611: while (errorListIter.hasNext()) {
1612: String errorMsg = (String) errorListIter.next();
1613: successString.append(errorMsg);
1614: if (errorListIter.hasNext()) {
1615: successString.append(", ");
1616: }
1617: }
1618: }
1619: return ServiceUtil.returnSuccess(successString.toString());
1620: } else {
1621: errorList.add(0, "The UPS ShipmentConfirm failed");
1622: return ServiceUtil.returnError(errorList);
1623: }
1624: }
1625:
1626: public static Map upsVoidShipment(DispatchContext dctx, Map context) {
1627: Map result = new HashMap();
1628: GenericDelegator delegator = dctx.getDelegator();
1629: String shipmentId = (String) context.get("shipmentId");
1630: String shipmentRouteSegmentId = (String) context
1631: .get("shipmentRouteSegmentId");
1632:
1633: boolean shipmentUpsSaveCertificationInfo = "true"
1634: .equals(UtilProperties.getPropertyValue("shipment",
1635: "shipment.ups.save.certification.info"));
1636: String shipmentUpsSaveCertificationPath = UtilProperties
1637: .getPropertyValue("shipment",
1638: "shipment.ups.save.certification.path");
1639: File shipmentUpsSaveCertificationFile = null;
1640: if (shipmentUpsSaveCertificationInfo) {
1641: shipmentUpsSaveCertificationFile = new File(
1642: shipmentUpsSaveCertificationPath);
1643: if (!shipmentUpsSaveCertificationFile.exists()) {
1644: shipmentUpsSaveCertificationFile.mkdirs();
1645: }
1646: }
1647:
1648: String voidShipmentResponseString = null;
1649:
1650: try {
1651: GenericValue shipment = delegator.findByPrimaryKey(
1652: "Shipment", UtilMisc
1653: .toMap("shipmentId", shipmentId));
1654: GenericValue shipmentRouteSegment = delegator
1655: .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
1656: .toMap("shipmentId", shipmentId,
1657: "shipmentRouteSegmentId",
1658: shipmentRouteSegmentId));
1659:
1660: if (!"UPS".equals(shipmentRouteSegment
1661: .getString("carrierPartyId"))) {
1662: return ServiceUtil
1663: .returnError("ERROR: The Carrier for ShipmentRouteSegment "
1664: + shipmentRouteSegmentId
1665: + " of Shipment "
1666: + shipmentId
1667: + ", is not UPS.");
1668: }
1669:
1670: // add ShipmentRouteSegment carrierServiceStatusId, check before all UPS services
1671: if (!"SHRSCS_CONFIRMED".equals(shipmentRouteSegment
1672: .getString("carrierServiceStatusId"))
1673: && !"SHRSCS_ACCEPTED".equals(shipmentRouteSegment
1674: .getString("carrierServiceStatusId"))) {
1675: return ServiceUtil
1676: .returnError("ERROR: The Carrier Service Status for ShipmentRouteSegment "
1677: + shipmentRouteSegmentId
1678: + " of Shipment "
1679: + shipmentId
1680: + ", is ["
1681: + shipmentRouteSegment
1682: .getString("carrierServiceStatusId")
1683: + "], but must be [SHRSCS_CONFIRMED] or [SHRSCS_ACCEPTED] to perform the UPS Void Shipment operation.");
1684: }
1685:
1686: if (UtilValidate.isEmpty(shipmentRouteSegment
1687: .getString("trackingIdNumber"))) {
1688: return ServiceUtil
1689: .returnError("ERROR: The trackingIdNumber was not set for this Route Segment, meaning that a UPS shipment confirm has not been done.");
1690: }
1691:
1692: Document voidShipmentRequestDoc = UtilXml
1693: .makeEmptyXmlDocument("VoidShipmentRequest");
1694: Element voidShipmentRequestElement = voidShipmentRequestDoc
1695: .getDocumentElement();
1696: voidShipmentRequestElement
1697: .setAttribute("xml:lang", "en-US");
1698:
1699: // Top Level Element: Request
1700: Element requestElement = UtilXml.addChildElement(
1701: voidShipmentRequestElement, "Request",
1702: voidShipmentRequestDoc);
1703:
1704: Element transactionReferenceElement = UtilXml
1705: .addChildElement(requestElement,
1706: "TransactionReference",
1707: voidShipmentRequestDoc);
1708: UtilXml.addChildElementValue(transactionReferenceElement,
1709: "CustomerContext", "Void / 1",
1710: voidShipmentRequestDoc);
1711: UtilXml.addChildElementValue(transactionReferenceElement,
1712: "XpciVersion", "1.0001", voidShipmentRequestDoc);
1713:
1714: UtilXml.addChildElementValue(requestElement,
1715: "RequestAction", "Void", voidShipmentRequestDoc);
1716: UtilXml.addChildElementValue(requestElement,
1717: "RequestOption", "1", voidShipmentRequestDoc);
1718:
1719: UtilXml.addChildElementValue(voidShipmentRequestElement,
1720: "ShipmentIdentificationNumber",
1721: shipmentRouteSegment.getString("trackingIdNumber"),
1722: voidShipmentRequestDoc);
1723:
1724: String voidShipmentRequestString = null;
1725: try {
1726: voidShipmentRequestString = UtilXml
1727: .writeXmlDocument(voidShipmentRequestDoc);
1728: } catch (IOException e) {
1729: String ioeErrMsg = "Error writing the VoidShipmentRequest XML Document to a String: "
1730: + e.toString();
1731: Debug.logError(e, ioeErrMsg, module);
1732: return ServiceUtil.returnError(ioeErrMsg);
1733: }
1734:
1735: // create AccessRequest XML doc
1736: Document accessRequestDocument = createAccessRequestDocument();
1737: String accessRequestString = null;
1738: try {
1739: accessRequestString = UtilXml
1740: .writeXmlDocument(accessRequestDocument);
1741: } catch (IOException e) {
1742: String ioeErrMsg = "Error writing the AccessRequest XML Document to a String: "
1743: + e.toString();
1744: Debug.logError(e, ioeErrMsg, module);
1745: return ServiceUtil.returnError(ioeErrMsg);
1746: }
1747:
1748: // connect to UPS server, send AccessRequest to auth
1749: // send ShipmentConfirmRequest String
1750: // get ShipmentConfirmResponse String back
1751: StringBuffer xmlString = new StringBuffer();
1752: // TODO: note that we may have to append <?xml version="1.0"?> before each string
1753: xmlString.append(accessRequestString);
1754: xmlString.append(voidShipmentRequestString);
1755:
1756: if (shipmentUpsSaveCertificationInfo) {
1757: String outFileName = shipmentUpsSaveCertificationPath
1758: + "/UpsVoidShipmentRequest"
1759: + shipmentId
1760: + "_"
1761: + shipmentRouteSegment
1762: .getString("shipmentRouteSegmentId")
1763: + ".xml";
1764: try {
1765: FileOutputStream fileOut = new FileOutputStream(
1766: outFileName);
1767: fileOut.write(xmlString.toString().getBytes());
1768: fileOut.flush();
1769: fileOut.close();
1770: } catch (IOException e) {
1771: Debug.log(e, "Could not save UPS XML file: [[["
1772: + xmlString.toString() + "]]] to file: "
1773: + outFileName, module);
1774: }
1775: }
1776:
1777: try {
1778: voidShipmentResponseString = sendUpsRequest("Void",
1779: xmlString.toString());
1780: } catch (UpsConnectException e) {
1781: String uceErrMsg = "Error sending UPS request for UPS Service Void: "
1782: + e.toString();
1783: Debug.logError(e, uceErrMsg, module);
1784: return ServiceUtil.returnError(uceErrMsg);
1785: }
1786:
1787: if (shipmentUpsSaveCertificationInfo) {
1788: String outFileName = shipmentUpsSaveCertificationPath
1789: + "/UpsVoidShipmentResponse"
1790: + shipmentId
1791: + "_"
1792: + shipmentRouteSegment
1793: .getString("shipmentRouteSegmentId")
1794: + ".xml";
1795: try {
1796: FileOutputStream fileOut = new FileOutputStream(
1797: outFileName);
1798: fileOut
1799: .write(voidShipmentResponseString
1800: .getBytes());
1801: fileOut.flush();
1802: fileOut.close();
1803: } catch (IOException e) {
1804: Debug.log(e, "Could not save UPS XML file: [[["
1805: + xmlString.toString() + "]]] to file: "
1806: + outFileName, module);
1807: }
1808: }
1809:
1810: Document voidShipmentResponseDocument = null;
1811: try {
1812: voidShipmentResponseDocument = UtilXml.readXmlDocument(
1813: voidShipmentResponseString, false);
1814: } catch (SAXException e2) {
1815: String excErrMsg = "Error parsing the VoidShipmentResponse: "
1816: + e2.toString();
1817: Debug.logError(e2, excErrMsg, module);
1818: return ServiceUtil.returnError(excErrMsg);
1819: } catch (ParserConfigurationException e2) {
1820: String excErrMsg = "Error parsing the VoidShipmentResponse: "
1821: + e2.toString();
1822: Debug.logError(e2, excErrMsg, module);
1823: return ServiceUtil.returnError(excErrMsg);
1824: } catch (IOException e2) {
1825: String excErrMsg = "Error parsing the VoidShipmentResponse: "
1826: + e2.toString();
1827: Debug.logError(e2, excErrMsg, module);
1828: return ServiceUtil.returnError(excErrMsg);
1829: }
1830:
1831: return handleUpsVoidShipmentResponse(
1832: voidShipmentResponseDocument, shipmentRouteSegment);
1833: } catch (GenericEntityException e) {
1834: Debug.logError(e, module);
1835: return ServiceUtil
1836: .returnError("Error reading or writing Shipment data for UPS Void Shipment: "
1837: + e.toString());
1838: }
1839: }
1840:
1841: public static Map handleUpsVoidShipmentResponse(
1842: Document voidShipmentResponseDocument,
1843: GenericValue shipmentRouteSegment)
1844: throws GenericEntityException {
1845: // process VoidShipmentResponse, update data as needed
1846: Element voidShipmentResponseElement = voidShipmentResponseDocument
1847: .getDocumentElement();
1848:
1849: // handle Response element info
1850: Element responseElement = UtilXml.firstChildElement(
1851: voidShipmentResponseElement, "Response");
1852: Element responseTransactionReferenceElement = UtilXml
1853: .firstChildElement(responseElement,
1854: "TransactionReference");
1855: String responseTransactionReferenceCustomerContext = UtilXml
1856: .childElementValue(responseTransactionReferenceElement,
1857: "CustomerContext");
1858: String responseTransactionReferenceXpciVersion = UtilXml
1859: .childElementValue(responseTransactionReferenceElement,
1860: "XpciVersion");
1861:
1862: String responseStatusCode = UtilXml.childElementValue(
1863: responseElement, "ResponseStatusCode");
1864: String responseStatusDescription = UtilXml.childElementValue(
1865: responseElement, "ResponseStatusDescription");
1866: List errorList = new LinkedList();
1867: UpsServices.handleErrors(responseElement, errorList);
1868:
1869: // handle other response elements
1870: Element statusElement = UtilXml.firstChildElement(
1871: voidShipmentResponseElement, "Status");
1872:
1873: Element statusTypeElement = UtilXml.firstChildElement(
1874: statusElement, "StatusType");
1875: String statusTypeCode = UtilXml.childElementValue(
1876: statusTypeElement, "Code");
1877: String statusTypeDescription = UtilXml.childElementValue(
1878: statusTypeElement, "Description");
1879:
1880: Element statusCodeElement = UtilXml.firstChildElement(
1881: statusElement, "StatusCode");
1882: String statusCodeCode = UtilXml.childElementValue(
1883: statusCodeElement, "Code");
1884: String statusCodeDescription = UtilXml.childElementValue(
1885: statusCodeElement, "Description");
1886:
1887: if ("1".equals(responseStatusCode)) {
1888: // set ShipmentRouteSegment carrierServiceStatusId after each UPS service applicable
1889: shipmentRouteSegment.put("carrierServiceStatusId",
1890: "SHRSCS_VOIDED");
1891: shipmentRouteSegment.store();
1892:
1893: // -=-=-=- Okay, now done with that, just return any extra info...
1894: StringBuffer successString = new StringBuffer(
1895: "The UPS VoidShipment succeeded; the StatusType is: ["
1896: + statusTypeCode + ":"
1897: + statusTypeDescription
1898: + "], the StatusCode is: ["
1899: + statusCodeCode + ":"
1900: + statusCodeDescription + "]");
1901: if (errorList.size() > 0) {
1902: // this shouldn't happen much, but handle it anyway
1903: successString.append(", but the following occurred: ");
1904: Iterator errorListIter = errorList.iterator();
1905: while (errorListIter.hasNext()) {
1906: String errorMsg = (String) errorListIter.next();
1907: successString.append(errorMsg);
1908: if (errorListIter.hasNext()) {
1909: successString.append(", ");
1910: }
1911: }
1912: }
1913: return ServiceUtil.returnSuccess(successString.toString());
1914: } else {
1915: errorList.add(0,
1916: "The UPS ShipmentConfirm failed; the StatusType is: ["
1917: + statusTypeCode + ":"
1918: + statusTypeDescription
1919: + "], the StatusCode is: ["
1920: + statusCodeCode + ":"
1921: + statusCodeDescription + "]");
1922: return ServiceUtil.returnError(errorList);
1923: }
1924: }
1925:
1926: public static Map upsTrackShipment(DispatchContext dctx, Map context) {
1927: Map result = new HashMap();
1928: GenericDelegator delegator = dctx.getDelegator();
1929: String shipmentId = (String) context.get("shipmentId");
1930: String shipmentRouteSegmentId = (String) context
1931: .get("shipmentRouteSegmentId");
1932:
1933: boolean shipmentUpsSaveCertificationInfo = "true"
1934: .equals(UtilProperties.getPropertyValue("shipment",
1935: "shipment.ups.save.certification.info"));
1936: String shipmentUpsSaveCertificationPath = UtilProperties
1937: .getPropertyValue("shipment",
1938: "shipment.ups.save.certification.path");
1939: File shipmentUpsSaveCertificationFile = null;
1940: if (shipmentUpsSaveCertificationInfo) {
1941: shipmentUpsSaveCertificationFile = new File(
1942: shipmentUpsSaveCertificationPath);
1943: if (!shipmentUpsSaveCertificationFile.exists()) {
1944: shipmentUpsSaveCertificationFile.mkdirs();
1945: }
1946: }
1947:
1948: String trackResponseString = null;
1949:
1950: try {
1951: GenericValue shipment = delegator.findByPrimaryKey(
1952: "Shipment", UtilMisc
1953: .toMap("shipmentId", shipmentId));
1954: GenericValue shipmentRouteSegment = delegator
1955: .findByPrimaryKey("ShipmentRouteSegment", UtilMisc
1956: .toMap("shipmentId", shipmentId,
1957: "shipmentRouteSegmentId",
1958: shipmentRouteSegmentId));
1959:
1960: if (!"UPS".equals(shipmentRouteSegment
1961: .getString("carrierPartyId"))) {
1962: return ServiceUtil
1963: .returnError("ERROR: The Carrier for ShipmentRouteSegment "
1964: + shipmentRouteSegmentId
1965: + " of Shipment "
1966: + shipmentId
1967: + ", is not UPS.");
1968: }
1969:
1970: // add ShipmentRouteSegment carrierServiceStatusId, check before all UPS services
1971: if (!"SHRSCS_ACCEPTED".equals(shipmentRouteSegment
1972: .getString("carrierServiceStatusId"))) {
1973: return ServiceUtil
1974: .returnError("ERROR: The Carrier Service Status for ShipmentRouteSegment "
1975: + shipmentRouteSegmentId
1976: + " of Shipment "
1977: + shipmentId
1978: + ", is ["
1979: + shipmentRouteSegment
1980: .getString("carrierServiceStatusId")
1981: + "], but must be [SHRSCS_ACCEPTED] to perform the UPS Track Shipment operation.");
1982: }
1983:
1984: List shipmentPackageRouteSegs = shipmentRouteSegment
1985: .getRelated("ShipmentPackageRouteSeg", null,
1986: UtilMisc.toList("+shipmentPackageSeqId"));
1987: if (shipmentPackageRouteSegs == null
1988: || shipmentPackageRouteSegs.size() == 0) {
1989: return ServiceUtil
1990: .returnError("No ShipmentPackageRouteSegs found for ShipmentRouteSegment with shipmentId "
1991: + shipmentId
1992: + " and shipmentRouteSegmentId "
1993: + shipmentRouteSegmentId);
1994: }
1995:
1996: if (UtilValidate.isEmpty(shipmentRouteSegment
1997: .getString("trackingIdNumber"))) {
1998: return ServiceUtil
1999: .returnError("ERROR: The trackingIdNumber was not set for this Route Segment, meaning that a UPS shipment confirm has not been done.");
2000: }
2001:
2002: Document trackRequestDoc = UtilXml
2003: .makeEmptyXmlDocument("TrackRequest");
2004: Element trackRequestElement = trackRequestDoc
2005: .getDocumentElement();
2006: trackRequestElement.setAttribute("xml:lang", "en-US");
2007:
2008: // Top Level Element: Request
2009: Element requestElement = UtilXml.addChildElement(
2010: trackRequestElement, "Request", trackRequestDoc);
2011:
2012: Element transactionReferenceElement = UtilXml
2013: .addChildElement(requestElement,
2014: "TransactionReference", trackRequestDoc);
2015: UtilXml.addChildElementValue(transactionReferenceElement,
2016: "CustomerContext", "Track", trackRequestDoc);
2017: UtilXml.addChildElementValue(transactionReferenceElement,
2018: "XpciVersion", "1.0001", trackRequestDoc);
2019:
2020: UtilXml.addChildElementValue(requestElement,
2021: "RequestAction", "Track", trackRequestDoc);
2022:
2023: UtilXml.addChildElementValue(trackRequestElement,
2024: "ShipmentIdentificationNumber",
2025: shipmentRouteSegment.getString("trackingIdNumber"),
2026: trackRequestDoc);
2027:
2028: String trackRequestString = null;
2029: try {
2030: trackRequestString = UtilXml
2031: .writeXmlDocument(trackRequestDoc);
2032: } catch (IOException e) {
2033: String ioeErrMsg = "Error writing the TrackRequest XML Document to a String: "
2034: + e.toString();
2035: Debug.logError(e, ioeErrMsg, module);
2036: return ServiceUtil.returnError(ioeErrMsg);
2037: }
2038:
2039: // create AccessRequest XML doc
2040: Document accessRequestDocument = createAccessRequestDocument();
2041: String accessRequestString = null;
2042: try {
2043: accessRequestString = UtilXml
2044: .writeXmlDocument(accessRequestDocument);
2045: } catch (IOException e) {
2046: String ioeErrMsg = "Error writing the AccessRequest XML Document to a String: "
2047: + e.toString();
2048: Debug.logError(e, ioeErrMsg, module);
2049: return ServiceUtil.returnError(ioeErrMsg);
2050: }
2051:
2052: // connect to UPS server, send AccessRequest to auth
2053: // send ShipmentConfirmRequest String
2054: // get ShipmentConfirmResponse String back
2055: StringBuffer xmlString = new StringBuffer();
2056: // TODO: note that we may have to append <?xml version="1.0"?> before each string
2057: xmlString.append(accessRequestString);
2058: xmlString.append(trackRequestString);
2059:
2060: if (shipmentUpsSaveCertificationInfo) {
2061: String outFileName = shipmentUpsSaveCertificationPath
2062: + "/UpsTrackRequest"
2063: + shipmentId
2064: + "_"
2065: + shipmentRouteSegment
2066: .getString("shipmentRouteSegmentId")
2067: + ".xml";
2068: try {
2069: FileOutputStream fileOut = new FileOutputStream(
2070: outFileName);
2071: fileOut.write(xmlString.toString().getBytes());
2072: fileOut.flush();
2073: fileOut.close();
2074: } catch (IOException e) {
2075: Debug.log(e, "Could not save UPS XML file: [[["
2076: + xmlString.toString() + "]]] to file: "
2077: + outFileName, module);
2078: }
2079: }
2080:
2081: try {
2082: trackResponseString = sendUpsRequest("Track", xmlString
2083: .toString());
2084: } catch (UpsConnectException e) {
2085: String uceErrMsg = "Error sending UPS request for UPS Service Track: "
2086: + e.toString();
2087: Debug.logError(e, uceErrMsg, module);
2088: return ServiceUtil.returnError(uceErrMsg);
2089: }
2090:
2091: if (shipmentUpsSaveCertificationInfo) {
2092: String outFileName = shipmentUpsSaveCertificationPath
2093: + "/UpsTrackResponseString"
2094: + shipmentId
2095: + "_"
2096: + shipmentRouteSegment
2097: .getString("shipmentRouteSegmentId")
2098: + ".xml";
2099: try {
2100: FileOutputStream fileOut = new FileOutputStream(
2101: outFileName);
2102: fileOut.write(trackResponseString.getBytes());
2103: fileOut.flush();
2104: fileOut.close();
2105: } catch (IOException e) {
2106: Debug.log(e, "Could not save UPS XML file: [[["
2107: + xmlString.toString() + "]]] to file: "
2108: + outFileName, module);
2109: }
2110: }
2111:
2112: Document trackResponseDocument = null;
2113: try {
2114: trackResponseDocument = UtilXml.readXmlDocument(
2115: trackResponseString, false);
2116: } catch (SAXException e2) {
2117: String excErrMsg = "Error parsing the TrackResponse: "
2118: + e2.toString();
2119: Debug.logError(e2, excErrMsg, module);
2120: return ServiceUtil.returnError(excErrMsg);
2121: } catch (ParserConfigurationException e2) {
2122: String excErrMsg = "Error parsing the TrackResponse: "
2123: + e2.toString();
2124: Debug.logError(e2, excErrMsg, module);
2125: return ServiceUtil.returnError(excErrMsg);
2126: } catch (IOException e2) {
2127: String excErrMsg = "Error parsing the TrackResponse: "
2128: + e2.toString();
2129: Debug.logError(e2, excErrMsg, module);
2130: return ServiceUtil.returnError(excErrMsg);
2131: }
2132:
2133: return handleUpsTrackShipmentResponse(
2134: trackResponseDocument, shipmentRouteSegment,
2135: shipmentPackageRouteSegs);
2136: } catch (GenericEntityException e) {
2137: Debug.logError(e, module);
2138: return ServiceUtil
2139: .returnError("Error reading or writing Shipment data for UPS Track Shipment: "
2140: + e.toString());
2141: }
2142: }
2143:
2144: public static Map handleUpsTrackShipmentResponse(
2145: Document trackResponseDocument,
2146: GenericValue shipmentRouteSegment,
2147: List shipmentPackageRouteSegs)
2148: throws GenericEntityException {
2149: // process TrackResponse, update data as needed
2150: Element trackResponseElement = trackResponseDocument
2151: .getDocumentElement();
2152:
2153: // handle Response element info
2154: Element responseElement = UtilXml.firstChildElement(
2155: trackResponseElement, "Response");
2156: Element responseTransactionReferenceElement = UtilXml
2157: .firstChildElement(responseElement,
2158: "TransactionReference");
2159: String responseTransactionReferenceCustomerContext = UtilXml
2160: .childElementValue(responseTransactionReferenceElement,
2161: "CustomerContext");
2162: String responseTransactionReferenceXpciVersion = UtilXml
2163: .childElementValue(responseTransactionReferenceElement,
2164: "XpciVersion");
2165:
2166: String responseStatusCode = UtilXml.childElementValue(
2167: responseElement, "ResponseStatusCode");
2168: String responseStatusDescription = UtilXml.childElementValue(
2169: responseElement, "ResponseStatusDescription");
2170: List errorList = new LinkedList();
2171: UpsServices.handleErrors(responseElement, errorList);
2172:
2173: if ("1".equals(responseStatusCode)) {
2174: // TODO: handle other response elements
2175: Element shipmentElement = UtilXml.firstChildElement(
2176: trackResponseElement, "Shipment");
2177:
2178: Element shipperElement = UtilXml.firstChildElement(
2179: shipmentElement, "Shipper");
2180: String shipperNumber = UtilXml.childElementValue(
2181: shipperElement, "ShipperNumber");
2182:
2183: Element serviceElement = UtilXml.firstChildElement(
2184: shipmentElement, "Service");
2185: String serviceCode = UtilXml.childElementValue(
2186: serviceElement, "Code");
2187: String serviceDescription = UtilXml.childElementValue(
2188: serviceElement, "Description");
2189:
2190: String shipmentIdentificationNumber = UtilXml
2191: .childElementValue(shipmentElement,
2192: "ShipmentIdentificationNumber");
2193:
2194: List packageElements = UtilXml.childElementList(
2195: shipmentElement, "Package");
2196: Iterator packageElementIter = packageElements.iterator();
2197: while (packageElementIter.hasNext()) {
2198: Element packageElement = (Element) packageElementIter
2199: .next();
2200: }
2201: /*
2202: <Package>
2203: <TrackingNumber>1Z12345E1512345676</TrackingNumber>
2204: <Activity>
2205: <ActivityLocation>
2206: <Address>
2207: <City>CLAKVILLE</City>
2208: <StateProvinceCode>AK</StateProvinceCode>
2209: <PostalCode>99901</PostalCode>
2210: <CountryCode>US</CountryCode>
2211: </Address>
2212: <Code>MG</Code>
2213: <Description>MC MAN</Description>
2214: </ActivityLocation>
2215: <Status>
2216: <StatusType>
2217: <Code>D</Code>
2218: <Description>DELIVERED</Description>
2219: </StatusType>
2220: <StatusCode>
2221: <Code>FS</Code>
2222: </StatusCode>
2223: </Status>
2224: <Date>20020930</Date>
2225: <Time>130900</Time>
2226: </Activity>
2227: <PackageWeight>
2228: <UnitOfMeasurement>
2229: <Code>LBS</Code>
2230: </UnitOfMeasurement>
2231: <Weight>0.00</Weight>
2232: </PackageWeight>
2233: </Package>
2234: *
2235: */
2236:
2237: // -=-=-=- Okay, now done with that, just return any extra info...
2238: StringBuffer successString = new StringBuffer(
2239: "The UPS TrackShipment succeeded");
2240: if (errorList.size() > 0) {
2241: // this shouldn't happen much, but handle it anyway
2242: successString.append(", but the following occurred: ");
2243: Iterator errorListIter = errorList.iterator();
2244: while (errorListIter.hasNext()) {
2245: String errorMsg = (String) errorListIter.next();
2246: successString.append(errorMsg);
2247: if (errorListIter.hasNext()) {
2248: successString.append(", ");
2249: }
2250: }
2251: }
2252: return ServiceUtil.returnSuccess(successString.toString());
2253: } else {
2254: errorList.add(0, "The UPS ShipmentConfirm failed");
2255: return ServiceUtil.returnError(errorList);
2256: }
2257: }
2258:
2259: public static Document createAccessRequestDocument() {
2260: Document accessRequestDocument = UtilXml
2261: .makeEmptyXmlDocument("AccessRequest");
2262: Element accessRequestElement = accessRequestDocument
2263: .getDocumentElement();
2264: UtilXml.addChildElementValue(accessRequestElement,
2265: "AccessLicenseNumber", UtilProperties.getPropertyValue(
2266: "shipment",
2267: "shipment.ups.access.license.number"),
2268: accessRequestDocument);
2269: UtilXml.addChildElementValue(accessRequestElement, "UserId",
2270: UtilProperties.getPropertyValue("shipment",
2271: "shipment.ups.access.user.id"),
2272: accessRequestDocument);
2273: UtilXml.addChildElementValue(accessRequestElement, "Password",
2274: UtilProperties.getPropertyValue("shipment",
2275: "shipment.ups.access.password"),
2276: accessRequestDocument);
2277: return accessRequestDocument;
2278: }
2279:
2280: public static void handleErrors(Element responseElement,
2281: List errorList) {
2282: List errorElements = UtilXml.childElementList(responseElement,
2283: "Error");
2284: Iterator errorElementIter = errorElements.iterator();
2285: while (errorElementIter.hasNext()) {
2286: StringBuffer errorMessageBuf = new StringBuffer();
2287: Element errorElement = (Element) errorElementIter.next();
2288:
2289: String errorSeverity = UtilXml.childElementValue(
2290: errorElement, "ErrorSeverity");
2291: String errorCode = UtilXml.childElementValue(errorElement,
2292: "ErrorCode");
2293: String errorDescription = UtilXml.childElementValue(
2294: errorElement, "ErrorDescription");
2295: String minimumRetrySeconds = UtilXml.childElementValue(
2296: errorElement, "MinimumRetrySeconds");
2297:
2298: errorMessageBuf.append("An error occurred [code:");
2299: errorMessageBuf.append(errorCode);
2300: errorMessageBuf.append("] with severity ");
2301: errorMessageBuf.append(errorSeverity);
2302: errorMessageBuf.append(": ");
2303: errorMessageBuf.append(errorDescription);
2304: if (UtilValidate.isNotEmpty(minimumRetrySeconds)) {
2305: errorMessageBuf.append("; you should wait ");
2306: errorMessageBuf.append(minimumRetrySeconds);
2307: errorMessageBuf.append(" seconds before retrying. ");
2308: } else {
2309: errorMessageBuf.append(". ");
2310: }
2311:
2312: List errorLocationElements = UtilXml.childElementList(
2313: errorElement, "ErrorLocation");
2314: Iterator errorLocationElementIter = errorLocationElements
2315: .iterator();
2316: while (errorLocationElementIter.hasNext()) {
2317: Element errorLocationElement = (Element) errorLocationElementIter
2318: .next();
2319: String errorLocationElementName = UtilXml
2320: .childElementValue(errorLocationElement,
2321: "ErrorLocationElementName");
2322: String errorLocationAttributeName = UtilXml
2323: .childElementValue(errorLocationElement,
2324: "ErrorLocationAttributeName");
2325:
2326: errorMessageBuf.append("The error was at Element [");
2327: errorMessageBuf.append(errorLocationElementName);
2328: errorMessageBuf.append("]");
2329:
2330: if (UtilValidate.isNotEmpty(errorLocationAttributeName)) {
2331: errorMessageBuf.append(" in the attribute [");
2332: errorMessageBuf.append(errorLocationAttributeName);
2333: errorMessageBuf.append("]");
2334: }
2335:
2336: List errorDigestElements = UtilXml.childElementList(
2337: errorLocationElement, "ErrorDigest");
2338: Iterator errorDigestElementIter = errorDigestElements
2339: .iterator();
2340: while (errorDigestElementIter.hasNext()) {
2341: Element errorDigestElement = (Element) errorDigestElementIter
2342: .next();
2343: errorMessageBuf.append(" full text: [");
2344: errorMessageBuf.append(UtilXml
2345: .elementValue(errorDigestElement));
2346: errorMessageBuf.append("]");
2347: }
2348: }
2349:
2350: errorList.add(errorMessageBuf.toString());
2351: }
2352: }
2353:
2354: /**
2355: * Opens a URL to UPS and makes a request.
2356: * @param upsService Name of the UPS service to invoke
2357: * @param xmlString XML message to send
2358: * @return XML string response from UPS
2359: * @throws UpsConnectException
2360: */
2361: public static String sendUpsRequest(String upsService,
2362: String xmlString) throws UpsConnectException {
2363: String conStr = UtilProperties.getPropertyValue(
2364: "shipment.properties", "shipment.ups.connect.url");
2365: if (conStr == null) {
2366: throw new UpsConnectException(
2367: "Incomplete connection URL; check your UPS configuration");
2368: }
2369:
2370: // need a ups service to call
2371: if (upsService == null) {
2372: throw new UpsConnectException(
2373: "UPS service name cannot be null");
2374: }
2375:
2376: // xmlString should contain the auth document at the beginning
2377: // all documents require an <?xml version="1.0"?> header
2378: if (xmlString == null) {
2379: throw new UpsConnectException("XML message cannot be null");
2380: }
2381:
2382: // prepare the connect string
2383: conStr = conStr.trim();
2384: if (!conStr.endsWith("/")) {
2385: conStr = conStr + "/";
2386: }
2387: conStr = conStr + upsService;
2388:
2389: if (Debug.verboseOn())
2390: Debug.logVerbose("UPS Connect URL : " + conStr, module);
2391: if (Debug.verboseOn())
2392: Debug.logVerbose("UPS XML String : " + xmlString, module);
2393:
2394: HttpClient http = new HttpClient(conStr);
2395: String response = null;
2396: try {
2397: response = http.post(xmlString);
2398: } catch (HttpClientException e) {
2399: Debug.logError(e, "Problem connecting with UPS server",
2400: module);
2401: throw new UpsConnectException("URL Connection problem", e);
2402: }
2403:
2404: if (response == null) {
2405: throw new UpsConnectException("Received a null response");
2406: }
2407: if (Debug.verboseOn())
2408: Debug.logVerbose("UPS Response : " + response, module);
2409:
2410: return response;
2411: }
2412: }
2413:
2414: class UpsConnectException extends GeneralException {
2415: UpsConnectException() {
2416: super ();
2417: }
2418:
2419: UpsConnectException(String msg) {
2420: super (msg);
2421: }
2422:
2423: UpsConnectException(Throwable t) {
2424: super (t);
2425: }
2426:
2427: UpsConnectException(String msg, Throwable t) {
2428: super (msg, t);
2429: }
2430: }
2431:
2432: /*
2433: * UPS Code Reference
2434:
2435: UPS Service IDs
2436: ShipConfirm
2437: ShipAccept
2438: Void
2439: Track
2440:
2441: Package Type Code
2442: 00 Unknown
2443: 01 UPS Letter
2444: 02 Package
2445: 03 UPS Tube
2446: 04 UPS Pak
2447: 21 UPS Express Box
2448: 24 UPS 25KG Box
2449: 25 UPS 10KG Box
2450:
2451: Pickup Types
2452: 01 Daily Pickup
2453: 03 Customer Counter
2454: 06 One Time Pickup
2455: 07 On Call Air Pickup
2456: 19 Letter Center
2457: 20 Air Service Center
2458:
2459: UPS Service Codes
2460: US Origin
2461: 01 UPS Next Day Air
2462: 02 UPS 2nd Day Air
2463: 03 UPS Ground
2464: 07 UPS Worldwide Express
2465: 08 UPS Worldwide Expedited
2466: 11 UPS Standard
2467: 12 UPS 3-Day Select
2468: 13 UPS Next Day Air Saver
2469: 14 UPS Next Day Air Early AM
2470: 54 UPS Worldwide Express Plus
2471: 59 UPS 2nd Day Air AM
2472: 64 N/A
2473: 65 UPS Express Saver
2474:
2475: Reference Number Codes
2476: AJ Acct. Rec. Customer Acct.
2477: AT Appropriation Number
2478: BM Bill of Lading Number
2479: 9V COD Number
2480: ON Dealer Order Number
2481: DP Department Number
2482: EI Employer's ID Number
2483: 3Q FDA Product Code
2484: TJ Federal Taxpayer ID Number
2485: IK Invoice Number
2486: MK Manifest Key Number
2487: MJ Model Number
2488: PM Part Number
2489: PC Production Code
2490: PO Purchase Order No.
2491: RQ Purchase Request No.
2492: RZ Return Authorization No.
2493: SA Salesperson No.
2494: SE Serial No.
2495: SY Social Security No.
2496: ST Store No.
2497: TN Transaction Ref. No.
2498:
2499: Error Codes
2500: First note that in the ref guide there are about 21 pages of error codes
2501: Here are some overalls:
2502: 1 Success (no error)
2503: 01xxxx XML Error
2504: 02xxxx Architecture Error
2505: 15xxxx Tracking Specific Error
2506:
2507: */
2508:
2509: /*
2510: * Sample XML documents:
2511: *
2512: <?xml version="1.0"?>
2513: <AccessRequest xml:lang="en-US">
2514: <AccessLicenseNumber>TEST262223144CAT</AccessLicenseNumber>
2515: <UserId>REG111111</UserId>
2516: <Password>REG111111</Password>
2517: </AccessRequest>
2518:
2519: =======================================
2520: Shipment Confirm Request/Response
2521: =======================================
2522:
2523: <?xml version="1.0"?>
2524: <ShipmentConfirmRequest xml:lang="en-US">
2525: <Request>
2526: <TransactionReference>
2527: <CustomerContext>Ship Confirm / nonvalidate</CustomerContext>
2528: <XpciVersion>1.0001</XpciVersion>
2529: </TransactionReference>
2530: <RequestAction>ShipConfirm</RequestAction>
2531: <RequestOption>nonvalidate</RequestOption>
2532: </Request>
2533: <LabelSpecification>
2534: <LabelPrintMethod>
2535: <Code>GIF</Code>
2536: </LabelPrintMethod>
2537: <HTTPUserAgent>Mozilla/5.0</HTTPUserAgent>
2538: <LabelImageFormat>
2539: <Code>GIF</Code>
2540: </LabelImageFormat>
2541: </LabelSpecification>
2542: <Shipment>
2543: <Description>DescriptionofGoodsTest</Description>
2544: <Shipper>
2545: <Name>ShipperName</Name>
2546: <AttentionName>ShipperName</AttentionName>
2547: <PhoneNumber>2226267227</PhoneNumber>
2548: <ShipperNumber>12345E</ShipperNumber>
2549: <Address>
2550: <AddressLine1>123 ShipperStreet</AddressLine1>
2551: <AddressLine2>123 ShipperStreet</AddressLine2>
2552: <AddressLine3>123 ShipperStreet</AddressLine3>
2553: <City>ShipperCity</City>
2554: <StateProvinceCode>foo</StateProvinceCode>
2555: <PostalCode>03570</PostalCode>
2556: <CountryCode>DE</CountryCode>
2557: </Address>
2558: </Shipper>
2559: <ShipTo>
2560: <CompanyName>ShipToCompanyName</CompanyName>
2561: <AttentionName>ShipToAttnName</AttentionName>
2562: <PhoneNumber>3336367336</PhoneNumber>
2563: <Address>
2564: <AddressLine1>123 ShipToStreet</AddressLine1>
2565: <PostalCode>DT09</PostalCode>
2566: <City>Trent</City>
2567: <CountryCode>GB</CountryCode>
2568: </Address>
2569: </ShipTo>
2570: <ShipFrom>
2571: <CompanyName>ShipFromCompanyName</CompanyName>
2572: <AttentionName>ShipFromAttnName</AttentionName>
2573: <PhoneNumber>7525565064</PhoneNumber>
2574: <Address>
2575: <AddressLine1>123 ShipFromStreet</AddressLine1>
2576: <City>Berlin</City>
2577: <PostalCode>03570</PostalCode>
2578: <CountryCode>DE</CountryCode>
2579: </Address>
2580: </ShipFrom>
2581: <PaymentInformation>
2582: <Prepaid>
2583: <BillShipper>
2584: <AccountNumber>12345E</AccountNumber>
2585: </BillShipper>
2586: </Prepaid>
2587: </PaymentInformation>
2588: <Service>
2589: <Code>07</Code>
2590: </Service>
2591: <Package>
2592: <PackagingType>
2593: <Code>02</Code>
2594: </PackagingType>
2595: <Dimensions>
2596: <UnitOfMeasurement>
2597: <Code>CM</Code>
2598: </UnitOfMeasurement>
2599: <Length>60</Length>
2600: <Width>7</Width>
2601: <Height>5</Height>
2602: </Dimensions>
2603: <PackageWeight>
2604: <UnitOfMeasurement>
2605: <Code>KGS</Code>
2606: </UnitOfMeasurement>
2607: <Weight>3.0</Weight>
2608: </PackageWeight>
2609: <ReferenceNumber>
2610: <Code>MK</Code>
2611: <Value>00001</Value>
2612: </ReferenceNumber>
2613: </Package>
2614: </Shipment>
2615: </ShipmentConfirmRequest>
2616:
2617: =======================================
2618:
2619: <?xml version="1.0"?>
2620: <ShipmentConfirmResponse>
2621: <Response>
2622: <TransactionReference>
2623: <CustomerContext>ShipConfirmUS</CustomerContext>
2624: <XpciVersion>1.0001</XpciVersion>
2625: </TransactionReference>
2626: <ResponseStatusCode>1</ResponseStatusCode>
2627: <ResponseStatusDescription>Success</ResponseStatusDescription>
2628: </Response>
2629: <ShipmentCharges>
2630: <TransportationCharges>
2631: <CurrencyCode>USD</CurrencyCode>
2632: <MonetaryValue>31.38</MonetaryValue>
2633: </TransportationCharges>
2634: <ServiceOptionsCharges>
2635: <CurrencyCode>USD</CurrencyCode>
2636: <MonetaryValue>7.75</MonetaryValue>
2637: </ServiceOptionsCharges>
2638: <TotalCharges>
2639: <CurrencyCode>USD</CurrencyCode>
2640: <MonetaryValue>39.13</MonetaryValue>
2641: </TotalCharges>
2642: </ShipmentCharges>
2643: <BillingWeight>
2644: <UnitOfMeasurement>
2645: <Code>LBS</Code>
2646: </UnitOfMeasurement>
2647: <Weight>4.0</Weight>
2648: </BillingWeight>
2649: <ShipmentIdentificationNumber>1Z12345E1512345676</ShipmentIdentificationNumber>
2650: <ShipmentDigest>INSERT SHIPPING DIGEST HERE</ShipmentDigest>
2651: </ShipmentConfirmResponse>
2652:
2653: =======================================
2654: Shipment Accept Request/Response
2655: =======================================
2656:
2657: <?xml version="1.0"?>
2658: <ShipmentAcceptRequest>
2659: <Request>
2660: <TransactionReference>
2661: <CustomerContext>TR01</CustomerContext>
2662: <XpciVersion>1.0001</XpciVersion>
2663: </TransactionReference>
2664: <RequestAction>ShipAccept</RequestAction>
2665: <RequestOption>01</RequestOption>
2666: </Request>
2667: <ShipmentDigest>INSERT SHIPPING DIGEST HERE</ShipmentDigest>
2668: </ShipmentAcceptRequest>
2669:
2670: =======================================
2671:
2672: <?xml version="1.0"?>
2673: <ShipmentAcceptResponse>
2674: <Response>
2675: <TransactionReference>
2676: <CustomerContext>TR01</CustomerContext>
2677: <XpciVersion>1.0001</XpciVersion>
2678: </TransactionReference>
2679: <ResponseStatusCode>1</ResponseStatusCode>
2680: <ResponseStatusDescription>Success</ResponseStatusDescription>
2681: </Response>
2682: <ShipmentResults>
2683: <ShipmentCharges>
2684: <TransportationCharges>
2685: <CurrencyCode>USD</CurrencyCode>
2686: <MonetaryValue>31.38</MonetaryValue>
2687: </TransportationCharges>
2688: <ServiceOptionsCharges>
2689: <CurrencyCode>USD</CurrencyCode>
2690: <MonetaryValue>7.75</MonetaryValue>
2691: </ServiceOptionsCharges>
2692: <TotalCharges>
2693: <CurrencyCode>USD</CurrencyCode>
2694: <MonetaryValue>39.13</MonetaryValue>
2695: </TotalCharges>
2696: </ShipmentCharges>
2697: <BillingWeight>
2698: <UnitOfMeasurement>
2699: <Code>LBS</Code>
2700: </UnitOfMeasurement>
2701: <Weight>4.0</Weight>
2702: </BillingWeight>
2703: <ShipmentIdentificationNumber>1Z12345E1512345676</ShipmentIdentificationNumber>
2704: <PackageResults>
2705: <TrackingNumber>1Z12345E1512345676</TrackingNumber>
2706: <ServiceOptionsCharges>
2707: <CurrencyCode>USD</CurrencyCode>
2708: <MonetaryValue>0.00</MonetaryValue>
2709: </ServiceOptionsCharges>
2710: <LabelImage>
2711: <LabelImageFormat>
2712: <Code>epl</Code>
2713: </LabelImageFormat>
2714: <GraphicImage>INSERT GRAPHIC IMAGE HERE</GraphicImage>
2715: </LabelImage>
2716: </PackageResults>
2717: <PackageResults>
2718: <TrackingNumber>1Z12345E1512345686</TrackingNumber>
2719: <ServiceOptionsCharges>
2720: <CurrencyCode>USD</CurrencyCode>
2721: <MonetaryValue>7.75</MonetaryValue>
2722: </ServiceOptionsCharges>
2723: <LabelImage>
2724: <LabelImageFormat>
2725: <Code>epl</Code>
2726: </LabelImageFormat>
2727: <GraphicImage>INSERT GRAPHIC IMAGE HERE</GraphicImage>
2728: </LabelImage>
2729: </PackageResults>
2730: </ShipmentResults>
2731: </ShipmentAcceptResponse>
2732:
2733: =======================================
2734: Void Shipment Request/Response
2735: =======================================
2736:
2737: <?xml version="1.0"?>
2738: <VoidShipmentRequest>
2739: <Request>
2740: <TransactionReference>
2741: <CustomerContext>Void</CustomerContext>
2742: <XpciVersion>1.0001</XpciVersion>
2743: </TransactionReference>
2744: <RequestAction>Void</RequestAction>
2745: <RequestOption>1</RequestOption>
2746: </Request>
2747: <ShipmentIdentificationNumber>1Z12345E1512345676</ShipmentIdentificationNumber>
2748: </VoidShipmentRequest>
2749:
2750: =======================================
2751:
2752: <?xml version="1.0"?>
2753: <VoidShipmentResponse>
2754: <Response>
2755: <TransactionReference>
2756: <XpciVersion>1.0001</XpciVersion>
2757: </TransactionReference>
2758: <ResponseStatusCode>1</ResponseStatusCode>
2759: <ResponseStatusDescription>Success</ResponseStatusDescription>
2760: </Response>
2761: <Status>
2762: <StatusType>
2763: <Code>1</Code>
2764: <Description>Success</Description>
2765: </StatusType>
2766: <StatusCode>
2767: <Code>1</Code>
2768: <Description>Success</Description>
2769: </StatusCode>
2770: </Status>
2771: </VoidShipmentResponse>
2772:
2773: =======================================
2774: Track Shipment Request/Response
2775: =======================================
2776:
2777: <?xml version="1.0"?>
2778: <TrackRequest xml:lang="en-US">
2779: <Request>
2780: <TransactionReference>
2781: <CustomerContext>sample</CustomerContext>
2782: <XpciVersion>1.0001</XpciVersion>
2783: </TransactionReference>
2784: <RequestAction>Track</RequestAction>
2785: </Request>
2786: <TrackingNumber>1Z12345E1512345676</TrackingNumber>
2787: </TrackRequest>
2788:
2789: =======================================
2790:
2791: <?xml version="1.0" encoding="UTF-8"?>
2792: <TrackResponse>
2793: <Response>
2794: <TransactionReference>
2795: <CustomerContext>sample</CustomerContext>
2796: <XpciVersion>1.0001</XpciVersion>
2797: </TransactionReference>
2798: <ResponseStatusCode>1</ResponseStatusCode>
2799: <ResponseStatusDescription>Success</ResponseStatusDescription>
2800: </Response>
2801: <Shipment>
2802: <Shipper>
2803: <ShipperNumber>12345E</ShipperNumber>
2804: </Shipper>
2805: <Service>
2806: <Code>15</Code>
2807: <Description>NDA EAM/EXP EAM</Description>
2808: </Service>
2809: <ShipmentIdentificationNumber>1Z12345E1512345676</ShipmentIdentificationNumber>
2810: <Package>
2811: <TrackingNumber>1Z12345E1512345676</TrackingNumber>
2812: <Activity>
2813: <ActivityLocation>
2814: <Address>
2815: <City>CLAKVILLE</City>
2816: <StateProvinceCode>AK</StateProvinceCode>
2817: <PostalCode>99901</PostalCode>
2818: <CountryCode>US</CountryCode>
2819: </Address>
2820: <Code>MG</Code>
2821: <Description>MC MAN</Description>
2822: </ActivityLocation>
2823: <Status>
2824: <StatusType>
2825: <Code>D</Code>
2826: <Description>DELIVERED</Description>
2827: </StatusType>
2828: <StatusCode>
2829: <Code>FS</Code>
2830: </StatusCode>
2831: </Status>
2832: <Date>20020930</Date>
2833: <Time>130900</Time>
2834: </Activity>
2835: <PackageWeight>
2836: <UnitOfMeasurement>
2837: <Code>LBS</Code>
2838: </UnitOfMeasurement>
2839: <Weight>0.00</Weight>
2840: </PackageWeight>
2841: </Package>
2842: </Shipment>
2843: </TrackResponse>
2844:
2845: */
|