00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 class Mage_Usa_Model_Shipping_Carrier_Usps
00037 extends Mage_Usa_Model_Shipping_Carrier_Abstract
00038 implements Mage_Shipping_Model_Carrier_Interface
00039 {
00040
00041 protected $_code = 'usps';
00042
00043 protected $_request = null;
00044
00045 protected $_result = null;
00046
00047 protected $_defaultGatewayUrl = 'http://production.shippingapis.com/ShippingAPI.dll';
00048
00049 public function collectRates(Mage_Shipping_Model_Rate_Request $request)
00050 {
00051 if (!$this->getConfigFlag('active')) {
00052 return false;
00053 }
00054
00055 $this->setRequest($request);
00056
00057 $this->_result = $this->_getQuotes();
00058
00059 $this->_updateFreeMethodQuote($request);
00060
00061 return $this->getResult();
00062 }
00063
00064 public function setRequest(Mage_Shipping_Model_Rate_Request $request)
00065 {
00066 $this->_request = $request;
00067
00068 $r = new Varien_Object();
00069
00070 if ($request->getLimitMethod()) {
00071 $r->setService($request->getLimitMethod());
00072 } else {
00073 $r->setService('ALL');
00074 }
00075
00076 if ($request->getUspsUserid()) {
00077 $userId = $request->getUspsUserid();
00078 } else {
00079 $userId = $this->getConfigData('userid');
00080 }
00081 $r->setUserId($userId);
00082
00083 if ($request->getUspsContainer()) {
00084 $container = $request->getUspsContainer();
00085 } else {
00086 $container = $this->getConfigData('container');
00087 }
00088 $r->setContainer($container);
00089
00090 if ($request->getUspsSize()) {
00091 $size = $request->getUspsSize();
00092 } else {
00093 $size = $this->getConfigData('size');
00094 }
00095 $r->setSize($size);
00096
00097 if ($request->getUspsMachinable()) {
00098 $machinable = $request->getUspsMachinable();
00099 } else {
00100 $machinable = $this->getConfigData('machinable');
00101 }
00102 $r->setMachinable($machinable);
00103
00104 if ($request->getOrigPostcode()) {
00105 $r->setOrigPostal($request->getOrigPostcode());
00106 } else {
00107 $r->setOrigPostal(Mage::getStoreConfig('shipping/origin/postcode'));
00108 }
00109
00110 if ($request->getDestCountryId()) {
00111 $destCountry = $request->getDestCountryId();
00112 } else {
00113 $destCountry = self::USA_COUNTRY_ID;
00114 }
00115
00116 $r->setDestCountryId($destCountry);
00117
00118
00119
00120
00121 if ($destCountry=='GB') {
00122 $countryName = 'Great Britain and Northern Ireland';
00123 } else {
00124 $countries = Mage::getResourceModel('directory/country_collection')
00125 ->addCountryIdFilter($destCountry)
00126 ->load()
00127 ->getItems();
00128 $country = array_shift($countries);
00129 $countryName = $country->getName();
00130 }
00131 $r->setDestCountryName($countryName);
00132
00133 if ($request->getDestPostcode()) {
00134 $r->setDestPostal($request->getDestPostcode());
00135 }
00136
00137 $weight = $this->getTotalNumOfBoxes($request->getPackageWeight());
00138 $r->setWeightPounds(floor($weight));
00139 $r->setWeightOunces(round(($weight-floor($weight))*16, 1));
00140 if ($request->getFreeMethodWeight()!=$request->getPackageWeight()) {
00141 $r->setFreeMethodWeight($request->getFreeMethodWeight());
00142 }
00143
00144 $r->setValue($request->getPackageValue());
00145 $r->setValueWithDiscount($request->getPackageValueWithDiscount());
00146
00147 $this->_rawRequest = $r;
00148
00149 return $this;
00150 }
00151
00152 public function getResult()
00153 {
00154 return $this->_result;
00155 }
00156
00157 protected function _getQuotes()
00158 {
00159 return $this->_getXmlQuotes();
00160 }
00161
00162 protected function _setFreeMethodRequest($freeMethod)
00163 {
00164 $r = $this->_rawRequest;
00165
00166 $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight());
00167 $r->setWeightPounds(floor($weight));
00168 $r->setWeightOunces(round(($weight-floor($weight))*16, 1));
00169 $r->setService($freeMethod);
00170 }
00171
00172 protected function _getXmlQuotes()
00173 {
00174 $r = $this->_rawRequest;
00175 if ($r->getDestCountryId() == self::USA_COUNTRY_ID || $r->getDestCountryId() == self::PUERTORICO_COUNTRY_ID) {
00176 $xml = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><RateV3Request/>');
00177
00178 $xml->addAttribute('USERID', $r->getUserId());
00179
00180 $package = $xml->addChild('Package');
00181 $package->addAttribute('ID', 0);
00182 $package->addChild('Service', $r->getService());
00183
00184
00185 if ($r->getService() == 'FIRST CLASS') {
00186 $package->addChild('FirstClassMailType', 'PARCEL');
00187 }
00188 $package->addChild('ZipOrigination', $r->getOrigPostal());
00189
00190 $package->addChild('ZipDestination', substr($r->getDestPostal(),0,5));
00191 $package->addChild('Pounds', $r->getWeightPounds());
00192 $package->addChild('Ounces', $r->getWeightOunces());
00193
00194
00195 $package->addChild('Container', $r->getContainer());
00196 $package->addChild('Size', $r->getSize());
00197 $package->addChild('Machinable', $r->getMachinable());
00198
00199 $api = 'RateV3';
00200 $request = $xml->asXML();
00201
00202 } else {
00203 $xml = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><IntlRateRequest/>');
00204
00205 $xml->addAttribute('USERID', $r->getUserId());
00206
00207 $package = $xml->addChild('Package');
00208 $package->addAttribute('ID', 0);
00209 $package->addChild('Pounds', $r->getWeightPounds());
00210 $package->addChild('Ounces', $r->getWeightOunces());
00211 $package->addChild('MailType', 'Package');
00212 $package->addChild('ValueOfContents', $r->getValue());
00213 $package->addChild('Country', $r->getDestCountryName());
00214
00215 $api = 'IntlRate';
00216 $request = $xml->asXML();
00217 }
00218
00219 try {
00220 $url = $this->getConfigData('gateway_url');
00221 if (!$url) {
00222 $url = $this->_defaultGatewayUrl;
00223 }
00224 $client = new Zend_Http_Client();
00225 $client->setUri($url);
00226 $client->setConfig(array('maxredirects'=>0, 'timeout'=>30));
00227 $client->setParameterGet('API', $api);
00228 $client->setParameterGet('XML', $request);
00229 $response = $client->request();
00230 $responseBody = $response->getBody();
00231 } catch (Exception $e) {
00232 $responseBody = '';
00233 }
00234
00235 return $this->_parseXmlResponse($responseBody);;
00236 }
00237
00238 protected function _parseXmlResponse($response)
00239 {
00240 $costArr = array();
00241 $priceArr = array();
00242 $errorTitle = 'Unable to retrieve quotes';
00243 if (strlen(trim($response))>0) {
00244 if (strpos(trim($response), '<?xml')===0) {
00245 if (preg_match('#<\?xml version="1.0"\?>#', $response)) {
00246 $response = str_replace('<?xml version="1.0"?>', '<?xml version="1.0" encoding="ISO-8859-1"?>', $response);
00247 }
00248
00249 $xml = simplexml_load_string($response);
00250 if (is_object($xml)) {
00251 if (is_object($xml->Number) && is_object($xml->Description) && (string)$xml->Description!='') {
00252 $errorTitle = (string)$xml->Description;
00253 } elseif (is_object($xml->Package) && is_object($xml->Package->Error) && is_object($xml->Package->Error->Description) && (string)$xml->Package->Error->Description!='') {
00254 $errorTitle = (string)$xml->Package->Error->Description;
00255 } else {
00256 $errorTitle = 'Unknown error';
00257 }
00258 $r = $this->_rawRequest;
00259 $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
00260 $allMethods = $this->getCode('method');
00261 $newMethod = false;
00262 if ($r->getDestCountryId() == self::USA_COUNTRY_ID || $r->getDestCountryId() == self::PUERTORICO_COUNTRY_ID) {
00263 if (is_object($xml->Package) && is_object($xml->Package->Postage)) {
00264 foreach ($xml->Package->Postage as $postage) {
00265
00266 if (in_array((string)$postage->MailService, $allowedMethods)) {
00267 $costArr[(string)$postage->MailService] = (string)$postage->Rate;
00268
00269 $priceArr[(string)$postage->MailService] = $this->getMethodPrice((string)$postage->Rate, (string)$postage->MailService);
00270 } elseif (!in_array((string)$postage->MailService, $allMethods)) {
00271 $allMethods[] = (string)$postage->MailService;
00272 $newMethod = true;
00273 }
00274 }
00275 asort($priceArr);
00276 }
00277 } else {
00278 if (is_object($xml->Package) && is_object($xml->Package->Service)) {
00279 foreach ($xml->Package->Service as $service) {
00280
00281 if (in_array((string)$service->SvcDescription, $allowedMethods)) {
00282 $costArr[(string)$service->SvcDescription] = (string)$service->Postage;
00283
00284 $priceArr[(string)$service->SvcDescription] = $this->getMethodPrice((string)$service->Postage, (string)$service->SvcDescription);
00285 } elseif (!in_array((string)$service->SvcDescription, $allMethods)) {
00286 $allMethods[] = (string)$service->SvcDescription;
00287 $newMethod = true;
00288 }
00289 }
00290 asort($priceArr);
00291 }
00292 }
00293
00294
00295
00296
00297 if (false && $newMethod) {
00298 sort($allMethods);
00299 $insert['usps']['fields']['methods']['value'] = $allMethods;
00300 Mage::getResourceModel('adminhtml/config')->saveSectionPost('carriers','','',$insert);
00301 }
00302 }
00303 } else {
00304 $errorTitle = 'Response is in the wrong format';
00305 }
00306 }
00307
00308 $result = Mage::getModel('shipping/rate_result');
00309 $defaults = $this->getDefaults();
00310 if (empty($priceArr)) {
00311 $error = Mage::getModel('shipping/rate_result_error');
00312 $error->setCarrier('usps');
00313 $error->setCarrierTitle($this->getConfigData('title'));
00314
00315 $error->setErrorMessage($this->getConfigData('specificerrmsg'));
00316 $result->append($error);
00317 } else {
00318 foreach ($priceArr as $method=>$price) {
00319 $rate = Mage::getModel('shipping/rate_result_method');
00320 $rate->setCarrier('usps');
00321 $rate->setCarrierTitle($this->getConfigData('title'));
00322 $rate->setMethod($method);
00323 $rate->setMethodTitle($method);
00324 $rate->setCost($costArr[$method]);
00325 $rate->setPrice($price);
00326 $result->append($rate);
00327 }
00328 }
00329 return $result;
00330 }
00331
00332 public function getCode($type, $code='')
00333 {
00334 $codes = array(
00335
00336 'service'=>array(
00337 'FIRST CLASS' => Mage::helper('usa')->__('First-Class'),
00338 'PRIORITY' => Mage::helper('usa')->__('Priority Mail'),
00339 'EXPRESS' => Mage::helper('usa')->__('Express Mail'),
00340 'BPM' => Mage::helper('usa')->__('Bound Printed Matter'),
00341 'PARCEL' => Mage::helper('usa')->__('Parcel Post'),
00342 'MEDIA' => Mage::helper('usa')->__('Media Mail'),
00343 'LIBRARY' => Mage::helper('usa')->__('Library'),
00344
00345 ),
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 'service_to_code'=>array(
00371 'First-Class' => 'FIRST CLASS',
00372 'Express Mail' => 'EXPRESS',
00373 'Express Mail PO to PO' => 'EXPRESS',
00374 'Priority Mail' => 'PRIORITY',
00375 'Parcel Post' => 'PARCEL',
00376 'Express Mail Flat-Rate Envelope' => 'EXPRESS',
00377 'Priority Mail Flat-Rate Box' => 'PRIORITY',
00378 'Bound Printed Matter' => 'BPM',
00379 'Media Mail' => 'MEDIA',
00380 'Library Mail' => 'LIBRARY',
00381 'Priority Mail Flat-Rate Envelope' => 'PRIORITY',
00382 'Global Express Guaranteed' => 'EXPRESS',
00383 'Global Express Guaranteed Non-Document Rectangular' => 'EXPRESS',
00384 'Global Express Guaranteed Non-Document Non-Rectangular' => 'EXPRESS',
00385 'Express Mail International (EMS)' => 'EXPRESS',
00386 'Express Mail International (EMS) Flat-Rate Envelope' => 'EXPRESS',
00387 'Priority Mail International' => 'PRIORITY',
00388 'Priority Mail International Flat-Rate Box' => 'PRIORITY',
00389 'Priority Mail International Large Flat-Rate Box' => 'PRIORITY'
00390 ),
00391
00392 'first_class_mail_type'=>array(
00393 'LETTER' => Mage::helper('usa')->__('Letter'),
00394 'FLAT' => Mage::helper('usa')->__('Flat'),
00395 'PARCEL' => Mage::helper('usa')->__('Parcel'),
00396 ),
00397
00398 'container'=>array(
00399 'VARIABLE' => Mage::helper('usa')->__('Variable'),
00400 'FLAT RATE BOX' => Mage::helper('usa')->__('Flat-Rate Box'),
00401 'FLAT RATE ENVELOPE' => Mage::helper('usa')->__('Flat-Rate Envelope'),
00402 'RECTANGULAR' => Mage::helper('usa')->__('Rectangular'),
00403 'NONRECTANGULAR' => Mage::helper('usa')->__('Non-rectangular'),
00404 ),
00405
00406 'size'=>array(
00407 'REGULAR' => Mage::helper('usa')->__('Regular'),
00408 'LARGE' => Mage::helper('usa')->__('Large'),
00409 'OVERSIZE' => Mage::helper('usa')->__('Oversize'),
00410 ),
00411
00412 'machinable'=>array(
00413 'true' => Mage::helper('usa')->__('Yes'),
00414 'false' => Mage::helper('usa')->__('No'),
00415 ),
00416
00417 );
00418
00419 $methods = $this->getConfigData('methods');
00420 if (!empty($methods)) {
00421 $codes['method'] = explode(",", $methods);
00422 } else {
00423 $codes['method'] = array();
00424 }
00425
00426 if (!isset($codes[$type])) {
00427
00428 return false;
00429 } elseif (''===$code) {
00430 return $codes[$type];
00431 }
00432
00433 if (!isset($codes[$type][$code])) {
00434
00435 return false;
00436 } else {
00437 return $codes[$type][$code];
00438 }
00439 }
00440
00441 public function getTracking($trackings)
00442 {
00443 $this->setTrackingReqeust();
00444
00445 if (!is_array($trackings)) {
00446 $trackings = array($trackings);
00447 }
00448
00449 $this->_getXmlTracking($trackings);
00450
00451 return $this->_result;
00452 }
00453
00454 protected function setTrackingReqeust()
00455 {
00456 $r = new Varien_Object();
00457
00458 $userId = $this->getConfigData('userid');
00459 $r->setUserId($userId);
00460
00461 $this->_rawTrackRequest = $r;
00462
00463 }
00464
00465 protected function _getXmlTracking($trackings)
00466 {
00467 $r = $this->_rawTrackRequest;
00468
00469 foreach ($trackings as $tracking){
00470 $xml = new SimpleXMLElement('<?xml version = "1.0" encoding = "UTF-8"?><TrackRequest/>');
00471 $xml->addAttribute('USERID', $r->getUserId());
00472
00473
00474 $trackid = $xml->addChild('TrackID');
00475 $trackid->addAttribute('ID',$tracking);
00476
00477 $api = 'TrackV2';
00478 $request = $xml->asXML();
00479
00480 try {
00481 $url = $this->getConfigData('gateway_url');
00482 if (!$url) {
00483 $url = $this->_defaultGatewayUrl;
00484 }
00485 $client = new Zend_Http_Client();
00486 $client->setUri($url);
00487 $client->setConfig(array('maxredirects'=>0, 'timeout'=>30));
00488 $client->setParameterGet('API', $api);
00489 $client->setParameterGet('XML', $request);
00490 $response = $client->request();
00491 $responseBody = $response->getBody();
00492 } catch (Exception $e) {
00493 $responseBody = '';
00494 }
00495
00496 $this->_parseXmlTrackingResponse($tracking, $responseBody);
00497 }
00498 }
00499
00500 protected function _parseXmlTrackingResponse($trackingvalue, $response)
00501 {
00502 $errorTitle = 'Unable to retrieve tracking';
00503 $resultArr=array();
00504 if (strlen(trim($response))>0) {
00505 if (strpos(trim($response), '<?xml')===0) {
00506 $xml = simplexml_load_string($response);
00507 if (is_object($xml)) {
00508 if (isset($xml->Number) && isset($xml->Description) && (string)$xml->Description!='') {
00509 $errorTitle = (string)$xml->Description;
00510 } elseif (isset($xml->TrackInfo) && isset($xml->TrackInfo->Error) && isset($xml->TrackInfo->Error->Description) && (string)$xml->TrackInfo->Error->Description!='') {
00511 $errorTitle = (string)$xml->TrackInfo->Error->Description;
00512 } else {
00513 $errorTitle = 'Unknown error';
00514 }
00515
00516 if(isset($xml->TrackInfo) && isset($xml->TrackInfo->TrackSummary)){
00517 $resultArr['tracksummary'] = (string)$xml->TrackInfo->TrackSummary;
00518
00519 }
00520 }
00521 }
00522 }
00523
00524 if(!$this->_result){
00525 $this->_result = Mage::getModel('shipping/tracking_result');
00526 }
00527 $defaults = $this->getDefaults();
00528
00529 if ($resultArr) {
00530 $tracking = Mage::getModel('shipping/tracking_result_status');
00531 $tracking->setCarrier('usps');
00532 $tracking->setCarrierTitle($this->getConfigData('title'));
00533 $tracking->setTracking($trackingvalue);
00534 $tracking->setTrackSummary($resultArr['tracksummary']);
00535 $this->_result->append($tracking);
00536 } else {
00537 $error = Mage::getModel('shipping/tracking_result_error');
00538 $error->setCarrier('usps');
00539 $error->setCarrierTitle($this->getConfigData('title'));
00540 $error->setTracking($trackingvalue);
00541 $error->setErrorMessage($errorTitle);
00542 $this->_result->append($error);
00543 }
00544 }
00545
00546 public function getResponse()
00547 {
00548 $statuses = '';
00549 if ($this->_result instanceof Mage_Shipping_Model_Tracking_Result){
00550 if ($trackings = $this->_result->getAllTrackings()) {
00551 foreach ($trackings as $tracking){
00552 if($data = $tracking->getAllData()){
00553 if (!empty($data['track_summary'])) {
00554 $statuses .= Mage::helper('usa')->__($data['track_summary']);
00555 } else {
00556 $statuses .= Mage::helper('usa')->__('Empty response');
00557 }
00558 }
00559 }
00560 }
00561 }
00562 if (empty($statuses)) {
00563 $statuses = Mage::helper('usa')->__('Empty response');
00564 }
00565 return $statuses;
00566 }
00567
00568
00569
00570
00571
00572
00573 public function getAllowedMethods()
00574 {
00575 $allowed = explode(',', $this->getConfigData('allowed_methods'));
00576 $arr = array();
00577 foreach ($allowed as $k) {
00578 $arr[$k] = $k;
00579 }
00580 return $arr;
00581 }
00582
00583 }