*/
class Mage_Usa_Model_Shipping_Carrier_Dhl_International
extends Mage_Usa_Model_Shipping_Carrier_Dhl_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
/**
* Carrier Product indicator
*/
const DHL_CONTENT_TYPE_DOC = 'D';
const DHL_CONTENT_TYPE_NON_DOC = 'N';
/**
* Minimum allowed values for shipping package dimensions
*/
const DIMENSION_MIN_CM = 3;
const DIMENSION_MIN_IN = 1;
/**
* Container types that could be customized
*
* @var array
*/
protected $_customizableContainerTypes = array(self::DHL_CONTENT_TYPE_NON_DOC);
/**
* Code of the carrier
*/
const CODE = 'dhlint';
/**
* Rate request data
*
* @var Mage_Shipping_Model_Rate_Request|null
*/
protected $_request = null;
/**
* Raw rate request data
*
* @var Varien_Object|null
*/
protected $_rawRequest = null;
/**
* Rate result data
*
* @var Mage_Shipping_Model_Rate_Result|null
*/
protected $_result = null;
/**
* Countries parameters data
*
* @var SimpleXMLElement|null
*/
protected $_countryParams = null;
/**
* Errors placeholder
*
* @var array
*/
protected $_errors = array();
/**
* Dhl rates result
*
* @var array
*/
protected $_rates = array();
/**
* Carrier's code
*
* @var string
*/
protected $_code = self::CODE;
/**
* Free Method config path
*
* @var string
*/
protected $_freeMethod = 'free_method_nondoc';
/**
* Max weight without fee
*
* @var int
*/
protected $_maxWeight = 70;
/**
* Flag if response is for shipping label creating
*
* @var bool
*/
protected $_isShippingLabelFlag = false;
/**
* Request variables array
*
* @var array
*/
protected $_requestVariables = array(
'id' => array('code' => 'dhl_id', 'setCode' => 'id'),
'password' => array('code' => 'dhl_password', 'setCode' => 'password'),
'account' => array('code' => 'dhl_account', 'setCode' => 'account_nbr'),
'shipping_key' => array('code' => 'dhl_shipping_key', 'setCode' => 'shipping_key'),
'shipping_intlkey' => array('code' => 'dhl_shipping_intl_key', 'setCode' => 'shipping_intl_key'),
'shipment_type' => array('code' => 'dhl_shipment_type', 'setCode' => 'shipment_type'),
'dutiable' => array('code' => 'dhl_dutiable', 'setCode' => 'dutiable'),
'dutypaymenttype' => array('code' => 'dhl_duty_payment_type', 'setCode' => 'duty_payment_type'),
'contentdesc' => array('code' => 'dhl_content_desc', 'setCode' => 'content_desc')
);
/**
* Flag that shows if shipping is domestic
*
* @var bool
*/
protected $_isDomestic = false;
/**
* Dhl International Class constructor
*
* Sets necessary data
*/
protected function _construct()
{
if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_DOC) {
$this->_freeMethod = 'free_method_doc';
}
}
/**
* Returns value of given variable
*
* @param mixed $origValue
* @param string $pathToValue
* @return mixed
*/
protected function _getDefaultValue($origValue, $pathToValue)
{
if (!$origValue) {
$origValue = Mage::getStoreConfig(
$pathToValue,
$this->getStore()
);
}
return $origValue;
}
/**
* Collect and get rates
*
* @param Mage_Shipping_Model_Rate_Request $request
* @return bool|Mage_Shipping_Model_Rate_Result|null
*/
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
if (!$this->getConfigFlag($this->_activeFlag)) {
return false;
}
$requestDhl = clone $request;
$this->setStore($requestDhl->getStoreId());
$origCompanyName = $this->_getDefaultValue(
$requestDhl->getOrigCompanyName(),
Mage_Core_Model_Store::XML_PATH_STORE_STORE_NAME
);
$origCountryId = $this->_getDefaultValue(
$requestDhl->getOrigCountryId(),
Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID
);
$origState = $this->_getDefaultValue(
$requestDhl->getOrigState(),
Mage_Shipping_Model_Shipping::XML_PATH_STORE_REGION_ID
);
$origCity = $this->_getDefaultValue(
$requestDhl->getOrigCity(),
Mage_Shipping_Model_Shipping::XML_PATH_STORE_CITY
);
$origPostcode = $this->_getDefaultValue(
$requestDhl->getOrigPostcode(),
Mage_Shipping_Model_Shipping::XML_PATH_STORE_ZIP
);
$requestDhl->setOrigCompanyName($origCompanyName)
->setCountryId($origCountryId)
->setOrigState($origState)
->setOrigCity($origCity)
->setOrigPostal($origPostcode);
$this->setRequest($requestDhl);
$this->_result = $this->_getQuotes();
$this->_updateFreeMethodQuote($request);
return $this->_result;
}
/**
* Set Free Method Request
*
* @param string $freeMethod
* @return void
*/
protected function _setFreeMethodRequest($freeMethod)
{
$rawRequest = $this->_rawRequest;
$rawRequest->setFreeMethodRequest(true);
$freeWeight = $this->getTotalNumOfBoxes($rawRequest->getFreeMethodWeight());
$rawRequest->setWeight($freeWeight);
$rawRequest->setService($freeMethod);
}
/**
* Returns request result
*
* @return Mage_Shipping_Model_Rate_Result|null
*/
public function getResult()
{
return $this->_result;
}
protected function _addParams($requestObject)
{
$request = $this->_request;
foreach ($this->_requestVariables as $code => $objectCode) {
if ($request->getDhlId()) {
$value = $request->getData($objectCode['code']);
} else {
$value = $this->getConfigData($code);
}
$requestObject->setData($objectCode['setCode'], $value);
}
return $requestObject;
}
/**
* Prepare and set request in property of current instance
*
* @param Varien_Object $request
* @return Mage_Usa_Model_Shipping_Carrier_Dhl
*/
public function setRequest(Varien_Object $request)
{
$this->_request = $request;
$this->setStore($request->getStoreId());
$requestObject = new Varien_Object();
$requestObject->setIsGenerateLabelReturn($request->getIsGenerateLabelReturn());
$requestObject->setStoreId($request->getStoreId());
if ($request->getLimitMethod()) {
$requestObject->setService($request->getLimitMethod());
}
$requestObject = $this->_addParams($requestObject);
if ($request->getDestPostcode()) {
$requestObject->setDestPostal($request->getDestPostcode());
}
$requestObject->setOrigCountry(
$this->_getDefaultValue(
$request->getOrigCountry(), Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID)
)
->setOrigCountryId(
$this->_getDefaultValue(
$request->getOrigCountryId(), Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID)
);
$shippingWeight = $request->getPackageWeight();
$requestObject->setValue(round($request->getPackageValue(), 2))
->setValueWithDiscount($request->getPackageValueWithDiscount())
->setCustomsValue($request->getPackageCustomsValue())
->setDestStreet(
Mage::helper('core/string')->substr(str_replace("\n", '', $request->getDestStreet()), 0, 35))
->setDestStreetLine2($request->getDestStreetLine2())
->setDestCity($request->getDestCity())
->setOrigCompanyName($request->getOrigCompanyName())
->setOrigCity($request->getOrigCity())
->setOrigPhoneNumber($request->getOrigPhoneNumber())
->setOrigPersonName($request->getOrigPersonName())
->setOrigEmail(Mage::getStoreConfig('trans_email/ident_general/email', $requestObject->getStoreId()))
->setOrigCity($request->getOrigCity())
->setOrigPostal($request->getOrigPostal())
->setOrigStreetLine2($request->getOrigStreetLine2())
->setDestPhoneNumber($request->getDestPhoneNumber())
->setDestPersonName($request->getDestPersonName())
->setDestCompanyName($request->getDestCompanyName());
$originStreet2 = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_ADDRESS2, $requestObject->getStoreId());
$requestObject->setOrigStreet($request->getOrigStreet() ? $request->getOrigStreet() : $originStreet2);
if (is_numeric($request->getOrigState())) {
$requestObject->setOrigState(Mage::getModel('directory/region')->load($request->getOrigState())->getCode());
} else {
$requestObject->setOrigState($request->getOrigState());
}
if ($request->getDestCountryId()) {
$destCountry = $request->getDestCountryId();
} else {
$destCountry = self::USA_COUNTRY_ID;
}
// for DHL, Puerto Rico state for US will assume as Puerto Rico country
// for Puerto Rico, dhl will ship as international
if ($destCountry == self::USA_COUNTRY_ID && ($request->getDestPostcode() == '00912'
|| $request->getDestRegionCode() == self::PUERTORICO_COUNTRY_ID)
) {
$destCountry = self::PUERTORICO_COUNTRY_ID;
}
$requestObject->setDestCountryId($destCountry)
->setDestState($request->getDestRegionCode())
->setWeight($shippingWeight)
->setFreeMethodWeight($request->getFreeMethodWeight())
->setOrderShipment($request->getOrderShipment());
if ($request->getPackageId()) {
$requestObject->setPackageId($request->getPackageId());
}
$requestObject->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
$this->_rawRequest = $requestObject;
return $this;
}
/**
* Get allowed shipping methods
*
* @return array
*/
public function getAllowedMethods()
{
$contentType = $this->getConfigData('content_type');
$allowedMethods = array();
if ($this->_isDomestic) {
$allowedMethods = array_merge(explode(',', $this->getConfigData('doc_methods')),
explode(',', $this->getConfigData('nondoc_methods'))
);
} else {
switch ($contentType) {
case self::DHL_CONTENT_TYPE_DOC:
$allowedMethods = explode(',', $this->getConfigData('doc_methods'));
break;
case self::DHL_CONTENT_TYPE_NON_DOC:
$allowedMethods = explode(',', $this->getConfigData('nondoc_methods'));
break;
default:
Mage::throwException(Mage::helper('usa')->__('Wrong Content Type.'));
}
}
$methods = array();
foreach ($allowedMethods as $method) {
$methods[$method] = $this->getDhlProductTitle($method);
}
return $methods;
}
/**
* Get configuration data of carrier
*
* @param strin $type
* @param string $code
* @return array|bool
*/
public function getCode($type, $code = '')
{
$codes = array(
'unit_of_measure' => array(
'L' => Mage::helper('usa')->__('Pounds'),
'K' => Mage::helper('usa')->__('Kilograms'),
),
'unit_of_dimension' => array(
'I' => Mage::helper('usa')->__('Inches'),
'C' => Mage::helper('usa')->__('Centimeters'),
),
'unit_of_dimension_cut' => array(
'I' => Mage::helper('usa')->__('inch'),
'C' => Mage::helper('usa')->__('cm'),
),
'dimensions' => array(
'HEIGHT' => Mage::helper('usa')->__('Height'),
'DEPTH' => Mage::helper('usa')->__('Depth'),
'WIDTH' => Mage::helper('usa')->__('Width'),
),
'size' => array(
'0' => Mage::helper('usa')->__('Regular'),
'1' => Mage::helper('usa')->__('Specific'),
),
'dimensions_variables' => array(
'L' => Zend_Measure_Weight::POUND,
'LB' => Zend_Measure_Weight::POUND,
'POUND' => Zend_Measure_Weight::POUND,
'K' => Zend_Measure_Weight::KILOGRAM,
'KG' => Zend_Measure_Weight::KILOGRAM,
'KILOGRAM' => Zend_Measure_Weight::KILOGRAM,
'I' => Zend_Measure_Length::INCH,
'IN' => Zend_Measure_Length::INCH,
'INCH' => Zend_Measure_Length::INCH,
'C' => Zend_Measure_Length::CENTIMETER,
'CM' => Zend_Measure_Length::CENTIMETER,
'CENTIMETER'=> Zend_Measure_Length::CENTIMETER,
)
);
if (!isset($codes[$type])) {
return false;
} elseif ('' === $code) {
return $codes[$type];
}
$code = strtoupper($code);
if (!isset($codes[$type][$code])) {
return false;
} else {
return $codes[$type][$code];
}
}
/**
* Returns DHL shipment methods (depending on package content type, if necessary)
*
* @param string $doc Package content type (doc/non-doc) see DHL_CONTENT_TYPE_* constants
* @return array
*/
public function getDhlProducts($doc)
{
$docType = array(
'2' => Mage::helper('usa')->__('Easy shop'),
'5' => Mage::helper('usa')->__('Sprintline'),
'6' => Mage::helper('usa')->__('Secureline'),
'7' => Mage::helper('usa')->__('Express easy'),
'9' => Mage::helper('usa')->__('Europack'),
'B' => Mage::helper('usa')->__('Break bulk express'),
'C' => Mage::helper('usa')->__('Medical express'),
'D' => Mage::helper('usa')->__('Express worldwide'), // product content code: DOX
'U' => Mage::helper('usa')->__('Express worldwide'), // product content code: ECX
'K' => Mage::helper('usa')->__('Express 9:00'),
'L' => Mage::helper('usa')->__('Express 10:30'),
'G' => Mage::helper('usa')->__('Domestic economy select'),
'W' => Mage::helper('usa')->__('Economy select'),
'I' => Mage::helper('usa')->__('Break bulk economy'),
'N' => Mage::helper('usa')->__('Domestic express'),
'O' => Mage::helper('usa')->__('Others'),
'R' => Mage::helper('usa')->__('Globalmail business'),
'S' => Mage::helper('usa')->__('Same day'),
'T' => Mage::helper('usa')->__('Express 12:00'),
'X' => Mage::helper('usa')->__('Express envelope'),
);
$nonDocType = array(
'1' => Mage::helper('usa')->__('Customer services'),
'3' => Mage::helper('usa')->__('Easy shop'),
'4' => Mage::helper('usa')->__('Jetline'),
'8' => Mage::helper('usa')->__('Express easy'),
'P' => Mage::helper('usa')->__('Express worldwide'),
'Q' => Mage::helper('usa')->__('Medical express'),
'E' => Mage::helper('usa')->__('Express 9:00'),
'F' => Mage::helper('usa')->__('Freight worldwide'),
'H' => Mage::helper('usa')->__('Economy select'),
'J' => Mage::helper('usa')->__('Jumbo box'),
'M' => Mage::helper('usa')->__('Express 10:30'),
'V' => Mage::helper('usa')->__('Europack'),
'Y' => Mage::helper('usa')->__('Express 12:00'),
);
if ($this->_isDomestic) {
return $docType + $nonDocType;
}
if ($doc == self::DHL_CONTENT_TYPE_DOC) {
// Documents shipping
return $docType;
} else {
// Services for shipping non-documents cargo
return $nonDocType;
}
}
/**
* Returns title of DHL shipping method by its code
*
* @param string $code One-symbol code (see getDhlProducts())
* @return bool
*/
public function getDhlProductTitle($code)
{
$contentType = $this->getConfigData('content_type');
$dhlProducts = $this->getDhlProducts($contentType);
return isset($dhlProducts[$code]) ? $dhlProducts[$code] : false;
}
/**
* Convert item weight to needed weight based on config weight unit dimensions
*
* @param float $weight
* @param bool $maxWeight
* @param string|bool $configWeightUnit
* @return float
*/
protected function _getWeight($weight, $maxWeight = false, $configWeightUnit = false)
{
if ($maxWeight) {
$configWeightUnit = Zend_Measure_Weight::KILOGRAM;
} elseif ($configWeightUnit) {
$configWeightUnit = $this->getCode('dimensions_variables', $configWeightUnit);
} else {
$configWeightUnit = $this->getCode('dimensions_variables', (string)$this->getConfigData('unit_of_measure'));
}
$countryWeightUnit = $this->getCode('dimensions_variables', $this->_getWeightUnit());
if ($configWeightUnit != $countryWeightUnit) {
$weight = Mage::helper('usa')->convertMeasureWeight(
round($weight,3),
$configWeightUnit,
$countryWeightUnit
);
}
return round($weight, 3);
}
/**
* Prepare items to pieces
*
* @return array
*/
protected function _getAllItems()
{
$allItems = $this->_request->getAllItems();
$fullItems = array();
foreach ($allItems as $item) {
if ($item->getProductType() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
&& $item->getProduct()->getShipmentType()
) {
continue;
}
$qty = $item->getQty();
$changeQty = true;
$checkWeight = true;
$decimalItems = array();
if ($item->getParentItem()) {
if (!$item->getParentItem()->getProduct()->getShipmentType()) {
continue;
}
$qty = $item->getIsQtyDecimal()
? $item->getParentItem()->getQty()
: $item->getParentItem()->getQty() * $item->getQty();
}
$itemWeight = $item->getWeight();
if ($item->getIsQtyDecimal() && $item->getProductType() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
$stockItem = $item->getProduct()->getStockItem();
if ($stockItem->getIsDecimalDivided()) {
if ($stockItem->getEnableQtyIncrements() && $stockItem->getQtyIncrements()) {
$itemWeight = $itemWeight * $stockItem->getQtyIncrements();
$qty = round(($item->getWeight() / $itemWeight) * $qty);
$changeQty = false;
} else {
$itemWeight = $this->_getWeight($itemWeight * $item->getQty());
$maxWeight = $this->_getWeight($this->_maxWeight, true);
if ($itemWeight > $maxWeight) {
$qtyItem = floor($itemWeight / $maxWeight);
$decimalItems[] = array('weight' => $maxWeight, 'qty' => $qtyItem);
$weightItem = Mage::helper('core')->getExactDivision($itemWeight, $maxWeight);
if ($weightItem) {
$decimalItems[] = array('weight' => $weightItem, 'qty' => 1);
}
$checkWeight = false;
} else {
$itemWeight = $itemWeight * $item->getQty();
}
}
} else {
$itemWeight = $itemWeight * $item->getQty();
}
}
if ($checkWeight && $this->_getWeight($itemWeight) > $this->_getWeight($this->_maxWeight, true)) {
return array();
}
if ($changeQty && !$item->getParentItem() && $item->getIsQtyDecimal()
&& $item->getProductType() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE
) {
$qty = 1;
}
if (!empty($decimalItems)) {
foreach ($decimalItems as $decimalItem) {
$fullItems = array_merge($fullItems,
array_fill(0, $decimalItem['qty'] * $qty, $decimalItem['weight'])
);
}
} else {
$fullItems = array_merge($fullItems, array_fill(0, $qty, $this->_getWeight($itemWeight)));
}
}
sort($fullItems);
return $fullItems;
}
/**
* Make pieces
*
* @param SimpleXMLElement $nodeBkgDetails
* @return void
*/
protected function _makePieces(SimpleXMLElement $nodeBkgDetails)
{
$divideOrderWeight = (string)$this->getConfigData('divide_order_weight');
$nodePieces = $nodeBkgDetails->addChild('Pieces', '', '');
$items = $this->_getAllItems();
$numberOfPieces = 0;
if ($divideOrderWeight && !empty($items)) {
$maxWeight = $this->_getWeight($this->_maxWeight, true);
$sumWeight = 0;
$reverseOrderItems = $items;
arsort($reverseOrderItems);
foreach ($reverseOrderItems as $key => $weight) {
if (!isset($items[$key])) {
continue;
}
unset($items[$key]);
$sumWeight = $weight;
foreach ($items as $key => $weight) {
if (($sumWeight + $weight) < $maxWeight) {
unset($items[$key]);
$sumWeight += $weight;
} elseif (($sumWeight + $weight) > $maxWeight) {
$numberOfPieces++;
$nodePiece = $nodePieces->addChild('Piece', '', '');
$nodePiece->addChild('PieceID', $numberOfPieces);
$this->_addDimension($nodePiece);
$nodePiece->addChild('Weight', $sumWeight);
break;
} else {
unset($items[$key]);
$numberOfPieces++;
$sumWeight += $weight;
$nodePiece = $nodePieces->addChild('Piece', '', '');
$nodePiece->addChild('PieceID', $numberOfPieces);
$this->_addDimension($nodePiece);
$nodePiece->addChild('Weight', $sumWeight);
$sumWeight = 0;
break;
}
}
}
if ($sumWeight > 0) {
$numberOfPieces++;
$nodePiece = $nodePieces->addChild('Piece', '', '');
$nodePiece->addChild('PieceID', $numberOfPieces);
$this->_addDimension($nodePiece);
$nodePiece->addChild('Weight', $sumWeight);
}
} else {
$nodePiece = $nodePieces->addChild('Piece', '', '');
$nodePiece->addChild('PieceID', 1);
$this->_addDimension($nodePiece);
$nodePiece->addChild('Weight', $this->_getWeight($this->_rawRequest->getWeight()));
}
$handlingAction = $this->getConfigData('handling_action');
if ($handlingAction == Mage_Shipping_Model_Carrier_Abstract::HANDLING_ACTION_PERORDER || !$numberOfPieces) {
$numberOfPieces = 1;
}
$this->_numBoxes = $numberOfPieces;
}
/**
* Convert item dimension to needed dimension based on config dimension unit of measure
*
* @param float $dimension
* @param string|bool $configWeightUnit
* @return float
*/
protected function _getDimension($dimension, $configWeightUnit = false)
{
if (!$configWeightUnit) {
$configWeightUnit = $this->getCode('dimensions_variables', (string)$this->getConfigData('unit_of_measure'));
} else {
$configWeightUnit = $this->getCode('dimensions_variables', $configWeightUnit);
}
if ($configWeightUnit == Zend_Measure_Weight::POUND) {
$configDimensionUnit = Zend_Measure_Length::INCH;
} else {
$configDimensionUnit = Zend_Measure_Length::CENTIMETER;
}
$countryDimensionUnit = $this->getCode('dimensions_variables', $this->_getDimensionUnit());
if ($configDimensionUnit != $countryDimensionUnit) {
$dimension = Mage::helper('usa')->convertMeasureDimension(
round($dimension, 3),
$configDimensionUnit,
$countryDimensionUnit
);
}
return round($dimension, 3);
}
/**
* Add dimension to piece
*
* @param SimpleXMLElement $nodePiece
* @return void
*/
protected function _addDimension($nodePiece)
{
$sizeChecker = (string)$this->getConfigData('size');
$height = $this->_getDimension((string)$this->getConfigData('height'));
$depth = $this->_getDimension((string)$this->getConfigData('depth'));
$width = $this->_getDimension((string)$this->getConfigData('width'));
if ($sizeChecker && $height && $depth && $width) {
$nodePiece->addChild('Height', $height);
$nodePiece->addChild('Depth', $depth);
$nodePiece->addChild('Width', $width);
}
}
/**
* Get shipping quotes
*
* @return Mage_Core_Model_Abstract|Mage_Shipping_Model_Rate_Result
*/
protected function _getQuotes()
{
$responseBody = '';
try {
$debugData = array();
for ($offset = 0; $offset <= self::UNAVAILABLE_DATE_LOOK_FORWARD; $offset++) {
$debugData['try-' . $offset] = array();
$debugPoint = &$debugData['try-' . $offset];
$requestXml = $this->_buildQuotesRequestXml();
$date = date(self::REQUEST_DATE_FORMAT, strtotime($this->_getShipDate() . " +$offset days"));
$this->_setQuotesRequestXmlDate($requestXml, $date);
$request = $requestXml->asXML();
$debugPoint['request'] = $request;
$responseBody = $this->_getCachedQuotes($request);
if ($debugPoint['from_cache'] = ($responseBody === null)) {
$responseBody = $this->_getQuotesFromServer($request);
}
$debugPoint['response'] = $responseBody;
$bodyXml = new SimpleXMLElement($responseBody);
$code = $bodyXml->xpath('//GetQuoteResponse/Note/Condition/ConditionCode');
if (isset($code[0]) && (int)$code[0] == self::CONDITION_CODE_SERVICE_DATE_UNAVAILABLE) {
$debugPoint['info'] = sprintf(
Mage::helper('usa')->__("DHL service is not available at %s date"),
$date
);
} else {
break;
}
$this->_setCachedQuotes($request, $responseBody);
}
$this->_debug($debugData);
} catch (Exception $e) {
$this->_errors[$e->getCode()] = $e->getMessage();
}
return $this->_parseResponse($responseBody);
}
/**
* Get shipping quotes from DHL service
*
* @param string $request
* @return string
*/
protected function _getQuotesFromServer($request)
{
$client = new Varien_Http_Client();
$client->setUri((string)$this->getConfigData('gateway_url'));
$client->setConfig(array(
'maxredirects' => 0,
'timeout' => 30,
'verifypeer' => $this->getConfigFlag('verify_peer'),
'verifyhost' => 2,
));
$client->setRawData(utf8_encode($request));
return $client->request(Varien_Http_Client::POST)->getBody();
}
/**
* Build qoutes request XML object
*
* @return SimpleXMLElement
*/
protected function _buildQuotesRequestXml()
{
$rawRequest = $this->_rawRequest;
$xmlStr = ''
. '';
$xml = new SimpleXMLElement($xmlStr);
$nodeGetQuote = $xml->addChild('GetQuote', '', '');
$nodeRequest = $nodeGetQuote->addChild('Request');
$nodeServiceHeader = $nodeRequest->addChild('ServiceHeader');
$nodeServiceHeader->addChild('SiteID', (string)$this->getConfigData('id'));
$nodeServiceHeader->addChild('Password', (string)$this->getConfigData('password'));
$nodeFrom = $nodeGetQuote->addChild('From');
$nodeFrom->addChild('CountryCode', $rawRequest->getOrigCountryId());
$nodeFrom->addChild('Postalcode', $rawRequest->getOrigPostal());
$nodeFrom->addChild('City', $rawRequest->getOrigCity());
$nodeBkgDetails = $nodeGetQuote->addChild('BkgDetails');
$nodeBkgDetails->addChild('PaymentCountryCode', $rawRequest->getOrigCountryId());
$nodeBkgDetails->addChild('Date', $this->_getShipDate());
$nodeBkgDetails->addChild('ReadyTime', 'PT' . (int)(string)$this->getConfigData('ready_time') . 'H00M');
$nodeBkgDetails->addChild('DimensionUnit', $this->_getDimensionUnit());
$nodeBkgDetails->addChild('WeightUnit', $this->_getWeightUnit());
$this->_makePieces($nodeBkgDetails);
$nodeBkgDetails->addChild('PaymentAccountNumber', (string)$this->getConfigData('account'));
$nodeTo = $nodeGetQuote->addChild('To');
$nodeTo->addChild('CountryCode', $rawRequest->getDestCountryId());
$nodeTo->addChild('Postalcode', $rawRequest->getDestPostal());
$nodeTo->addChild('City', $rawRequest->getDestCity());
$this->_checkDomesticStatus($rawRequest->getOrigCountryId(), $rawRequest->getDestCountryId());
if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_NON_DOC && !$this->_isDomestic) {
// IsDutiable flag and Dutiable node indicates that cargo is not a documentation
$nodeBkgDetails->addChild('IsDutiable', 'Y');
$nodeDutiable = $nodeGetQuote->addChild('Dutiable');
$baseCurrencyCode = Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode();
$nodeDutiable->addChild('DeclaredCurrency', $baseCurrencyCode);
$nodeDutiable->addChild('DeclaredValue', sprintf("%.2F", $rawRequest->getValue()));
}
return $xml;
}
/**
* Set pick-up date in request XML object
*
* @param SimpleXMLElement $requestXml
* @param string $date
* @return SimpleXMLElement
*/
protected function _setQuotesRequestXmlDate(SimpleXMLElement $requestXml, $date)
{
$requestXml->GetQuote->BkgDetails->Date = $date;
return $requestXml;
}
/**
* Parse response from DHL web service
*
* @param string $response
* @return Mage_Shipping_Model_Rate_Result
*/
protected function _parseResponse($response)
{
$responseError = Mage::helper('usa')->__('The response is in wrong format.');
if (strlen(trim($response)) > 0) {
if (strpos(trim($response), 'getName(), array('ErrorResponse', 'ShipmentValidateErrorResponse'))
|| isset($xml->GetQuoteResponse->Note->Condition)
) {
$code = null;
$data = null;
if (isset($xml->Response->Status->Condition)) {
$nodeCondition = $xml->Response->Status->Condition;
} else {
$nodeCondition = $xml->GetQuoteResponse->Note->Condition;
}
if ($this->_isShippingLabelFlag) {
foreach ($nodeCondition as $condition) {
$code = isset($condition->ConditionCode) ? (string)$condition->ConditionCode : 0;
$data = isset($condition->ConditionData) ? (string)$condition->ConditionData : '';
if (!empty($code) && !empty($data)) {
break;
}
}
Mage::throwException(Mage::helper('usa')->__('Error #%s : %s', trim($code), trim($data)));
}
$code = isset($nodeCondition->ConditionCode) ? (string)$nodeCondition->ConditionCode : 0;
$data = isset($nodeCondition->ConditionData) ? (string)$nodeCondition->ConditionData : '';
$this->_errors[$code] = Mage::helper('usa')->__('Error #%s : %s', trim($code), trim($data));
} else {
if (isset($xml->GetQuoteResponse->BkgDetails->QtdShp)) {
foreach ($xml->GetQuoteResponse->BkgDetails->QtdShp as $quotedShipment) {
$this->_addRate($quotedShipment);
}
} elseif (isset($xml->AirwayBillNumber)) {
$result = new Varien_Object();
$result->setTrackingNumber((string)$xml->AirwayBillNumber);
try {
$labelContent = (string)$xml->LabelImage->OutputImage;
$result->setShippingLabelContent(base64_decode($labelContent));
} catch (Exception $e) {
Mage::throwException(Mage::helper('usa')->__($e->getMessage()));
}
return $result;
} else {
$this->_errors[] = $responseError;
}
}
}
} else {
$this->_errors[] = $responseError;
}
} else {
$this->_errors[] = $responseError;
}
/* @var $result Mage_Shipping_Model_Rate_Result */
$result = Mage::getModel('shipping/rate_result');
if ($this->_rates) {
foreach ($this->_rates as $rate) {
$method = $rate['service'];
$data = $rate['data'];
/* @var $rate Mage_Shipping_Model_Rate_Result_Method */
$rate = Mage::getModel('shipping/rate_result_method');
$rate->setCarrier(self::CODE);
$rate->setCarrierTitle($this->getConfigData('title'));
$rate->setMethod($method);
$rate->setMethodTitle($data['term']);
$rate->setCost($data['price_total']);
$rate->setPrice($data['price_total']);
$result->append($rate);
}
} else if (!empty($this->_errors)) {
if ($this->_isShippingLabelFlag) {
Mage::throwException($responseError);
}
return $this->_showError();
}
return $result;
}
/**
* Add rate to DHL rates array
*
* @param SimpleXMLElement $shipmentDetails
* @return Mage_Usa_Model_Shipping_Carrier_Dhl_International
*/
protected function _addRate(SimpleXMLElement $shipmentDetails)
{
if (isset($shipmentDetails->ProductShortName)
&& isset($shipmentDetails->ShippingCharge)
&& isset($shipmentDetails->GlobalProductCode)
&& isset($shipmentDetails->CurrencyCode)
&& array_key_exists((string)$shipmentDetails->GlobalProductCode, $this->getAllowedMethods())
) {
// DHL product code, e.g. '3', 'A', 'Q', etc.
$dhlProduct = (string)$shipmentDetails->GlobalProductCode;
$totalEstimate = (float)(string)$shipmentDetails->ShippingCharge;
$currencyCode = (string)$shipmentDetails->CurrencyCode;
$baseCurrencyCode = Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode();
$dhlProductDescription = $this->getDhlProductTitle($dhlProduct);
if ($currencyCode != $baseCurrencyCode) {
/* @var $currency Mage_Directory_Model_Currency */
$currency = Mage::getModel('directory/currency');
$rates = $currency->getCurrencyRates($currencyCode, array($baseCurrencyCode));
if (!empty($rates) && isset($rates[$baseCurrencyCode])) {
// Convert to store display currency using store exchange rate
$totalEstimate = $totalEstimate * $rates[$baseCurrencyCode];
} else {
$rates = $currency->getCurrencyRates($baseCurrencyCode, array($currencyCode));
if (!empty($rates) && isset($rates[$currencyCode])) {
$totalEstimate = $totalEstimate/$rates[$currencyCode];
}
if (!isset($rates[$currencyCode]) || !$totalEstimate) {
$totalEstimate = false;
$this->_errors[] = Mage::helper('usa')->__("Exchange rate %s (Base Currency) -> %s not found. DHL method %s skipped", $currencyCode, $baseCurrencyCode, $dhlProductDescription);
}
}
}
if ($totalEstimate) {
$data = array('term' => $dhlProductDescription,
'price_total' => $this->getMethodPrice($totalEstimate, $dhlProduct));
if (!empty($this->_rates)) {
foreach ($this->_rates as $product) {
if ($product['data']['term'] == $data['term']
&& $product['data']['price_total'] == $data['price_total']
) {
return $this;
}
}
}
$this->_rates[] = array('service' => $dhlProduct, 'data' => $data);
} else {
$this->_errors[] = Mage::helper('usa')->__("Zero shipping charge for '%s'", $dhlProductDescription);
}
} else {
$dhlProductDescription = false;
if (isset($shipmentDetails->GlobalProductCode)) {
$dhlProductDescription = $this->getDhlProductTitle((string)$shipmentDetails->GlobalProductCode);
}
$dhlProductDescription = $dhlProductDescription ? $dhlProductDescription : Mage::helper('usa')->__("DHL");
$this->_errors[] = Mage::helper('usa')->__("Zero shipping charge for '%s'", $dhlProductDescription);
}
return $this;
}
/**
* Returns dimension unit (cm or inch)
*
* @return string
*/
protected function _getDimensionUnit()
{
$countryId = $this->_rawRequest->getOrigCountryId();
$measureUnit = $this->getCountryParams($countryId)->getMeasureUnit();
if (empty($measureUnit)) {
Mage::throwException(Mage::helper('usa')->__("Cannot identify measure unit for %s", $countryId));
}
return $measureUnit;
}
/**
* Returns weight unit (kg or pound)
*
* @return string
*/
protected function _getWeightUnit()
{
$countryId = $this->_rawRequest->getOrigCountryId();
$weightUnit = $this->getCountryParams($countryId)->getWeightUnit();
if (empty($weightUnit)) {
Mage::throwException(Mage::helper('usa')->__("Cannot identify weight unit for %s", $countryId));
}
return $weightUnit;
}
/**
* Get Country Params by Country Code
*
* @param string $countryCode
* @return Varien_Object
*
* @see $countryCode ISO 3166 Codes (Countries) A2
*/
protected function getCountryParams($countryCode)
{
if (empty($this->_countryParams)) {
$dhlConfigPath = Mage::getModuleDir('etc', 'Mage_Usa') . DS . 'dhl' . DS;
$countriesXml = file_get_contents($dhlConfigPath . 'international' . DS . 'countries.xml');
$this->_countryParams = new Varien_Simplexml_Element($countriesXml);
}
if (isset($this->_countryParams->$countryCode)) {
$countryParams = new Varien_Object($this->_countryParams->$countryCode->asArray());
}
return isset($countryParams) ? $countryParams : new Varien_Object();
}
/**
* Do shipment request to carrier web service, obtain Print Shipping Labels and process errors in response
*
* @param Varien_Object $request
* @return Varien_Object
*/
protected function _doShipmentRequest(Varien_Object $request)
{
$this->_prepareShipmentRequest($request);
$this->_mapRequestToShipment($request);
$this->setRequest($request);
return $this->_doRequest();
}
/**
* Processing additional validation to check is carrier applicable.
*
* @param Mage_Shipping_Model_Rate_Request $request
* @return Mage_Shipping_Model_Carrier_Abstract|Mage_Shipping_Model_Rate_Result_Error|boolean
*/
public function proccessAdditionalValidation(Mage_Shipping_Model_Rate_Request $request)
{
//Skip by item validation if there is no items in request
if (!count($this->getAllItems($request))) {
$this->_errors[] = Mage::helper('usa')->__('There is no items in this order');
}
$countryParams = $this->getCountryParams(
Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID, $request->getStoreId())
);
if (!$countryParams->getData()) {
$this->_errors[] = Mage::helper('usa')->__('Please, specify origin country');
}
if (!empty($this->_errors)) {
return $this->_showError();
}
return $this;
}
/**
* Show default error
*
* @return bool|Mage_Shipping_Model_Rate_Result_Error
*/
protected function _showError()
{
$showMethod = $this->getConfigData('showmethod');
if ($showMethod) {
/* @var $error Mage_Shipping_Model_Rate_Result_Error */
$error = Mage::getModel('shipping/rate_result_error');
$error->setCarrier(self::CODE);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setErrorMessage($this->getConfigData('specificerrmsg'));
$this->_debug($this->_errors);
return $error;
} else {
return false;
}
}
/**
* Return container types of carrier
*
* @param Varien_Object|null $params
* @return array
*/
public function getContainerTypes(Varien_Object $params = null)
{
return array(
self::DHL_CONTENT_TYPE_DOC => Mage::helper('usa')->__('Documents'),
self::DHL_CONTENT_TYPE_NON_DOC => Mage::helper('usa')->__('Non Documents')
);
}
/**
* Map request to shipment
*
* @param Varien_Object $request
* @return null
*/
protected function _mapRequestToShipment(Varien_Object $request)
{
$request->setOrigCountryId($request->getShipperAddressCountryCode());
$this->_rawRequest = $request;
$customsValue = 0;
$packageWeight = 0;
$packages = $request->getPackages();
foreach ($packages as &$piece) {
$params = $piece['params'];
if ($params['width'] || $params['length'] || $params['height']) {
$minValue = $this->_getMinDimension($params['dimension_units']);
if ($params['width'] < $minValue || $params['length'] < $minValue || $params['height'] < $minValue) {
$message = Mage::helper('usa')->__('Height, width and length should be equal or greater than %s', $minValue);
Mage::throwException($message);
}
}
$weightUnits = $piece['params']['weight_units'];
$piece['params']['height'] = $this->_getDimension($piece['params']['height'], $weightUnits);
$piece['params']['length'] = $this->_getDimension($piece['params']['length'], $weightUnits);
$piece['params']['width'] = $this->_getDimension($piece['params']['width'], $weightUnits);
$piece['params']['dimension_units'] = $this->_getDimensionUnit();
$piece['params']['weight'] = $this->_getWeight($piece['params']['weight'], false, $weightUnits);
$piece['params']['weight_units'] = $this->_getWeightUnit();
$customsValue += $piece['params']['customs_value'];
$packageWeight += $piece['params']['weight'];
}
$request->setPackages($packages)
->setPackageWeight($packageWeight)
->setPackageValue($customsValue)
->setValueWithDiscount($customsValue)
->setPackageCustomsValue($customsValue)
->setFreeMethodWeight(0);
}
/**
* Retrieve minimum allowed value for dimensions in given dimension unit
*
* @param string $dimensionUnit
* @return int
*/
protected function _getMinDimension($dimensionUnit)
{
return $dimensionUnit == "CENTIMETER" ? self::DIMENSION_MIN_CM : self::DIMENSION_MIN_IN;
}
/**
* Do rate request and handle errors
*
* @return Mage_Shipping_Model_Rate_Result|Varien_Object
*/
protected function _doRequest()
{
$rawRequest = $this->_request;
$originRegion = (string)$this->getCountryParams(
Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID, $this->getStore())
)->region;
if (!$originRegion) {
Mage::throwException(Mage::helper('usa')->__('Wrong Region.'));
}
if ($originRegion == 'AM') {
$originRegion = '';
}
$xmlStr = ''
. '';
$xml = new SimpleXMLElement($xmlStr);
$nodeRequest = $xml->addChild('Request', '', '');
$nodeServiceHeader = $nodeRequest->addChild('ServiceHeader');
$nodeServiceHeader->addChild('SiteID', (string)$this->getConfigData('id'));
$nodeServiceHeader->addChild('Password', (string)$this->getConfigData('password'));
if (!$originRegion) {
$xml->addChild('RequestedPickupTime', 'N', '');
}
$xml->addChild('NewShipper', 'N', '');
$xml->addChild('LanguageCode', 'EN', '');
$xml->addChild('PiecesEnabled', 'Y', '');
/* Billing */
$nodeBilling = $xml->addChild('Billing', '', '');
$nodeBilling->addChild('ShipperAccountNumber', (string)$this->getConfigData('account'));
/*
* Method of Payment:
* S (Shipper)
* R (Receiver)
* T (Third Party)
*/
$nodeBilling->addChild('ShippingPaymentType', 'S');
/*
* Shipment bill to account ā required if Shipping PaymentType is other than 'S'
*/
$nodeBilling->addChild('BillingAccountNumber', (string)$this->getConfigData('account'));
$nodeBilling->addChild('DutyPaymentType', 'S');
$nodeBilling->addChild('DutyAccountNumber', (string)$this->getConfigData('account'));
/* Receiver */
$nodeConsignee = $xml->addChild('Consignee', '', '');
$companyName = ($rawRequest->getRecipientContactCompanyName())
? $rawRequest->getRecipientContactCompanyName()
: $rawRequest->getRecipientContactPersonName();
$nodeConsignee->addChild('CompanyName', substr($companyName, 0, 35));
$address = $rawRequest->getRecipientAddressStreet1(). ' ' . $rawRequest->getRecipientAddressStreet2();
$address = Mage::helper('core/string')->str_split($address, 35, false, true);
if (is_array($address)) {
foreach ($address as $addressLine) {
$nodeConsignee->addChild('AddressLine', $addressLine);
}
} else {
$nodeConsignee->addChild('AddressLine', $address);
}
$nodeConsignee->addChild('City', $rawRequest->getRecipientAddressCity());
$nodeConsignee->addChild('Division', $rawRequest->getRecipientAddressStateOrProvinceCode());
$nodeConsignee->addChild('PostalCode', $rawRequest->getRecipientAddressPostalCode());
$nodeConsignee->addChild('CountryCode', $rawRequest->getRecipientAddressCountryCode());
$nodeConsignee->addChild('CountryName',
(string)$this->getCountryParams($rawRequest->getRecipientAddressCountryCode())->name
);
$nodeContact = $nodeConsignee->addChild('Contact');
$nodeContact->addChild('PersonName', substr($rawRequest->getRecipientContactPersonName(), 0, 34));
$nodeContact->addChild('PhoneNumber', substr($rawRequest->getRecipientContactPhoneNumber(), 0, 24));
/* Commodity
* The CommodityCode element contains commodity code for shipment contents. Its
* value should lie in between 1 to 9999.This field is mandatory.
*/
$nodeCommodity = $xml->addChild('Commodity', '', '');
$nodeCommodity->addChild('CommodityCode', '1');
$this->_checkDomesticStatus($rawRequest->getShipperAddressCountryCode(),
$rawRequest->getRecipientAddressCountryCode()
);
/* Dutiable */
if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_NON_DOC && !$this->_isDomestic) {
$nodeDutiable = $xml->addChild('Dutiable', '', '');
$nodeDutiable->addChild('DeclaredValue',
sprintf("%.2F", $rawRequest->getOrderShipment()->getOrder()->getSubtotal())
);
$baseCurrencyCode = Mage::app()->getWebsite($rawRequest->getWebsiteId())->getBaseCurrencyCode();
$nodeDutiable->addChild('DeclaredCurrency', $baseCurrencyCode);
}
/* Reference
* This element identifies the reference information. It is an optional field in the
* shipment validation request. Only the first reference will be taken currently.
*/
$nodeReference = $xml->addChild('Reference', '', '');
$nodeReference->addChild('ReferenceID', 'shipment reference');
$nodeReference->addChild('ReferenceType', 'St');
/* Shipment Details */
$this->_shipmentDetails($xml, $rawRequest, $originRegion);
/* Shipper */
$nodeShipper = $xml->addChild('Shipper', '', '');
$nodeShipper->addChild('ShipperID', (string)$this->getConfigData('account'));
$nodeShipper->addChild('CompanyName', $rawRequest->getShipperContactCompanyName());
$nodeShipper->addChild('RegisteredAccount', (string)$this->getConfigData('account'));
$address = $rawRequest->getShipperAddressStreet1(). ' ' . $rawRequest->getShipperAddressStreet2();
$address = Mage::helper('core/string')->str_split($address, 35, false, true);
if (is_array($address)) {
foreach ($address as $addressLine) {
$nodeShipper->addChild('AddressLine', $addressLine);
}
} else {
$nodeShipper->addChild('AddressLine', $address);
}
$nodeShipper->addChild('City', $rawRequest->getShipperAddressCity());
$nodeShipper->addChild('Division', $rawRequest->getShipperAddressStateOrProvinceCode());
$nodeShipper->addChild('PostalCode', $rawRequest->getShipperAddressPostalCode());
$nodeShipper->addChild('CountryCode', $rawRequest->getShipperAddressCountryCode());
$nodeShipper->addChild('CountryName',
(string)$this->getCountryParams($rawRequest->getShipperAddressCountryCode())->name
);
$nodeContact = $nodeShipper->addChild('Contact', '', '');
$nodeContact->addChild('PersonName', substr($rawRequest->getShipperContactPersonName(), 0, 34));
$nodeContact->addChild('PhoneNumber', substr($rawRequest->getShipperContactPhoneNumber(), 0, 24));
$xml->addChild('LabelImageFormat', 'PDF', '');
$request = $xml->asXML();
$request = utf8_encode($request);
$responseBody = $this->_getCachedQuotes($request);
if ($responseBody === null) {
$debugData = array('request' => $request);
try {
$client = new Varien_Http_Client();
$client->setUri((string)$this->getConfigData('gateway_url'));
$client->setConfig(array(
'maxredirects' => 0,
'timeout' => 30,
'verifypeer' => $this->getConfigFlag('verify_peer'),
'verifyhost' => 2,
));
$client->setRawData($request);
$responseBody = $client->request(Varien_Http_Client::POST)->getBody();
$debugData['result'] = $responseBody;
$this->_setCachedQuotes($request, $responseBody);
} catch (Exception $e) {
$this->_errors[$e->getCode()] = $e->getMessage();
$responseBody = '';
}
$this->_debug($debugData);
}
$this->_isShippingLabelFlag = true;
return $this->_parseResponse($responseBody);
}
/**
* Generation Shipment Details Node according to origin region
*
* @param SimpleXMLElement $xml
* @param Mage_Shipping_Model_Rate_Request $rawRequest
* @param string $originRegion
* @return void
*/
protected function _shipmentDetails($xml, $rawRequest, $originRegion = '')
{
$nodeShipmentDetails = $xml->addChild('ShipmentDetails', '', '');
$nodeShipmentDetails->addChild('NumberOfPieces', count($rawRequest->getPackages()));
if ($originRegion) {
$nodeShipmentDetails->addChild('CurrencyCode',
Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode()
);
}
$nodePieces = $nodeShipmentDetails->addChild('Pieces', '', '');
/*
* Package type
* EE (DHL Express Envelope), OD (Other DHL Packaging), CP (Custom Packaging)
* DC (Document), DM (Domestic), ED (Express Document), FR (Freight)
* BD (Jumbo Document), BP (Jumbo Parcel), JD (Jumbo Junior Document)
* JP (Jumbo Junior Parcel), PA (Parcel), DF (DHL Flyer)
*/
$i = 0;
foreach ($rawRequest->getPackages() as $package) {
$nodePiece = $nodePieces->addChild('Piece', '', '');
$packageType = 'EE';
if ($package['params']['container'] == self::DHL_CONTENT_TYPE_NON_DOC) {
$packageType = 'CP';
}
$nodePiece->addChild('PieceID', ++$i);
$nodePiece->addChild('PackageType', $packageType);
$nodePiece->addChild('Weight', round($package['params']['weight'],1));
$params = $package['params'];
if ($params['width'] && $params['length'] && $params['height']) {
if (!$originRegion) {
$nodePiece->addChild('Width', round($params['width']));
$nodePiece->addChild('Height', round($params['height']));
$nodePiece->addChild('Depth', round($params['length']));
} else {
$nodePiece->addChild('Depth', round($params['length']));
$nodePiece->addChild('Width', round($params['width']));
$nodePiece->addChild('Height', round($params['height']));
}
}
$content = array();
foreach ($package['items'] as $item) {
$content[] = $item['name'];
}
$nodePiece->addChild('PieceContents', substr(implode(',', $content), 0, 34));
}
if (!$originRegion) {
$nodeShipmentDetails->addChild('Weight', round($rawRequest->getPackageWeight(),1));
$nodeShipmentDetails->addChild('WeightUnit', substr($this->_getWeightUnit(),0,1));
$nodeShipmentDetails->addChild('GlobalProductCode', $rawRequest->getShippingMethod());
$nodeShipmentDetails->addChild('LocalProductCode', $rawRequest->getShippingMethod());
$nodeShipmentDetails->addChild('Date', Mage::getModel('core/date')->date(self::REQUEST_DATE_FORMAT));
$nodeShipmentDetails->addChild('Contents', 'DHL Parcel');
/*
* The DoorTo Element defines the type of delivery service that applies to the shipment.
* The valid values are DD (Door to Door), DA (Door to Airport) , AA and DC (Door to
* Door non-compliant)
*/
$nodeShipmentDetails->addChild('DoorTo', 'DD');
$nodeShipmentDetails->addChild('DimensionUnit', substr($this->_getDimensionUnit(),0,1));
if ($package['params']['container'] == self::DHL_CONTENT_TYPE_NON_DOC) {
$packageType = 'CP';
}
$nodeShipmentDetails->addChild('PackageType', $packageType);
if ($this->getConfigData('content_type') == self::DHL_CONTENT_TYPE_NON_DOC) {
$nodeShipmentDetails->addChild('IsDutiable', 'Y');
}
$nodeShipmentDetails->addChild('CurrencyCode',
Mage::app()->getWebsite($this->_request->getWebsiteId())->getBaseCurrencyCode()
);
} else {
if ($package['params']['container'] == self::DHL_CONTENT_TYPE_NON_DOC) {
$packageType = 'CP';
}
$nodeShipmentDetails->addChild('PackageType', $packageType);
$nodeShipmentDetails->addChild('Weight', $rawRequest->getPackageWeight());
$nodeShipmentDetails->addChild('DimensionUnit', substr($this->_getDimensionUnit(),0,1));
$nodeShipmentDetails->addChild('WeightUnit', substr($this->_getWeightUnit(),0,1));
$nodeShipmentDetails->addChild('GlobalProductCode', $rawRequest->getShippingMethod());
$nodeShipmentDetails->addChild('LocalProductCode', $rawRequest->getShippingMethod());
/*
* The DoorTo Element defines the type of delivery service that applies to the shipment.
* The valid values are DD (Door to Door), DA (Door to Airport) , AA and DC (Door to
* Door non-compliant)
*/
$nodeShipmentDetails->addChild('DoorTo', 'DD');
$nodeShipmentDetails->addChild('Date', Mage::getModel('core/date')->date(self::REQUEST_DATE_FORMAT));
$nodeShipmentDetails->addChild('Contents', 'DHL Parcel');
}
}
/**
* Get tracking
*
* @param mixed $trackings
* @return mixed
*/
public function getTracking($trackings)
{
if (!is_array($trackings)) {
$trackings = array($trackings);
}
$this->_getXMLTracking($trackings);
return $this->_result;
}
/**
* Send request for tracking
*
* @param array $trackings
* @return void
*/
protected function _getXMLTracking($trackings)
{
$xmlStr = ''
. '';
$xml = new SimpleXMLElement($xmlStr);
$requestNode = $xml->addChild('Request', '', '');
$serviceHeaderNode = $requestNode->addChild('ServiceHeader', '', '');
$serviceHeaderNode->addChild('SiteID', (string)$this->getConfigData('id'));
$serviceHeaderNode->addChild('Password', (string)$this->getConfigData('password'));
$xml->addChild('LanguageCode', 'EN', '');
foreach ($trackings as $tracking) {
$xml->addChild('AWBNumber', $tracking, '');
}
/*
* Checkpoint details selection flag
* LAST_CHECK_POINT_ONLY
* ALL_CHECK_POINTS
*/
$xml->addChild('LevelOfDetails', 'ALL_CHECK_POINTS', '');
/*
* Value that indicates for getting the tracking details with the additional
* piece details and its respective Piece Details, Piece checkpoints along with
* Shipment Details if queried.
*
* S-Only Shipment Details
* B-Both Shipment & Piece Details
* P-Only Piece Details
* Default is āSā
*/
//$xml->addChild('PiecesEnabled', 'ALL_CHECK_POINTS');
$request = $xml->asXML();
$request = utf8_encode($request);
$responseBody = $this->_getCachedQuotes($request);
if ($responseBody === null) {
$debugData = array('request' => $request);
try {
$client = new Varien_Http_Client();
$client->setUri((string)$this->getConfigData('gateway_url'));
$client->setConfig(array(
'maxredirects' => 0,
'timeout' => 30,
'verifypeer' => $this->getConfigFlag('verify_peer'),
'verifyhost' => 2,
));
$client->setRawData($request);
$responseBody = $client->request(Varien_Http_Client::POST)->getBody();
$debugData['result'] = $responseBody;
$this->_setCachedQuotes($request, $responseBody);
} catch (Exception $e) {
$this->_errors[$e->getCode()] = $e->getMessage();
$responseBody = '';
}
$this->_debug($debugData);
}
$this->_parseXmlTrackingResponse($trackings, $responseBody);
}
/**
* Parse xml tracking response
*
* @param array $trackings
* @param string $response
* @return void
*/
protected function _parseXmlTrackingResponse($trackings, $response)
{
$errorTitle = Mage::helper('usa')->__('Unable to retrieve tracking');
$resultArr = array();
if (strlen(trim($response)) > 0) {
$xml = simplexml_load_string($response);
if (!is_object($xml)) {
$errorTitle = Mage::helper('usa')->__('Response is in the wrong format');
}
if (is_object($xml) && ((isset($xml->Response->Status->ActionStatus)
&& $xml->Response->Status->ActionStatus == 'Failure')
|| isset($xml->GetQuoteResponse->Note->Condition))
) {
if (isset($xml->Response->Status->Condition)) {
$nodeCondition = $xml->Response->Status->Condition;
}
$code = isset($nodeCondition->ConditionCode) ? (string)$nodeCondition->ConditionCode : 0;
$data = isset($nodeCondition->ConditionData) ? (string)$nodeCondition->ConditionData : '';
$this->_errors[$code] = Mage::helper('usa')->__('Error #%s : %s', $code, $data);
} elseif (is_object($xml) && is_object($xml->AWBInfo)) {
foreach ($xml->AWBInfo as $awbinfo) {
$awbinfoData = array();
$trackNum = isset($awbinfo->AWBNumber) ? (string)$awbinfo->AWBNumber : '';
if (!is_object($awbinfo) || !$awbinfo->ShipmentInfo) {
$this->_errors[$trackNum] = Mage::helper('usa')->__('Unable to retrieve tracking');
continue;
}
$shipmentInfo = $awbinfo->ShipmentInfo;
if ($shipmentInfo->ShipmentDesc) {
$awbinfoData['service'] = (string)$shipmentInfo->ShipmentDesc;
}
$awbinfoData['weight'] = (string)$shipmentInfo->Weight . ' ' . (string)$shipmentInfo->WeightUnit;
$packageProgress = array();
if (isset($shipmentInfo->ShipmentEvent)) {
foreach ($shipmentInfo->ShipmentEvent as $shipmentEvent) {
$shipmentEventArray = array();
$shipmentEventArray['activity'] = (string)$shipmentEvent->ServiceEvent->EventCode
. ' ' . (string)$shipmentEvent->ServiceEvent->Description;
$shipmentEventArray['deliverydate'] = (string)$shipmentEvent->Date;
$shipmentEventArray['deliverytime'] = (string)$shipmentEvent->Time;
$shipmentEventArray['deliverylocation'] = (string)$shipmentEvent->ServiceArea->Description
. ' [' . (string)$shipmentEvent->ServiceArea->ServiceAreaCode . ']';
$packageProgress[] = $shipmentEventArray;
}
$awbinfoData['progressdetail'] = $packageProgress;
}
$resultArr[$trackNum] = $awbinfoData;
}
}
}
$result = Mage::getModel('shipping/tracking_result');
if (!empty($resultArr)) {
foreach ($resultArr as $trackNum => $data) {
$tracking = Mage::getModel('shipping/tracking_result_status');
$tracking->setCarrier($this->_code);
$tracking->setCarrierTitle($this->getConfigData('title'));
$tracking->setTracking($trackNum);
$tracking->addData($data);
$result->append($tracking);
}
}
if (!empty($this->_errors) || empty($resultArr)) {
$resultArr = !empty($this->_errors) ? $this->_errors : $trackings;
foreach ($resultArr as $trackNum => $err) {
$error = Mage::getModel('shipping/tracking_result_error');
$error->setCarrier($this->_code);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setTracking(!empty($this->_errors) ? $trackNum : $err);
$error->setErrorMessage(!empty($this->_errors) ? $err : $errorTitle);
$result->append($error);
}
}
$this->_result = $result;
}
/**
* Get final price for shipping method with handling fee per package
*
* @param float $cost
* @param string $handlingType
* @param float $handlingFee
* @return float
*/
protected function _getPerpackagePrice($cost, $handlingType, $handlingFee)
{
if ($handlingType == Mage_Shipping_Model_Carrier_Abstract::HANDLING_TYPE_PERCENT) {
return $cost + ($cost * $this->_numBoxes * $handlingFee / 100);
}
return $cost + $this->_numBoxes * $handlingFee;
}
/**
* Do request to shipment
*
* @param Mage_Shipping_Model_Shipment_Request $request
* @return Varien_Object
*/
public function requestToShipment(Mage_Shipping_Model_Shipment_Request $request)
{
$packages = $request->getPackages();
if (!is_array($packages) || !$packages) {
Mage::throwException(Mage::helper('usa')->__('No packages for request'));
}
$result = $this->_doShipmentRequest($request);
$response = new Varien_Object(array(
'info' => array(array(
'tracking_number' => $result->getTrackingNumber(),
'label_content' => $result->getShippingLabelContent()
))
));
$request->setMasterTrackingId($result->getTrackingNumber());
return $response;
}
/**
* Check if shipping is domestic
*
* @param string $origCountryCode
* @param string $destCountryCode
* @return bool
*/
protected function _checkDomesticStatus($origCountryCode, $destCountryCode)
{
$this->_isDomestic = false;
$origCountry = (string)$this->getCountryParams($origCountryCode)->name;
$destCountry = (string)$this->getCountryParams($destCountryCode)->name;
$isDomestic = (string)$this->getCountryParams($destCountryCode)->domestic;
if ($origCountry == $destCountry && $isDomestic) {
$this->_isDomestic = true;
}
return $this->_isDomestic;
}
}