1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27:
28: 29: 30: 31: 32: 33: 34:
35: class Mage_Usa_Model_Shipping_Carrier_Dhl
36: extends Mage_Usa_Model_Shipping_Carrier_Abstract
37: implements Mage_Shipping_Model_Carrier_Interface
38: {
39:
40: 41: 42: 43: 44:
45: const CODE = 'dhl';
46:
47: 48: 49: 50: 51:
52: protected $_code = self::CODE;
53:
54: 55: 56: 57: 58:
59: protected $_request = null;
60:
61: 62: 63: 64: 65:
66: protected $_rawRequest = null;
67:
68: 69: 70: 71: 72:
73: protected $_result = null;
74:
75: 76: 77: 78: 79:
80: protected $_errors = array();
81:
82: 83: 84: 85: 86:
87: protected $_dhlRates = array();
88:
89: 90: 91: 92: 93:
94: protected $_defaultGatewayUrl = 'https://eCommerce.airborne.com/ApiLandingTest.asp';
95:
96: 97: 98: 99: 100:
101: protected $_customizableContainerTypes = array('P');
102:
103: const SUCCESS_CODE = 203;
104: const SUCCESS_LABEL_CODE = 100;
105:
106: const ADDITIONAL_PROTECTION_ASSET = 'AP';
107: const ADDITIONAL_PROTECTION_NOT_REQUIRED = 'NR';
108:
109: const ADDITIONAL_PROTECTION_VALUE_CONFIG = 0;
110: const ADDITIONAL_PROTECTION_VALUE_SUBTOTAL = 1;
111: const ADDITIONAL_PROTECTION_VALUE_SUBTOTAL_WITH_DISCOUNT = 2;
112:
113: const ADDITIONAL_PROTECTION_ROUNDING_FLOOR = 0;
114: const ADDITIONAL_PROTECTION_ROUNDING_CEIL = 1;
115: const ADDITIONAL_PROTECTION_ROUNDING_ROUND = 2;
116:
117: 118: 119: 120: 121: 122:
123: public function collectRates(Mage_Shipping_Model_Rate_Request $request)
124: {
125: if (!$this->getConfigFlag($this->_activeFlag)) {
126: return false;
127: }
128:
129: $requestDhl = clone $request;
130: $origCompanyName = $requestDhl->getOrigCompanyName();
131: if (!$origCompanyName) {
132: $origCompanyName = Mage::getStoreConfig(
133: Mage_Core_Model_Store::XML_PATH_STORE_STORE_NAME,
134: $requestDhl->getStoreId()
135: );
136: }
137:
138: $origCountryId = $requestDhl->getOrigCountryId();
139: if (!$origCountryId) {
140: $origCountryId = Mage::getStoreConfig(
141: Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
142: $requestDhl->getStoreId()
143: );
144: }
145: $origState = $requestDhl->getOrigState();
146: if (!$origState) {
147: $origState = Mage::getStoreConfig(
148: Mage_Shipping_Model_Shipping::XML_PATH_STORE_REGION_ID,
149: $requestDhl->getStoreId()
150: );
151: }
152: $origCity = $requestDhl->getOrigCity();
153: if (!$origCity) {
154: $origCity = Mage::getStoreConfig(
155: Mage_Shipping_Model_Shipping::XML_PATH_STORE_CITY,
156: $requestDhl->getStoreId()
157: );
158: }
159:
160: $origPostcode = $requestDhl->getOrigPostcode();
161: if (!$origPostcode) {
162: $origPostcode = Mage::getStoreConfig(
163: Mage_Shipping_Model_Shipping::XML_PATH_STORE_ZIP,
164: $requestDhl->getStoreId()
165: );
166: }
167: $requestDhl->setOrigCompanyName($origCompanyName)
168: ->setCountryId($origCountryId)
169: ->setOrigState($origState)
170: ->setOrigCity($origCity)
171: ->setOrigPostal($origPostcode);
172: $this->setRequest($requestDhl);
173: $this->_result = $this->_getQuotes();
174: $this->_updateFreeMethodQuote($request);
175:
176: return $this->getResult();
177: }
178:
179: 180: 181: 182: 183: 184:
185: public function setRequest(Varien_Object $request)
186: {
187: $this->_request = $request;
188:
189: $r = new Varien_Object();
190:
191: if ($request->getAction() == 'GenerateLabel') {
192: $r->setAction('GenerateLabel');
193: } else {
194: $r->setAction('RateEstimate');
195: }
196: $r->setIsGenerateLabelReturn($request->getIsGenerateLabelReturn());
197:
198: $r->setStoreId($request->getStoreId());
199:
200: if ($request->getLimitMethod()) {
201: $r->setService($request->getLimitMethod());
202: }
203:
204: if ($request->getDhlId()) {
205: $id = $request->getDhlId();
206: } else {
207: $id = $this->getConfigData('id');
208: }
209: $r->setId($id);
210:
211: if ($request->getDhlPassword()) {
212: $password = $request->getDhlPassword();
213: } else {
214: $password = $this->getConfigData('password');
215: }
216: $r->setPassword($password);
217:
218: if ($request->getDhlAccount()) {
219: $accountNbr = $request->getDhlAccount();
220: } else {
221: $accountNbr = $this->getConfigData('account');
222: }
223: $r->setAccountNbr($accountNbr);
224:
225: if ($request->getDhlShippingKey()) {
226: $shippingKey = $request->getDhlShippingKey();
227: } else {
228: $shippingKey = $this->getConfigData('shipping_key');
229: }
230: $r->setShippingKey($shippingKey);
231:
232: if ($request->getDhlShippingIntlKey()) {
233: $shippingKey = $request->getDhlShippingIntlKey();
234: } else {
235: $shippingKey = $this->getConfigData('shipping_intlkey');
236: }
237: $r->setShippingIntlKey($shippingKey);
238:
239: if ($request->getDhlShipmentType()) {
240: $shipmentType = $request->getDhlShipmentType();
241: } else {
242: $shipmentType = $this->getConfigData('shipment_type');
243: }
244: $r->setShipmentType($shipmentType);
245:
246: if ($request->getDhlDutiable()) {
247: $shipmentDutible = $request->getDhlDutiable();
248: } else {
249: $shipmentDutible = $this->getConfigData('dutiable');
250: }
251: $r->setDutiable($shipmentDutible);
252:
253: if ($request->getDhlDutyPaymentType()) {
254: $dutypaytype = $request->getDhlDutyPaymentType();
255: } else {
256: $dutypaytype = $this->getConfigData('dutypaymenttype');
257: }
258: $r->setDutyPaymentType($dutypaytype);
259:
260: if ($request->getDhlContentDesc()) {
261: $contentdesc = $request->getDhlContentDesc();
262: } else {
263: $contentdesc = $this->getConfigData('contentdesc');
264: }
265: $r->setContentDesc($contentdesc);
266:
267: if ($request->getDestPostcode()) {
268: $r->setDestPostal($request->getDestPostcode());
269: }
270:
271: if ($request->getOrigCountry()) {
272: $origCountry = $request->getOrigCountry();
273: } else {
274: $origCountry = Mage::getStoreConfig(
275: Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
276: $r->getStoreId()
277: );
278: }
279: $r->setOrigCountry($origCountry);
280:
281: if ($request->getOrigCountryId()) {
282: $origCountryId = $request->getOrigCountryId();
283: } else {
284: $origCountryId = Mage::getStoreConfig(
285: Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
286: $r->getStoreId()
287: );
288: }
289: $r->setOrigCountryId($origCountryId);
290:
291: if ($request->getAction() == 'GenerateLabel') {
292: $packageParams = $request->getPackageParams();
293: $shippingWeight = $request->getPackageWeight();
294: if ($packageParams->getWeightUnits() != Zend_Measure_Weight::POUND) {
295: $shippingWeight = round(Mage::helper('usa')->convertMeasureWeight(
296: $request->getPackageWeight(),
297: $packageParams->getWeightUnits(),
298: Zend_Measure_Weight::POUND
299: ));
300: }
301: if ($packageParams->getDimensionUnits() != Zend_Measure_Length::INCH) {
302: $packageParams->setLength(round(Mage::helper('usa')->convertMeasureDimension(
303: $packageParams->getLength(),
304: $packageParams->getDimensionUnits(),
305: Zend_Measure_Length::INCH
306: )));
307: $packageParams->setWidth(round(Mage::helper('usa')->convertMeasureDimension(
308: $packageParams->getWidth(),
309: $packageParams->getDimensionUnits(),
310: Zend_Measure_Length::INCH
311: )));
312: $packageParams->setHeight(round(Mage::helper('usa')->convertMeasureDimension(
313: $packageParams->getHeight(),
314: $packageParams->getDimensionUnits(),
315: Zend_Measure_Length::INCH
316: )));
317: }
318: $r->setPackageParams($packageParams);
319: } else {
320: 321: 322:
323: $shippingWeight = $request->getPackageWeight();
324: if ($shipmentType != 'L') {
325: $weight = $this->getTotalNumOfBoxes($shippingWeight);
326: $shippingWeight = round(max(1, $weight), 0);
327: }
328: }
329:
330: $r->setValue(round($request->getPackageValue(), 2));
331: $r->setValueWithDiscount($request->getPackageValueWithDiscount());
332: $r->setCustomsValue($request->getPackageCustomsValue());
333: $r->setDestStreet(Mage::helper('core/string')->substr(str_replace("\n", '', $request->getDestStreet()), 0, 35));
334: $r->setDestStreetLine2($request->getDestStreetLine2());
335: $r->setDestCity($request->getDestCity());
336: $r->setOrigCompanyName($request->getOrigCompanyName());
337: $r->setOrigCity($request->getOrigCity());
338: $r->setOrigPhoneNumber($request->getOrigPhoneNumber());
339: $r->setOrigPersonName($request->getOrigPersonName());
340: $r->setOrigEmail(Mage::getStoreConfig('trans_email/ident_general/email', $r->getStoreId()));
341: $r->setOrigCity($request->getOrigCity());
342: $r->setOrigPostal($request->getOrigPostal());
343: $originStreet1 = Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_ADDRESS1,$r->getStoreId());
344: $originStreet2 = Mage::getStoreConfig(Mage_Shipping_Model_Shipping::XML_PATH_STORE_ADDRESS2, $r->getStoreId());
345: $r->setOrigStreet($request->getOrigStreet() ? $request->getOrigStreet() : $originStreet2);
346: $r->setOrigStreetLine2($request->getOrigStreetLine2());
347: $r->setDestPhoneNumber($request->getDestPhoneNumber());
348: $r->setDestPersonName($request->getDestPersonName());
349: $r->setDestCompanyName($request->getDestCompanyName());
350:
351:
352: if (is_numeric($request->getOrigState())) {
353: $r->setOrigState(Mage::getModel('directory/region')->load($request->getOrigState())->getCode());
354: } else {
355: $r->setOrigState($request->getOrigState());
356: }
357:
358: if ($request->getDestCountryId()) {
359: $destCountry = $request->getDestCountryId();
360: } else {
361: $destCountry = self::USA_COUNTRY_ID;
362: }
363:
364:
365:
366: if ($destCountry == self::USA_COUNTRY_ID && ($request->getDestPostcode() == '00912'
367: || $request->getDestRegionCode() == self::PUERTORICO_COUNTRY_ID)
368: ) {
369: $destCountry = self::PUERTORICO_COUNTRY_ID;
370: }
371:
372: $r->setDestCountryId($destCountry);
373: $r->setDestState($request->getDestRegionCode());
374:
375: $r->setWeight($shippingWeight);
376: $r->setFreeMethodWeight($request->getFreeMethodWeight());
377:
378: $r->setOrderShipment($request->getOrderShipment());
379:
380: if ($request->getPackageId()) {
381: $r->setPackageId($request->getPackageId());
382: }
383:
384: $r->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
385:
386: $this->_rawRequest = $r;
387: return $this;
388: }
389:
390: 391: 392: 393: 394:
395: public function getResult()
396: {
397: return $this->_result;
398: }
399:
400: 401: 402: 403: 404:
405: protected function _getQuotes()
406: {
407: return $this->_getXmlQuotes();
408: }
409:
410: 411: 412: 413: 414: 415:
416: protected function _setFreeMethodRequest($freeMethod)
417: {
418: $r = $this->_rawRequest;
419:
420: $r->setFreeMethodRequest(true);
421: $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight());
422: $freeWeight = round(max(1, $weight), 0);
423: $r->setWeight($freeWeight);
424: $r->setService($freeMethod);
425: }
426:
427: 428: 429: 430: 431: 432:
433: protected function _getShipDate($domestic = true)
434: {
435: if ($domestic) {
436: $days = explode(',', $this->getConfigData('shipment_days'));
437: } else {
438: $days = explode(',', $this->getConfigData('intl_shipment_days'));
439: }
440:
441: if (!$days) {
442: return date('Y-m-d');
443: }
444:
445: $i = 0;
446: $weekday = date('w');
447: while (!in_array($weekday, $days) && $i < 10) {
448: $i++;
449: $weekday = date('w', strtotime("+$i day"));
450: }
451:
452: return date('Y-m-d', strtotime("+$i day"));
453: }
454:
455: 456: 457: 458: 459:
460: protected function _getXmlQuotes()
461: {
462: return $this->_doRequest();
463: }
464:
465: 466: 467: 468: 469:
470: protected function _doRequest()
471: {
472: $r = $this->_rawRequest;
473:
474: $xml = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><eCommerce/>');
475: $xml->addAttribute('action', 'Request');
476: $xml->addAttribute('version', '1.1');
477:
478: $requestor = $xml->addChild('Requestor');
479: $requestor->addChild('ID', $r->getId());
480: $requestor->addChild('Password', $r->getPassword());
481:
482: $methods = explode(',', $this->getConfigData('allowed_methods'));
483: $internationcode = $this->getCode('international_searvice');
484: $hasShipCode = false;
485:
486: $shipDate = $this->_getShipDate();
487:
488: if ($r->hasService() && $r->getFreeMethodRequest()) {
489: if ($r->getDestCountryId() == self::USA_COUNTRY_ID) {
490: $shipment = $xml->addChild('Shipment');
491: $shipKey = $r->getShippingKey();
492: $r->setShipDate($shipDate);
493: } else {
494: $shipment = $xml->addChild('IntlShipment');
495: $shipKey = $r->getShippingIntlKey();
496: $r->setShipDate($this->_getShipDate(false));
497: 498: 499:
500: $shippingDuty = $shipment->addChild('Dutiable');
501: $shippingDuty->addChild('DutiableFlag', ($r->getDutiable() ? 'Y' : 'N'));
502: $shippingDuty->addChild('CustomsValue', $r->getValue());
503: $shippingDuty->addChild('IsSEDReqd', 'N');
504: }
505: $hasShipCode = true;
506: $this->_createShipmentXml($shipment, $shipKey);
507: } else {
508: if ($r->getAction() == 'GenerateLabel') {
509: $methods = array($r->getService());
510: }
511:
512: foreach ($methods as $method) {
513: $shipment = false;
514: if (in_array($method, array_keys($this->getCode('special_express')))) {
515: $r->setService('E');
516: $r->setExtendedService($this->getCode('special_express', $method));
517: } else {
518: $r->setService($method);
519: $r->setExtendedService(null);
520: }
521: if ($r->getDestCountryId() == self::USA_COUNTRY_ID && $method != $internationcode) {
522: $shipment = $xml->addChild('Shipment');
523: $shipKey = $r->getShippingKey();
524: $r->setShipDate($shipDate);
525: } elseif ($r->getDestCountryId() != self::USA_COUNTRY_ID && $method == $internationcode) {
526: $shipment = $xml->addChild('IntlShipment');
527: $shipKey = $r->getShippingIntlKey();
528: if ($r->getCustomsValue() != null && $r->getCustomsValue() != '') {
529: $customsValue = $r->getCustomsValue();
530: } else {
531: $customsValue = $r->getValue();
532: }
533:
534: $r->setShipDate($this->_getShipDate(false));
535:
536: 537: 538:
539: $shippingDuty = $shipment->addChild('Dutiable');
540: $shippingDuty->addChild('DutiableFlag', ($r->getDutiable() ? 'Y' : 'N'));
541: $shippingDuty->addChild('CustomsValue', $customsValue);
542: $shippingDuty->addChild('IsSEDReqd', 'N');
543: }
544: if ($shipment !== false) {
545: $hasShipCode = true;
546: $this->_createShipmentXml($shipment, $shipKey);
547: }
548: }
549: }
550:
551: if (!$hasShipCode) {
552: $this->_errors[] = Mage::helper('usa')->__('There is no available method for selected shipping address.');
553: return;
554: }
555:
556: $request = $xml->asXML();
557: $request = utf8_encode($request);
558: $responseBody = $this->_getCachedQuotes($request);
559: if ($responseBody === null) {
560: $debugData = array('request' => $request);
561: try {
562: $url = $this->getConfigData('gateway_url');
563: if (!$url) {
564: $url = $this->_defaultGatewayUrl;
565: }
566: $ch = curl_init();
567: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
568: curl_setopt($ch, CURLOPT_URL, $url);
569: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
570: curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
571: curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
572: $responseBody = curl_exec($ch);
573: curl_close($ch);
574:
575: $debugData['result'] = $responseBody;
576: $this->_setCachedQuotes($request, $responseBody);
577: }
578: catch (Exception $e) {
579: $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
580: $responseBody = '';
581: }
582: $this->_debug($debugData);
583: }
584:
585: return $this->_parseXmlResponse($responseBody);
586: }
587:
588: 589: 590: 591: 592: 593: 594:
595: protected function _createShipmentXml($shipment, $shipKey)
596: {
597: $r = $this->_rawRequest;
598:
599: $store = Mage::app()->getStore($r->getStoreId());
600:
601: $_haz = $this->getConfigFlag('hazardous_materials');
602:
603: $_subtotal = $r->getValue();
604: $_subtotalWithDiscount = $r->getValueWithDiscount();
605:
606: $_width = max(0, (double)$this->getConfigData('default_width'));
607: $_height = max(0, (double)$this->getConfigData('default_height'));
608: $_length = max(0, (double)$this->getConfigData('default_length'));
609:
610: $packageParams = $r->getPackageParams();
611: if ($packageParams) {
612: $_length = $packageParams->getLength();
613: $_width = $packageParams->getWidth();
614: $_height = $packageParams->getHeight();
615: }
616:
617: $_apEnabled = $this->getConfigFlag('additional_protection_enabled');
618: $_apUseSubtotal = $this->getConfigData('additional_protection_use_subtotal');
619: $_apConfigValue = max(0, (double)$this->getConfigData('additional_protection_value'));
620: $_apMinValue = max(0, (double)$this->getConfigData('additional_protection_min_value'));
621: $_apValueRounding = $this->getConfigData('additional_protection_rounding');
622:
623: $apValue = 0;
624: $apCode = self::ADDITIONAL_PROTECTION_NOT_REQUIRED;
625: if ($_apEnabled) {
626: if ($_apMinValue <= $_subtotal) {
627: switch ($_apUseSubtotal) {
628: case self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL:
629: $apValue = $_subtotal;
630: break;
631: case self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL_WITH_DISCOUNT:
632: $apValue = $_subtotalWithDiscount;
633: break;
634: default:
635: case self::ADDITIONAL_PROTECTION_VALUE_CONFIG:
636: $apValue = $_apConfigValue;
637: break;
638: }
639:
640: if ($apValue) {
641: $apCode = self::ADDITIONAL_PROTECTION_ASSET;
642:
643:
644: switch ($_apValueRounding) {
645: case self::ADDITIONAL_PROTECTION_ROUNDING_CEIL:
646: $apValue = ceil($apValue);
647: break;
648: case self::ADDITIONAL_PROTECTION_ROUNDING_ROUND:
649: $apValue = round($apValue);
650: break;
651: default:
652: case self::ADDITIONAL_PROTECTION_ROUNDING_FLOOR:
653: $apValue = floor($apValue);
654: break;
655: }
656: }
657: }
658: }
659:
660: if ($r->getAction() == 'GenerateLabel') {
661: $shipment->addAttribute('action', 'GenerateLabel');
662: } else {
663: $shipment->addAttribute('action', 'RateEstimate');
664: }
665: $shipment->addAttribute('version', '1.0');
666:
667: $shippingCredentials = $shipment->addChild('ShippingCredentials');
668: $shippingCredentials->addChild('ShippingKey', $shipKey);
669: $shippingCredentials->addChild('AccountNbr', $r->getAccountNbr());
670:
671: $shipmentDetail = $shipment->addChild('ShipmentDetail');
672: if ($r->getAction() == 'GenerateLabel') {
673: if ($this->_request->getReferenceData()) {
674: $referenceData = $this->_request->getReferenceData() . $this->_request->getPackageId();
675: } else {
676: $referenceData = 'Order #'
677: . $r->getOrderShipment()->getOrder()->getIncrementId()
678: . ' P'
679: . $r->getPackageId();
680: }
681:
682: $shipmentDetail->addChild('ShipperReference', $referenceData);
683: }
684: $shipmentDetail->addChild('ShipDate', $r->getShipDate());
685: $shipmentDetail->addChild('Service')->addChild('Code', $r->getService());
686: $shipmentDetail->addChild('ShipmentType')->addChild('Code', $r->getShipmentType());
687: $shipmentDetail->addChild('Weight', $r->getWeight());
688: $shipmentDetail->addChild('ContentDesc', $r->getContentDesc());
689: $additionalProtection = $shipmentDetail->addChild('AdditionalProtection');
690: $additionalProtection->addChild('Code', $apCode);
691: $additionalProtection->addChild('Value', floor($apValue));
692:
693: if ($_width || $_height || $_length) {
694: $dimensions = $shipmentDetail->addChild('Dimensions');
695: $dimensions->addChild('Length', $_length);
696: $dimensions->addChild('Width', $_width);
697: $dimensions->addChild('Height', $_height);
698: }
699:
700: if ($_haz || ($r->getExtendedService())) {
701: $specialServices = $shipmentDetail->addChild('SpecialServices');
702: }
703:
704: if ($_haz) {
705: $hazardousMaterials = $specialServices->addChild('SpecialService');
706: $hazardousMaterials->addChild('Code', 'HAZ');
707: }
708:
709: if ($r->getExtendedService()) {
710: $extendedService = $specialServices->addChild('SpecialService');
711: $extendedService->addChild('Code', $r->getExtendedService());
712: }
713:
714:
715: 716: 717: 718: 719:
720: $billing = $shipment->addChild('Billing');
721: $billing->addChild('Party')->addChild('Code', $r->getIsGenerateLabelReturn() ? 'R' : 'S');
722: $billing->addChild('DutyPaymentType', $r->getDutyPaymentType());
723: if ($r->getIsGenerateLabelReturn()) {
724: $billing->addChild('AccountNbr', $r->getAccountNbr());
725: }
726:
727: $sender = $shipment->addChild('Sender');
728: $sender->addChild('SentBy', ($r->getOrigPersonName()));
729: $sender->addChild('PhoneNbr', $r->getOrigPhoneNumber());
730: $sender->addChild('Email', $r->getOrigEmail());
731:
732: $senderAddress = $sender->addChild('Address');
733: $senderAddress->addChild('Street', htmlspecialchars($r->getOrigStreet() ? $r->getOrigStreet() : 'N/A'));
734: $senderAddress->addChild('City', htmlspecialchars($r->getOrigCity()));
735: $senderAddress->addChild('State', htmlspecialchars($r->getOrigState()));
736: $senderAddress->addChild('CompanyName', htmlspecialchars($r->getOrigCompanyName()));
737: 738: 739:
740: $senderAddress->addChild('Country', ($r->getOrigCountryId() == 'GB' ? 'UK' : $r->getOrigCountryId()));
741: $senderAddress->addChild('PostalCode', $r->getOrigPostal());
742:
743: $receiver = $shipment->addChild('Receiver');
744: $receiver->addChild('AttnTo', $r->getDestPersonName());
745: $receiver->addChild('PhoneNbr', $r->getDestPhoneNumber());
746:
747: $receiverAddress = $receiver->addChild('Address');
748: $receiverAddress->addChild('Street', htmlspecialchars($r->getDestStreet() ? $r->getDestStreet() : 'N/A'));
749: $receiverAddress->addChild('StreetLine2',
750: htmlspecialchars($r->getDestStreetLine2() ? $r->getDestStreetLine2() : 'N/A')
751: );
752: $receiverAddress->addChild('City', htmlspecialchars($r->getDestCity()));
753: $receiverAddress->addChild('State', htmlspecialchars($r->getDestState()));
754: $receiverAddress->addChild('CompanyName',
755: htmlspecialchars($r->getDestCompanyName() ? $r->getDestCompanyName() : 'N/A')
756: );
757:
758: 759: 760:
761: $receiverAddress->addChild('Country', ($r->getDestCountryId() == 'GB' ? 'UK' : $r->getDestCountryId()));
762: $receiverAddress->addChild('PostalCode', $r->getDestPostal());
763:
764: if ($r->getAction() == 'GenerateLabel') {
765: $label = $shipment->addChild('ShipmentProcessingInstructions')->addChild('Label');
766: $label->addChild('ImageType', 'PNG');
767: }
768: }
769:
770: 771: 772: 773: 774: 775:
776: protected function _parseXmlResponse($response)
777: {
778: $r = $this->_rawRequest;
779: $costArr = array();
780: $priceArr = array();
781: $errorTitle = 'Unable to retrieve quotes';
782:
783: $tr = get_html_translation_table(HTML_ENTITIES);
784: unset($tr['<'], $tr['>'], $tr['"']);
785: $response = str_replace(array_keys($tr), array_values($tr), $response);
786:
787: if (strlen(trim($response)) > 0) {
788: if (strpos(trim($response), '<?xml') === 0) {
789: $xml = simplexml_load_string($response);
790: if (is_object($xml)) {
791: if (
792: is_object($xml->Faults)
793: && is_object($xml->Faults->Fault)
794: && is_object($xml->Faults->Fault->Code)
795: && is_object($xml->Faults->Fault->Description)
796: && is_object($xml->Faults->Fault->Context)
797: ) {
798: $code = (string)$xml->Faults->Fault->Code;
799: $description = $xml->Faults->Fault->Description;
800: $context = $xml->Faults->Fault->Context;
801: $this->_errors[$code] = Mage::helper('usa')->__('Error #%s : %s (%s)', $code, $description, $context);
802: } else {
803: if ($r->getDestCountryId() == self::USA_COUNTRY_ID) {
804: if ($xml->Shipment) {
805: foreach ($xml->Shipment as $shipXml) {
806: $this->_parseXmlObject($shipXml);
807: }
808: } else {
809: $this->_errors[] = Mage::helper('usa')->__('Shipment is not available.');
810: }
811: } else {
812: $shipXml = $xml->IntlShipment;
813: $this->_parseXmlObject($shipXml);
814: }
815: $shipXml = (($r->getDestCountryId() == self::USA_COUNTRY_ID)
816: ? $xml->Shipment
817: : $xml->IntlShipment
818: );
819: }
820: }
821: } else {
822: $this->_errors[] = Mage::helper('usa')->__('The response is in wrong format.');
823: }
824: }
825:
826: if ($this->_rawRequest->getAction() == 'GenerateLabel') {
827: $result = new Varien_Object();
828: if (!empty($this->_errors)) {
829: $result->setErrors(implode($this->_errors, '; '));
830: } else {
831: if ($xml !== false) {
832: if ($r->getDestCountryId() == self::USA_COUNTRY_ID) {
833: $shippingLabelContent = base64_decode((string)$xml->Shipment->Label->Image);
834: $trackingNumber = (string)$xml->Shipment->ShipmentDetail->AirbillNbr;
835: } else {
836: $shippingLabelContent = base64_decode((string)$xml->IntlShipment->Label->Image);
837: $trackingNumber = (string)$xml->IntlShipment->ShipmentDetail->AirbillNbr;
838: }
839: }
840: $result->setShippingLabelContent($shippingLabelContent);
841: $result->setTrackingNumber($trackingNumber);
842: }
843: return $result;
844: } else {
845: $result = Mage::getModel('shipping/rate_result');
846: if ($this->_dhlRates) {
847: foreach ($this->_dhlRates as $rate) {
848: $method = $rate['service'];
849: $data = $rate['data'];
850: $rate = Mage::getModel('shipping/rate_result_method');
851: $rate->setCarrier('dhl');
852: $rate->setCarrierTitle($this->getConfigData('title'));
853: $rate->setMethod($method);
854: $rate->setMethodTitle($data['term']);
855: $rate->setCost($data['price_total']);
856: $rate->setPrice($data['price_total']);
857: $result->append($rate);
858: }
859: } else if (!empty($this->_errors)) {
860: $error = Mage::getModel('shipping/rate_result_error');
861: $error->setCarrier('dhl');
862: $error->setCarrierTitle($this->getConfigData('title'));
863: $error->setErrorMessage($this->getConfigData('specificerrmsg'));
864: $result->append($error);
865: }
866: return $result;
867: }
868: }
869:
870: 871: 872: 873: 874: 875:
876: protected function _parseXmlObject($shipXml)
877: {
878: if (
879: is_object($shipXml->Faults)
880: && is_object($shipXml->Faults->Fault)
881: && is_object($shipXml->Faults->Fault->Desc)
882: && intval($shipXml->Faults->Fault->Code) != self::SUCCESS_CODE
883: && intval($shipXml->Faults->Fault->Code) != self::SUCCESS_LABEL_CODE
884: ) {
885: $code = (string)$shipXml->Faults->Fault->Code;
886: $description = $shipXml->Faults->Fault->Desc;
887: $this->_errors[$code] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
888: } elseif (
889: is_object($shipXml->Faults)
890: && is_object($shipXml->Result->Code)
891: && is_object($shipXml->Result->Desc)
892: && intval($shipXml->Result->Code) != self::SUCCESS_CODE
893: && intval($shipXml->Result->Code) != self::SUCCESS_LABEL_CODE
894: ) {
895: $code = (string)$shipXml->Result->Code;
896: $description = $shipXml->Result->Desc;
897: $this->_errors[$code] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
898: } else {
899: $this->_addRate($shipXml);
900: }
901: return $this;
902: }
903:
904: 905: 906: 907: 908: 909: 910:
911: public function getCode($type, $code = '')
912: {
913: static $codes;
914: $codes = array(
915: 'service' => array(
916: 'IE' => Mage::helper('usa')->__('International Express'),
917: 'E SAT' => Mage::helper('usa')->__('Express Saturday'),
918: 'E 10:30AM' => Mage::helper('usa')->__('Express 10:30 AM'),
919: 'E' => Mage::helper('usa')->__('Express'),
920: 'N' => Mage::helper('usa')->__('Next Afternoon'),
921: 'S' => Mage::helper('usa')->__('Second Day Service'),
922: 'G' => Mage::helper('usa')->__('Ground'),
923: ),
924: 'shipment_type' => array(
925: 'L' => Mage::helper('usa')->__('Letter'),
926: 'P' => Mage::helper('usa')->__('Package'),
927: ),
928: 'international_searvice' => 'IE',
929: 'dutypayment_type' => array(
930: 'S' => Mage::helper('usa')->__('Sender'),
931: 'R' => Mage::helper('usa')->__('Receiver'),
932: '3' => Mage::helper('usa')->__('Third Party'),
933: ),
934:
935: 'special_express' => array(
936: 'E SAT' => 'SAT',
937: 'E 10:30AM' => '1030',
938: ),
939:
940: 'descr_to_service' => array(
941: 'E SAT' => 'Saturday',
942: 'E 10:30AM' => '10:30 A.M',
943: ),
944:
945: );
946:
947:
948: if (!isset($codes[$type])) {
949: return false;
950: } elseif ('' === $code) {
951: return $codes[$type];
952: }
953:
954: if (!isset($codes[$type][$code])) {
955: return false;
956: } else {
957: return $codes[$type][$code];
958: }
959: }
960:
961: 962: 963: 964: 965: 966:
967: protected function _addRate($shipXml)
968: {
969: $r = $this->_rawRequest;
970: $services = $this->getCode('service');
971: $regexps = $this->getCode('descr_to_service');
972: $desc = ($shipXml->EstimateDetail) ? (string)$shipXml->EstimateDetail->ServiceLevelCommitment->Desc : null;
973:
974: $totalEstimate = $shipXml->EstimateDetail
975: ? (string)$shipXml->EstimateDetail->RateEstimate->TotalChargeEstimate
976: : null;
977: 978: 979: 980:
981: if ($desc && $totalEstimate) {
982: $service = (string)$shipXml->EstimateDetail->Service->Code;
983: $description = (string)$shipXml->EstimateDetail->ServiceLevelCommitment->Desc;
984: if ($service == 'E') {
985: foreach ($regexps as $expService => $exp) {
986: if (preg_match('/' . preg_quote($exp, '/') . '/', $description)) {
987: $service = $expService;
988: }
989: }
990: }
991:
992: $data['term'] = (isset($services[$service]) ? $services[$service] : $desc);
993: $data['price_total'] = $this->getMethodPrice($totalEstimate, $service);
994: $this->_dhlRates[] = array('service' => $service, 'data' => $data);
995: }
996: }
997:
998: 999: 1000: 1001: 1002: 1003:
1004: public function getTracking($trackings)
1005: {
1006: $this->setTrackingReqeust();
1007:
1008: if (!is_array($trackings)) {
1009: $trackings = array($trackings);
1010: }
1011: $this->_getXMLTracking($trackings);
1012:
1013: return $this->_result;
1014: }
1015:
1016: 1017: 1018: 1019: 1020:
1021: protected function setTrackingReqeust()
1022: {
1023: $r = new Varien_Object();
1024:
1025: $id = $this->getConfigData('id');
1026: $r->setId($id);
1027:
1028: $password = $this->getConfigData('password');
1029: $r->setPassword($password);
1030:
1031: $this->_rawTrackRequest = $r;
1032: }
1033:
1034: 1035: 1036: 1037: 1038: 1039:
1040: protected function _getXMLTracking($trackings)
1041: {
1042: $r = $this->_rawTrackRequest;
1043:
1044: $xml = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><eCommerce/>');
1045: $xml->addAttribute('action', 'Request');
1046: $xml->addAttribute('version', '1.1');
1047:
1048: $requestor = $xml->addChild('Requestor');
1049: $requestor->addChild('ID', $r->getId());
1050: $requestor->addChild('Password', $r->getPassword());
1051:
1052: $track = $xml->addChild('Track');
1053: $track->addAttribute('action', 'Get');
1054: $track->addAttribute('version', '1.0');
1055:
1056: foreach ($trackings as $tracking) {
1057: $track->addChild('Shipment')->addChild('TrackingNbr', $tracking);
1058: }
1059: $request = $xml->asXML();
1060: $debugData = array('request' => $request);
1061: 1062: 1063: 1064:
1065: try {
1066: $url = $this->getConfigData('gateway_url');
1067: if (!$url) {
1068: $url = $this->_defaultGatewayUrl;
1069: }
1070: $ch = curl_init();
1071: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
1072: curl_setopt($ch, CURLOPT_URL, $url);
1073: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
1074: curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
1075: curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
1076: $responseBody = curl_exec($ch);
1077: $debugData['result'] = $responseBody;
1078: curl_close($ch);
1079: } catch (Exception $e) {
1080: $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
1081: $responseBody = '';
1082: }
1083: $this->_debug($debugData);
1084: $this->_parseXmlTrackingResponse($trackings, $responseBody);
1085: }
1086:
1087: 1088: 1089: 1090: 1091: 1092: 1093:
1094: protected function _parseXmlTrackingResponse($trackings, $response)
1095: {
1096: $errorTitle = Mage::helper('usa')->__('Unable to retrieve tracking');
1097: $resultArr = array();
1098: $errorArr = array();
1099: $trackingserror = array();
1100: $tracknum = '';
1101: if (strlen(trim($response)) > 0) {
1102: if (strpos(trim($response), '<?xml') === 0) {
1103: $xml = simplexml_load_string($response);
1104: if (is_object($xml)) {
1105: $trackxml = $xml->Track;
1106: if (
1107: is_object($xml->Faults)
1108: && is_object($xml->Faults->Fault)
1109: && is_object($xml->Faults->Fault->Code)
1110: && is_object($xml->Faults->Fault->Description)
1111: && is_object($xml->Faults->Fault->Context)
1112: ) {
1113: $code = (string)$xml->Faults->Fault->Code;
1114: $description = $xml->Faults->Fault->Description;
1115: $context = $xml->Faults->Fault->Context;
1116: $errorTitle = Mage::helper('usa')->__('Error #%s : %s (%s)', $code, $description, $context);
1117: } elseif (is_object($trackxml) && is_object($trackxml->Shipment)) {
1118: foreach ($trackxml->Shipment as $txml) {
1119: $rArr = array();
1120:
1121: if (is_object($txml)) {
1122: $tracknum = (string)$txml->TrackingNbr;
1123: if ($txml->Fault) {
1124: $code = (string)$txml->Fault->Code;
1125: $description = $txml->Fault->Description;
1126: $errorArr[$tracknum] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
1127: } elseif ($txml->Result) {
1128: $code = (int)$txml->Result->Code;
1129: if ($code === 0) {
1130: 1131: 1132:
1133: $rArr['service'] = (string)$txml->Service->Desc;
1134: if (isset($txml->Weight))
1135: $rArr['weight'] = (string)$txml->Weight . " lbs";
1136: if (isset($txml->Delivery)) {
1137: $rArr['deliverydate'] = (string)$txml->Delivery->Date;
1138: $rArr['deliverytime'] = (string)$txml->Delivery->Time . ':00';
1139: $rArr['status'] = Mage::helper('usa')->__('Delivered');
1140: if (isset($txml->Delivery->Location->Desc)) {
1141: $rArr['deliverylocation'] = (string)$txml->Delivery->Location->Desc;
1142: }
1143: } elseif (isset($txml->Pickup)) {
1144: $rArr['deliverydate'] = (string)$txml->Pickup->Date;
1145: $rArr['deliverytime'] = (string)$txml->Pickup->Time . ':00';
1146: $rArr['status'] = Mage::helper('usa')->__('Shipment picked up');
1147: } else {
1148: $rArr['status'] = (string)$txml->ShipmentType->Desc
1149: . Mage::helper('usa')->__(' was not delivered nor scanned');
1150: }
1151:
1152: $packageProgress = array();
1153: if (isset($txml->TrackingHistory) && isset($txml->TrackingHistory->Status)) {
1154:
1155: foreach ($txml->TrackingHistory->Status as $thistory) {
1156: $tempArr = array();
1157: $tempArr['activity'] = (string)$thistory->StatusDesc;
1158: $tempArr['deliverydate'] = (string)$thistory->Date;
1159: $tempArr['deliverytime'] = (string)$thistory->Time . ':00';
1160: $addArr = array();
1161: if (isset($thistory->Location->City)) {
1162: $addArr[] = (string)$thistory->Location->City;
1163: }
1164: if (isset($thistory->Location->State)) {
1165: $addArr[] = (string)$thistory->Location->State;
1166: }
1167: if (isset($thistory->Location->CountryCode)) {
1168: $addArr[] = (string)$thistory->Location->Country;
1169: }
1170: if ($addArr) {
1171: $tempArr['deliverylocation'] = implode(', ', $addArr);
1172: } elseif (isset($thistory['final_delivery'])
1173: && (string)$thistory['final_delivery'] === 'true'
1174: ) {
1175: 1176: 1177: 1178:
1179: $addArr = array();
1180: if (isset($txml->Receiver->City)) {
1181: $addArr[] = (string)$txml->Receiver->City;
1182: }
1183: if (isset($thistory->Receiver->State)) {
1184: $addArr[] = (string)$txml->Receiver->State;
1185: }
1186: if (isset($thistory->Receiver->CountryCode)) {
1187: $addArr[] = (string)$txml->Receiver->Country;
1188: }
1189: $tempArr['deliverylocation'] = implode(', ', $addArr);
1190: }
1191: $packageProgress[] = $tempArr;
1192: }
1193: $rArr['progressdetail'] = $packageProgress;
1194:
1195: }
1196: $resultArr[$tracknum] = $rArr;
1197: } else {
1198: $description = (string)$txml->Result->Desc;
1199: if ($description)
1200: $errorArr[$tracknum] = Mage::helper('usa')->__('Error #%s: %s', $code, $description);
1201: else
1202: $errorArr[$tracknum] = Mage::helper('usa')->__('Unable to retrieve tracking');
1203: }
1204: } else {
1205: $errorArr[$tracknum] = Mage::helper('usa')->__('Unable to retrieve tracking');
1206: }
1207:
1208: }
1209: }
1210:
1211: }
1212: }
1213: } else {
1214: $errorTitle = Mage::helper('usa')->__('Response is in the wrong format');
1215: }
1216: }
1217:
1218: $result = Mage::getModel('shipping/tracking_result');
1219: if ($errorArr || $resultArr) {
1220: foreach ($errorArr as $t => $r) {
1221: $error = Mage::getModel('shipping/tracking_result_error');
1222: $error->setCarrier('dhl');
1223: $error->setCarrierTitle($this->getConfigData('title'));
1224: $error->setTracking($t);
1225: $error->setErrorMessage($r);
1226: $result->append($error);
1227: }
1228:
1229: foreach ($resultArr as $t => $data) {
1230: $tracking = Mage::getModel('shipping/tracking_result_status');
1231: $tracking->setCarrier('dhl');
1232: $tracking->setCarrierTitle($this->getConfigData('title'));
1233: $tracking->setTracking($t);
1234: $tracking->addData($data);
1235:
1236: $result->append($tracking);
1237: }
1238: } else {
1239: foreach ($trackings as $t) {
1240: $error = Mage::getModel('shipping/tracking_result_error');
1241: $error->setCarrier('dhl');
1242: $error->setCarrierTitle($this->getConfigData('title'));
1243: $error->setTracking($t);
1244: $error->setErrorMessage($errorTitle);
1245: $result->append($error);
1246:
1247: }
1248: }
1249: $this->_result = $result;
1250: }
1251:
1252: 1253: 1254: 1255: 1256:
1257: public function getResponse()
1258: {
1259: $statuses = '';
1260: if ($this->_result instanceof Mage_Shipping_Model_Tracking_Result) {
1261: if ($trackings = $this->_result->getAllTrackings()) {
1262: foreach ($trackings as $tracking) {
1263: if ($data = $tracking->getAllData()) {
1264: if (isset($data['status'])) {
1265: $statuses .= Mage::helper('usa')->__($data['status']) . "\n<br/>";
1266: } else {
1267: $statuses .= Mage::helper('usa')->__($data['error_message']) . "\n<br/>";
1268: }
1269: }
1270: }
1271: }
1272: }
1273: if (empty($statuses)) {
1274: $statuses = Mage::helper('usa')->__('Empty response');
1275: }
1276: return $statuses;
1277: }
1278:
1279: 1280: 1281: 1282: 1283:
1284: public function getAllowedMethods()
1285: {
1286: $allowed = explode(',', $this->getConfigData('allowed_methods'));
1287: $arr = array();
1288: foreach ($allowed as $k) {
1289: $arr[$k] = $this->getCode('service', $k);
1290: }
1291: return $arr;
1292: }
1293:
1294: 1295: 1296: 1297: 1298:
1299: public function isStateProvinceRequired()
1300: {
1301: return true;
1302: }
1303:
1304: 1305: 1306: 1307: 1308:
1309: public function getAdditionalProtectionValueTypes()
1310: {
1311: return array(
1312: self::ADDITIONAL_PROTECTION_VALUE_CONFIG => Mage::helper('usa')->__('Configuration'),
1313: self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL => Mage::helper('usa')->__('Subtotal'),
1314: self::ADDITIONAL_PROTECTION_VALUE_SUBTOTAL_WITH_DISCOUNT => Mage::helper('usa')->__('Subtotal With Discount'),
1315: );
1316: }
1317:
1318: 1319: 1320: 1321: 1322:
1323: public function getAdditionalProtectionRoundingTypes()
1324: {
1325: return array(
1326: self::ADDITIONAL_PROTECTION_ROUNDING_FLOOR => Mage::helper('usa')->__('To Lower'),
1327: self::ADDITIONAL_PROTECTION_ROUNDING_CEIL => Mage::helper('usa')->__('To Upper'),
1328: self::ADDITIONAL_PROTECTION_ROUNDING_ROUND => Mage::helper('usa')->__('Round'),
1329: );
1330: }
1331:
1332: 1333: 1334: 1335: 1336: 1337:
1338: protected function _mapRequestToShipment(Varien_Object $request)
1339: {
1340: $customsValue = $request->getPackageParams()->getCustomsValue();
1341: $request->setOrigPersonName($request->getShipperContactPersonName());
1342: $request->setOrigPostal($request->getShipperAddressPostalCode());
1343: $request->setOrigPhoneNumber($request->getShipperContactPhoneNumber());
1344: $request->setOrigCompanyName($request->getShipperContactCompanyName());
1345: $request->setOrigCountryId($request->getShipperAddressCountryCode());
1346: $request->setOrigState($request->getShipperAddressStateOrProvinceCode());
1347: $request->setOrigCity($request->getShipperAddressCity());
1348: $request->setOrigStreet($request->getShipperAddressStreet1() . ' ' . $request->getShipperAddressStreet2());
1349: $request->setOrigStreetLine2($request->getShipperAddressStreet2());
1350:
1351: $request->setDestPersonName($request->getRecipientContactPersonName());
1352: $request->setDestPostcode($request->getRecipientAddressPostalCode());
1353: $request->setDestPhoneNumber($request->getRecipientContactPhoneNumber());
1354: $request->setDestCompanyName($request->getRecipientContactCompanyName());
1355: $request->setDestCountryId($request->getRecipientAddressCountryCode());
1356: $request->setDestRegionCode($request->getRecipientAddressStateOrProvinceCode());
1357: $request->setDestCity($request->getRecipientAddressCity());
1358: $request->setDestStreet($request->getRecipientAddressStreet1());
1359: $request->setDestStreetLine2($request->getRecipientAddressStreet2());
1360:
1361: $request->setLimitMethod($request->getShippingMethod());
1362: $request->setPackageValue($customsValue);
1363: $request->setValueWithDiscount($customsValue);
1364: $request->setPackageCustomsValue($customsValue);
1365: $request->setFreeMethodWeight(0);
1366: $request->setDhlShipmentType($request->getPackagingType());
1367:
1368: $request->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
1369: }
1370:
1371: 1372: 1373: 1374: 1375: 1376:
1377: protected function _doShipmentRequest(Varien_Object $request)
1378: {
1379: $this->_prepareShipmentRequest($request);
1380: $request->setAction('GenerateLabel');
1381: $this->_mapRequestToShipment($request);
1382: $this->setRequest($request);
1383:
1384: return $this->_doRequest();
1385: }
1386:
1387: 1388: 1389: 1390: 1391: 1392:
1393: public function getContainerTypes(Varien_Object $params = null)
1394: {
1395: return $this->getCode('shipment_type');
1396: }
1397: }
1398: