*/
class Mage_Usa_Model_Shipping_Carrier_Dhl
extends Mage_Usa_Model_Shipping_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
/**
* Code of the carrier
*
* @var string
*/
const CODE = 'dhl';
/**
* Code of the carrier
*
* @var string
*/
protected $_code = self::CODE;
/**
* 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;
/**
* Errors placeholder
*
* @var array
*/
protected $_errors = array();
/**
* Dhl rates result
*
* @var array
*/
protected $_dhlRates = array();
/**
* Default gateway url
*
* @var string
*/
protected $_defaultGatewayUrl = 'https://eCommerce.airborne.com/ApiLandingTest.asp';
/**
* Container types that could be customized
*
* @var array
*/
protected $_customizableContainerTypes = array('P');
const SUCCESS_CODE = 203;
const SUCCESS_LABEL_CODE = 100;
const ADDITIONAL_PROTECTION_ASSET = 'AP';
const ADDITIONAL_PROTECTION_NOT_REQUIRED = 'NR';
const ADDITIONAL_PROTECTION_VALUE_CONFIG = 0;
const ADDITIONAL_PROTECTION_VALUE_SUBTOTAL = 1;
const ADDITIONAL_PROTECTION_VALUE_SUBTOTAL_WITH_DISCOUNT = 2;
const ADDITIONAL_PROTECTION_ROUNDING_FLOOR = 0;
const ADDITIONAL_PROTECTION_ROUNDING_CEIL = 1;
const ADDITIONAL_PROTECTION_ROUNDING_ROUND = 2;
/**
* 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;
$origCompanyName = $requestDhl->getOrigCompanyName();
if (!$origCompanyName) {
$origCompanyName = Mage::getStoreConfig(
Mage_Core_Model_Store::XML_PATH_STORE_STORE_NAME,
$requestDhl->getStoreId()
);
}
$origCountryId = $requestDhl->getOrigCountryId();
if (!$origCountryId) {
$origCountryId = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
$requestDhl->getStoreId()
);
}
$origState = $requestDhl->getOrigState();
if (!$origState) {
$origState = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_REGION_ID,
$requestDhl->getStoreId()
);
}
$origCity = $requestDhl->getOrigCity();
if (!$origCity) {
$origCity = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_CITY,
$requestDhl->getStoreId()
);
}
$origPostcode = $requestDhl->getOrigPostcode();
if (!$origPostcode) {
$origPostcode = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_ZIP,
$requestDhl->getStoreId()
);
}
$requestDhl->setOrigCompanyName($origCompanyName)
->setCountryId($origCountryId)
->setOrigState($origState)
->setOrigCity($origCity)
->setOrigPostal($origPostcode);
$this->setRequest($requestDhl);
$this->_result = $this->_getQuotes();
$this->_updateFreeMethodQuote($request);
return $this->getResult();
}
/**
* 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;
$r = new Varien_Object();
if ($request->getAction() == 'GenerateLabel') {
$r->setAction('GenerateLabel');
} else {
$r->setAction('RateEstimate');
}
$r->setIsGenerateLabelReturn($request->getIsGenerateLabelReturn());
$r->setStoreId($request->getStoreId());
if ($request->getLimitMethod()) {
$r->setService($request->getLimitMethod());
}
if ($request->getDhlId()) {
$id = $request->getDhlId();
} else {
$id = $this->getConfigData('id');
}
$r->setId($id);
if ($request->getDhlPassword()) {
$password = $request->getDhlPassword();
} else {
$password = $this->getConfigData('password');
}
$r->setPassword($password);
if ($request->getDhlAccount()) {
$accountNbr = $request->getDhlAccount();
} else {
$accountNbr = $this->getConfigData('account');
}
$r->setAccountNbr($accountNbr);
if ($request->getDhlShippingKey()) {
$shippingKey = $request->getDhlShippingKey();
} else {
$shippingKey = $this->getConfigData('shipping_key');
}
$r->setShippingKey($shippingKey);
if ($request->getDhlShippingIntlKey()) {
$shippingKey = $request->getDhlShippingIntlKey();
} else {
$shippingKey = $this->getConfigData('shipping_intlkey');
}
$r->setShippingIntlKey($shippingKey);
if ($request->getDhlShipmentType()) {
$shipmentType = $request->getDhlShipmentType();
} else {
$shipmentType = $this->getConfigData('shipment_type');
}
$r->setShipmentType($shipmentType);
if ($request->getDhlDutiable()) {
$shipmentDutible = $request->getDhlDutiable();
} else {
$shipmentDutible = $this->getConfigData('dutiable');
}
$r->setDutiable($shipmentDutible);
if ($request->getDhlDutyPaymentType()) {
$dutypaytype = $request->getDhlDutyPaymentType();
} else {
$dutypaytype = $this->getConfigData('dutypaymenttype');
}
$r->setDutyPaymentType($dutypaytype);
if ($request->getDhlContentDesc()) {
$contentdesc = $request->getDhlContentDesc();
} else {
$contentdesc = $this->getConfigData('contentdesc');
}
$r->setContentDesc($contentdesc);
if ($request->getDestPostcode()) {
$r->setDestPostal($request->getDestPostcode());
}
if ($request->getOrigCountry()) {
$origCountry = $request->getOrigCountry();
} else {
$origCountry = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
$r->getStoreId()
);
}
$r->setOrigCountry($origCountry);
if ($request->getOrigCountryId()) {
$origCountryId = $request->getOrigCountryId();
} else {
$origCountryId = Mage::getStoreConfig(
Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
$r->getStoreId()
);
}
$r->setOrigCountryId($origCountryId);
if ($request->getAction() == 'GenerateLabel') {
$packageParams = $request->getPackageParams();
$shippingWeight = $request->getPackageWeight();
if ($packageParams->getWeightUnits() != Zend_Measure_Weight::POUND) {
$shippingWeight = round(Mage::helper('usa')->convertMeasureWeight(
$request->getPackageWeight(),
$packageParams->getWeightUnits(),
Zend_Measure_Weight::POUND
));
}
if ($packageParams->getDimensionUnits() != Zend_Measure_Length::INCH) {
$packageParams->setLength(round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getLength(),
$packageParams->getDimensionUnits(),
Zend_Measure_Length::INCH
)));
$packageParams->setWidth(round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getWidth(),
$packageParams->getDimensionUnits(),
Zend_Measure_Length::INCH
)));
$packageParams->setHeight(round(Mage::helper('usa')->convertMeasureDimension(
$packageParams->getHeight(),
$packageParams->getDimensionUnits(),
Zend_Measure_Length::INCH
)));
}
$r->setPackageParams($packageParams);
} else {
/*
* DHL only accepts weight as a whole number. Maximum length is 3 digits.
*/
$shippingWeight = $request->getPackageWeight();
if ($shipmentType != 'L') {
$weight = $this->getTotalNumOfBoxes($shippingWeight);
$shippingWeight = round(max(1, $weight), 0);
}
}
$r->setValue(round($request->getPackageValue(), 2));
$r->setValueWithDiscount($request->getPackageValueWithDiscount());
$r->setCustomsValue($request->getPackageCustomsValue());
$r->setDestStreet(Mage::helper('core/string')->substr(str_replace("\n", '', $request->getDestStreet()), 0, 35));
$r->setDestStreetLine2($request->getDestStreetLine2());
$r->setDestCity($request->getDestCity());
$r->setOrigCompanyName($request->getOrigCompanyName());
$r->setOrigCity($request->getOrigCity());
$r->setOrigPhoneNumber($request->getOrigPhoneNumber());
$r->setOrigPersonName($request->getOrigPersonName());
$r->setOrigEmail(Mage::getStoreConfig('trans_email/ident_general/email', $r->getStoreId()));
$r->setOrigCity($request->getOrigCity());
$r->setOrigPostal($request->getOrigPostal());
$originStreet1 = Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_ADDRESS1,$r->getStoreId());
$originStreet2 = Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_ADDRESS2, $r->getStoreId());
$r->setOrigStreet($request->getOrigStreet() ? $request->getOrigStreet() : $originStreet2);
$r->setOrigStreetLine2($request->getOrigStreetLine2());
$r->setDestPhoneNumber($request->getDestPhoneNumber());
$r->setDestPersonName($request->getDestPersonName());
$r->setDestCompanyName($request->getDestCompanyName());
if (is_numeric($request->getOrigState())) {
$r->setOrigState(Mage::getModel('directory/region')->load($request->getOrigState())->getCode());
} else {
$r->setOrigState($request->getOrigState());
}
if ($request->getDestCountryId()) {
$destCountry = $request->getDestCountryId();
} else {
$destCountry = self::USA_COUNTRY_ID;
}
//for DHL, puero 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;
}
$r->setDestCountryId($destCountry);
$r->setDestState($request->getDestRegionCode());
$r->setWeight($shippingWeight);
$r->setFreeMethodWeight($request->getFreeMethodWeight());
$r->setOrderShipment($request->getOrderShipment());
if ($request->getPackageId()) {
$r->setPackageId($request->getPackageId());
}
$r->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
$this->_rawRequest = $r;
return $this;
}
/**
* Get result of request
*
* @return mixed
*/
public function getResult()
{
return $this->_result;
}
/**
* Get quotes
*
* @return Mage_Shipping_Model_Rate_Result
*/
protected function _getQuotes()
{
return $this->_getXmlQuotes();
}
/**
* Set free method request
*
* @param $freeMethod
* @return void
*/
protected function _setFreeMethodRequest($freeMethod)
{
$r = $this->_rawRequest;
$r->setFreeMethodRequest(true);
$weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight());
$freeWeight = round(max(1, $weight), 0);
$r->setWeight($freeWeight);
$r->setService($freeMethod);
}
/**
* Get shipping date
*
* @param bool $domestic
* @return string
*/
protected function _getShipDate($domestic = true)
{
if ($domestic) {
$days = explode(',', $this->getConfigData('shipment_days'));
} else {
$days = explode(',', $this->getConfigData('intl_shipment_days'));
}
if (!$days) {
return date('Y-m-d');
}
$i = 0;
$weekday = date('w');
while (!in_array($weekday, $days) && $i < 10) {
$i++;
$weekday = date('w', strtotime("+$i day"));
}
return date('Y-m-d', strtotime("+$i day"));
}
/**
* Get xml quotes
*
* @return Mage_Core_Model_Abstract|Varien_Object
*/
protected function _getXmlQuotes()
{
return $this->_doRequest();
}
/**
* Do rate request and handle errors
*
* @return Mage_Shipping_Model_Rate_Result|Varien_Object
*/
protected function _doRequest()
{
$r = $this->_rawRequest;
$xml = new SimpleXMLElement('');
$xml->addAttribute('action', 'Request');
$xml->addAttribute('version', '1.1');
$requestor = $xml->addChild('Requestor');
$requestor->addChild('ID', $r->getId());
$requestor->addChild('Password', $r->getPassword());
$methods = explode(',', $this->getConfigData('allowed_methods'));
$internationcode = $this->getCode('international_searvice');
$hasShipCode = false;
$shipDate = $this->_getShipDate();
if ($r->hasService() && $r->getFreeMethodRequest()) {
if ($r->getDestCountryId() == self::USA_COUNTRY_ID) {
$shipment = $xml->addChild('Shipment');
$shipKey = $r->getShippingKey();
$r->setShipDate($shipDate);
} else {
$shipment = $xml->addChild('IntlShipment');
$shipKey = $r->getShippingIntlKey();
$r->setShipDate($this->_getShipDate(false));
/*
* For internation shippingment customsvalue must be posted
*/
$shippingDuty = $shipment->addChild('Dutiable');
$shippingDuty->addChild('DutiableFlag', ($r->getDutiable() ? 'Y' : 'N'));
$shippingDuty->addChild('CustomsValue', $r->getValue());
$shippingDuty->addChild('IsSEDReqd', 'N');
}
$hasShipCode = true;
$this->_createShipmentXml($shipment, $shipKey);
} else {
if ($r->getAction() == 'GenerateLabel') {
$methods = array($r->getService());
}
foreach ($methods as $method) {
$shipment = false;
if (in_array($method, array_keys($this->getCode('special_express')))) {
$r->setService('E');
$r->setExtendedService($this->getCode('special_express', $method));
} else {
$r->setService($method);
$r->setExtendedService(null);
}
if ($r->getDestCountryId() == self::USA_COUNTRY_ID && $method != $internationcode) {
$shipment = $xml->addChild('Shipment');
$shipKey = $r->getShippingKey();
$r->setShipDate($shipDate);
} elseif ($r->getDestCountryId() != self::USA_COUNTRY_ID && $method == $internationcode) {
$shipment = $xml->addChild('IntlShipment');
$shipKey = $r->getShippingIntlKey();
if ($r->getCustomsValue() != null && $r->getCustomsValue() != '') {
$customsValue = $r->getCustomsValue();
} else {
$customsValue = $r->getValue();
}
$r->setShipDate($this->_getShipDate(false));
/*
* For internation shippingment customsvalue must be posted
*/
$shippingDuty = $shipment->addChild('Dutiable');
$shippingDuty->addChild('DutiableFlag', ($r->getDutiable() ? 'Y' : 'N'));
$shippingDuty->addChild('CustomsValue', $customsValue);
$shippingDuty->addChild('IsSEDReqd', 'N');
}
if ($shipment !== false) {
$hasShipCode = true;
$this->_createShipmentXml($shipment, $shipKey);
}
}
}
if (!$hasShipCode) {
$this->_errors[] = Mage::helper('usa')->__('There is no available method for selected shipping address.');
return;
}
$request = $xml->asXML();
$request = utf8_encode($request);
$responseBody = $this->_getCachedQuotes($request);
if ($responseBody === null) {
$debugData = array('request' => $request);
try {
$url = $this->getConfigData('gateway_url');
if (!$url) {
$url = $this->_defaultGatewayUrl;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$responseBody = curl_exec($ch);
curl_close($ch);
$debugData['result'] = $responseBody;
$this->_setCachedQuotes($request, $responseBody);
}
catch (Exception $e) {
$debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
$responseBody = '';
}
$this->_debug($debugData);
}
return $this->_parseXmlResponse($responseBody);
}
/**
* Create shipment xml
*
* @param $shipment
* @param $shipKey
* @return void
*/
protected function _createShipmentXml($shipment, $shipKey)
{
$r = $this->_rawRequest;
$store = Mage::app()->getStore($r->getStoreId());
$_haz = $this->getConfigFlag('hazardous_materials');
$_subtotal = $r->getValue();
$_subtotalWithDiscount = $r->getValueWithDiscount();
$_width = max(0, (double)$this->getConfigData('default_width'));
$_height = max(0, (double)$this->getConfigData('default_height'));
$_length = max(0, (double)$this->getConfigData('default_length'));
$packageParams = $r->getPackageParams();
if ($packageParams) {
$_length = $packageParams->getLength();
$_width = $packageParams->getWidth();
$_height = $packageParams->getHeight();
}
$_apEnabled = $this->getConfigFlag('additional_protection_enabled');
$_apUseSubtotal = $this->getConfigData('additional_protection_use_subtotal');
$_apConfigValue = max(0, (double)$this->getConfigData('additional_protection_value'));
$_apMinValue = max(0, (double)$this->getConfigData('additional_protection_min_value'));
$_apValueRounding = $this->getConfigData('additional_protection_rounding');
$apValue = 0;
$apCode = self::ADDITIONAL_PROTECTION_NOT_REQUIRED;
if ($_apEnabled) {
if ($_apMinValue <= $_subtotal) {
switch ($_apUseSubtotal) {
case self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL:
$apValue = $_subtotal;
break;
case self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL_WITH_DISCOUNT:
$apValue = $_subtotalWithDiscount;
break;
default:
case self::ADDITIONAL_PROTECTION_VALUE_CONFIG:
$apValue = $_apConfigValue;
break;
}
if ($apValue) {
$apCode = self::ADDITIONAL_PROTECTION_ASSET;
switch ($_apValueRounding) {
case self::ADDITIONAL_PROTECTION_ROUNDING_CEIL:
$apValue = ceil($apValue);
break;
case self::ADDITIONAL_PROTECTION_ROUNDING_ROUND:
$apValue = round($apValue);
break;
default:
case self::ADDITIONAL_PROTECTION_ROUNDING_FLOOR:
$apValue = floor($apValue);
break;
}
}
}
}
if ($r->getAction() == 'GenerateLabel') {
$shipment->addAttribute('action', 'GenerateLabel');
} else {
$shipment->addAttribute('action', 'RateEstimate');
}
$shipment->addAttribute('version', '1.0');
$shippingCredentials = $shipment->addChild('ShippingCredentials');
$shippingCredentials->addChild('ShippingKey', $shipKey);
$shippingCredentials->addChild('AccountNbr', $r->getAccountNbr());
$shipmentDetail = $shipment->addChild('ShipmentDetail');
if ($r->getAction() == 'GenerateLabel') {
if ($this->_request->getReferenceData()) {
$referenceData = $this->_request->getReferenceData() . $this->_request->getPackageId();
} else {
$referenceData = 'Order #'
. $r->getOrderShipment()->getOrder()->getIncrementId()
. ' P'
. $r->getPackageId();
}
$shipmentDetail->addChild('ShipperReference', $referenceData);
}
$shipmentDetail->addChild('ShipDate', $r->getShipDate());
$shipmentDetail->addChild('Service')->addChild('Code', $r->getService());
$shipmentDetail->addChild('ShipmentType')->addChild('Code', $r->getShipmentType());
$shipmentDetail->addChild('Weight', $r->getWeight());
$shipmentDetail->addChild('ContentDesc', $r->getContentDesc());
$additionalProtection = $shipmentDetail->addChild('AdditionalProtection');
$additionalProtection->addChild('Code', $apCode);
$additionalProtection->addChild('Value', floor($apValue));
if ($_width || $_height || $_length) {
$dimensions = $shipmentDetail->addChild('Dimensions');
$dimensions->addChild('Length', $_length);
$dimensions->addChild('Width', $_width);
$dimensions->addChild('Height', $_height);
}
if ($_haz || ($r->getExtendedService())) {
$specialServices = $shipmentDetail->addChild('SpecialServices');
}
if ($_haz) {
$hazardousMaterials = $specialServices->addChild('SpecialService');
$hazardousMaterials->addChild('Code', 'HAZ');
}
if ($r->getExtendedService()) {
$extendedService = $specialServices->addChild('SpecialService');
$extendedService->addChild('Code', $r->getExtendedService());
}
/*
* R = Receiver (if receiver, need AccountNbr)
* S = Sender
* 3 = Third Party (if third party, need AccountNbr)
*/
$billing = $shipment->addChild('Billing');
$billing->addChild('Party')->addChild('Code', $r->getIsGenerateLabelReturn() ? 'R' : 'S');
$billing->addChild('DutyPaymentType', $r->getDutyPaymentType());
if ($r->getIsGenerateLabelReturn()) {
$billing->addChild('AccountNbr', $r->getAccountNbr());
}
$sender = $shipment->addChild('Sender');
$sender->addChild('SentBy', ($r->getOrigPersonName()));
$sender->addChild('PhoneNbr', $r->getOrigPhoneNumber());
$sender->addChild('Email', $r->getOrigEmail());
$senderAddress = $sender->addChild('Address');
$senderAddress->addChild('Street', htmlspecialchars($r->getOrigStreet() ? $r->getOrigStreet() : 'N/A'));
$senderAddress->addChild('City', htmlspecialchars($r->getOrigCity()));
$senderAddress->addChild('State', htmlspecialchars($r->getOrigState()));
$senderAddress->addChild('CompanyName', htmlspecialchars($r->getOrigCompanyName()));
/*
* DHL xml service is using UK for united kingdom instead of GB which is a standard ISO country code
*/
$senderAddress->addChild('Country', ($r->getOrigCountryId() == 'GB' ? 'UK' : $r->getOrigCountryId()));
$senderAddress->addChild('PostalCode', $r->getOrigPostal());
$receiver = $shipment->addChild('Receiver');
$receiver->addChild('AttnTo', $r->getDestPersonName());
$receiver->addChild('PhoneNbr', $r->getDestPhoneNumber());
$receiverAddress = $receiver->addChild('Address');
$receiverAddress->addChild('Street', htmlspecialchars($r->getDestStreet() ? $r->getDestStreet() : 'N/A'));
$receiverAddress->addChild('StreetLine2',
htmlspecialchars($r->getDestStreetLine2() ? $r->getDestStreetLine2() : 'N/A')
);
$receiverAddress->addChild('City', htmlspecialchars($r->getDestCity()));
$receiverAddress->addChild('State', htmlspecialchars($r->getDestState()));
$receiverAddress->addChild('CompanyName',
htmlspecialchars($r->getDestCompanyName() ? $r->getDestCompanyName() : 'N/A')
);
/*
* DHL xml service is using UK for united kingdom instead of GB which is a standard ISO country code
*/
$receiverAddress->addChild('Country', ($r->getDestCountryId() == 'GB' ? 'UK' : $r->getDestCountryId()));
$receiverAddress->addChild('PostalCode', $r->getDestPostal());
if ($r->getAction() == 'GenerateLabel') {
$label = $shipment->addChild('ShipmentProcessingInstructions')->addChild('Label');
$label->addChild('ImageType', 'PNG');
}
}
/**
* Parse xml response and return result
*
* @param string $response
* @return Mage_Shipping_Model_Rate_Result|Varien_Object
*/
protected function _parseXmlResponse($response)
{
$r = $this->_rawRequest;
$costArr = array();
$priceArr = array();
$errorTitle = 'Unable to retrieve quotes';
$tr = get_html_translation_table(HTML_ENTITIES);
unset($tr['<'], $tr['>'], $tr['"']);
$response = str_replace(array_keys($tr), array_values($tr), $response);
if (strlen(trim($response)) > 0) {
if (strpos(trim($response), 'Faults)
&& is_object($xml->Faults->Fault)
&& is_object($xml->Faults->Fault->Code)
&& is_object($xml->Faults->Fault->Description)
&& is_object($xml->Faults->Fault->Context)
) {
$code = (string)$xml->Faults->Fault->Code;
$description = $xml->Faults->Fault->Description;
$context = $xml->Faults->Fault->Context;
$this->_errors[$code] = Mage::helper('usa')->__('Error #%s : %s (%s)', $code, $description, $context);
} else {
if ($r->getDestCountryId() == self::USA_COUNTRY_ID) {
if ($xml->Shipment) {
foreach ($xml->Shipment as $shipXml) {
$this->_parseXmlObject($shipXml);
}
} else {
$this->_errors[] = Mage::helper('usa')->__('Shipment is not available.');
}
} else {
$shipXml = $xml->IntlShipment;
$this->_parseXmlObject($shipXml);
}
$shipXml = (($r->getDestCountryId() == self::USA_COUNTRY_ID)
? $xml->Shipment
: $xml->IntlShipment
);
}
}
} else {
$this->_errors[] = Mage::helper('usa')->__('The response is in wrong format.');
}
}
if ($this->_rawRequest->getAction() == 'GenerateLabel') {
$result = new Varien_Object();
if (!empty($this->_errors)) {
$result->setErrors(implode($this->_errors, '; '));
} else {
if ($xml !== false) {
if ($r->getDestCountryId() == self::USA_COUNTRY_ID) {
$shippingLabelContent = base64_decode((string)$xml->Shipment->Label->Image);
$trackingNumber = (string)$xml->Shipment->ShipmentDetail->AirbillNbr;
} else {
$shippingLabelContent = base64_decode((string)$xml->IntlShipment->Label->Image);
$trackingNumber = (string)$xml->IntlShipment->ShipmentDetail->AirbillNbr;
}
}
$result->setShippingLabelContent($shippingLabelContent);
$result->setTrackingNumber($trackingNumber);
}
return $result;
} else {
$result = Mage::getModel('shipping/rate_result');
if ($this->_dhlRates) {
foreach ($this->_dhlRates as $rate) {
$method = $rate['service'];
$data = $rate['data'];
$rate = Mage::getModel('shipping/rate_result_method');
$rate->setCarrier('dhl');
$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)) {
$error = Mage::getModel('shipping/rate_result_error');
$error->setCarrier('dhl');
$error->setCarrierTitle($this->getConfigData('title'));
$error->setErrorMessage($this->getConfigData('specificerrmsg'));
$result->append($error);
}
return $result;
}
}
/**
* Parse xml object
*
* @param mixed $shipXml
* @return Mage_Usa_Model_Shipping_Carrier_Dhl
*/
protected function _parseXmlObject($shipXml)
{
if (
is_object($shipXml->Faults)
&& is_object($shipXml->Faults->Fault)
&& is_object($shipXml->Faults->Fault->Desc)
&& intval($shipXml->Faults->Fault->Code) != self::SUCCESS_CODE
&& intval($shipXml->Faults->Fault->Code) != self::SUCCESS_LABEL_CODE
) {
$code = (string)$shipXml->Faults->Fault->Code;
$description = $shipXml->Faults->Fault->Desc;
$this->_errors[$code] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
} elseif (
is_object($shipXml->Faults)
&& is_object($shipXml->Result->Code)
&& is_object($shipXml->Result->Desc)
&& intval($shipXml->Result->Code) != self::SUCCESS_CODE
&& intval($shipXml->Result->Code) != self::SUCCESS_LABEL_CODE
) {
$code = (string)$shipXml->Result->Code;
$description = $shipXml->Result->Desc;
$this->_errors[$code] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
} else {
$this->_addRate($shipXml);
}
return $this;
}
/**
* Get configuration data of carrier
*
* @param string $type
* @param string $code
* @return array|bool
*/
public function getCode($type, $code = '')
{
static $codes;
$codes = array(
'service' => array(
'IE' => Mage::helper('usa')->__('International Express'),
'E SAT' => Mage::helper('usa')->__('Express Saturday'),
'E 10:30AM' => Mage::helper('usa')->__('Express 10:30 AM'),
'E' => Mage::helper('usa')->__('Express'),
'N' => Mage::helper('usa')->__('Next Afternoon'),
'S' => Mage::helper('usa')->__('Second Day Service'),
'G' => Mage::helper('usa')->__('Ground'),
),
'shipment_type' => array(
'L' => Mage::helper('usa')->__('Letter'),
'P' => Mage::helper('usa')->__('Package'),
),
'international_searvice' => 'IE',
'dutypayment_type' => array(
'S' => Mage::helper('usa')->__('Sender'),
'R' => Mage::helper('usa')->__('Receiver'),
'3' => Mage::helper('usa')->__('Third Party'),
),
'special_express' => array(
'E SAT' => 'SAT',
'E 10:30AM' => '1030',
),
'descr_to_service' => array(
'E SAT' => 'Saturday',
'E 10:30AM' => '10:30 A.M',
),
);
if (!isset($codes[$type])) {
return false;
} elseif ('' === $code) {
return $codes[$type];
}
if (!isset($codes[$type][$code])) {
return false;
} else {
return $codes[$type][$code];
}
}
/**
* Parse xml and add rates to instance property
*
* @param mixed $shipXml
* @return void
*/
protected function _addRate($shipXml)
{
$r = $this->_rawRequest;
$services = $this->getCode('service');
$regexps = $this->getCode('descr_to_service');
$desc = ($shipXml->EstimateDetail) ? (string)$shipXml->EstimateDetail->ServiceLevelCommitment->Desc : null;
$totalEstimate = $shipXml->EstimateDetail
? (string)$shipXml->EstimateDetail->RateEstimate->TotalChargeEstimate
: null;
/*
* DHL can return with empty result and success code
* we need to make sure there is shipping estimate and code
*/
if ($desc && $totalEstimate) {
$service = (string)$shipXml->EstimateDetail->Service->Code;
$description = (string)$shipXml->EstimateDetail->ServiceLevelCommitment->Desc;
if ($service == 'E') {
foreach ($regexps as $expService => $exp) {
if (preg_match('/' . preg_quote($exp, '/') . '/', $description)) {
$service = $expService;
}
}
}
$data['term'] = (isset($services[$service]) ? $services[$service] : $desc);
$data['price_total'] = $this->getMethodPrice($totalEstimate, $service);
$this->_dhlRates[] = array('service' => $service, 'data' => $data);
}
}
/**
* Get tracking
*
* @param mixed $trackings
* @return mixed
*/
public function getTracking($trackings)
{
$this->setTrackingReqeust();
if (!is_array($trackings)) {
$trackings = array($trackings);
}
$this->_getXMLTracking($trackings);
return $this->_result;
}
/**
* Set tracking request
*
* @return null
*/
protected function setTrackingReqeust()
{
$r = new Varien_Object();
$id = $this->getConfigData('id');
$r->setId($id);
$password = $this->getConfigData('password');
$r->setPassword($password);
$this->_rawTrackRequest = $r;
}
/**
* Send request for tracking
*
* @param array $tracking
* @return null
*/
protected function _getXMLTracking($trackings)
{
$r = $this->_rawTrackRequest;
$xml = new SimpleXMLElement('');
$xml->addAttribute('action', 'Request');
$xml->addAttribute('version', '1.1');
$requestor = $xml->addChild('Requestor');
$requestor->addChild('ID', $r->getId());
$requestor->addChild('Password', $r->getPassword());
$track = $xml->addChild('Track');
$track->addAttribute('action', 'Get');
$track->addAttribute('version', '1.0');
foreach ($trackings as $tracking) {
$track->addChild('Shipment')->addChild('TrackingNbr', $tracking);
}
$request = $xml->asXML();
$debugData = array('request' => $request);
/*
* tracking api cannot process from 3pm to 5pm PST time on Sunday
* DHL Airborne conduts a maintainance during that period.
*/
try {
$url = $this->getConfigData('gateway_url');
if (!$url) {
$url = $this->_defaultGatewayUrl;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$responseBody = curl_exec($ch);
$debugData['result'] = $responseBody;
curl_close($ch);
} catch (Exception $e) {
$debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
$responseBody = '';
}
$this->_debug($debugData);
$this->_parseXmlTrackingResponse($trackings, $responseBody);
}
/**
* Parse xml tracking response
*
* @param array $trackingvalue
* @param string $response
* @return null
*/
protected function _parseXmlTrackingResponse($trackings, $response)
{
$errorTitle = Mage::helper('usa')->__('Unable to retrieve tracking');
$resultArr = array();
$errorArr = array();
$trackingserror = array();
$tracknum = '';
if (strlen(trim($response)) > 0) {
if (strpos(trim($response), 'Track;
if (
is_object($xml->Faults)
&& is_object($xml->Faults->Fault)
&& is_object($xml->Faults->Fault->Code)
&& is_object($xml->Faults->Fault->Description)
&& is_object($xml->Faults->Fault->Context)
) {
$code = (string)$xml->Faults->Fault->Code;
$description = $xml->Faults->Fault->Description;
$context = $xml->Faults->Fault->Context;
$errorTitle = Mage::helper('usa')->__('Error #%s : %s (%s)', $code, $description, $context);
} elseif (is_object($trackxml) && is_object($trackxml->Shipment)) {
foreach ($trackxml->Shipment as $txml) {
$rArr = array();
if (is_object($txml)) {
$tracknum = (string)$txml->TrackingNbr;
if ($txml->Fault) {
$code = (string)$txml->Fault->Code;
$description = $txml->Fault->Description;
$errorArr[$tracknum] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
} elseif ($txml->Result) {
$code = (int)$txml->Result->Code;
if ($code === 0) {
/*
* Code 0== airbill found
*/
$rArr['service'] = (string)$txml->Service->Desc;
if (isset($txml->Weight))
$rArr['weight'] = (string)$txml->Weight . " lbs";
if (isset($txml->Delivery)) {
$rArr['deliverydate'] = (string)$txml->Delivery->Date;
$rArr['deliverytime'] = (string)$txml->Delivery->Time . ':00';
$rArr['status'] = Mage::helper('usa')->__('Delivered');
if (isset($txml->Delivery->Location->Desc)) {
$rArr['deliverylocation'] = (string)$txml->Delivery->Location->Desc;
}
} elseif (isset($txml->Pickup)) {
$rArr['deliverydate'] = (string)$txml->Pickup->Date;
$rArr['deliverytime'] = (string)$txml->Pickup->Time . ':00';
$rArr['status'] = Mage::helper('usa')->__('Shipment picked up');
} else {
$rArr['status'] = (string)$txml->ShipmentType->Desc
. Mage::helper('usa')->__(' was not delivered nor scanned');
}
$packageProgress = array();
if (isset($txml->TrackingHistory) && isset($txml->TrackingHistory->Status)) {
foreach ($txml->TrackingHistory->Status as $thistory) {
$tempArr = array();
$tempArr['activity'] = (string)$thistory->StatusDesc;
$tempArr['deliverydate'] = (string)$thistory->Date; //YYYY-MM-DD
$tempArr['deliverytime'] = (string)$thistory->Time . ':00'; //HH:MM:ss
$addArr = array();
if (isset($thistory->Location->City)) {
$addArr[] = (string)$thistory->Location->City;
}
if (isset($thistory->Location->State)) {
$addArr[] = (string)$thistory->Location->State;
}
if (isset($thistory->Location->CountryCode)) {
$addArr[] = (string)$thistory->Location->Country;
}
if ($addArr) {
$tempArr['deliverylocation'] = implode(', ', $addArr);
} elseif (isset($thistory['final_delivery'])
&& (string)$thistory['final_delivery'] === 'true'
) {
/*
* if the history is final delivery, there is no informationabout
* city, state and country
*/
$addArr = array();
if (isset($txml->Receiver->City)) {
$addArr[] = (string)$txml->Receiver->City;
}
if (isset($thistory->Receiver->State)) {
$addArr[] = (string)$txml->Receiver->State;
}
if (isset($thistory->Receiver->CountryCode)) {
$addArr[] = (string)$txml->Receiver->Country;
}
$tempArr['deliverylocation'] = implode(', ', $addArr);
}
$packageProgress[] = $tempArr;
}
$rArr['progressdetail'] = $packageProgress;
}
$resultArr[$tracknum] = $rArr;
} else {
$description = (string)$txml->Result->Desc;
if ($description)
$errorArr[$tracknum] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
else
$errorArr[$tracknum] = Mage::helper('usa')->__('Unable to retrieve tracking');
}
} else {
$errorArr[$tracknum] = Mage::helper('usa')->__('Unable to retrieve tracking');
}
}
}
}
}
} else {
$errorTitle = Mage::helper('usa')->__('Response is in the wrong format');
}
}
$result = Mage::getModel('shipping/tracking_result');
if ($errorArr || $resultArr) {
foreach ($errorArr as $t => $r) {
$error = Mage::getModel('shipping/tracking_result_error');
$error->setCarrier('dhl');
$error->setCarrierTitle($this->getConfigData('title'));
$error->setTracking($t);
$error->setErrorMessage($r);
$result->append($error);
}
foreach ($resultArr as $t => $data) {
$tracking = Mage::getModel('shipping/tracking_result_status');
$tracking->setCarrier('dhl');
$tracking->setCarrierTitle($this->getConfigData('title'));
$tracking->setTracking($t);
$tracking->addData($data);
$result->append($tracking);
}
} else {
foreach ($trackings as $t) {
$error = Mage::getModel('shipping/tracking_result_error');
$error->setCarrier('dhl');
$error->setCarrierTitle($this->getConfigData('title'));
$error->setTracking($t);
$error->setErrorMessage($errorTitle);
$result->append($error);
}
}
$this->_result = $result;
}
/**
* Get tracking response
*
* @return string
*/
public function getResponse()
{
$statuses = '';
if ($this->_result instanceof Mage_Shipping_Model_Tracking_Result) {
if ($trackings = $this->_result->getAllTrackings()) {
foreach ($trackings as $tracking) {
if ($data = $tracking->getAllData()) {
if (isset($data['status'])) {
$statuses .= Mage::helper('usa')->__($data['status']) . "\n
";
} else {
$statuses .= Mage::helper('usa')->__($data['error_message']) . "\n
";
}
}
}
}
}
if (empty($statuses)) {
$statuses = Mage::helper('usa')->__('Empty response');
}
return $statuses;
}
/**
* Get allowed shipping methods
*
* @return array
*/
public function getAllowedMethods()
{
$allowed = explode(',', $this->getConfigData('allowed_methods'));
$arr = array();
foreach ($allowed as $k) {
$arr[$k] = $this->getCode('service', $k);
}
return $arr;
}
/**
* Is state province required
*
* @return bool
*/
public function isStateProvinceRequired()
{
return true;
}
/**
* Get additional protection value types
*
* @return array
*/
public function getAdditionalProtectionValueTypes()
{
return array(
self::ADDITIONAL_PROTECTION_VALUE_CONFIG => Mage::helper('usa')->__('Configuration'),
self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL => Mage::helper('usa')->__('Subtotal'),
self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL_WITH_DISCOUNT => Mage::helper('usa')->__('Subtotal With Discount'),
);
}
/**
* Get additional protection rounding types
*
* @return array
*/
public function getAdditionalProtectionRoundingTypes()
{
return array(
self::ADDITIONAL_PROTECTION_ROUNDING_FLOOR => Mage::helper('usa')->__('To Lower'),
self::ADDITIONAL_PROTECTION_ROUNDING_CEIL => Mage::helper('usa')->__('To Upper'),
self::ADDITIONAL_PROTECTION_ROUNDING_ROUND => Mage::helper('usa')->__('Round'),
);
}
/**
* Map request to shipment
*
* @param Varien_Object $request
* @return null
*/
protected function _mapRequestToShipment(Varien_Object $request)
{
$customsValue = $request->getPackageParams()->getCustomsValue();
$request->setOrigPersonName($request->getShipperContactPersonName());
$request->setOrigPostal($request->getShipperAddressPostalCode());
$request->setOrigPhoneNumber($request->getShipperContactPhoneNumber());
$request->setOrigCompanyName($request->getShipperContactCompanyName());
$request->setOrigCountryId($request->getShipperAddressCountryCode());
$request->setOrigState($request->getShipperAddressStateOrProvinceCode());
$request->setOrigCity($request->getShipperAddressCity());
$request->setOrigStreet($request->getShipperAddressStreet1() . ' ' . $request->getShipperAddressStreet2());
$request->setOrigStreetLine2($request->getShipperAddressStreet2());
$request->setDestPersonName($request->getRecipientContactPersonName());
$request->setDestPostcode($request->getRecipientAddressPostalCode());
$request->setDestPhoneNumber($request->getRecipientContactPhoneNumber());
$request->setDestCompanyName($request->getRecipientContactCompanyName());
$request->setDestCountryId($request->getRecipientAddressCountryCode());
$request->setDestRegionCode($request->getRecipientAddressStateOrProvinceCode());
$request->setDestCity($request->getRecipientAddressCity());
$request->setDestStreet($request->getRecipientAddressStreet1());
$request->setDestStreetLine2($request->getRecipientAddressStreet2());
$request->setLimitMethod($request->getShippingMethod());
$request->setPackageValue($customsValue);
$request->setValueWithDiscount($customsValue);
$request->setPackageCustomsValue($customsValue);
$request->setFreeMethodWeight(0);
$request->setDhlShipmentType($request->getPackagingType());
$request->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
}
/**
* 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);
$request->setAction('GenerateLabel');
$this->_mapRequestToShipment($request);
$this->setRequest($request);
return $this->_doRequest();
}
/**
* Return container types of carrier
*
* @param Varien_Object|null $params
* @return array|bool
*/
public function getContainerTypes(Varien_Object $params = null)
{
return $this->getCode('shipment_type');
}
}