Overview

Packages

  • currencysymbol
  • MAbout
  • Mage
    • Admin
    • Adminhtml
    • AdminNotification
    • Api
    • Api2
    • Authorizenet
    • Backup
    • Bundle
    • Captcha
    • Catalog
    • CatalogIndex
    • CatalogInventory
    • CatalogRule
    • CatalogSearch
    • Centinel
    • Checkout
    • Cms
    • Compiler
    • Connect
    • Contacts
    • Core
    • Cron
    • CurrencySymbol
    • Customer
    • Dataflow
    • Directory
    • DirtectPost
    • Downloadable
    • Eav
    • GiftMessage
    • GoogleAnalytics
    • GoogleBase
    • GoogleCheckout
    • ImportExport
    • Index
    • Install
    • Log
    • Media
    • Newsletter
    • Oauth
    • Page
    • PageCache
    • Paygate
    • Payment
    • Paypal
    • PaypalUk
    • Persistent
    • Poll
    • ProductAlert
    • Rating
    • Reports
    • Review
    • Rss
    • Rule
    • Sales
    • SalesRule
    • Sedfriend
    • Sendfriend
    • Shipping
    • Sitemap
    • Tag
    • Tax
    • Usa
    • Weee
    • Widget
    • Wishlist
    • XmlConnect
  • None
  • Phoenix
    • Moneybookers
  • PHP
  • Zend
    • Date
    • Mime
    • XmlRpc

Classes

  • Mage_Usa_Block_Adminhtml_Dhl_Unitofmeasure
  • Mage_Usa_Helper_Data
  • Mage_Usa_Model_Shipping_Carrier_Abstract
  • Mage_Usa_Model_Shipping_Carrier_Abstract_Source_Mode
  • Mage_Usa_Model_Shipping_Carrier_Abstract_Source_Requesttype
  • Mage_Usa_Model_Shipping_Carrier_Dhl
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Contenttype
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Abstract
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Doc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Freedoc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Freenondoc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Nondoc
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Size
  • Mage_Usa_Model_Shipping_Carrier_Dhl_International_Source_Method_Unitofmeasure
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf_Page
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Label_Pdf_PageBuilder
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Dutypaymenttype
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Protection_Rounding
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Protection_Value
  • Mage_Usa_Model_Shipping_Carrier_Dhl_Source_Shipmenttype
  • Mage_Usa_Model_Shipping_Carrier_Fedex
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Dropoff
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Fedex_Source_Packaging
  • Mage_Usa_Model_Shipping_Carrier_Ups
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Container
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_DestType
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_OriginShipment
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Pickup
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Type
  • Mage_Usa_Model_Shipping_Carrier_Ups_Source_Unitofmeasure
  • Mage_Usa_Model_Shipping_Carrier_Usps
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Container
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Freemethod
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Machinable
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Method
  • Mage_Usa_Model_Shipping_Carrier_Usps_Source_Size
  • Overview
  • Package
  • Class
  • Tree
   1: <?php
   2: /**
   3:  * Magento
   4:  *
   5:  * NOTICE OF LICENSE
   6:  *
   7:  * This source file is subject to the Open Software License (OSL 3.0)
   8:  * that is bundled with this package in the file LICENSE.txt.
   9:  * It is also available through the world-wide-web at this URL:
  10:  * http://opensource.org/licenses/osl-3.0.php
  11:  * If you did not receive a copy of the license and are unable to
  12:  * obtain it through the world-wide-web, please send an email
  13:  * to license@magentocommerce.com so we can send you a copy immediately.
  14:  *
  15:  * DISCLAIMER
  16:  *
  17:  * Do not edit or add to this file if you wish to upgrade Magento to newer
  18:  * versions in the future. If you wish to customize Magento for your
  19:  * needs please refer to http://www.magentocommerce.com for more information.
  20:  *
  21:  * @category    Mage
  22:  * @package     Mage_Usa
  23:  * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24:  * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
  25:  */
  26: 
  27: 
  28: /**
  29:  * UPS shipping implementation
  30:  *
  31:  * @category   Mage
  32:  * @package    Mage_Usa
  33:  * @author      Magento Core Team <core@magentocommerce.com>
  34:  */
  35: class Mage_Usa_Model_Shipping_Carrier_Ups
  36:     extends Mage_Usa_Model_Shipping_Carrier_Abstract
  37:     implements Mage_Shipping_Model_Carrier_Interface
  38: {
  39: 
  40:     /**
  41:      * Code of the carrier
  42:      *
  43:      * @var string
  44:      */
  45:     const CODE = 'ups';
  46: 
  47:     /**
  48:      * Delivery Confirmation level based on origin/destination
  49:      *
  50:      * @var int
  51:      */
  52:     const DELIVERY_CONFIRMATION_SHIPMENT = 1;
  53:     const DELIVERY_CONFIRMATION_PACKAGE = 2;
  54: 
  55:     /**
  56:      * Code of the carrier
  57:      *
  58:      * @var string
  59:      */
  60:     protected $_code = self::CODE;
  61: 
  62:     /**
  63:      * Rate request data
  64:      *
  65:      * @var Mage_Shipping_Model_Rate_Request|null
  66:      */
  67:     protected $_request = null;
  68: 
  69:     /**
  70:      * Raw rate request data
  71:      *
  72:      * @var Varien_Object|null
  73:      */
  74:     protected $_rawRequest = null;
  75: 
  76:     /**
  77:      * Rate result data
  78:      *
  79:      * @var Mage_Shipping_Model_Rate_Result|null
  80:      */
  81:     protected $_result = null;
  82: 
  83:     /**
  84:      * Base currency rate
  85:      *
  86:      * @var double
  87:      */
  88:     protected $_baseCurrencyRate;
  89: 
  90:     /**
  91:      * Xml access request
  92:      *
  93:      * @var string
  94:      */
  95:     protected $_xmlAccessRequest = null;
  96: 
  97:     /**
  98:      * Default cgi gateway url
  99:      *
 100:      * @var string
 101:      */
 102:     protected $_defaultCgiGatewayUrl = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi';
 103: 
 104:     /**
 105:      * Default urls for shipment
 106:      *
 107:      * @var array
 108:      */
 109:     protected $_defaultUrls = array(
 110:         'ShipConfirm' => 'https://wwwcie.ups.com/ups.app/xml/ShipConfirm',
 111:         'ShipAccept'  => 'https://wwwcie.ups.com/ups.app/xml/ShipAccept',
 112:     );
 113: 
 114:     /**
 115:      * Container types that could be customized for UPS carrier
 116:      *
 117:      * @var array
 118:      */
 119:     protected $_customizableContainerTypes = array('CP', 'CSP');
 120: 
 121:     /**
 122:      * Collect and get rates
 123:      *
 124:      * @param Mage_Shipping_Model_Rate_Request $request
 125:      * @return Mage_Shipping_Model_Rate_Result|bool|null
 126:      */
 127: 
 128:     public function collectRates(Mage_Shipping_Model_Rate_Request $request)
 129:     {
 130:         if (!$this->getConfigFlag($this->_activeFlag)) {
 131:             return false;
 132:         }
 133: 
 134:         $this->setRequest($request);
 135: 
 136:         $this->_result = $this->_getQuotes();
 137:         $this->_updateFreeMethodQuote($request);
 138: 
 139:         return $this->getResult();
 140:     }
 141: 
 142:     /**
 143:      * Prepare and set request to this instance
 144:      *
 145:      * @param Mage_Shipping_Model_Rate_Request $request
 146:      * @return Mage_Usa_Model_Shipping_Carrier_Ups
 147:      */
 148:     public function setRequest(Mage_Shipping_Model_Rate_Request $request)
 149:     {
 150:         $this->_request = $request;
 151: 
 152:         $r = new Varien_Object();
 153: 
 154:         if ($request->getLimitMethod()) {
 155:             $r->setAction($this->getCode('action', 'single'));
 156:             $r->setProduct($request->getLimitMethod());
 157:         } else {
 158:             $r->setAction($this->getCode('action', 'all'));
 159:             $r->setProduct('GND'.$this->getConfigData('dest_type'));
 160:         }
 161: 
 162:         if ($request->getUpsPickup()) {
 163:             $pickup = $request->getUpsPickup();
 164:         } else {
 165:             $pickup = $this->getConfigData('pickup');
 166:         }
 167:         $r->setPickup($this->getCode('pickup', $pickup));
 168: 
 169:         if ($request->getUpsContainer()) {
 170:             $container = $request->getUpsContainer();
 171:         } else {
 172:             $container = $this->getConfigData('container');
 173:         }
 174:         $r->setContainer($this->getCode('container', $container));
 175: 
 176:         if ($request->getUpsDestType()) {
 177:             $destType = $request->getUpsDestType();
 178:         } else {
 179:             $destType = $this->getConfigData('dest_type');
 180:         }
 181:         $r->setDestType($this->getCode('dest_type', $destType));
 182: 
 183:         if ($request->getOrigCountry()) {
 184:             $origCountry = $request->getOrigCountry();
 185:         } else {
 186:             $origCountry = Mage::getStoreConfig(
 187:                 Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
 188:                 $request->getStoreId()
 189:             );
 190:         }
 191: 
 192:         $r->setOrigCountry(Mage::getModel('directory/country')->load($origCountry)->getIso2Code());
 193: 
 194:         if ($request->getOrigRegionCode()) {
 195:             $origRegionCode = $request->getOrigRegionCode();
 196:         } else {
 197:             $origRegionCode = Mage::getStoreConfig(
 198:                 Mage_Shipping_Model_Shipping::XML_PATH_STORE_REGION_ID,
 199:                 $request->getStoreId()
 200:             );
 201:         }
 202:         if (is_numeric($origRegionCode)) {
 203:             $origRegionCode = Mage::getModel('directory/region')->load($origRegionCode)->getCode();
 204:         }
 205:         $r->setOrigRegionCode($origRegionCode);
 206: 
 207:         if ($request->getOrigPostcode()) {
 208:             $r->setOrigPostal($request->getOrigPostcode());
 209:         } else {
 210:             $r->setOrigPostal(Mage::getStoreConfig(
 211:                 Mage_Shipping_Model_Shipping::XML_PATH_STORE_ZIP,
 212:                 $request->getStoreId()
 213:             ));
 214:         }
 215: 
 216:         if ($request->getOrigCity()) {
 217:             $r->setOrigCity($request->getOrigCity());
 218:         } else {
 219:             $r->setOrigCity(Mage::getStoreConfig(
 220:                 Mage_Shipping_Model_Shipping::XML_PATH_STORE_CITY,
 221:                 $request->getStoreId()
 222:             ));
 223:         }
 224: 
 225: 
 226:         if ($request->getDestCountryId()) {
 227:             $destCountry = $request->getDestCountryId();
 228:         } else {
 229:             $destCountry = self::USA_COUNTRY_ID;
 230:         }
 231: 
 232:         //for UPS, puero rico state for US will assume as puerto rico country
 233:         if ($destCountry == self::USA_COUNTRY_ID
 234:             && ($request->getDestPostcode()=='00912' || $request->getDestRegionCode()==self::PUERTORICO_COUNTRY_ID)
 235:         ) {
 236:             $destCountry = self::PUERTORICO_COUNTRY_ID;
 237:         }
 238: 
 239:         // For UPS, Guam state of the USA will be represented by Guam country
 240:         if ($destCountry == self::USA_COUNTRY_ID && $request->getDestRegionCode() == self::GUAM_REGION_CODE) {
 241:             $destCountry = self::GUAM_COUNTRY_ID;
 242:         }
 243: 
 244:         $r->setDestCountry(Mage::getModel('directory/country')->load($destCountry)->getIso2Code());
 245: 
 246:         $r->setDestRegionCode($request->getDestRegionCode());
 247: 
 248:         if ($request->getDestPostcode()) {
 249:             $r->setDestPostal($request->getDestPostcode());
 250:         } else {
 251: 
 252:         }
 253: 
 254:         $weight = $this->getTotalNumOfBoxes($request->getPackageWeight());
 255: 
 256:         $weight = $this->_getCorrectWeight($weight);
 257: 
 258:         $r->setWeight($weight);
 259:         if ($request->getFreeMethodWeight()!=$request->getPackageWeight()) {
 260:             $r->setFreeMethodWeight($request->getFreeMethodWeight());
 261:         }
 262: 
 263:         $r->setValue($request->getPackageValue());
 264:         $r->setValueWithDiscount($request->getPackageValueWithDiscount());
 265: 
 266:         if ($request->getUpsUnitMeasure()) {
 267:             $unit = $request->getUpsUnitMeasure();
 268:         } else {
 269:             $unit = $this->getConfigData('unit_of_measure');
 270:         }
 271:         $r->setUnitMeasure($unit);
 272: 
 273:         $r->setIsReturn($request->getIsReturn());
 274: 
 275:         $r->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
 276: 
 277:         $this->_rawRequest = $r;
 278: 
 279:         return $this;
 280:     }
 281: 
 282:     /**
 283:      * Get correct weigt.
 284:      *
 285:      * Namely:
 286:      * Checks the current weight to comply with the minimum weight standards set by the carrier.
 287:      * Then strictly rounds the weight up until the first significant digit after the decimal point.
 288:      *
 289:      * @param float|integer|double $weight
 290:      * @return float
 291:      */
 292:     protected function _getCorrectWeight($weight)
 293:     {
 294:         $minWeight = $this->getConfigData('min_package_weight');
 295: 
 296:         if($weight < $minWeight){
 297:             $weight = $minWeight;
 298:         }
 299: 
 300:         //rounds a number to one significant figure
 301:         $weight = ceil($weight*10) / 10;
 302: 
 303:         return $weight;
 304:     }
 305: 
 306:     /**
 307:      * Get result of request
 308:      *
 309:      * @return mixed
 310:      */
 311:     public function getResult()
 312:     {
 313:        return $this->_result;
 314:     }
 315: 
 316:     /**
 317:      * Do remote request for  and handle errors
 318:      *
 319:      * @return Mage_Shipping_Model_Rate_Result
 320:      */
 321:     protected function _getQuotes()
 322:     {
 323:         switch ($this->getConfigData('type')) {
 324:             case 'UPS':
 325:                return $this->_getCgiQuotes();
 326: 
 327:             case 'UPS_XML':
 328:                return $this->_getXmlQuotes();
 329:         }
 330:         return null;
 331:     }
 332: 
 333:     /**
 334:      * Set free method request
 335:      *
 336:      * @param string $freeMethod
 337:      * @return null
 338:      */
 339:     protected function _setFreeMethodRequest($freeMethod)
 340:     {
 341:         $r = $this->_rawRequest;
 342: 
 343:         $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight());
 344:         $weight = $this->_getCorrectWeight($weight);
 345:         $r->setWeight($weight);
 346:         $r->setAction($this->getCode('action', 'single'));
 347:         $r->setProduct($freeMethod);
 348:     }
 349: 
 350:     /**
 351:      * Get cgi rates
 352:      *
 353:      * @return Mage_Shipping_Model_Rate_Result
 354:      */
 355:     protected function _getCgiQuotes()
 356:     {
 357:         $r = $this->_rawRequest;
 358: 
 359:         $params = array(
 360:             'accept_UPS_license_agreement' => 'yes',
 361:             '10_action'      => $r->getAction(),
 362:             '13_product'     => $r->getProduct(),
 363:             '14_origCountry' => $r->getOrigCountry(),
 364:             '15_origPostal'  => $r->getOrigPostal(),
 365:             'origCity'       => $r->getOrigCity(),
 366:             '19_destPostal'  => Mage_Usa_Model_Shipping_Carrier_Abstract::USA_COUNTRY_ID == $r->getDestCountry() ?
 367:                 substr($r->getDestPostal(), 0, 5) :
 368:                 $r->getDestPostal(),
 369:             '22_destCountry' => $r->getDestCountry(),
 370:             '23_weight'      => $r->getWeight(),
 371:             '47_rate_chart'  => $r->getPickup(),
 372:             '48_container'   => $r->getContainer(),
 373:             '49_residential' => $r->getDestType(),
 374:             'weight_std'     => strtolower($r->getUnitMeasure()),
 375:         );
 376:         $params['47_rate_chart'] = $params['47_rate_chart']['label'];
 377: 
 378:         $responseBody = $this->_getCachedQuotes($params);
 379:         if ($responseBody === null) {
 380:             $debugData = array('request' => $params);
 381:             try {
 382:                 $url = $this->getConfigData('gateway_url');
 383:                 if (!$url) {
 384:                     $url = $this->_defaultCgiGatewayUrl;
 385:                 }
 386:                 $client = new Zend_Http_Client();
 387:                 $client->setUri($url);
 388:                 $client->setConfig(array('maxredirects'=>0, 'timeout'=>30));
 389:                 $client->setParameterGet($params);
 390:                 $response = $client->request();
 391:                 $responseBody = $response->getBody();
 392: 
 393:                 $debugData['result'] = $responseBody;
 394:                 $this->_setCachedQuotes($params, $responseBody);
 395:             }
 396:             catch (Exception $e) {
 397:                 $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
 398:                 $responseBody = '';
 399:             }
 400:             $this->_debug($debugData);
 401:         }
 402: 
 403:         return $this->_parseCgiResponse($responseBody);
 404:     }
 405: 
 406:     /**
 407:      * Get shipment by code
 408:      *
 409:      * @param string $code
 410:      * @param string $origin
 411:      * @return array|bool
 412:      */
 413:     public function getShipmentByCode($code, $origin = null){
 414:         if($origin===null){
 415:             $origin = $this->getConfigData('origin_shipment');
 416:         }
 417:         $arr = $this->getCode('originShipment',$origin);
 418:         if(isset($arr[$code]))
 419:             return $arr[$code];
 420:         else
 421:             return false;
 422:     }
 423: 
 424: 
 425:     /**
 426:      * Prepare shipping rate result based on response
 427:      *
 428:      * @param mixed $response
 429:      * @return Mage_Shipping_Model_Rate_Result
 430:      */
 431:     protected function _parseCgiResponse($response)
 432:     {
 433:         $costArr = array();
 434:         $priceArr = array();
 435:         $errorTitle = Mage::helper('usa')->__('Unknown error');
 436:         if (strlen(trim($response))>0) {
 437:             $rRows = explode("\n", $response);
 438:             $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
 439:             foreach ($rRows as $rRow) {
 440:                 $r = explode('%', $rRow);
 441:                 switch (substr($r[0],-1)) {
 442:                     case 3: case 4:
 443:                         if (in_array($r[1], $allowedMethods)) {
 444:                             $responsePrice = Mage::app()->getLocale()->getNumber($r[8]);
 445:                             $costArr[$r[1]] = $responsePrice;
 446:                             $priceArr[$r[1]] = $this->getMethodPrice($responsePrice, $r[1]);
 447:                         }
 448:                         break;
 449:                     case 5:
 450:                         $errorTitle = $r[1];
 451:                         break;
 452:                     case 6:
 453:                         if (in_array($r[3], $allowedMethods)) {
 454:                             $responsePrice = Mage::app()->getLocale()->getNumber($r[10]);
 455:                             $costArr[$r[3]] = $responsePrice;
 456:                             $priceArr[$r[3]] = $this->getMethodPrice($responsePrice, $r[3]);
 457:                         }
 458:                         break;
 459:                 }
 460:             }
 461:             asort($priceArr);
 462:         }
 463: 
 464:         $result = Mage::getModel('shipping/rate_result');
 465:         $defaults = $this->getDefaults();
 466:         if (empty($priceArr)) {
 467:             $error = Mage::getModel('shipping/rate_result_error');
 468:             $error->setCarrier('ups');
 469:             $error->setCarrierTitle($this->getConfigData('title'));
 470:             $error->setErrorMessage($this->getConfigData('specificerrmsg'));
 471:             $result->append($error);
 472:         } else {
 473:             foreach ($priceArr as $method=>$price) {
 474:                 $rate = Mage::getModel('shipping/rate_result_method');
 475:                 $rate->setCarrier('ups');
 476:                 $rate->setCarrierTitle($this->getConfigData('title'));
 477:                 $rate->setMethod($method);
 478:                 $method_arr = $this->getCode('method', $method);
 479:                 $rate->setMethodTitle(Mage::helper('usa')->__($method_arr));
 480:                 $rate->setCost($costArr[$method]);
 481:                 $rate->setPrice($price);
 482:                 $result->append($rate);
 483:             }
 484:         }
 485: 
 486:         return $result;
 487:     }
 488: 
 489:     /**
 490:      * Get configuration data of carrier
 491:      *
 492:      * @param string $type
 493:      * @param string $code
 494:      * @return array|bool
 495:      */
 496:     public function getCode($type, $code='')
 497:     {
 498:         $codes = array(
 499:             'action'=>array(
 500:                 'single'=>'3',
 501:                 'all'=>'4',
 502:             ),
 503: 
 504:             'originShipment'=>array(
 505:                 // United States Domestic Shipments
 506:                 'United States Domestic Shipments' => array(
 507:                     '01' => Mage::helper('usa')->__('UPS Next Day Air'),
 508:                     '02' => Mage::helper('usa')->__('UPS Second Day Air'),
 509:                     '03' => Mage::helper('usa')->__('UPS Ground'),
 510:                     '07' => Mage::helper('usa')->__('UPS Worldwide Express'),
 511:                     '08' => Mage::helper('usa')->__('UPS Worldwide Expedited'),
 512:                     '11' => Mage::helper('usa')->__('UPS Standard'),
 513:                     '12' => Mage::helper('usa')->__('UPS Three-Day Select'),
 514:                     '13' => Mage::helper('usa')->__('UPS Next Day Air Saver'),
 515:                     '14' => Mage::helper('usa')->__('UPS Next Day Air Early A.M.'),
 516:                     '54' => Mage::helper('usa')->__('UPS Worldwide Express Plus'),
 517:                     '59' => Mage::helper('usa')->__('UPS Second Day Air A.M.'),
 518:                     '65' => Mage::helper('usa')->__('UPS Saver'),
 519:                 ),
 520:                 // Shipments Originating in United States
 521:                 'Shipments Originating in United States' => array(
 522:                     '01' => Mage::helper('usa')->__('UPS Next Day Air'),
 523:                     '02' => Mage::helper('usa')->__('UPS Second Day Air'),
 524:                     '03' => Mage::helper('usa')->__('UPS Ground'),
 525:                     '07' => Mage::helper('usa')->__('UPS Worldwide Express'),
 526:                     '08' => Mage::helper('usa')->__('UPS Worldwide Expedited'),
 527:                     '11' => Mage::helper('usa')->__('UPS Standard'),
 528:                     '12' => Mage::helper('usa')->__('UPS Three-Day Select'),
 529:                     '14' => Mage::helper('usa')->__('UPS Next Day Air Early A.M.'),
 530:                     '54' => Mage::helper('usa')->__('UPS Worldwide Express Plus'),
 531:                     '59' => Mage::helper('usa')->__('UPS Second Day Air A.M.'),
 532:                     '65' => Mage::helper('usa')->__('UPS Worldwide Saver'),
 533:                 ),
 534:                 // Shipments Originating in Canada
 535:                 'Shipments Originating in Canada' => array(
 536:                     '01' => Mage::helper('usa')->__('UPS Express'),
 537:                     '02' => Mage::helper('usa')->__('UPS Expedited'),
 538:                     '07' => Mage::helper('usa')->__('UPS Worldwide Express'),
 539:                     '08' => Mage::helper('usa')->__('UPS Worldwide Expedited'),
 540:                     '11' => Mage::helper('usa')->__('UPS Standard'),
 541:                     '12' => Mage::helper('usa')->__('UPS Three-Day Select'),
 542:                     '14' => Mage::helper('usa')->__('UPS Express Early A.M.'),
 543:                     '65' => Mage::helper('usa')->__('UPS Saver'),
 544:                 ),
 545:                 // Shipments Originating in the European Union
 546:                 'Shipments Originating in the European Union' => array(
 547:                     '07' => Mage::helper('usa')->__('UPS Express'),
 548:                     '08' => Mage::helper('usa')->__('UPS Expedited'),
 549:                     '11' => Mage::helper('usa')->__('UPS Standard'),
 550:                     '54' => Mage::helper('usa')->__('UPS Worldwide Express PlusSM'),
 551:                     '65' => Mage::helper('usa')->__('UPS Saver'),
 552:                 ),
 553:                 // Polish Domestic Shipments
 554:                 'Polish Domestic Shipments' => array(
 555:                     '07' => Mage::helper('usa')->__('UPS Express'),
 556:                     '08' => Mage::helper('usa')->__('UPS Expedited'),
 557:                     '11' => Mage::helper('usa')->__('UPS Standard'),
 558:                     '54' => Mage::helper('usa')->__('UPS Worldwide Express Plus'),
 559:                     '65' => Mage::helper('usa')->__('UPS Saver'),
 560:                     '82' => Mage::helper('usa')->__('UPS Today Standard'),
 561:                     '83' => Mage::helper('usa')->__('UPS Today Dedicated Courrier'),
 562:                     '84' => Mage::helper('usa')->__('UPS Today Intercity'),
 563:                     '85' => Mage::helper('usa')->__('UPS Today Express'),
 564:                     '86' => Mage::helper('usa')->__('UPS Today Express Saver'),
 565:                 ),
 566:                 // Puerto Rico Origin
 567:                 'Puerto Rico Origin' => array(
 568:                     '01' => Mage::helper('usa')->__('UPS Next Day Air'),
 569:                     '02' => Mage::helper('usa')->__('UPS Second Day Air'),
 570:                     '03' => Mage::helper('usa')->__('UPS Ground'),
 571:                     '07' => Mage::helper('usa')->__('UPS Worldwide Express'),
 572:                     '08' => Mage::helper('usa')->__('UPS Worldwide Expedited'),
 573:                     '14' => Mage::helper('usa')->__('UPS Next Day Air Early A.M.'),
 574:                     '54' => Mage::helper('usa')->__('UPS Worldwide Express Plus'),
 575:                     '65' => Mage::helper('usa')->__('UPS Saver'),
 576:                 ),
 577:                 // Shipments Originating in Mexico
 578:                 'Shipments Originating in Mexico' => array(
 579:                     '07' => Mage::helper('usa')->__('UPS Express'),
 580:                     '08' => Mage::helper('usa')->__('UPS Expedited'),
 581:                     '54' => Mage::helper('usa')->__('UPS Express Plus'),
 582:                     '65' => Mage::helper('usa')->__('UPS Saver'),
 583:                 ),
 584:                 // Shipments Originating in Other Countries
 585:                 'Shipments Originating in Other Countries' => array(
 586:                     '07' => Mage::helper('usa')->__('UPS Express'),
 587:                     '08' => Mage::helper('usa')->__('UPS Worldwide Expedited'),
 588:                     '11' => Mage::helper('usa')->__('UPS Standard'),
 589:                     '54' => Mage::helper('usa')->__('UPS Worldwide Express Plus'),
 590:                     '65' => Mage::helper('usa')->__('UPS Saver')
 591:                 )
 592:             ),
 593: 
 594:             'method'=>array(
 595:                 '1DM'    => Mage::helper('usa')->__('Next Day Air Early AM'),
 596:                 '1DML'   => Mage::helper('usa')->__('Next Day Air Early AM Letter'),
 597:                 '1DA'    => Mage::helper('usa')->__('Next Day Air'),
 598:                 '1DAL'   => Mage::helper('usa')->__('Next Day Air Letter'),
 599:                 '1DAPI'  => Mage::helper('usa')->__('Next Day Air Intra (Puerto Rico)'),
 600:                 '1DP'    => Mage::helper('usa')->__('Next Day Air Saver'),
 601:                 '1DPL'   => Mage::helper('usa')->__('Next Day Air Saver Letter'),
 602:                 '2DM'    => Mage::helper('usa')->__('2nd Day Air AM'),
 603:                 '2DML'   => Mage::helper('usa')->__('2nd Day Air AM Letter'),
 604:                 '2DA'    => Mage::helper('usa')->__('2nd Day Air'),
 605:                 '2DAL'   => Mage::helper('usa')->__('2nd Day Air Letter'),
 606:                 '3DS'    => Mage::helper('usa')->__('3 Day Select'),
 607:                 'GND'    => Mage::helper('usa')->__('Ground'),
 608:                 'GNDCOM' => Mage::helper('usa')->__('Ground Commercial'),
 609:                 'GNDRES' => Mage::helper('usa')->__('Ground Residential'),
 610:                 'STD'    => Mage::helper('usa')->__('Canada Standard'),
 611:                 'XPR'    => Mage::helper('usa')->__('Worldwide Express'),
 612:                 'WXS'    => Mage::helper('usa')->__('Worldwide Express Saver'),
 613:                 'XPRL'   => Mage::helper('usa')->__('Worldwide Express Letter'),
 614:                 'XDM'    => Mage::helper('usa')->__('Worldwide Express Plus'),
 615:                 'XDML'   => Mage::helper('usa')->__('Worldwide Express Plus Letter'),
 616:                 'XPD'    => Mage::helper('usa')->__('Worldwide Expedited'),
 617:             ),
 618: 
 619:             'pickup'=>array(
 620:                 'RDP'    => array("label"=>'Regular Daily Pickup',"code"=>"01"),
 621:                 'OCA'    => array("label"=>'On Call Air',"code"=>"07"),
 622:                 'OTP'    => array("label"=>'One Time Pickup',"code"=>"06"),
 623:                 'LC'     => array("label"=>'Letter Center',"code"=>"19"),
 624:                 'CC'     => array("label"=>'Customer Counter',"code"=>"03"),
 625:             ),
 626: 
 627:             'container'=>array(
 628:                 'CP'     => '00', // Customer Packaging
 629:                 'ULE'    => '01', // UPS Letter Envelope
 630:                 'CSP'    => '02', // Customer Supplied Package
 631:                 'UT'     => '03', // UPS Tube
 632:                 'PAK'    => '04', // PAK
 633:                 'UEB'    => '21', // UPS Express Box
 634:                 'UW25'   => '24', // UPS Worldwide 25 kilo
 635:                 'UW10'   => '25', // UPS Worldwide 10 kilo
 636:                 'PLT'    => '30', // Pallet
 637:                 'SEB'    => '2a', // Small Express Box
 638:                 'MEB'    => '2b', // Medium Express Box
 639:                 'LEB'    => '2c', // Large Express Box
 640:             ),
 641: 
 642:             'container_description'=>array(
 643:                 'CP'     => Mage::helper('usa')->__('Customer Packaging'),
 644:                 'ULE'    => Mage::helper('usa')->__('UPS Letter Envelope'),
 645:                 'CSP'    => Mage::helper('usa')->__('Customer Supplied Package'),
 646:                 'UT'     => Mage::helper('usa')->__('UPS Tube'),
 647:                 'PAK'    => Mage::helper('usa')->__('PAK'),
 648:                 'UEB'    => Mage::helper('usa')->__('UPS Express Box'),
 649:                 'UW25'   => Mage::helper('usa')->__('UPS Worldwide 25 kilo'),
 650:                 'UW10'   => Mage::helper('usa')->__('UPS Worldwide 10 kilo'),
 651:                 'PLT'    => Mage::helper('usa')->__('Pallet'),
 652:                 'SEB'    => Mage::helper('usa')->__('Small Express Box'),
 653:                 'MEB'    => Mage::helper('usa')->__('Medium Express Box'),
 654:                 'LEB'    => Mage::helper('usa')->__('Large Express Box'),
 655:             ),
 656: 
 657:             'dest_type'=>array(
 658:                 'RES'    => '01', // Residential
 659:                 'COM'    => '02', // Commercial
 660:             ),
 661: 
 662:             'dest_type_description'=>array(
 663:                 'RES'    => Mage::helper('usa')->__('Residential'),
 664:                 'COM'    => Mage::helper('usa')->__('Commercial'),
 665:             ),
 666: 
 667:             'unit_of_measure'=>array(
 668:                 'LBS'   =>  Mage::helper('usa')->__('Pounds'),
 669:                 'KGS'   =>  Mage::helper('usa')->__('Kilograms'),
 670:             ),
 671:             'containers_filter' => array(
 672:                 array(
 673:                     'containers' => array('00'), // Customer Packaging
 674:                     'filters'    => array(
 675:                         'within_us' => array(
 676:                             'method' => array(
 677:                                 '01', // Next Day Air
 678:                                 '13', // Next Day Air Saver
 679:                                 '12', // 3 Day Select
 680:                                 '59', // 2nd Day Air AM
 681:                                 '03', // Ground
 682:                                 '14', // Next Day Air Early AM
 683:                                 '02', // 2nd Day Air
 684:                             )
 685:                         ),
 686:                         'from_us' => array(
 687:                             'method' => array(
 688:                                 '07', // Worldwide Express
 689:                                 '54', // Worldwide Express Plus
 690:                                 '08', // Worldwide Expedited
 691:                                 '65', // Worldwide Saver
 692:                                 '11', // Standard
 693:                             )
 694:                         )
 695:                     )
 696:                 ),
 697:                 array(
 698:                     // Small Express Box, Medium Express Box, Large Express Box, UPS Tube
 699:                     'containers' => array('2a', '2b', '2c', '03'),
 700:                     'filters'    => array(
 701:                         'within_us' => array(
 702:                             'method' => array(
 703:                                 '01', // Next Day Air
 704:                                 '13', // Next Day Air Saver
 705:                                 '14', // Next Day Air Early AM
 706:                                 '02', // 2nd Day Air
 707:                                 '59', // 2nd Day Air AM
 708:                                 '13', // Next Day Air Saver
 709:                             )
 710:                         ),
 711:                         'from_us' => array(
 712:                             'method' => array(
 713:                                 '07', // Worldwide Express
 714:                                 '54', // Worldwide Express Plus
 715:                                 '08', // Worldwide Expedited
 716:                                 '65', // Worldwide Saver
 717:                             )
 718:                         )
 719:                     )
 720:                 ),
 721:                 array(
 722:                     'containers' => array('24', '25'), // UPS Worldwide 25 kilo, UPS Worldwide 10 kilo
 723:                     'filters'    => array(
 724:                         'within_us' => array(
 725:                             'method' => array()
 726:                         ),
 727:                         'from_us' => array(
 728:                             'method' => array(
 729:                                 '07', // Worldwide Express
 730:                                 '54', // Worldwide Express Plus
 731:                                 '65', // Worldwide Saver
 732:                             )
 733:                         )
 734:                     )
 735:                 ),
 736:                 array(
 737:                     'containers' => array('01', '04'), // UPS Letter, UPS PAK
 738:                     'filters'    => array(
 739:                         'within_us' => array(
 740:                             'method' => array(
 741:                                 '01', // Next Day Air
 742:                                 '14', // Next Day Air Early AM
 743:                                 '02', // 2nd Day Air
 744:                                 '59', // 2nd Day Air AM
 745:                                 '13', // Next Day Air Saver
 746:                             )
 747:                         ),
 748:                         'from_us' => array(
 749:                             'method' => array(
 750:                                 '07', // Worldwide Express
 751:                                 '54', // Worldwide Express Plus
 752:                                 '65', // Worldwide Saver
 753:                             )
 754:                         )
 755:                     )
 756:                 ),
 757:                 array(
 758:                     'containers' => array('04'), // UPS PAK
 759:                     'filters'    => array(
 760:                         'within_us' => array(
 761:                             'method' => array()
 762:                         ),
 763:                         'from_us' => array(
 764:                             'method' => array(
 765:                                 '08', // Worldwide Expedited
 766:                             )
 767:                         )
 768:                     )
 769:                 ),
 770:             )
 771:         );
 772: 
 773:         if (!isset($codes[$type])) {
 774:             return false;
 775:         } elseif (''===$code) {
 776:             return $codes[$type];
 777:         }
 778: 
 779:         if (!isset($codes[$type][$code])) {
 780:             return false;
 781:         } else {
 782:             return $codes[$type][$code];
 783:         }
 784:     }
 785: 
 786:     /**
 787:      * Get xml rates
 788:      *
 789:      * @return Mage_Shipping_Model_Rate_Result
 790:      */
 791:     protected function _getXmlQuotes()
 792:     {
 793:         $url = $this->getConfigData('gateway_xml_url');
 794: 
 795:         $this->setXMLAccessRequest();
 796:         $xmlRequest=$this->_xmlAccessRequest;
 797: 
 798:         $r = $this->_rawRequest;
 799:         $params = array(
 800:             'accept_UPS_license_agreement' => 'yes',
 801:             '10_action'      => $r->getAction(),
 802:             '13_product'     => $r->getProduct(),
 803:             '14_origCountry' => $r->getOrigCountry(),
 804:             '15_origPostal'  => $r->getOrigPostal(),
 805:             'origCity'       => $r->getOrigCity(),
 806:             'origRegionCode' => $r->getOrigRegionCode(),
 807:             '19_destPostal'  => Mage_Usa_Model_Shipping_Carrier_Abstract::USA_COUNTRY_ID == $r->getDestCountry() ?
 808:                 substr($r->getDestPostal(), 0, 5) :
 809:                 $r->getDestPostal(),
 810:             '22_destCountry' => $r->getDestCountry(),
 811:             'destRegionCode' => $r->getDestRegionCode(),
 812:             '23_weight'      => $r->getWeight(),
 813:             '47_rate_chart'  => $r->getPickup(),
 814:             '48_container'   => $r->getContainer(),
 815:             '49_residential' => $r->getDestType(),
 816:         );
 817: 
 818:         if ($params['10_action'] == '4') {
 819:             $params['10_action'] = 'Shop';
 820:             $serviceCode = null; // Service code is not relevant when we're asking ALL possible services' rates
 821:         } else {
 822:             $params['10_action'] = 'Rate';
 823:             $serviceCode = $r->getProduct() ? $r->getProduct() : '';
 824:         }
 825:         $serviceDescription = $serviceCode ? $this->getShipmentByCode($serviceCode) : '';
 826: 
 827: $xmlRequest .= <<< XMLRequest
 828: <?xml version="1.0"?>
 829: <RatingServiceSelectionRequest xml:lang="en-US">
 830:   <Request>
 831:     <TransactionReference>
 832:       <CustomerContext>Rating and Service</CustomerContext>
 833:       <XpciVersion>1.0</XpciVersion>
 834:     </TransactionReference>
 835:     <RequestAction>Rate</RequestAction>
 836:     <RequestOption>{$params['10_action']}</RequestOption>
 837:   </Request>
 838:   <PickupType>
 839:           <Code>{$params['47_rate_chart']['code']}</Code>
 840:           <Description>{$params['47_rate_chart']['label']}</Description>
 841:   </PickupType>
 842: 
 843:   <Shipment>
 844: XMLRequest;
 845: 
 846:         if ($serviceCode !== null) {
 847:             $xmlRequest .= "<Service>" .
 848:                 "<Code>{$serviceCode}</Code>" .
 849:                 "<Description>{$serviceDescription}</Description>" .
 850:                 "</Service>";
 851:         }
 852: 
 853:       $xmlRequest .= <<< XMLRequest
 854:       <Shipper>
 855: XMLRequest;
 856: 
 857:         if ($this->getConfigFlag('negotiated_active') && ($shipper = $this->getConfigData('shipper_number')) ) {
 858:             $xmlRequest .= "<ShipperNumber>{$shipper}</ShipperNumber>";
 859:         }
 860: 
 861:         if ($r->getIsReturn()) {
 862:             $shipperCity = '';
 863:             $shipperPostalCode = $params['19_destPostal'];
 864:             $shipperCountryCode = $params['22_destCountry'];
 865:             $shipperStateProvince = $params['destRegionCode'];
 866:         } else {
 867:             $shipperCity = $params['origCity'];
 868:             $shipperPostalCode = $params['15_origPostal'];
 869:             $shipperCountryCode = $params['14_origCountry'];
 870:             $shipperStateProvince = $params['origRegionCode'];
 871:         }
 872: 
 873: $xmlRequest .= <<< XMLRequest
 874:       <Address>
 875:           <City>{$shipperCity}</City>
 876:           <PostalCode>{$shipperPostalCode}</PostalCode>
 877:           <CountryCode>{$shipperCountryCode}</CountryCode>
 878:           <StateProvinceCode>{$shipperStateProvince}</StateProvinceCode>
 879:       </Address>
 880:     </Shipper>
 881:     <ShipTo>
 882:       <Address>
 883:           <PostalCode>{$params['19_destPostal']}</PostalCode>
 884:           <CountryCode>{$params['22_destCountry']}</CountryCode>
 885:           <ResidentialAddress>{$params['49_residential']}</ResidentialAddress>
 886:           <StateProvinceCode>{$params['destRegionCode']}</StateProvinceCode>
 887: XMLRequest;
 888: 
 889:           $xmlRequest .= ($params['49_residential']==='01'
 890:                   ? "<ResidentialAddressIndicator>{$params['49_residential']}</ResidentialAddressIndicator>"
 891:                   : ''
 892:           );
 893: 
 894: $xmlRequest .= <<< XMLRequest
 895:       </Address>
 896:     </ShipTo>
 897: 
 898: 
 899:     <ShipFrom>
 900:       <Address>
 901:           <PostalCode>{$params['15_origPostal']}</PostalCode>
 902:           <CountryCode>{$params['14_origCountry']}</CountryCode>
 903:           <StateProvinceCode>{$params['origRegionCode']}</StateProvinceCode>
 904:       </Address>
 905:     </ShipFrom>
 906: 
 907:     <Package>
 908:       <PackagingType><Code>{$params['48_container']}</Code></PackagingType>
 909:       <PackageWeight>
 910:          <UnitOfMeasurement><Code>{$r->getUnitMeasure()}</Code></UnitOfMeasurement>
 911:         <Weight>{$params['23_weight']}</Weight>
 912:       </PackageWeight>
 913:     </Package>
 914: XMLRequest;
 915:         if ($this->getConfigFlag('negotiated_active')) {
 916:             $xmlRequest .= "<RateInformation><NegotiatedRatesIndicator/></RateInformation>";
 917:         }
 918: 
 919: $xmlRequest .= <<< XMLRequest
 920:   </Shipment>
 921: </RatingServiceSelectionRequest>
 922: XMLRequest;
 923: 
 924:         $xmlResponse = $this->_getCachedQuotes($xmlRequest);
 925:         if ($xmlResponse === null) {
 926:             $debugData = array('request' => $xmlRequest);
 927:             try {
 928:                 $ch = curl_init();
 929:                 curl_setopt($ch, CURLOPT_URL, $url);
 930:                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 931:                 curl_setopt($ch, CURLOPT_HEADER, 0);
 932:                 curl_setopt($ch, CURLOPT_POST, 1);
 933:                 curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
 934:                 curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 935:                 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (boolean)$this->getConfigFlag('mode_xml'));
 936:                 $xmlResponse = curl_exec ($ch);
 937: 
 938:                 $debugData['result'] = $xmlResponse;
 939:                 $this->_setCachedQuotes($xmlRequest, $xmlResponse);
 940:             }
 941:             catch (Exception $e) {
 942:                 $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
 943:                 $xmlResponse = '';
 944:             }
 945:             $this->_debug($debugData);
 946:         }
 947: 
 948:         return $this->_parseXmlResponse($xmlResponse);
 949:     }
 950: 
 951:     /**
 952:      * Get base currency rate
 953:      *
 954:      * @param string $code
 955:      * @return double
 956:      */
 957:     protected function _getBaseCurrencyRate($code)
 958:     {
 959:         if (!$this->_baseCurrencyRate) {
 960:             $this->_baseCurrencyRate = Mage::getModel('directory/currency')
 961:                 ->load($code)
 962:                 ->getAnyRate($this->_request->getBaseCurrency()->getCode());
 963:         }
 964: 
 965:         return $this->_baseCurrencyRate;
 966:     }
 967: 
 968:     /**
 969:      * Prepare shipping rate result based on response
 970:      *
 971:      * @param mixed $response
 972:      * @return Mage_Shipping_Model_Rate_Result
 973:      */
 974:     protected function _parseXmlResponse($xmlResponse)
 975:     {
 976:         $costArr = array();
 977:         $priceArr = array();
 978:         if (strlen(trim($xmlResponse))>0) {
 979:             $xml = new Varien_Simplexml_Config();
 980:             $xml->loadString($xmlResponse);
 981:             $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/ResponseStatusCode/text()");
 982:             $success = (int)$arr[0];
 983:             if ($success===1) {
 984:                 $arr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment");
 985:                 $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
 986: 
 987:                 // Negotiated rates
 988:                 $negotiatedArr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates");
 989:                 $negotiatedActive = $this->getConfigFlag('negotiated_active')
 990:                     && $this->getConfigData('shipper_number')
 991:                     && !empty($negotiatedArr);
 992: 
 993:                 $allowedCurrencies = Mage::getModel('directory/currency')->getConfigAllowCurrencies();
 994: 
 995:                 foreach ($arr as $shipElement){
 996:                     $code = (string)$shipElement->Service->Code;
 997:                     if (in_array($code, $allowedMethods)) {
 998: 
 999:                         if ($negotiatedActive) {
1000:                             $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue;
1001:                         } else {
1002:                             $cost = $shipElement->TotalCharges->MonetaryValue;
1003:                         }
1004: 
1005:                         //convert price with Origin country currency code to base currency code
1006:                         $successConversion = true;
1007:                         $responseCurrencyCode = (string) $shipElement->TotalCharges->CurrencyCode;
1008:                         if ($responseCurrencyCode) {
1009:                             if (in_array($responseCurrencyCode, $allowedCurrencies)) {
1010:                                 $cost = (float) $cost * $this->_getBaseCurrencyRate($responseCurrencyCode);
1011:                             } else {
1012:                                 $errorTitle = Mage::helper('directory')->__('Can\'t convert rate from "%s-%s".', $responseCurrencyCode, $this->_request->getPackageCurrency()->getCode());
1013:                                 $error = Mage::getModel('shipping/rate_result_error');
1014:                                 $error->setCarrier('ups');
1015:                                 $error->setCarrierTitle($this->getConfigData('title'));
1016:                                 $error->setErrorMessage($errorTitle);
1017:                                 $successConversion = false;
1018:                             }
1019:                         }
1020: 
1021:                         if ($successConversion) {
1022:                             $costArr[$code] = $cost;
1023:                             $priceArr[$code] = $this->getMethodPrice(floatval($cost),$code);
1024:                         }
1025:                     }
1026:                 }
1027:             } else {
1028:                 $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/Error/ErrorDescription/text()");
1029:                 $errorTitle = (string)$arr[0][0];
1030:                 $error = Mage::getModel('shipping/rate_result_error');
1031:                 $error->setCarrier('ups');
1032:                 $error->setCarrierTitle($this->getConfigData('title'));
1033:                 $error->setErrorMessage($this->getConfigData('specificerrmsg'));
1034:             }
1035:         }
1036: 
1037:         $result = Mage::getModel('shipping/rate_result');
1038:         $defaults = $this->getDefaults();
1039:         if (empty($priceArr)) {
1040:             $error = Mage::getModel('shipping/rate_result_error');
1041:             $error->setCarrier('ups');
1042:             $error->setCarrierTitle($this->getConfigData('title'));
1043:             if(!isset($errorTitle)){
1044:                 $errorTitle = Mage::helper('usa')->__('Cannot retrieve shipping rates');
1045:             }
1046:             $error->setErrorMessage($this->getConfigData('specificerrmsg'));
1047:             $result->append($error);
1048:         } else {
1049:             foreach ($priceArr as $method=>$price) {
1050:                 $rate = Mage::getModel('shipping/rate_result_method');
1051:                 $rate->setCarrier('ups');
1052:                 $rate->setCarrierTitle($this->getConfigData('title'));
1053:                 $rate->setMethod($method);
1054:                 $method_arr = $this->getShipmentByCode($method);
1055:                 $rate->setMethodTitle($method_arr);
1056:                 $rate->setCost($costArr[$method]);
1057:                 $rate->setPrice($price);
1058:                 $result->append($rate);
1059:             }
1060:         }
1061:         return $result;
1062:     }
1063: 
1064:     /**
1065:      * Get tracking
1066:      *
1067:      * @param mixed $trackings
1068:      * @return mixed
1069:      */
1070:     public function getTracking($trackings)
1071:     {
1072:         $return = array();
1073: 
1074:         if (!is_array($trackings)) {
1075:             $trackings = array($trackings);
1076:         }
1077: 
1078:         if ($this->getConfigData('type')=='UPS') {
1079:             $this->_getCgiTracking($trackings);
1080:         } elseif ($this->getConfigData('type')=='UPS_XML'){
1081:             $this->setXMLAccessRequest();
1082:             $this->_getXmlTracking($trackings);
1083:         }
1084: 
1085:         return $this->_result;
1086:     }
1087: 
1088:     /**
1089:      * Set xml access request
1090:      *
1091:      * @return null
1092:      */
1093:     protected function setXMLAccessRequest()
1094:     {
1095:         $userid = $this->getConfigData('username');
1096:         $userid_pass = $this->getConfigData('password');
1097:         $access_key = $this->getConfigData('access_license_number');
1098: 
1099:         $this->_xmlAccessRequest =  <<<XMLAuth
1100: <?xml version="1.0"?>
1101: <AccessRequest xml:lang="en-US">
1102:   <AccessLicenseNumber>$access_key</AccessLicenseNumber>
1103:   <UserId>$userid</UserId>
1104:   <Password>$userid_pass</Password>
1105: </AccessRequest>
1106: XMLAuth;
1107:     }
1108: 
1109:     /**
1110:      * Get cgi tracking
1111:      *
1112:      * @param mixed $trackings
1113:      * @return mixed
1114:      */
1115:     protected function _getCgiTracking($trackings)
1116:     {
1117:         //ups no longer support tracking for data streaming version
1118:         //so we can only reply the popup window to ups.
1119:         $result = Mage::getModel('shipping/tracking_result');
1120:         $defaults = $this->getDefaults();
1121:         foreach($trackings as $tracking){
1122:             $status = Mage::getModel('shipping/tracking_result_status');
1123:             $status->setCarrier('ups');
1124:             $status->setCarrierTitle($this->getConfigData('title'));
1125:             $status->setTracking($tracking);
1126:             $status->setPopup(1);
1127:             $status->setUrl("http://wwwapps.ups.com/WebTracking/processInputRequest?HTMLVersion=5.0&error_carried=true"
1128:                 . "&tracknums_displayed=5&TypeOfInquiryNumber=T&loc=en_US&InquiryNumber1=$tracking"
1129:                 . "&AgreeToTermsAndConditions=yes"
1130:             );
1131:             $result->append($status);
1132:         }
1133: 
1134:         $this->_result = $result;
1135:         return $result;
1136:     }
1137: 
1138:     /**
1139:      * Get xml tracking
1140:      *
1141:      * @param mixed $trackings
1142:      * @return mixed
1143:      */
1144:     protected function _getXmlTracking($trackings)
1145:     {
1146:         $url = $this->getConfigData('tracking_xml_url');
1147: 
1148:         foreach($trackings as $tracking){
1149:             $xmlRequest=$this->_xmlAccessRequest;
1150: 
1151: /*
1152: * RequestOption==>'activity' or '1' to request all activities
1153: */
1154: $xmlRequest .=  <<<XMLAuth
1155: <?xml version="1.0" ?>
1156: <TrackRequest xml:lang="en-US">
1157:     <Request>
1158:         <RequestAction>Track</RequestAction>
1159:         <RequestOption>activity</RequestOption>
1160:     </Request>
1161:     <TrackingNumber>$tracking</TrackingNumber>
1162:     <IncludeFreight>01</IncludeFreight>
1163: </TrackRequest>
1164: XMLAuth;
1165:             $debugData = array('request' => $xmlRequest);
1166: 
1167:             try {
1168:                 $ch = curl_init();
1169:                    curl_setopt($ch, CURLOPT_URL, $url);
1170:                 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1171:                 curl_setopt($ch, CURLOPT_HEADER, 0);
1172:                 curl_setopt($ch, CURLOPT_POST, 1);
1173:                 curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
1174:                 curl_setopt($ch, CURLOPT_TIMEOUT, 30);
1175:                 $xmlResponse = curl_exec ($ch);
1176:                 $debugData['result'] = $xmlResponse;
1177:                 curl_close ($ch);
1178:             }
1179:             catch (Exception $e) {
1180:                 $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
1181:                 $xmlResponse = '';
1182:             }
1183: 
1184:             $this->_debug($debugData);
1185:             $this->_parseXmlTrackingResponse($tracking, $xmlResponse);
1186:         }
1187: 
1188:         return $this->_result;
1189:     }
1190: 
1191:     /**
1192:      * Parse xml tracking response
1193:      *
1194:      * @param string $trackingvalue
1195:      * @param string $response
1196:      * @return null
1197:      */
1198:     protected function _parseXmlTrackingResponse($trackingvalue, $xmlResponse)
1199:     {
1200:         $errorTitle = 'Unable to retrieve tracking';
1201:         $resultArr = array();
1202:         $packageProgress = array();
1203: 
1204:         if ($xmlResponse) {
1205:             $xml = new Varien_Simplexml_Config();
1206:             $xml->loadString($xmlResponse);
1207:             $arr = $xml->getXpath("//TrackResponse/Response/ResponseStatusCode/text()");
1208:             $success = (int)$arr[0][0];
1209: 
1210:             if($success===1){
1211:                 $arr = $xml->getXpath("//TrackResponse/Shipment/Service/Description/text()");
1212:                 $resultArr['service'] = (string)$arr[0];
1213: 
1214:                 $arr = $xml->getXpath("//TrackResponse/Shipment/PickupDate/text()");
1215:                 $resultArr['shippeddate'] = (string)$arr[0];
1216: 
1217:                 $arr = $xml->getXpath("//TrackResponse/Shipment/Package/PackageWeight/Weight/text()");
1218:                 $weight = (string)$arr[0];
1219: 
1220:                 $arr = $xml->getXpath("//TrackResponse/Shipment/Package/PackageWeight/UnitOfMeasurement/Code/text()");
1221:                 $unit = (string)$arr[0];
1222: 
1223:                 $resultArr['weight'] = "{$weight} {$unit}";
1224: 
1225:                 $activityTags = $xml->getXpath("//TrackResponse/Shipment/Package/Activity");
1226:                 if ($activityTags) {
1227:                     $i=1;
1228:                     foreach ($activityTags as $activityTag) {
1229:                         $addArr=array();
1230:                         if (isset($activityTag->ActivityLocation->Address->City)) {
1231:                             $addArr[] = (string)$activityTag->ActivityLocation->Address->City;
1232:                         }
1233:                         if (isset($activityTag->ActivityLocation->Address->StateProvinceCode)) {
1234:                             $addArr[] = (string)$activityTag->ActivityLocation->Address->StateProvinceCode;
1235:                         }
1236:                         if (isset($activityTag->ActivityLocation->Address->CountryCode)) {
1237:                             $addArr[] = (string)$activityTag->ActivityLocation->Address->CountryCode;
1238:                         }
1239:                         $dateArr = array();
1240:                         $date = (string)$activityTag->Date;//YYYYMMDD
1241:                         $dateArr[] = substr($date,0,4);
1242:                         $dateArr[] = substr($date,4,2);
1243:                         $dateArr[] = substr($date,-2,2);
1244: 
1245:                         $timeArr = array();
1246:                         $time = (string)$activityTag->Time;//HHMMSS
1247:                         $timeArr[] = substr($time,0,2);
1248:                         $timeArr[] = substr($time,2,2);
1249:                         $timeArr[] = substr($time,-2,2);
1250: 
1251:                         if($i==1){
1252:                            $resultArr['status'] = (string)$activityTag->Status->StatusType->Description;
1253:                            $resultArr['deliverydate'] = implode('-',$dateArr);//YYYY-MM-DD
1254:                            $resultArr['deliverytime'] = implode(':',$timeArr);//HH:MM:SS
1255:                            $resultArr['deliverylocation'] = (string)$activityTag->ActivityLocation->Description;
1256:                            $resultArr['signedby'] = (string)$activityTag->ActivityLocation->SignedForByName;
1257:                            if ($addArr) {
1258:                             $resultArr['deliveryto']=implode(', ',$addArr);
1259:                            }
1260:                         }else{
1261:                            $tempArr=array();
1262:                            $tempArr['activity'] = (string)$activityTag->Status->StatusType->Description;
1263:                            $tempArr['deliverydate'] = implode('-',$dateArr);//YYYY-MM-DD
1264:                            $tempArr['deliverytime'] = implode(':',$timeArr);//HH:MM:SS
1265:                            if ($addArr) {
1266:                             $tempArr['deliverylocation']=implode(', ',$addArr);
1267:                            }
1268:                            $packageProgress[] = $tempArr;
1269:                         }
1270:                         $i++;
1271:                     }
1272:                     $resultArr['progressdetail'] = $packageProgress;
1273:                 }
1274:             } else {
1275:                 $arr = $xml->getXpath("//TrackResponse/Response/Error/ErrorDescription/text()");
1276:                 $errorTitle = (string)$arr[0][0];
1277:             }
1278:         }
1279: 
1280:         if (!$this->_result) {
1281:             $this->_result = Mage::getModel('shipping/tracking_result');
1282:         }
1283: 
1284:         $defaults = $this->getDefaults();
1285: 
1286:         if ($resultArr) {
1287:             $tracking = Mage::getModel('shipping/tracking_result_status');
1288:             $tracking->setCarrier('ups');
1289:             $tracking->setCarrierTitle($this->getConfigData('title'));
1290:             $tracking->setTracking($trackingvalue);
1291:             $tracking->addData($resultArr);
1292:             $this->_result->append($tracking);
1293:         } else {
1294:             $error = Mage::getModel('shipping/tracking_result_error');
1295:             $error->setCarrier('ups');
1296:             $error->setCarrierTitle($this->getConfigData('title'));
1297:             $error->setTracking($trackingvalue);
1298:             $error->setErrorMessage($errorTitle);
1299:             $this->_result->append($error);
1300:         }
1301:         return $this->_result;
1302:     }
1303: 
1304:     /**
1305:      * Get tracking response
1306:      *
1307:      * @return string
1308:      */
1309:     public function getResponse()
1310:     {
1311:         $statuses = '';
1312:         if ($this->_result instanceof Mage_Shipping_Model_Tracking_Result){
1313:             if ($trackings = $this->_result->getAllTrackings()) {
1314:                 foreach ($trackings as $tracking){
1315:                     if($data = $tracking->getAllData()){
1316:                         if (isset($data['status'])) {
1317:                             $statuses .= Mage::helper('usa')->__($data['status']);
1318:                         } else {
1319:                             $statuses .= Mage::helper('usa')->__($data['error_message']);
1320:                         }
1321:                     }
1322:                 }
1323:             }
1324:         }
1325:         if (empty($statuses)) {
1326:             $statuses = Mage::helper('usa')->__('Empty response');
1327:         }
1328:         return $statuses;
1329:     }
1330: 
1331:     /**
1332:      * Get allowed shipping methods
1333:      *
1334:      * @return array
1335:      */
1336:     public function getAllowedMethods()
1337:     {
1338:          $allowed = explode(',', $this->getConfigData('allowed_methods'));
1339:          $arr = array();
1340:          $isByCode = $this->getConfigData('type') == 'UPS_XML';
1341:          foreach ($allowed as $k) {
1342:              $arr[$k] = $isByCode ? $this->getShipmentByCode($k) : $this->getCode('method', $k);
1343:          }
1344:          return $arr;
1345:     }
1346: 
1347:     /**
1348:      * Form XML for shipment request
1349:      *
1350:      * @param Varien_Object $request
1351:      * @return string
1352:      */
1353:     protected function _formShipmentRequest(Varien_Object $request)
1354:     {
1355:         $packageParams = $request->getPackageParams();
1356:         $height = $packageParams->getHeight();
1357:         $width = $packageParams->getWidth();
1358:         $length = $packageParams->getLength();
1359:         $weightUnits = $packageParams->getWeightUnits() == Zend_Measure_Weight::POUND ? 'LBS' : 'KGS';
1360:         $dimensionsUnits = $packageParams->getDimensionUnits() == Zend_Measure_Length::INCH ? 'IN' : 'CM';
1361: 
1362:         $itemsDesc = array();
1363:         $itemsShipment = $request->getPackageItems();
1364:         foreach ($itemsShipment as $itemShipment) {
1365:             $item = new Varien_Object();
1366:             $item->setData($itemShipment);
1367:             $itemsDesc[] = $item->getName();
1368:         }
1369: 
1370:         $xmlRequest = new SimpleXMLElement('<?xml version = "1.0" ?><ShipmentConfirmRequest xml:lang="en-US"/>');
1371:         $requestPart = $xmlRequest->addChild('Request');
1372:         $requestPart->addChild('RequestAction', 'ShipConfirm');
1373:         $requestPart->addChild('RequestOption', 'nonvalidate');
1374: 
1375:         $shipmentPart = $xmlRequest->addChild('Shipment');
1376:         if ($request->getIsReturn()) {
1377:             $returnPart = $shipmentPart->addChild('ReturnService');
1378:             // UPS Print Return Label
1379:             $returnPart->addChild('Code', '9');
1380:         }
1381:         $shipmentPart->addChild('Description', substr(implode(' ', $itemsDesc), 0, 35));//empirical
1382: 
1383:         $shipperPart = $shipmentPart->addChild('Shipper');
1384:         if ($request->getIsReturn()) {
1385:             $shipperPart->addChild('Name', $request->getRecipientContactCompanyName());
1386:             $shipperPart->addChild('AttentionName', $request->getRecipientContactPersonName());
1387:             $shipperPart->addChild('ShipperNumber', $this->getConfigData('shipper_number'));
1388:             $shipperPart->addChild('PhoneNumber', $request->getRecipientContactPhoneNumber());
1389: 
1390:             $addressPart = $shipperPart->addChild('Address');
1391:             $addressPart->addChild('AddressLine1', $request->getRecipientAddressStreet());
1392:             $addressPart->addChild('AddressLine2', $request->getRecipientAddressStreet2());
1393:             $addressPart->addChild('City', $request->getRecipientAddressCity());
1394:             $addressPart->addChild('CountryCode', $request->getRecipientAddressCountryCode());
1395:             $addressPart->addChild('PostalCode', $request->getRecipientAddressPostalCode());
1396:             if ($request->getRecipientAddressStateOrProvinceCode()) {
1397:                 $addressPart->addChild('StateProvinceCode', $request->getRecipientAddressStateOrProvinceCode());
1398:             }
1399:         } else {
1400:             $shipperPart->addChild('Name', $request->getShipperContactCompanyName());
1401:             $shipperPart->addChild('AttentionName', $request->getShipperContactPersonName());
1402:             $shipperPart->addChild('ShipperNumber', $this->getConfigData('shipper_number'));
1403:             $shipperPart->addChild('PhoneNumber', $request->getShipperContactPhoneNumber());
1404: 
1405:             $addressPart = $shipperPart->addChild('Address');
1406:             $addressPart->addChild('AddressLine1', $request->getShipperAddressStreet());
1407:             $addressPart->addChild('AddressLine2', $request->getShipperAddressStreet2());
1408:             $addressPart->addChild('City', $request->getShipperAddressCity());
1409:             $addressPart->addChild('CountryCode', $request->getShipperAddressCountryCode());
1410:             $addressPart->addChild('PostalCode', $request->getShipperAddressPostalCode());
1411:             if ($request->getShipperAddressStateOrProvinceCode()) {
1412:                 $addressPart->addChild('StateProvinceCode', $request->getShipperAddressStateOrProvinceCode());
1413:             }
1414:         }
1415: 
1416:         $shipToPart = $shipmentPart->addChild('ShipTo');
1417:         $shipToPart->addChild('AttentionName', $request->getRecipientContactPersonName());
1418:         $shipToPart->addChild('CompanyName', $request->getRecipientContactCompanyName()
1419:             ? $request->getRecipientContactCompanyName()
1420:             : 'N/A');
1421:         $shipToPart->addChild('PhoneNumber', $request->getRecipientContactPhoneNumber());
1422: 
1423:         $addressPart = $shipToPart->addChild('Address');
1424:         $addressPart->addChild('AddressLine1', $request->getRecipientAddressStreet1());
1425:         $addressPart->addChild('AddressLine2', $request->getRecipientAddressStreet2());
1426:         $addressPart->addChild('City', $request->getRecipientAddressCity());
1427:         $addressPart->addChild('CountryCode', $request->getRecipientAddressCountryCode());
1428:         $addressPart->addChild('PostalCode', $request->getRecipientAddressPostalCode());
1429:         if ($request->getRecipientAddressStateOrProvinceCode()) {
1430:             $addressPart->addChild('StateProvinceCode', $request->getRecipientAddressRegionCode());
1431:         }
1432:         if ($this->getConfigData('dest_type') == 'RES') {
1433:             $addressPart->addChild('ResidentialAddress');
1434:         }
1435: 
1436:         if ($request->getIsReturn()) {
1437:             $shipFromPart = $shipmentPart->addChild('ShipFrom');
1438:             $shipFromPart->addChild('AttentionName', $request->getShipperContactPersonName());
1439:             $shipFromPart->addChild('CompanyName', $request->getShipperContactCompanyName()
1440:                 ? $request->getShipperContactCompanyName()
1441:                 : $request->getShipperContactPersonName());
1442:             $shipFromAddress = $shipFromPart->addChild('Address');
1443:             $shipFromAddress->addChild('AddressLine1', $request->getShipperAddressStreet1());
1444:             $shipFromAddress->addChild('AddressLine2', $request->getShipperAddressStreet2());
1445:             $shipFromAddress->addChild('City', $request->getShipperAddressCity());
1446:             $shipFromAddress->addChild('CountryCode', $request->getShipperAddressCountryCode());
1447:             $shipFromAddress->addChild('PostalCode', $request->getShipperAddressPostalCode());
1448:             if ($request->getShipperAddressStateOrProvinceCode()) {
1449:                 $shipFromAddress->addChild('StateProvinceCode', $request->getShipperAddressStateOrProvinceCode());
1450:             }
1451: 
1452:             $addressPart = $shipToPart->addChild('Address');
1453:             $addressPart->addChild('AddressLine1', $request->getShipperAddressStreet1());
1454:             $addressPart->addChild('AddressLine2', $request->getShipperAddressStreet2());
1455:             $addressPart->addChild('City', $request->getShipperAddressCity());
1456:             $addressPart->addChild('CountryCode', $request->getShipperAddressCountryCode());
1457:             $addressPart->addChild('PostalCode', $request->getShipperAddressPostalCode());
1458:             if ($request->getShipperAddressStateOrProvinceCode()) {
1459:                 $addressPart->addChild('StateProvinceCode', $request->getShipperAddressStateOrProvinceCode());
1460:             }
1461:             if ($this->getConfigData('dest_type') == 'RES') {
1462:                 $addressPart->addChild('ResidentialAddress');
1463:             }
1464:         }
1465: 
1466:         $servicePart = $shipmentPart->addChild('Service');
1467:         $servicePart->addChild('Code', $request->getShippingMethod());
1468:         $packagePart = $shipmentPart->addChild('Package');
1469:         $packagePart->addChild('Description', substr(implode(' ', $itemsDesc), 0, 35));//empirical
1470:         $packagePart->addChild('PackagingType')
1471:             ->addChild('Code', $request->getPackagingType());
1472:         $packageWeight = $packagePart->addChild('PackageWeight');
1473:         $packageWeight->addChild('Weight', $request->getPackageWeight());
1474:         $packageWeight->addChild('UnitOfMeasurement')->addChild('Code', $weightUnits);
1475: 
1476:         // set dimensions
1477:         if ($length || $width || $height) {
1478:             $packageDimensions = $packagePart->addChild('Dimensions');
1479:             $packageDimensions->addChild('UnitOfMeasurement')->addChild('Code', $dimensionsUnits);
1480:             $packageDimensions->addChild('Length', $length);
1481:             $packageDimensions->addChild('Width', $width);
1482:             $packageDimensions->addChild('Height', $height);
1483:         }
1484: 
1485:         // ups support reference number only for domestic service
1486:         if ($this->_isUSCountry($request->getRecipientAddressCountryCode())
1487:             && $this->_isUSCountry($request->getShipperAddressCountryCode())
1488:         ) {
1489:             if ($request->getReferenceData()) {
1490:                 $referenceData = $request->getReferenceData() . $request->getPackageId();
1491:             } else {
1492:                 $referenceData = 'Order #'
1493:                                  . $request->getOrderShipment()->getOrder()->getIncrementId()
1494:                                  . ' P'
1495:                                  . $request->getPackageId();
1496:             }
1497:             $referencePart = $packagePart->addChild('ReferenceNumber');
1498:             $referencePart->addChild('Code', '02');
1499:             $referencePart->addChild('Value', $referenceData);
1500:         }
1501: 
1502:         $deliveryConfirmation = $packageParams->getDeliveryConfirmation();
1503:         if ($deliveryConfirmation) {
1504:             /** @var $serviceOptionsNode SimpleXMLElement */
1505:             $serviceOptionsNode = null;
1506:             switch ($this->_getDeliveryConfirmationLevel($request->getRecipientAddressCountryCode())) {
1507:                 case self::DELIVERY_CONFIRMATION_PACKAGE:
1508:                     $serviceOptionsNode = $packagePart->addChild('PackageServiceOptions');
1509:                     break;
1510:                 case self::DELIVERY_CONFIRMATION_SHIPMENT:
1511:                     $serviceOptionsNode = $shipmentPart->addChild('ShipmentServiceOptions');
1512:                     break;
1513:             }
1514:             if (!is_null($serviceOptionsNode)) {
1515:                 $serviceOptionsNode
1516:                     ->addChild('DeliveryConfirmation')
1517:                     ->addChild('DCISType', $packageParams->getDeliveryConfirmation());
1518:             }
1519:         }
1520: 
1521:         $shipmentPart->addChild('PaymentInformation')
1522:             ->addChild('Prepaid')
1523:             ->addChild('BillShipper')
1524:             ->addChild('AccountNumber', $this->getConfigData('shipper_number'));
1525: 
1526:         if ($request->getPackagingType() != $this->getCode('container', 'ULE')
1527:             && $request->getShipperAddressCountryCode() == Mage_Usa_Model_Shipping_Carrier_Abstract::USA_COUNTRY_ID
1528:             && ($request->getRecipientAddressCountryCode() == 'CA' //Canada
1529:                 || $request->getRecipientAddressCountryCode() == 'PR' //Puerto Rico
1530:         )) {
1531:             $invoiceLineTotalPart = $shipmentPart->addChild('InvoiceLineTotal');
1532:             $invoiceLineTotalPart->addChild('CurrencyCode', $request->getBaseCurrencyCode());
1533:             $invoiceLineTotalPart->addChild('MonetaryValue', ceil($packageParams->getCustomsValue()));
1534:         }
1535: 
1536:         $labelPart = $xmlRequest->addChild('LabelSpecification');
1537:         $labelPart->addChild('LabelPrintMethod')
1538:                 ->addChild('Code', 'GIF');
1539:         $labelPart->addChild('LabelImageFormat')
1540:                 ->addChild('Code', 'GIF');
1541: 
1542:         $this->setXMLAccessRequest();
1543:         $xmlRequest = $this->_xmlAccessRequest . $xmlRequest->asXml();
1544:         return $xmlRequest;
1545:     }
1546: 
1547:     /**
1548:      * Send and process shipment accept request
1549:      *
1550:      * @param SimpleXMLElement
1551:      * @return Varien_Object
1552:      */
1553:     protected function _sendShipmentAcceptRequest(SimpleXMLElement $shipmentConfirmResponse)
1554:     {
1555:         $xmlRequest = new SimpleXMLElement('<?xml version = "1.0" ?><ShipmentAcceptRequest/>');
1556:         $request = $xmlRequest->addChild('Request');
1557:             $request->addChild('RequestAction', 'ShipAccept');
1558:         $xmlRequest->addChild('ShipmentDigest', $shipmentConfirmResponse->ShipmentDigest);
1559: 
1560:         $debugData = array('request' => $xmlRequest->asXML());
1561:         try {
1562:             $url = $this->_defaultUrls['ShipAccept'];
1563: 
1564:             $ch = curl_init($url);
1565:             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1566:             curl_setopt($ch, CURLOPT_HEADER, 0);
1567:             curl_setopt($ch, CURLOPT_POST, 1);
1568:             curl_setopt($ch, CURLOPT_POSTFIELDS, $this->_xmlAccessRequest . $xmlRequest->asXML());
1569:             curl_setopt($ch, CURLOPT_TIMEOUT, 30);
1570:             curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (boolean)$this->getConfigFlag('mode_xml'));
1571:             $xmlResponse = curl_exec ($ch);
1572: 
1573:             $debugData['result'] = $xmlResponse;
1574:             $this->_setCachedQuotes($xmlRequest, $xmlResponse);
1575:         } catch (Exception $e) {
1576:             $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
1577:             $xmlResponse = '';
1578:         }
1579: 
1580:         try {
1581:             $response = new SimpleXMLElement($xmlResponse);
1582:         } catch (Exception $e) {
1583:             $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
1584:         }
1585: 
1586:         $result = new Varien_Object();
1587:         if (isset($response->Error)) {
1588:             $result->setErrors((string)$response->Error->ErrorDescription);
1589:         } else {
1590:             $shippingLabelContent = (string)$response->ShipmentResults->PackageResults->LabelImage->GraphicImage;
1591:             $trackingNumber       = (string)$response->ShipmentResults->PackageResults->TrackingNumber;
1592: 
1593:             $result->setShippingLabelContent(base64_decode($shippingLabelContent));
1594:             $result->setTrackingNumber($trackingNumber);
1595:         }
1596: 
1597:         $this->_debug($debugData);
1598:         return $result;
1599:     }
1600: 
1601:     /**
1602:      * Do shipment request to carrier web service, obtain Print Shipping Labels and process errors in response
1603:      *
1604:      * @param Varien_Object $request
1605:      * @return Varien_Object
1606:      */
1607:     protected function _doShipmentRequest(Varien_Object $request)
1608:     {
1609:         $this->_prepareShipmentRequest($request);
1610:         $result = new Varien_Object();
1611:         $xmlRequest = $this->_formShipmentRequest($request);
1612:         $xmlResponse = $this->_getCachedQuotes($xmlRequest);
1613: 
1614:         if ($xmlResponse === null) {
1615:             $url = $this->getConfigData('url');
1616:             if (!$url) {
1617:                 $url = $this->_defaultUrls['ShipConfirm'];
1618:             }
1619: 
1620:             $debugData = array('request' => $xmlRequest);
1621:             $ch = curl_init();
1622:             curl_setopt($ch, CURLOPT_URL, $url);
1623:             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1624:             curl_setopt($ch, CURLOPT_HEADER, 0);
1625:             curl_setopt($ch, CURLOPT_POST, 1);
1626:             curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
1627:             curl_setopt($ch, CURLOPT_TIMEOUT, 30);
1628:             curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (boolean)$this->getConfigFlag('mode_xml'));
1629:             $xmlResponse = curl_exec($ch);
1630:             if ($xmlResponse === false) {
1631:                 throw new Exception(curl_error($ch));
1632:             } else {
1633:                 $debugData['result'] = $xmlResponse;
1634:                 $this->_setCachedQuotes($xmlRequest, $xmlResponse);
1635:             }
1636:         }
1637: 
1638:         try {
1639:             $response = new SimpleXMLElement($xmlResponse);
1640:         } catch (Exception $e) {
1641:             $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
1642:             $result->setErrors($e->getMessage());
1643:         }
1644: 
1645:         if (isset($response->Response->Error)
1646:             && in_array($response->Response->Error->ErrorSeverity, array('Hard', 'Transient'))
1647:         ) {
1648:             $result->setErrors((string)$response->Response->Error->ErrorDescription);
1649:         }
1650: 
1651:         $this->_debug($debugData);
1652: 
1653:         if ($result->hasErrors() || empty($response)) {
1654:             return $result;
1655:         } else {
1656:             return $this->_sendShipmentAcceptRequest($response);
1657:         }
1658:     }
1659: 
1660:     /**
1661:      * Return container types of carrier
1662:      *
1663:      * @param Varien_Object|null $params
1664:      * @return array|bool
1665:      */
1666:     public function getContainerTypes(Varien_Object $params = null)
1667:     {
1668:         if ($params == null) {
1669:             return $this->_getAllowedContainers($params);
1670:         }
1671:         $method             = $params->getMethod();
1672:         $countryShipper     = $params->getCountryShipper();
1673:         $countryRecipient   = $params->getCountryRecipient();
1674: 
1675:         if (($countryShipper == self::USA_COUNTRY_ID
1676:             && $countryRecipient == self::CANADA_COUNTRY_ID)
1677:             || ($countryShipper == self::CANADA_COUNTRY_ID
1678:             && $countryRecipient == self::USA_COUNTRY_ID)
1679:             || ($countryShipper == self::MEXICO_COUNTRY_ID
1680:             && $countryRecipient == self::USA_COUNTRY_ID)
1681:             && $method == '11' // UPS Standard
1682:         ) {
1683:             $containerTypes = array();
1684:             if ($method == '07' // Worldwide Express
1685:                 || $method == '08' // Worldwide Expedited
1686:                 || $method == '65' // Worldwide Saver
1687: 
1688:             ) {
1689:                 // Worldwide Expedited
1690:                 if ($method != '08') {
1691:                     $containerTypes = array(
1692:                         '01'   => Mage::helper('usa')->__('UPS Letter Envelope'),
1693:                         '24'   => Mage::helper('usa')->__('UPS Worldwide 25 kilo'),
1694:                         '25'   => Mage::helper('usa')->__('UPS Worldwide 10 kilo'),
1695:                     );
1696:                 }
1697:                 $containerTypes = $containerTypes + array(
1698:                     '03'     => Mage::helper('usa')->__('UPS Tube'),
1699:                     '04'    => Mage::helper('usa')->__('PAK'),
1700:                     '2a'    => Mage::helper('usa')->__('Small Express Box'),
1701:                     '2b'    => Mage::helper('usa')->__('Medium Express Box'),
1702:                     '2c'    => Mage::helper('usa')->__('Large Express Box'),
1703:                 );
1704:             }
1705:             return array('00' => Mage::helper('usa')->__('Customer Packaging')) + $containerTypes;
1706:         } elseif ($countryShipper == self::USA_COUNTRY_ID && $countryRecipient == self::PUERTORICO_COUNTRY_ID
1707:             && ($method == '03' // UPS Ground
1708:             || $method == '02' // UPS Second Day Air
1709:             || $method == '01' // UPS Next Day Air
1710:         )) {
1711:             // Container types should be the same as for domestic
1712:             $params->setCountryRecipient(self::USA_COUNTRY_ID);
1713:             $containerTypes = $this->_getAllowedContainers($params);
1714:             $params->setCountryRecipient($countryRecipient);
1715:             return $containerTypes;
1716:         }
1717:         return $this->_getAllowedContainers($params);
1718:     }
1719: 
1720:     /**
1721:      * Return all container types of carrier
1722:      *
1723:      * @return array|bool
1724:      */
1725:     public function getContainerTypesAll()
1726:     {
1727:         $codes        = $this->getCode('container');
1728:         $descriptions = $this->getCode('container_description');
1729:         $result       = array();
1730:         foreach ($codes as $key => &$code) {
1731:             $result[$code] = $descriptions[$key];
1732:         }
1733:         return $result;
1734: 
1735:     }
1736: 
1737:     /**
1738:      * Return structured data of containers witch related with shipping methods
1739:      *
1740:      * @return array|bool
1741:      */
1742:     public function getContainerTypesFilter()
1743:     {
1744:         return $this->getCode('containers_filter');
1745:     }
1746: 
1747:     /**
1748:      * Return delivery confirmation types of carrier
1749:      *
1750:      * @param Varien_Object|null $params
1751:      * @return array|bool
1752:      */
1753:     public function getDeliveryConfirmationTypes(Varien_Object $params = null)
1754:     {
1755:         $countryRecipient           = $params != null ? $params->getCountryRecipient() : null;
1756:         $deliveryConfirmationTypes  = array();
1757:         switch ($this->_getDeliveryConfirmationLevel($countryRecipient)) {
1758:             case self::DELIVERY_CONFIRMATION_PACKAGE:
1759:                 $deliveryConfirmationTypes = array(
1760:                     1 => Mage::helper('usa')->__('Delivery Confirmation'),
1761:                     2 => Mage::helper('usa')->__('Signature Required'),
1762:                     3 => Mage::helper('usa')->__('Adult Signature Required'),
1763:                 );
1764:                 break;
1765:             case self::DELIVERY_CONFIRMATION_SHIPMENT:
1766:                 $deliveryConfirmationTypes = array(
1767:                     1 => Mage::helper('usa')->__('Signature Required'),
1768:                     2 => Mage::helper('usa')->__('Adult Signature Required'),
1769:                 );
1770:         }
1771:         array_unshift($deliveryConfirmationTypes, Mage::helper('usa')->__('Not Required'));
1772: 
1773:         return $deliveryConfirmationTypes;
1774:     }
1775: 
1776:     /**
1777:      * Get Container Types, that could be customized for UPS carrier
1778:      *
1779:      * @return array
1780:      */
1781:     public function getCustomizableContainerTypes()
1782:     {
1783:         $result = array();
1784:         $containerTypes = $this->getCode('container');
1785:         foreach (parent::getCustomizableContainerTypes() as $containerType) {
1786:             $result[$containerType] = $containerTypes[$containerType];
1787:         }
1788:         return $result;
1789:     }
1790: 
1791:     /**
1792:      * Get delivery confirmation level based on origin/destination
1793:      * Return null if delivery confirmation is not acceptable
1794:      *
1795:      * @var string $countyDest
1796:      * @return int|null
1797:      */
1798:     protected function _getDeliveryConfirmationLevel($countyDest = null) {
1799:         if (is_null($countyDest)) {
1800:             return null;
1801:         }
1802: 
1803:         if ($countyDest == Mage_Usa_Model_Shipping_Carrier_Abstract::USA_COUNTRY_ID) {
1804:             return self::DELIVERY_CONFIRMATION_PACKAGE;
1805:         }
1806: 
1807:         return self::DELIVERY_CONFIRMATION_SHIPMENT;
1808:     }
1809: }
1810: 
Magento 1.7.0.2 API documentation generated by ApiGen 2.8.0