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: class Mage_Usa_Model_Shipping_Carrier_Fedex
35: extends Mage_Usa_Model_Shipping_Carrier_Abstract
36: implements Mage_Shipping_Model_Carrier_Interface
37: {
38:
39: 40: 41: 42: 43:
44: const CODE = 'fedex';
45:
46: 47: 48: 49: 50:
51: const RATE_REQUEST_GENERAL = 'general';
52:
53: 54: 55: 56: 57:
58: const RATE_REQUEST_SMARTPOST = 'SMART_POST';
59:
60: 61: 62: 63: 64:
65: protected $_code = self::CODE;
66:
67: 68: 69: 70: 71:
72: protected $_request = null;
73:
74: 75: 76: 77: 78:
79: protected $_rawRequest = null;
80:
81: 82: 83: 84: 85:
86: protected $_result = null;
87:
88: 89: 90: 91: 92:
93: protected $_rateServiceWsdl;
94:
95: 96: 97: 98: 99:
100: protected $_shipServiceWsdl = null;
101:
102: 103: 104: 105: 106:
107: protected $_trackServiceWsdl = null;
108:
109: 110: 111: 112: 113:
114: protected $_customizableContainerTypes = array('YOUR_PACKAGING');
115:
116: public function __construct()
117: {
118: parent::__construct();
119: $wsdlBasePath = Mage::getModuleDir('etc', 'Mage_Usa') . DS . 'wsdl' . DS . 'FedEx' . DS;
120: $this->_shipServiceWsdl = $wsdlBasePath . 'ShipService_v10.wsdl';
121: $this->_rateServiceWsdl = $wsdlBasePath . 'RateService_v10.wsdl';
122: $this->_trackServiceWsdl = $wsdlBasePath . 'TrackService_v5.wsdl';
123: }
124:
125: 126: 127: 128: 129: 130: 131:
132: protected function _createSoapClient($wsdl, $trace = false)
133: {
134: $client = new SoapClient($wsdl, array('trace' => $trace));
135: $client->__setLocation($this->getConfigFlag('sandbox_mode')
136: ? 'https://wsbeta.fedex.com:443/web-services/rate'
137: : 'https://ws.fedex.com:443/web-services/rate'
138: );
139:
140: return $client;
141: }
142:
143: 144: 145: 146: 147:
148: protected function _createRateSoapClient()
149: {
150: return $this->_createSoapClient($this->_rateServiceWsdl);
151: }
152:
153: 154: 155: 156: 157:
158: protected function _createShipSoapClient()
159: {
160: return $this->_createSoapClient($this->_shipServiceWsdl, 1);
161: }
162:
163: 164: 165: 166: 167:
168: protected function _createTrackSoapClient()
169: {
170: return $this->_createSoapClient($this->_trackServiceWsdl, 1);
171: }
172:
173: 174: 175: 176: 177: 178:
179: public function collectRates(Mage_Shipping_Model_Rate_Request $request)
180: {
181: if (!$this->getConfigFlag($this->_activeFlag)) {
182: return false;
183: }
184: $this->setRequest($request);
185:
186: $this->_getQuotes();
187:
188: $this->_updateFreeMethodQuote($request);
189:
190: return $this->getResult();
191: }
192:
193: 194: 195: 196: 197: 198:
199: public function setRequest(Mage_Shipping_Model_Rate_Request $request)
200: {
201: $this->_request = $request;
202:
203: $r = new Varien_Object();
204:
205: if ($request->getLimitMethod()) {
206: $r->setService($request->getLimitMethod());
207: }
208:
209: if ($request->getFedexAccount()) {
210: $account = $request->getFedexAccount();
211: } else {
212: $account = $this->getConfigData('account');
213: }
214: $r->setAccount($account);
215:
216: if ($request->getFedexDropoff()) {
217: $dropoff = $request->getFedexDropoff();
218: } else {
219: $dropoff = $this->getConfigData('dropoff');
220: }
221: $r->setDropoffType($dropoff);
222:
223: if ($request->getFedexPackaging()) {
224: $packaging = $request->getFedexPackaging();
225: } else {
226: $packaging = $this->getConfigData('packaging');
227: }
228: $r->setPackaging($packaging);
229:
230: if ($request->getOrigCountry()) {
231: $origCountry = $request->getOrigCountry();
232: } else {
233: $origCountry = Mage::getStoreConfig(
234: Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
235: $request->getStoreId()
236: );
237: }
238: $r->setOrigCountry(Mage::getModel('directory/country')->load($origCountry)->getIso2Code());
239:
240: if ($request->getOrigPostcode()) {
241: $r->setOrigPostal($request->getOrigPostcode());
242: } else {
243: $r->setOrigPostal(Mage::getStoreConfig(
244: Mage_Shipping_Model_Shipping::XML_PATH_STORE_ZIP,
245: $request->getStoreId()
246: ));
247: }
248:
249: if ($request->getDestCountryId()) {
250: $destCountry = $request->getDestCountryId();
251: } else {
252: $destCountry = self::USA_COUNTRY_ID;
253: }
254: $r->setDestCountry(Mage::getModel('directory/country')->load($destCountry)->getIso2Code());
255:
256: if ($request->getDestPostcode()) {
257: $r->setDestPostal($request->getDestPostcode());
258: } else {
259:
260: }
261:
262: $weight = $this->getTotalNumOfBoxes($request->getPackageWeight());
263: $r->setWeight($weight);
264: if ($request->getFreeMethodWeight()!= $request->getPackageWeight()) {
265: $r->setFreeMethodWeight($request->getFreeMethodWeight());
266: }
267:
268: $r->setValue($request->getPackagePhysicalValue());
269: $r->setValueWithDiscount($request->getPackageValueWithDiscount());
270:
271: $r->setMeterNumber($this->getConfigData('meter_number'));
272: $r->setKey($this->getConfigData('key'));
273: $r->setPassword($this->getConfigData('password'));
274:
275: $r->setIsReturn($request->getIsReturn());
276:
277: $r->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
278:
279: $this->_rawRequest = $r;
280:
281: return $this;
282: }
283:
284: 285: 286: 287: 288:
289: public function getResult()
290: {
291: return $this->_result;
292: }
293:
294: 295: 296: 297: 298:
299: public function getVersionInfo()
300: {
301: return array(
302: 'ServiceId' => 'crs',
303: 'Major' => '10',
304: 'Intermediate' => '0',
305: 'Minor' => '0'
306: );
307: }
308:
309: 310: 311: 312: 313: 314:
315: protected function _formRateRequest($purpose)
316: {
317: $r = $this->_rawRequest;
318: $ratesRequest = array(
319: 'WebAuthenticationDetail' => array(
320: 'UserCredential' => array(
321: 'Key' => $r->getKey(),
322: 'Password' => $r->getPassword()
323: )
324: ),
325: 'ClientDetail' => array(
326: 'AccountNumber' => $r->getAccount(),
327: 'MeterNumber' => $r->getMeterNumber()
328: ),
329: 'Version' => $this->getVersionInfo(),
330: 'RequestedShipment' => array(
331: 'DropoffType' => $r->getDropoffType(),
332: 'ShipTimestamp' => date('c'),
333: 'PackagingType' => $r->getPackaging(),
334: 'TotalInsuredValue' => array(
335: 'Amount' => $r->getValue(),
336: 'Currency' => $this->getCurrencyCode()
337: ),
338: 'Shipper' => array(
339: 'Address' => array(
340: 'PostalCode' => $r->getOrigPostal(),
341: 'CountryCode' => $r->getOrigCountry()
342: )
343: ),
344: 'Recipient' => array(
345: 'Address' => array(
346: 'PostalCode' => $r->getDestPostal(),
347: 'CountryCode' => $r->getDestCountry(),
348: 'Residential' => (bool)$this->getConfigData('residence_delivery')
349: )
350: ),
351: 'ShippingChargesPayment' => array(
352: 'PaymentType' => 'SENDER',
353: 'Payor' => array(
354: 'AccountNumber' => $r->getAccount(),
355: 'CountryCode' => $r->getOrigCountry()
356: )
357: ),
358: 'CustomsClearanceDetail' => array(
359: 'CustomsValue' => array(
360: 'Amount' => $r->getValue(),
361: 'Currency' => $this->getCurrencyCode()
362: )
363: ),
364: 'RateRequestTypes' => 'LIST',
365: 'PackageCount' => '1',
366: 'PackageDetail' => 'INDIVIDUAL_PACKAGES',
367: 'RequestedPackageLineItems' => array(
368: '0' => array(
369: 'Weight' => array(
370: 'Value' => (float)$r->getWeight(),
371: 'Units' => 'LB'
372: ),
373: 'GroupPackageCount' => 1,
374: )
375: )
376: )
377: );
378:
379: if ($purpose == self::RATE_REQUEST_GENERAL) {
380: $ratesRequest['RequestedShipment']['RequestedPackageLineItems'][0]['InsuredValue'] = array(
381: 'Amount' => $r->getValue(),
382: 'Currency' => $this->getCurrencyCode()
383: );
384: } else if ($purpose == self::RATE_REQUEST_SMARTPOST) {
385: $ratesRequest['RequestedShipment']['ServiceType'] = self::RATE_REQUEST_SMARTPOST;
386: $ratesRequest['RequestedShipment']['SmartPostDetail'] = array(
387: 'Indicia' => ((float)$r->getWeight() >= 1) ? 'PARCEL_SELECT' : 'PRESORTED_STANDARD',
388: 'HubId' => $this->getConfigData('smartpost_hubid')
389: );
390: }
391:
392: return $ratesRequest;
393: }
394:
395: 396: 397: 398: 399: 400:
401: protected function _doRatesRequest($purpose)
402: {
403: $ratesRequest = $this->_formRateRequest($purpose);
404: $requestString = serialize($ratesRequest);
405: $response = $this->_getCachedQuotes($requestString);
406: $debugData = array('request' => $ratesRequest);
407: if ($response === null) {
408: try {
409: $client = $this->_createRateSoapClient();
410: $response = $client->getRates($ratesRequest);
411: $this->_setCachedQuotes($requestString, serialize($response));
412: $debugData['result'] = $response;
413: } catch (Exception $e) {
414: $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
415: Mage::logException($e);
416: }
417: } else {
418: $response = unserialize($response);
419: $debugData['result'] = $response;
420: }
421: $this->_debug($debugData);
422: return $response;
423: }
424:
425: 426: 427: 428: 429:
430: protected function _getQuotes()
431: {
432: $this->_result = Mage::getModel('shipping/rate_result');
433:
434: $allowedMethods = explode(',', $this->getConfigData('allowed_methods'));
435: if (in_array(self::RATE_REQUEST_SMARTPOST, $allowedMethods)) {
436: $response = $this->_doRatesRequest(self::RATE_REQUEST_SMARTPOST);
437: $preparedSmartpost = $this->_prepareRateResponse($response);
438: if (!$preparedSmartpost->getError()) {
439: $this->_result->append($preparedSmartpost);
440: }
441: }
442:
443: $response = $this->_doRatesRequest(self::RATE_REQUEST_GENERAL);
444: $preparedGeneral = $this->_prepareRateResponse($response);
445: if (!$preparedGeneral->getError() || ($this->_result->getError() && $preparedGeneral->getError())) {
446: $this->_result->append($preparedGeneral);
447: }
448: return $this->_result;
449: }
450:
451: 452: 453: 454: 455: 456:
457: protected function _prepareRateResponse($response)
458: {
459: $costArr = array();
460: $priceArr = array();
461: $errorTitle = 'Unable to retrieve tracking';
462:
463: if (is_object($response)) {
464: if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') {
465: $errorTitle = (string)$response->Notifications->Message;
466: } elseif (isset($response->RateReplyDetails)) {
467: $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
468:
469: if (is_array($response->RateReplyDetails)) {
470: foreach ($response->RateReplyDetails as $rate) {
471: $serviceName = (string)$rate->ServiceType;
472: if (in_array($serviceName, $allowedMethods)) {
473: $amount = $this->_getRateAmountOriginBased($rate);
474: $costArr[$serviceName] = $amount;
475: $priceArr[$serviceName] = $this->getMethodPrice($amount, $serviceName);
476: }
477: }
478: asort($priceArr);
479: } else {
480: $rate = $response->RateReplyDetails;
481: $serviceName = (string)$rate->ServiceType;
482: if (in_array($serviceName, $allowedMethods)) {
483: $amount = $this->_getRateAmountOriginBased($rate);
484: $costArr[$serviceName] = $amount;
485: $priceArr[$serviceName] = $this->getMethodPrice($amount, $serviceName);
486: }
487: }
488: }
489: }
490:
491: $result = Mage::getModel('shipping/rate_result');
492: if (empty($priceArr)) {
493: $error = Mage::getModel('shipping/rate_result_error');
494: $error->setCarrier($this->_code);
495: $error->setCarrierTitle($this->getConfigData('title'));
496: $error->setErrorMessage($errorTitle);
497: $error->setErrorMessage($this->getConfigData('specificerrmsg'));
498: $result->append($error);
499: } else {
500: foreach ($priceArr as $method=>$price) {
501: $rate = Mage::getModel('shipping/rate_result_method');
502: $rate->setCarrier($this->_code);
503: $rate->setCarrierTitle($this->getConfigData('title'));
504: $rate->setMethod($method);
505: $rate->setMethodTitle($this->getCode('method', $method));
506: $rate->setCost($costArr[$method]);
507: $rate->setPrice($price);
508: $result->append($rate);
509: }
510: }
511: return $result;
512: }
513:
514: 515: 516: 517: 518: 519:
520: protected function _getRateAmountOriginBased($rate)
521: {
522: $amount = null;
523: $rateTypeAmounts = array();
524:
525: if (is_object($rate)) {
526:
527: foreach ($rate->RatedShipmentDetails as $ratedShipmentDetail) {
528: $netAmount = (string)$ratedShipmentDetail->ShipmentRateDetail->TotalNetCharge->Amount;
529: $rateType = (string)$ratedShipmentDetail->ShipmentRateDetail->RateType;
530: $rateTypeAmounts[$rateType] = $netAmount;
531: }
532:
533:
534: foreach (array('RATED_ACCOUNT_SHIPMENT', 'RATED_LIST_SHIPMENT', 'RATED_LIST_PACKAGE') as $rateType) {
535: if (!empty($rateTypeAmounts[$rateType])) {
536: $amount = $rateTypeAmounts[$rateType];
537: break;
538: }
539: }
540:
541: if (is_null($amount)) {
542: $amount = (string)$rate->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Amount;
543: }
544: }
545:
546: return $amount;
547: }
548:
549: 550: 551: 552: 553: 554:
555: protected function _setFreeMethodRequest($freeMethod)
556: {
557: $r = $this->_rawRequest;
558: $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight());
559: $r->setWeight($weight);
560: $r->setService($freeMethod);
561: }
562:
563: 564: 565: 566: 567:
568: protected function _getXmlQuotes()
569: {
570: $r = $this->_rawRequest;
571: $xml = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><FDXRateAvailableServicesRequest/>');
572:
573: $xml->addAttribute('xmlns:api', 'http://www.fedex.com/fsmapi');
574: $xml->addAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
575: $xml->addAttribute('xsi:noNamespaceSchemaLocation', 'FDXRateAvailableServicesRequest.xsd');
576:
577: $requestHeader = $xml->addChild('RequestHeader');
578: $requestHeader->addChild('AccountNumber', $r->getAccount());
579: $requestHeader->addChild('MeterNumber', '0');
580:
581: $xml->addChild('ShipDate', date('Y-m-d'));
582: $xml->addChild('DropoffType', $r->getDropoffType());
583: if ($r->hasService()) {
584: $xml->addChild('Service', $r->getService());
585: }
586: $xml->addChild('Packaging', $r->getPackaging());
587: $xml->addChild('WeightUnits', 'LBS');
588: $xml->addChild('Weight', $r->getWeight());
589:
590: $originAddress = $xml->addChild('OriginAddress');
591: $originAddress->addChild('PostalCode', $r->getOrigPostal());
592: $originAddress->addChild('CountryCode', $r->getOrigCountry());
593:
594: $destinationAddress = $xml->addChild('DestinationAddress');
595: $destinationAddress->addChild('PostalCode', $r->getDestPostal());
596: $destinationAddress->addChild('CountryCode', $r->getDestCountry());
597:
598: $payment = $xml->addChild('Payment');
599: $payment->addChild('PayorType', 'SENDER');
600:
601: $declaredValue = $xml->addChild('DeclaredValue');
602: $declaredValue->addChild('Value', $r->getValue());
603: $declaredValue->addChild('CurrencyCode', $this->getCurrencyCode());
604:
605: if ($this->getConfigData('residence_delivery')) {
606: $specialServices = $xml->addChild('SpecialServices');
607: $specialServices->addChild('ResidentialDelivery', 'true');
608: }
609:
610: $xml->addChild('PackageCount', '1');
611:
612: $request = $xml->asXML();
613:
614: $responseBody = $this->_getCachedQuotes($request);
615: if ($responseBody === null) {
616: $debugData = array('request' => $request);
617: try {
618: $url = $this->getConfigData('gateway_url');
619: if (!$url) {
620: $url = $this->_defaultGatewayUrl;
621: }
622: $ch = curl_init();
623: curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
624: curl_setopt($ch, CURLOPT_URL, $url);
625: curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
626: curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
627: curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
628: $responseBody = curl_exec($ch);
629: curl_close ($ch);
630:
631: $debugData['result'] = $responseBody;
632: $this->_setCachedQuotes($request, $responseBody);
633: }
634: catch (Exception $e) {
635: $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
636: $responseBody = '';
637: }
638: $this->_debug($debugData);
639: }
640: return $this->_parseXmlResponse($responseBody);
641: }
642:
643: 644: 645: 646: 647: 648:
649: protected function _parseXmlResponse($response)
650: {
651: $costArr = array();
652: $priceArr = array();
653:
654: if (strlen(trim($response))>0) {
655: if ($xml = $this->_parseXml($response)) {
656:
657: if (is_object($xml->Error) && is_object($xml->Error->Message)) {
658: $errorTitle = (string)$xml->Error->Message;
659: } elseif (is_object($xml->SoftError) && is_object($xml->SoftError->Message)) {
660: $errorTitle = (string)$xml->SoftError->Message;
661: } else {
662: $errorTitle = 'Unknown error';
663: }
664:
665: $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
666:
667: foreach ($xml->Entry as $entry) {
668: if (in_array((string)$entry->Service, $allowedMethods)) {
669: $costArr[(string)$entry->Service] =
670: (string)$entry->EstimatedCharges->DiscountedCharges->NetCharge;
671: $priceArr[(string)$entry->Service] = $this->getMethodPrice(
672: (string)$entry->EstimatedCharges->DiscountedCharges->NetCharge,
673: (string)$entry->Service
674: );
675: }
676: }
677:
678: asort($priceArr);
679:
680: } else {
681: $errorTitle = 'Response is in the wrong format.';
682: }
683: } else {
684: $errorTitle = 'Unable to retrieve tracking';
685: }
686:
687: $result = Mage::getModel('shipping/rate_result');
688: if (empty($priceArr)) {
689: $error = Mage::getModel('shipping/rate_result_error');
690: $error->setCarrier('fedex');
691: $error->setCarrierTitle($this->getConfigData('title'));
692: $error->setErrorMessage($this->getConfigData('specificerrmsg'));
693: $result->append($error);
694: } else {
695: foreach ($priceArr as $method=>$price) {
696: $rate = Mage::getModel('shipping/rate_result_method');
697: $rate->setCarrier('fedex');
698: $rate->setCarrierTitle($this->getConfigData('title'));
699: $rate->setMethod($method);
700: $rate->setMethodTitle($this->getCode('method', $method));
701: $rate->setCost($costArr[$method]);
702: $rate->setPrice($price);
703: $result->append($rate);
704: }
705: }
706: return $result;
707: }
708:
709: 710: 711: 712: 713: 714:
715: protected function _parseXml($xmlContent)
716: {
717: try {
718: try {
719: return simplexml_load_string($xmlContent);
720: } catch (Exception $e) {
721: throw new Exception(Mage::helper('usa')->__('Failed to parse xml document: %s', $xmlContent));
722: }
723: } catch (Exception $e) {
724: Mage::logException($e);
725: return false;
726: }
727: }
728:
729: 730: 731: 732: 733: 734: 735:
736: public function getCode($type, $code='')
737: {
738: $codes = array(
739: 'method' => array(
740: 'EUROPE_FIRST_INTERNATIONAL_PRIORITY' => Mage::helper('usa')->__('Europe First Priority'),
741: 'FEDEX_1_DAY_FREIGHT' => Mage::helper('usa')->__('1 Day Freight'),
742: 'FEDEX_2_DAY_FREIGHT' => Mage::helper('usa')->__('2 Day Freight'),
743: 'FEDEX_2_DAY' => Mage::helper('usa')->__('2 Day'),
744: 'FEDEX_2_DAY_AM' => Mage::helper('usa')->__('2 Day AM'),
745: 'FEDEX_3_DAY_FREIGHT' => Mage::helper('usa')->__('3 Day Freight'),
746: 'FEDEX_EXPRESS_SAVER' => Mage::helper('usa')->__('Express Saver'),
747: 'FEDEX_GROUND' => Mage::helper('usa')->__('Ground'),
748: 'FIRST_OVERNIGHT' => Mage::helper('usa')->__('First Overnight'),
749: 'GROUND_HOME_DELIVERY' => Mage::helper('usa')->__('Home Delivery'),
750: 'INTERNATIONAL_ECONOMY' => Mage::helper('usa')->__('International Economy'),
751: 'INTERNATIONAL_ECONOMY_FREIGHT' => Mage::helper('usa')->__('Intl Economy Freight'),
752: 'INTERNATIONAL_FIRST' => Mage::helper('usa')->__('International First'),
753: 'INTERNATIONAL_GROUND' => Mage::helper('usa')->__('International Ground'),
754: 'INTERNATIONAL_PRIORITY' => Mage::helper('usa')->__('International Priority'),
755: 'INTERNATIONAL_PRIORITY_FREIGHT' => Mage::helper('usa')->__('Intl Priority Freight'),
756: 'PRIORITY_OVERNIGHT' => Mage::helper('usa')->__('Priority Overnight'),
757: 'SMART_POST' => Mage::helper('usa')->__('Smart Post'),
758: 'STANDARD_OVERNIGHT' => Mage::helper('usa')->__('Standard Overnight'),
759: 'FEDEX_FREIGHT' => Mage::helper('usa')->__('Freight'),
760: 'FEDEX_NATIONAL_FREIGHT' => Mage::helper('usa')->__('National Freight'),
761: ),
762: 'dropoff' => array(
763: 'REGULAR_PICKUP' => Mage::helper('usa')->__('Regular Pickup'),
764: 'REQUEST_COURIER' => Mage::helper('usa')->__('Request Courier'),
765: 'DROP_BOX' => Mage::helper('usa')->__('Drop Box'),
766: 'BUSINESS_SERVICE_CENTER' => Mage::helper('usa')->__('Business Service Center'),
767: 'STATION' => Mage::helper('usa')->__('Station')
768: ),
769: 'packaging' => array(
770: 'FEDEX_ENVELOPE' => Mage::helper('usa')->__('FedEx Envelope'),
771: 'FEDEX_PAK' => Mage::helper('usa')->__('FedEx Pak'),
772: 'FEDEX_BOX' => Mage::helper('usa')->__('FedEx Box'),
773: 'FEDEX_TUBE' => Mage::helper('usa')->__('FedEx Tube'),
774: 'FEDEX_10KG_BOX' => Mage::helper('usa')->__('FedEx 10kg Box'),
775: 'FEDEX_25KG_BOX' => Mage::helper('usa')->__('FedEx 25kg Box'),
776: 'YOUR_PACKAGING' => Mage::helper('usa')->__('Your Packaging')
777: ),
778: 'containers_filter' => array(
779: array(
780: 'containers' => array('FEDEX_ENVELOPE', 'FEDEX_PAK'),
781: 'filters' => array(
782: 'within_us' => array(
783: 'method' => array(
784: 'FEDEX_EXPRESS_SAVER',
785: 'FEDEX_2_DAY',
786: 'FEDEX_2_DAY_AM',
787: 'STANDARD_OVERNIGHT',
788: 'PRIORITY_OVERNIGHT',
789: 'FIRST_OVERNIGHT',
790: )
791: ),
792: 'from_us' => array(
793: 'method' => array(
794: 'INTERNATIONAL_FIRST',
795: 'INTERNATIONAL_ECONOMY',
796: 'INTERNATIONAL_PRIORITY',
797: )
798: )
799: )
800: ),
801: array(
802: 'containers' => array('FEDEX_BOX', 'FEDEX_TUBE'),
803: 'filters' => array(
804: 'within_us' => array(
805: 'method' => array(
806: 'FEDEX_2_DAY',
807: 'FEDEX_2_DAY_AM',
808: 'STANDARD_OVERNIGHT',
809: 'PRIORITY_OVERNIGHT',
810: 'FIRST_OVERNIGHT',
811: 'FEDEX_FREIGHT',
812: 'FEDEX_1_DAY_FREIGHT',
813: 'FEDEX_2_DAY_FREIGHT',
814: 'FEDEX_3_DAY_FREIGHT',
815: 'FEDEX_NATIONAL_FREIGHT',
816: )
817: ),
818: 'from_us' => array(
819: 'method' => array(
820: 'INTERNATIONAL_FIRST',
821: 'INTERNATIONAL_ECONOMY',
822: 'INTERNATIONAL_PRIORITY',
823: )
824: )
825: )
826: ),
827: array(
828: 'containers' => array('FEDEX_10KG_BOX', 'FEDEX_25KG_BOX'),
829: 'filters' => array(
830: 'within_us' => array(),
831: 'from_us' => array('method' => array('INTERNATIONAL_PRIORITY'))
832: )
833: ),
834: array(
835: 'containers' => array('YOUR_PACKAGING'),
836: 'filters' => array(
837: 'within_us' => array(
838: 'method' =>array(
839: 'FEDEX_GROUND',
840: 'GROUND_HOME_DELIVERY',
841: 'SMART_POST',
842: 'FEDEX_EXPRESS_SAVER',
843: 'FEDEX_2_DAY',
844: 'FEDEX_2_DAY_AM',
845: 'STANDARD_OVERNIGHT',
846: 'PRIORITY_OVERNIGHT',
847: 'FIRST_OVERNIGHT',
848: 'FEDEX_FREIGHT',
849: 'FEDEX_1_DAY_FREIGHT',
850: 'FEDEX_2_DAY_FREIGHT',
851: 'FEDEX_3_DAY_FREIGHT',
852: 'FEDEX_NATIONAL_FREIGHT',
853: )
854: ),
855: 'from_us' => array(
856: 'method' =>array(
857: 'INTERNATIONAL_FIRST',
858: 'INTERNATIONAL_ECONOMY',
859: 'INTERNATIONAL_PRIORITY',
860: 'INTERNATIONAL_GROUND',
861: 'FEDEX_FREIGHT',
862: 'FEDEX_1_DAY_FREIGHT',
863: 'FEDEX_2_DAY_FREIGHT',
864: 'FEDEX_3_DAY_FREIGHT',
865: 'FEDEX_NATIONAL_FREIGHT',
866: 'INTERNATIONAL_ECONOMY_FREIGHT',
867: 'INTERNATIONAL_PRIORITY_FREIGHT',
868: )
869: )
870: )
871: )
872: ),
873:
874: 'delivery_confirmation_types' => array(
875: 'NO_SIGNATURE_REQUIRED' => Mage::helper('usa')->__('Not Required'),
876: 'ADULT' => Mage::helper('usa')->__('Adult'),
877: 'DIRECT' => Mage::helper('usa')->__('Direct'),
878: 'INDIRECT' => Mage::helper('usa')->__('Indirect'),
879: ),
880: );
881:
882: if (!isset($codes[$type])) {
883: return false;
884: } elseif ('' === $code) {
885: return $codes[$type];
886: }
887:
888: if (!isset($codes[$type][$code])) {
889: return false;
890: } else {
891: return $codes[$type][$code];
892: }
893: }
894:
895: 896: 897: 898: 899:
900: public function getCurrencyCode ()
901: {
902: $codes = array(
903: 'DOP' => 'RDD',
904: 'XCD' => 'ECD',
905: 'ARS' => 'ARN',
906: 'SGD' => 'SID',
907: 'KRW' => 'WON',
908: 'JMD' => 'JAD',
909: 'CHF' => 'SFR',
910: 'JPY' => 'JYE',
911: 'KWD' => 'KUD',
912: 'GBP' => 'UKL',
913: 'AED' => 'DHS',
914: 'MXN' => 'NMP',
915: 'UYU' => 'UYP',
916: 'CLP' => 'CHP',
917: 'TWD' => 'NTD',
918: );
919: $currencyCode = Mage::app()->getStore()->getBaseCurrencyCode();
920: return isset($codes[$currencyCode]) ? $codes[$currencyCode] : $currencyCode;
921: }
922:
923: 924: 925: 926: 927: 928:
929: public function getTracking($trackings)
930: {
931: $this->setTrackingReqeust();
932:
933: if (!is_array($trackings)) {
934: $trackings=array($trackings);
935: }
936:
937: foreach($trackings as $tracking){
938: $this->_getXMLTracking($tracking);
939: }
940:
941: return $this->_result;
942: }
943:
944: 945: 946: 947: 948:
949: protected function setTrackingReqeust()
950: {
951: $r = new Varien_Object();
952:
953: $account = $this->getConfigData('account');
954: $r->setAccount($account);
955:
956: $this->_rawTrackingRequest = $r;
957: }
958:
959: 960: 961: 962: 963: 964:
965: protected function _getXMLTracking($tracking)
966: {
967: $trackRequest = array(
968: 'WebAuthenticationDetail' => array(
969: 'UserCredential' => array(
970: 'Key' => $this->getConfigData('key'),
971: 'Password' => $this->getConfigData('password')
972: )
973: ),
974: 'ClientDetail' => array(
975: 'AccountNumber' => $this->getConfigData('account'),
976: 'MeterNumber' => $this->getConfigData('meter_number')
977: ),
978: 'Version' => array(
979: 'ServiceId' => 'trck',
980: 'Major' => '5',
981: 'Intermediate' => '0',
982: 'Minor' => '0'
983: ),
984: 'PackageIdentifier' => array(
985: 'Type' => 'TRACKING_NUMBER_OR_DOORTAG',
986: 'Value' => $tracking,
987: ),
988: 989: 990: 991:
992: 'IncludeDetailedScans' => 1,
993: );
994: $requestString = serialize($trackRequest);
995: $response = $this->_getCachedQuotes($requestString);
996: $debugData = array('request' => $trackRequest);
997: if ($response === null) {
998: try {
999: $client = $this->_createTrackSoapClient();
1000: $response = $client->track($trackRequest);
1001: $this->_setCachedQuotes($requestString, serialize($response));
1002: $debugData['result'] = $response;
1003: } catch (Exception $e) {
1004: $debugData['result'] = array('error' => $e->getMessage(), 'code' => $e->getCode());
1005: Mage::logException($e);
1006: }
1007: } else {
1008: $response = unserialize($response);
1009: $debugData['result'] = $response;
1010: }
1011: $this->_debug($debugData);
1012:
1013: $this->_parseTrackingResponse($tracking, $response);
1014: }
1015:
1016: 1017: 1018: 1019: 1020: 1021:
1022: protected function _parseTrackingResponse($trackingValue, $response)
1023: {
1024: if (is_object($response)) {
1025: if ($response->HighestSeverity == 'FAILURE' || $response->HighestSeverity == 'ERROR') {
1026: $errorTitle = (string)$response->Notifications->Message;
1027: } elseif (isset($response->TrackDetails)) {
1028: $trackInfo = $response->TrackDetails;
1029: $resultArray['status'] = (string)$trackInfo->StatusDescription;
1030: $resultArray['service'] = (string)$trackInfo->ServiceInfo;
1031: $timestamp = isset($trackInfo->EstimatedDeliveryTimestamp) ?
1032: $trackInfo->EstimatedDeliveryTimestamp : $trackInfo->ActualDeliveryTimestamp;
1033: $timestamp = strtotime((string)$timestamp);
1034: if ($timestamp) {
1035: $resultArray['deliverydate'] = date('Y-m-d', $timestamp);
1036: $resultArray['deliverytime'] = date('H:i:s', $timestamp);
1037: }
1038:
1039: $deliveryLocation = isset($trackInfo->EstimatedDeliveryAddress) ?
1040: $trackInfo->EstimatedDeliveryAddress : $trackInfo->ActualDeliveryAddress;
1041: $deliveryLocationArray = array();
1042: if (isset($deliveryLocation->City)) {
1043: $deliveryLocationArray[] = (string)$deliveryLocation->City;
1044: }
1045: if (isset($deliveryLocation->StateOrProvinceCode)) {
1046: $deliveryLocationArray[] = (string)$deliveryLocation->StateOrProvinceCode;
1047: }
1048: if (isset($deliveryLocation->CountryCode)) {
1049: $deliveryLocationArray[] = (string)$deliveryLocation->CountryCode;
1050: }
1051: if ($deliveryLocationArray) {
1052: $resultArray['deliverylocation'] = implode(', ', $deliveryLocationArray);
1053: }
1054:
1055: $resultArray['signedby'] = (string)$trackInfo->DeliverySignatureName;
1056: $resultArray['shippeddate'] = date('Y-m-d', (int)$trackInfo->ShipTimestamp);
1057: if (isset($trackInfo->PackageWeight) && isset($trackInfo->Units)) {
1058: $weight = (string)$trackInfo->PackageWeight;
1059: $unit = (string)$trackInfo->Units;
1060: $resultArray['weight'] = "{$weight} {$unit}";
1061: }
1062:
1063: $packageProgress = array();
1064: if (isset($trackInfo->Events)) {
1065: $events = $trackInfo->Events;
1066: if (isset($events->Address)) {
1067: $events = array($events);
1068: }
1069: foreach ($events as $event) {
1070: $tempArray = array();
1071: $tempArray['activity'] = (string)$event->EventDescription;
1072: $timestamp = strtotime((string)$event->Timestamp);
1073: if ($timestamp) {
1074: $tempArray['deliverydate'] = date('Y-m-d', $timestamp);
1075: $tempArray['deliverytime'] = date('H:i:s', $timestamp);
1076: }
1077: if (isset($event->Address)) {
1078: $addressArray = array();
1079: $address = $event->Address;
1080: if (isset($address->City)) {
1081: $addressArray[] = (string)$address->City;
1082: }
1083: if (isset($address->StateOrProvinceCode)) {
1084: $addressArray[] = (string)$address->StateOrProvinceCode;
1085: }
1086: if (isset($address->CountryCode)) {
1087: $addressArray[] = (string)$address->CountryCode;
1088: }
1089: if ($addressArray) {
1090: $tempArray['deliverylocation'] = implode(', ', $addressArray);
1091: }
1092: }
1093: $packageProgress[] = $tempArray;
1094: }
1095: }
1096:
1097: $resultArray['progressdetail'] = $packageProgress;
1098: }
1099: }
1100:
1101: if (!$this->_result) {
1102: $this->_result = Mage::getModel('shipping/tracking_result');
1103: }
1104:
1105: if (isset($resultArray)) {
1106: $tracking = Mage::getModel('shipping/tracking_result_status');
1107: $tracking->setCarrier('fedex');
1108: $tracking->setCarrierTitle($this->getConfigData('title'));
1109: $tracking->setTracking($trackingValue);
1110: $tracking->addData($resultArray);
1111: $this->_result->append($tracking);
1112: } else {
1113: $error = Mage::getModel('shipping/tracking_result_error');
1114: $error->setCarrier('fedex');
1115: $error->setCarrierTitle($this->getConfigData('title'));
1116: $error->setTracking($trackingValue);
1117: $error->setErrorMessage($errorTitle ? $errorTitle : Mage::helper('usa')->__('Unable to retrieve tracking'));
1118: $this->_result->append($error);
1119: }
1120: }
1121:
1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129:
1130: protected function _parseXmlTrackingResponse($trackingvalue, $response)
1131: {
1132: $resultArr=array();
1133: if (strlen(trim($response))>0) {
1134: if ($xml = $this->_parseXml($response)) {
1135:
1136: if (is_object($xml->Error) && is_object($xml->Error->Message)) {
1137: $errorTitle = (string)$xml->Error->Message;
1138: } elseif (is_object($xml->SoftError) && is_object($xml->SoftError->Message)) {
1139: $errorTitle = (string)$xml->SoftError->Message;
1140: }
1141:
1142: if (!isset($errorTitle)) {
1143: $resultArr['status'] = (string)$xml->Package->StatusDescription;
1144: $resultArr['service'] = (string)$xml->Package->Service;
1145: $resultArr['deliverydate'] = (string)$xml->Package->DeliveredDate;
1146: $resultArr['deliverytime'] = (string)$xml->Package->DeliveredTime;
1147: $resultArr['deliverylocation'] = (string)$xml->TrackProfile->DeliveredLocationDescription;
1148: $resultArr['signedby'] = (string)$xml->Package->SignedForBy;
1149: $resultArr['shippeddate'] = (string)$xml->Package->ShipDate;
1150: $weight = (string)$xml->Package->Weight;
1151: $unit = (string)$xml->Package->WeightUnits;
1152: $resultArr['weight'] = "{$weight} {$unit}";
1153:
1154: $packageProgress = array();
1155: if (isset($xml->Package->Event)) {
1156: foreach ($xml->Package->Event as $event) {
1157: $tempArr=array();
1158: $tempArr['activity'] = (string)$event->Description;
1159: $tempArr['deliverydate'] = (string)$event->Date;
1160: $tempArr['deliverytime'] = (string)$event->Time;
1161: $addArr=array();
1162: if (isset($event->Address->City)) {
1163: $addArr[] = (string)$event->Address->City;
1164: }
1165: if (isset($event->Address->StateProvinceCode)) {
1166: $addArr[] = (string)$event->Address->StateProvinceCode;
1167: }
1168: if (isset($event->Address->CountryCode)) {
1169: $addArr[] = (string)$event->Address->CountryCode;
1170: }
1171: if ($addArr) {
1172: $tempArr['deliverylocation']=implode(', ',$addArr);
1173: }
1174: $packageProgress[] = $tempArr;
1175: }
1176: }
1177:
1178: $resultArr['progressdetail'] = $packageProgress;
1179: }
1180: } else {
1181: $errorTitle = 'Response is in the wrong format';
1182: }
1183: } else {
1184: $errorTitle = false;
1185: }
1186:
1187: if (!$this->_result) {
1188: $this->_result = Mage::getModel('shipping/tracking_result');
1189: }
1190:
1191: if ($resultArr) {
1192: $tracking = Mage::getModel('shipping/tracking_result_status');
1193: $tracking->setCarrier('fedex');
1194: $tracking->setCarrierTitle($this->getConfigData('title'));
1195: $tracking->setTracking($trackingvalue);
1196: $tracking->addData($resultArr);
1197: $this->_result->append($tracking);
1198: } else {
1199: $error = Mage::getModel('shipping/tracking_result_error');
1200: $error->setCarrier('fedex');
1201: $error->setCarrierTitle($this->getConfigData('title'));
1202: $error->setTracking($trackingvalue);
1203: $error->setErrorMessage($errorTitle ? $errorTitle : Mage::helper('usa')->__('Unable to retrieve tracking'));
1204: $this->_result->append($error);
1205: }
1206: }
1207:
1208: 1209: 1210: 1211: 1212:
1213: public function getResponse()
1214: {
1215: $statuses = '';
1216: if ($this->_result instanceof Mage_Shipping_Model_Tracking_Result) {
1217: if ($trackings = $this->_result->getAllTrackings()) {
1218: foreach ($trackings as $tracking){
1219: if($data = $tracking->getAllData()){
1220: if (!empty($data['status'])) {
1221: $statuses .= Mage::helper('usa')->__($data['status']) . "\n<br/>";
1222: } else {
1223: $statuses .= Mage::helper('usa')->__('Empty response') . "\n<br/>";
1224: }
1225: }
1226: }
1227: }
1228: }
1229: if (empty($statuses)) {
1230: $statuses = Mage::helper('usa')->__('Empty response');
1231: }
1232: return $statuses;
1233: }
1234:
1235: 1236: 1237: 1238: 1239:
1240: public function getAllowedMethods()
1241: {
1242: $allowed = explode(',', $this->getConfigData('allowed_methods'));
1243: $arr = array();
1244: foreach ($allowed as $k) {
1245: $arr[$k] = $this->getCode('method', $k);
1246: }
1247: return $arr;
1248: }
1249:
1250: 1251: 1252: 1253: 1254:
1255: protected function _getAuthDetails()
1256: {
1257: return array(
1258: 'WebAuthenticationDetail' => array(
1259: 'UserCredential' => array(
1260: 'Key' => $this->getConfigData('key'),
1261: 'Password' => $this->getConfigData('password')
1262: )
1263: ),
1264: 'ClientDetail' => array(
1265: 'AccountNumber' => $this->getConfigData('account'),
1266: 'MeterNumber' => $this->getConfigData('meter_number')
1267: ),
1268: 'TransactionDetail' => array(
1269: 'CustomerTransactionId' => '*** Express Domestic Shipping Request v9 using PHP ***'
1270: ),
1271: 'Version' => array(
1272: 'ServiceId' => 'ship',
1273: 'Major' => '10',
1274: 'Intermediate' => '0',
1275: 'Minor' => '0'
1276: )
1277: );
1278: }
1279:
1280: 1281: 1282: 1283: 1284: 1285:
1286: protected function _formShipmentRequest(Varien_Object $request)
1287: {
1288: if ($request->getReferenceData()) {
1289: $referenceData = $request->getReferenceData() . $request->getPackageId();
1290: } else {
1291: $referenceData = 'Order #'
1292: . $request->getOrderShipment()->getOrder()->getIncrementId()
1293: . ' P'
1294: . $request->getPackageId();
1295: }
1296: $packageParams = $request->getPackageParams();
1297: $customsValue = $packageParams->getCustomsValue();
1298: $height = $packageParams->getHeight();
1299: $width = $packageParams->getWidth();
1300: $length = $packageParams->getLength();
1301: $weightUnits = $packageParams->getWeightUnits() == Zend_Measure_Weight::POUND ? 'LB' : 'KG';
1302: $dimensionsUnits = $packageParams->getDimensionUnits() == Zend_Measure_Length::INCH ? 'IN' : 'CM';
1303: $unitPrice = 0;
1304: $itemsQty = 0;
1305: $itemsDesc = array();
1306: $countriesOfManufacture = array();
1307: $productIds = array();
1308: $packageItems = $request->getPackageItems();
1309: foreach ($packageItems as $itemShipment) {
1310: $item = new Varien_Object();
1311: $item->setData($itemShipment);
1312:
1313: $unitPrice += $item->getPrice();
1314: $itemsQty += $item->getQty();
1315:
1316: $itemsDesc[] = $item->getName();
1317: $productIds[] = $item->getProductId();
1318: }
1319:
1320:
1321: $productCollection = Mage::getResourceModel('catalog/product_collection')
1322: ->addStoreFilter($request->getStoreId())
1323: ->addFieldToFilter('entity_id', array('in' => $productIds))
1324: ->addAttributeToSelect('country_of_manufacture');
1325: foreach ($productCollection as $product) {
1326: $countriesOfManufacture[] = $product->getCountryOfManufacture();
1327: }
1328:
1329: $paymentType = $request->getIsReturn() ? 'RECIPIENT' : 'SENDER';
1330: $requestClient = array(
1331: 'RequestedShipment' => array(
1332: 'ShipTimestamp' => time(),
1333: 'DropoffType' => $this->getConfigData('dropoff'),
1334: 'PackagingType' => $request->getPackagingType(),
1335: 'ServiceType' => $request->getShippingMethod(),
1336: 'Shipper' => array(
1337: 'Contact' => array(
1338: 'PersonName' => $request->getShipperContactPersonName(),
1339: 'CompanyName' => $request->getShipperContactCompanyName(),
1340: 'PhoneNumber' => $request->getShipperContactPhoneNumber()
1341: ),
1342: 'Address' => array(
1343: 'StreetLines' => array($request->getShipperAddressStreet()),
1344: 'City' => $request->getShipperAddressCity(),
1345: 'StateOrProvinceCode' => $request->getShipperAddressStateOrProvinceCode(),
1346: 'PostalCode' => $request->getShipperAddressPostalCode(),
1347: 'CountryCode' => $request->getShipperAddressCountryCode()
1348: )
1349: ),
1350: 'Recipient' => array(
1351: 'Contact' => array(
1352: 'PersonName' => $request->getRecipientContactPersonName(),
1353: 'CompanyName' => $request->getRecipientContactCompanyName(),
1354: 'PhoneNumber' => $request->getRecipientContactPhoneNumber()
1355: ),
1356: 'Address' => array(
1357: 'StreetLines' => array($request->getRecipientAddressStreet()),
1358: 'City' => $request->getRecipientAddressCity(),
1359: 'StateOrProvinceCode' => $request->getRecipientAddressStateOrProvinceCode(),
1360: 'PostalCode' => $request->getRecipientAddressPostalCode(),
1361: 'CountryCode' => $request->getRecipientAddressCountryCode(),
1362: 'Residential' => (bool)$this->getConfigData('residence_delivery')
1363: ),
1364: ),
1365: 'ShippingChargesPayment' => array(
1366: 'PaymentType' => $paymentType,
1367: 'Payor' => array(
1368: 'AccountNumber' => $this->getConfigData('account'),
1369: 'CountryCode' => Mage::getStoreConfig(
1370: Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
1371: $request->getStoreId()
1372: )
1373: )
1374: ),
1375: 'LabelSpecification' =>array(
1376: 'LabelFormatType' => 'COMMON2D',
1377: 'ImageType' => 'PNG',
1378: 'LabelStockType' => 'PAPER_8.5X11_TOP_HALF_LABEL',
1379: ),
1380: 'RateRequestTypes' => array('ACCOUNT'),
1381: 'PackageCount' => 1,
1382: 'RequestedPackageLineItems' => array(
1383: 'SequenceNumber' => '1',
1384: 'Weight' => array(
1385: 'Units' => $weightUnits,
1386: 'Value' => $request->getPackageWeight()
1387: ),
1388: 'CustomerReferences' => array(
1389: 'CustomerReferenceType' => 'CUSTOMER_REFERENCE',
1390: 'Value' => $referenceData
1391: ),
1392: 'SpecialServicesRequested' => array(
1393: 'SpecialServiceTypes' => 'SIGNATURE_OPTION',
1394: 'SignatureOptionDetail' => array('OptionType' => $packageParams->getDeliveryConfirmation())
1395: ),
1396: )
1397: )
1398: );
1399:
1400:
1401: if ($request->getShipperAddressCountryCode() != $request->getRecipientAddressCountryCode()) {
1402: $requestClient['RequestedShipment']['CustomsClearanceDetail'] =
1403: array(
1404: 'CustomsValue' =>
1405: array(
1406: 'Currency' => $request->getBaseCurrencyCode(),
1407: 'Amount' => $customsValue,
1408: ),
1409: 'DutiesPayment' => array(
1410: 'PaymentType' => $paymentType,
1411: 'Payor' => array(
1412: 'AccountNumber' => $this->getConfigData('account'),
1413: 'CountryCode' => Mage::getStoreConfig(
1414: Mage_Shipping_Model_Shipping::XML_PATH_STORE_COUNTRY_ID,
1415: $request->getStoreId()
1416: )
1417: )
1418: ),
1419: 'Commodities' => array(
1420: 'Weight' => array(
1421: 'Units' => $weightUnits,
1422: 'Value' => $request->getPackageWeight()
1423: ),
1424: 'NumberOfPieces' => 1,
1425: 'CountryOfManufacture' => implode(',', array_unique($countriesOfManufacture)),
1426: 'Description' => implode(', ', $itemsDesc),
1427: 'Quantity' => ceil($itemsQty),
1428: 'QuantityUnits' => 'pcs',
1429: 'UnitPrice' => array(
1430: 'Currency' => $request->getBaseCurrencyCode(),
1431: 'Amount' => $unitPrice
1432: ),
1433: 'CustomsValue' => array(
1434: 'Currency' => $request->getBaseCurrencyCode(),
1435: 'Amount' => $customsValue
1436: ),
1437: )
1438: );
1439: }
1440:
1441: if ($request->getMasterTrackingId()) {
1442: $requestClient['RequestedShipment']['MasterTrackingId'] = $request->getMasterTrackingId();
1443: }
1444:
1445:
1446: if ($length || $width || $height) {
1447: $requestClient['RequestedShipment']['RequestedPackageLineItems']['Dimensions'] = array();
1448: $dimenssions = &$requestClient['RequestedShipment']['RequestedPackageLineItems']['Dimensions'];
1449: $dimenssions['Length'] = $length;
1450: $dimenssions['Width'] = $width;
1451: $dimenssions['Height'] = $height;
1452: $dimenssions['Units'] = $dimensionsUnits;
1453: }
1454:
1455: return $this->_getAuthDetails() + $requestClient;
1456: }
1457:
1458: 1459: 1460: 1461: 1462: 1463:
1464: protected function _doShipmentRequest(Varien_Object $request)
1465: {
1466: $this->_prepareShipmentRequest($request);
1467: $result = new Varien_Object();
1468: $client = $this->_createShipSoapClient();
1469: $requestClient = $this->_formShipmentRequest($request);
1470: $response = $client->processShipment($requestClient);
1471:
1472: if ($response->HighestSeverity != 'FAILURE' && $response->HighestSeverity != 'ERROR') {
1473: $shippingLabelContent = $response->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image;
1474: $trackingNumber = $response->CompletedShipmentDetail->CompletedPackageDetails->TrackingIds->TrackingNumber;
1475: $result->setShippingLabelContent($shippingLabelContent);
1476: $result->setTrackingNumber($trackingNumber);
1477: $debugData = array('request' => $client->__getLastRequest(), 'result' => $client->__getLastResponse());
1478: $this->_debug($debugData);
1479: } else {
1480: $debugData = array(
1481: 'request' => $client->__getLastRequest(),
1482: 'result' => array(
1483: 'error' => '',
1484: 'code' => '',
1485: 'xml' => $client->__getLastResponse()
1486: )
1487: );
1488: if (is_array($response->Notifications)) {
1489: foreach ($response->Notifications as $notification) {
1490: $debugData['result']['code'] .= $notification->Code . '; ';
1491: $debugData['result']['error'] .= $notification->Message . '; ';
1492: }
1493: } else {
1494: $debugData['result']['code'] = $response->Notifications->Code . ' ';
1495: $debugData['result']['error'] = $response->Notifications->Message . ' ';
1496: }
1497: $this->_debug($debugData);
1498: $result->setErrors($debugData['result']['error']);
1499: }
1500: $result->setGatewayResponse($client->__getLastResponse());
1501:
1502: return $result;
1503: }
1504:
1505: 1506: 1507: 1508: 1509: 1510: 1511:
1512: public function rollBack($data)
1513: {
1514: $requestData = $this->_getAuthDetails();
1515: $requestData['DeletionControl'] = 'DELETE_ONE_PACKAGE';
1516: foreach ($data as &$item) {
1517: $requestData['TrackingId'] = $item['tracking_number'];
1518: $client = $this->_createShipSoapClient();
1519: $client->deleteShipment($requestData);
1520: }
1521: return true;
1522: }
1523:
1524: 1525: 1526: 1527: 1528: 1529:
1530: public function getContainerTypes(Varien_Object $params = null)
1531: {
1532: if ($params == null) {
1533: return $this->_getAllowedContainers($params);
1534: }
1535: $method = $params->getMethod();
1536: $countryShipper = $params->getCountryShipper();
1537: $countryRecipient = $params->getCountryRecipient();
1538:
1539: if (($countryShipper == self::USA_COUNTRY_ID && $countryRecipient == self::CANADA_COUNTRY_ID
1540: || $countryShipper == self::CANADA_COUNTRY_ID && $countryRecipient == self::USA_COUNTRY_ID)
1541: && $method == 'FEDEX_GROUND'
1542: ) {
1543: return array('YOUR_PACKAGING' => Mage::helper('usa')->__('Your Packaging'));
1544: } else if ($method == 'INTERNATIONAL_ECONOMY' || $method == 'INTERNATIONAL_FIRST') {
1545: $allTypes = $this->getContainerTypesAll();
1546: $exclude = array('FEDEX_10KG_BOX' => '', 'FEDEX_25KG_BOX' => '');
1547: return array_diff_key($allTypes, $exclude);
1548: } else if ($method == 'EUROPE_FIRST_INTERNATIONAL_PRIORITY') {
1549: $allTypes = $this->getContainerTypesAll();
1550: $exclude = array('FEDEX_BOX' => '', 'FEDEX_TUBE' => '');
1551: return array_diff_key($allTypes, $exclude);
1552: } else if ($countryShipper == self::CANADA_COUNTRY_ID && $countryRecipient == self::CANADA_COUNTRY_ID) {
1553:
1554: $params->setCountryShipper(self::USA_COUNTRY_ID);
1555: $params->setCountryRecipient(self::USA_COUNTRY_ID);
1556: }
1557:
1558: return $this->_getAllowedContainers($params);
1559: }
1560:
1561: 1562: 1563: 1564: 1565:
1566: public function getContainerTypesAll()
1567: {
1568: return $this->getCode('packaging');
1569: }
1570:
1571: 1572: 1573: 1574: 1575:
1576: public function getContainerTypesFilter()
1577: {
1578: return $this->getCode('containers_filter');
1579: }
1580:
1581: 1582: 1583: 1584: 1585: 1586:
1587: public function getDeliveryConfirmationTypes(Varien_Object $params = null)
1588: {
1589: return $this->getCode('delivery_confirmation_types');
1590: }
1591: }
1592: