_carrierHelper = $carrierHelper; $this->_productCollectionFactory = $productCollectionFactory; $this->_httpClientFactory = $httpClientFactory; parent::__construct( $scopeConfig, $rateErrorFactory, $logger, $xmlSecurity, $xmlElFactory, $rateFactory, $rateMethodFactory, $trackFactory, $trackErrorFactory, $trackStatusFactory, $regionFactory, $countryFactory, $currencyFactory, $directoryData, $stockRegistry, $data ); } /** * Collect and get rates * * @param RateRequest $request * @return \Magento\Quote\Model\Quote\Address\RateResult\Error|bool|Result */ public function collectRates(RateRequest $request) { if (!$this->canCollectRates()) { return $this->getErrorMessage(); } $this->setRequest($request); $this->_result = $this->_getQuotes(); $this->_updateFreeMethodQuote($request); return $this->getResult(); } /** * Prepare and set request to this instance * * @param \Magento\Quote\Model\Quote\Address\RateRequest $request * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function setRequest(\Magento\Quote\Model\Quote\Address\RateRequest $request) { $this->_request = $request; $r = new \Magento\Framework\DataObject(); if ($request->getLimitMethod()) { $r->setService($request->getLimitMethod()); } else { $r->setService('ALL'); } if ($request->getUspsUserid()) { $userId = $request->getUspsUserid(); } else { $userId = $this->getConfigData('userid'); } $r->setUserId($userId); if ($request->getUspsContainer()) { $container = $request->getUspsContainer(); } else { $container = $this->getConfigData('container'); } $r->setContainer($container); if ($request->getUspsSize()) { $size = $request->getUspsSize(); } else { $size = $this->getConfigData('size'); } $r->setSize($size); if ($request->getGirth()) { $girth = $request->getGirth(); } else { $girth = $this->getConfigData('girth'); } $r->setGirth($girth); if ($request->getHeight()) { $height = $request->getHeight(); } else { $height = $this->getConfigData('height'); } $r->setHeight($height); if ($request->getLength()) { $length = $request->getLength(); } else { $length = $this->getConfigData('length'); } $r->setLength($length); if ($request->getWidth()) { $width = $request->getWidth(); } else { $width = $this->getConfigData('width'); } $r->setWidth($width); if ($request->getUspsMachinable()) { $machinable = $request->getUspsMachinable(); } else { $machinable = $this->getConfigData('machinable'); } $r->setMachinable($machinable); if ($request->getOrigPostcode()) { $r->setOrigPostal($request->getOrigPostcode()); } else { $r->setOrigPostal( $this->_scopeConfig->getValue( \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $request->getStoreId() ) ); } if ($request->getOrigCountryId()) { $r->setOrigCountryId($request->getOrigCountryId()); } else { $r->setOrigCountryId( $this->_scopeConfig->getValue( \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_COUNTRY_ID, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $request->getStoreId() ) ); } if ($request->getDestCountryId()) { $destCountry = $request->getDestCountryId(); } else { $destCountry = self::USA_COUNTRY_ID; } $r->setDestCountryId($destCountry); if (!$this->_isUSCountry($destCountry)) { $r->setDestCountryName($this->_getCountryName($destCountry)); } if ($request->getDestPostcode()) { $r->setDestPostal($request->getDestPostcode()); } $weight = $this->getTotalNumOfBoxes($request->getPackageWeight()); $r->setWeightPounds(floor($weight)); $ounces = ($weight - floor($weight)) * self::OUNCES_POUND; $r->setWeightOunces(sprintf('%.' . self::$weightPrecision . 'f', $ounces)); if ($request->getFreeMethodWeight() != $request->getPackageWeight()) { $r->setFreeMethodWeight($request->getFreeMethodWeight()); } $r->setValue($request->getPackageValue()); $r->setValueWithDiscount($request->getPackageValueWithDiscount()); $r->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax()); $this->setRawRequest($r); return $this; } /** * Get result of request * * @return Result|null */ public function getResult() { return $this->_result; } /** * @inheritdoc * * Starting from 23.02.2018 USPS doesn't allow to create free shipping labels via their API. */ public function isShippingLabelsAvailable() { return false; } /** * Get quotes * * @return Result */ protected function _getQuotes() { return $this->_getXmlQuotes(); } /** * Set free method request * * @param string $freeMethod * @return void */ protected function _setFreeMethodRequest($freeMethod) { $r = $this->_rawRequest; $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight()); $r->setWeightPounds(floor($weight)); $ounces = ($weight - floor($weight)) * self::OUNCES_POUND; $r->setWeightOunces(sprintf('%.' . self::$weightPrecision . 'f', $ounces)); $r->setService($freeMethod); } /** * Build RateV3 request, send it to USPS gateway and retrieve quotes in XML format * * @link http://www.usps.com/webtools/htm/Rate-Calculators-v2-3.htm * @return Result * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function _getXmlQuotes() { $r = $this->_rawRequest; // The origin address(shipper) must be only in USA if (!$this->_isUSCountry($r->getOrigCountryId())) { $responseBody = ''; return $this->_parseXmlResponse($responseBody); } if ($this->_isUSCountry($r->getDestCountryId())) { $xml = $this->_xmlElFactory->create( ['data' => ''] ); $xml->addAttribute('USERID', $r->getUserId()); // according to usps v4 documentation $xml->addChild('Revision', '2'); $package = $xml->addChild('Package'); $package->addAttribute('ID', 0); $service = $this->getCode('service_to_code', $r->getService()); if (!$service) { $service = $r->getService(); } if (strpos($r->getContainer(), 'FLAT RATE ENVELOPE') !== false || strpos($r->getContainer(), 'FLAT RATE BOX') !== false ) { $service = 'Priority'; } $package->addChild('Service', $service); // no matter Letter, Flat or Parcel, use Parcel if ($r->getService() == 'FIRST CLASS' || $r->getService() == 'FIRST CLASS HFP COMMERCIAL') { $package->addChild('FirstClassMailType', 'PARCEL'); } $package->addChild('ZipOrigination', $r->getOrigPostal()); //only 5 chars available $package->addChild('ZipDestination', substr($r->getDestPostal(), 0, 5)); $package->addChild('Pounds', $r->getWeightPounds()); $package->addChild('Ounces', $r->getWeightOunces()); // Because some methods don't accept VARIABLE and (NON)RECTANGULAR containers $package->addChild('Container', $r->getContainer()); $package->addChild('Size', $r->getSize()); if ($r->getSize() == 'LARGE') { $package->addChild('Width', $r->getWidth()); $package->addChild('Length', $r->getLength()); $package->addChild('Height', $r->getHeight()); if ($r->getContainer() == 'NONRECTANGULAR' || $r->getContainer() == 'VARIABLE') { $package->addChild('Girth', $r->getGirth()); } } $package->addChild('Machinable', $r->getMachinable()); $api = 'RateV4'; } else { $xml = $this->_xmlElFactory->create( ['data' => ''] ); $xml->addAttribute('USERID', $r->getUserId()); // according to usps v4 documentation $xml->addChild('Revision', '2'); $package = $xml->addChild('Package'); $package->addAttribute('ID', 0); $package->addChild('Pounds', $r->getWeightPounds()); $package->addChild('Ounces', $r->getWeightOunces()); $package->addChild('MailType', 'All'); $package->addChild('ValueOfContents', $r->getValue()); $package->addChild('Country', $r->getDestCountryName()); $package->addChild('Container', $r->getContainer()); $package->addChild('Size', $r->getSize()); $width = $length = $height = $girth = ''; if ($r->getSize() == 'LARGE') { $width = $r->getWidth(); $length = $r->getLength(); $height = $r->getHeight(); if ($r->getContainer() == 'NONRECTANGULAR') { $girth = $r->getGirth(); } } $package->addChild('Width', $width); $package->addChild('Length', $length); $package->addChild('Height', $height); $package->addChild('Girth', $girth); $package->addChild('OriginZip', $r->getOrigPostal()); $package->addChild('AcceptanceDateTime', date('c')); $package->addChild('DestinationPostalCode', $r->getDestPostal()); $api = 'IntlRateV2'; } $request = $xml->asXML(); $responseBody = $this->_getCachedQuotes($request); if ($responseBody === null) { $debugData = ['request' => $this->filterDebugData($request)]; try { $url = $this->getConfigData('gateway_url'); if (!$url) { $url = $this->_defaultGatewayUrl; } $client = $this->_httpClientFactory->create(); $client->setUri($url); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setParameterGet('API', $api); $client->setParameterGet('XML', $request); $response = $client->request(); $responseBody = $response->getBody(); $debugData['result'] = $responseBody; $this->_setCachedQuotes($request, $responseBody); } catch (\Exception $e) { $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; $responseBody = ''; } $this->_debug($debugData); } return $this->_parseXmlResponse($responseBody); } /** * Parse calculated rates * * @param string $response * @return Result * @link http://www.usps.com/webtools/htm/Rate-Calculators-v2-3.htm * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _parseXmlResponse($response) { $r = $this->_rawRequest; $costArr = []; $priceArr = []; if (strlen(trim($response)) > 0) { if (strpos(trim($response), '') !== false) { $response = str_replace( '', '', $response ); } $xml = $this->parseXml($response); if (is_object($xml)) { $allowedMethods = explode(',', $this->getConfigData('allowed_methods')); $serviceCodeToActualNameMap = []; /** * US Rates */ if ($this->_isUSCountry($r->getDestCountryId())) { if (is_object($xml->Package) && is_object($xml->Package->Postage)) { foreach ($xml->Package->Postage as $postage) { $serviceName = $this->_filterServiceName((string)$postage->MailService); $_serviceCode = $this->getCode('method_to_code', $serviceName); $serviceCode = $_serviceCode ? $_serviceCode : (string)$postage->attributes()->CLASSID; $serviceCodeToActualNameMap[$serviceCode] = $serviceName; if (in_array($serviceCode, $allowedMethods)) { $costArr[$serviceCode] = (string)$postage->Rate; $priceArr[$serviceCode] = $this->getMethodPrice( (string)$postage->Rate, $serviceCode ); } } asort($priceArr); } } else { /* * International Rates */ if (is_object($xml->Package) && is_object($xml->Package->Service)) { foreach ($xml->Package->Service as $service) { $serviceName = $this->_filterServiceName((string)$service->SvcDescription); $serviceCode = 'INT_' . (string)$service->attributes()->ID; $serviceCodeToActualNameMap[$serviceCode] = $serviceName; if (!$this->isServiceAvailable($service)) { continue; } if (in_array($serviceCode, $allowedMethods)) { $costArr[$serviceCode] = (string)$service->Postage; $priceArr[$serviceCode] = $this->getMethodPrice( (string)$service->Postage, $serviceCode ); } } asort($priceArr); } } } } } $result = $this->_rateFactory->create(); if (empty($priceArr)) { $error = $this->_rateErrorFactory->create(); $error->setCarrier('usps'); $error->setCarrierTitle($this->getConfigData('title')); $error->setErrorMessage($this->getConfigData('specificerrmsg')); $result->append($error); } else { foreach ($priceArr as $method => $price) { $rate = $this->_rateMethodFactory->create(); $rate->setCarrier('usps'); $rate->setCarrierTitle($this->getConfigData('title')); $rate->setMethod($method); $rate->setMethodTitle( isset( $serviceCodeToActualNameMap[$method] ) ? $serviceCodeToActualNameMap[$method] : $this->getCode( 'method', $method ) ); $rate->setCost($costArr[$method]); $rate->setPrice($price); $result->append($rate); } } return $result; } /** * Get configuration data of carrier * * @param string $type * @param string $code * @return array|false * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getCode($type, $code = '') { $codes = [ 'method' => [ '0_FCLE' => __('First-Class Mail Large Envelope'), '0_FCL' => __('First-Class Mail Letter'), '0_FCP' => __('First-Class Package Service - Retail'), '0_FCPC' => __('First-Class Mail Postcards'), '1' => __('Priority Mail'), '2' => __('Priority Mail Express Hold For Pickup'), '3' => __('Priority Mail Express'), '4' => __('Retail Ground'), '6' => __('Media Mail'), '7' => __('Library Mail'), '13' => __('Priority Mail Express Flat Rate Envelope'), '15' => __('First-Class Mail Large Postcards'), '16' => __('Priority Mail Flat Rate Envelope'), '17' => __('Priority Mail Medium Flat Rate Box'), '22' => __('Priority Mail Large Flat Rate Box'), '23' => __('Priority Mail Express Sunday/Holiday Delivery'), '25' => __('Priority Mail Express Sunday/Holiday Delivery Flat Rate Envelope'), '27' => __('Priority Mail Express Flat Rate Envelope Hold For Pickup'), '28' => __('Priority Mail Small Flat Rate Box'), '29' => __('Priority Mail Padded Flat Rate Envelope'), '30' => __('Priority Mail Express Legal Flat Rate Envelope'), '31' => __('Priority Mail Express Legal Flat Rate Envelope Hold For Pickup'), '32' => __('Priority Mail Express Sunday/Holiday Delivery Legal Flat Rate Envelope'), '33' => __('Priority Mail Hold For Pickup'), '34' => __('Priority Mail Large Flat Rate Box Hold For Pickup'), '35' => __('Priority Mail Medium Flat Rate Box Hold For Pickup'), '36' => __('Priority Mail Small Flat Rate Box Hold For Pickup'), '37' => __('Priority Mail Flat Rate Envelope Hold For Pickup'), '38' => __('Priority Mail Gift Card Flat Rate Envelope'), '39' => __('Priority Mail Gift Card Flat Rate Envelope Hold For Pickup'), '40' => __('Priority Mail Window Flat Rate Envelope'), '41' => __('Priority Mail Window Flat Rate Envelope Hold For Pickup'), '42' => __('Priority Mail Small Flat Rate Envelope'), '43' => __('Priority Mail Small Flat Rate Envelope Hold For Pickup'), '44' => __('Priority Mail Legal Flat Rate Envelope'), '45' => __('Priority Mail Legal Flat Rate Envelope Hold For Pickup'), '46' => __('Priority Mail Padded Flat Rate Envelope Hold For Pickup'), '47' => __('Priority Mail Regional Rate Box A'), '48' => __('Priority Mail Regional Rate Box A Hold For Pickup'), '49' => __('Priority Mail Regional Rate Box B'), '50' => __('Priority Mail Regional Rate Box B Hold For Pickup'), '53' => __('First-Class Package Service Hold For Pickup'), '57' => __('Priority Mail Express Sunday/Holiday Delivery Flat Rate Boxes'), '58' => __('Priority Mail Regional Rate Box C'), '59' => __('Priority Mail Regional Rate Box C Hold For Pickup'), '61' => __('First-Class Package Service'), '62' => __('Priority Mail Express Padded Flat Rate Envelope'), '63' => __('Priority Mail Express Padded Flat Rate Envelope Hold For Pickup'), '64' => __('Priority Mail Express Sunday/Holiday Delivery Padded Flat Rate Envelope'), 'INT_1' => __('Priority Mail Express International'), 'INT_2' => __('Priority Mail International'), 'INT_4' => __('Global Express Guaranteed (GXG)'), 'INT_5' => __('Global Express Guaranteed Document'), 'INT_6' => __('Global Express Guaranteed Non-Document Rectangular'), 'INT_7' => __('Global Express Guaranteed Non-Document Non-Rectangular'), 'INT_8' => __('Priority Mail International Flat Rate Envelope'), 'INT_9' => __('Priority Mail International Medium Flat Rate Box'), 'INT_10' => __('Priority Mail Express International Flat Rate Envelope'), 'INT_11' => __('Priority Mail International Large Flat Rate Box'), 'INT_12' => __('USPS GXG Envelopes'), 'INT_13' => __('First-Class Mail International Letter'), 'INT_14' => __('First-Class Mail International Large Envelope'), 'INT_15' => __('First-Class Package International Service'), 'INT_16' => __('Priority Mail International Small Flat Rate Box'), 'INT_17' => __('Priority Mail Express International Legal Flat Rate Envelope'), 'INT_18' => __('Priority Mail International Gift Card Flat Rate Envelope'), 'INT_19' => __('Priority Mail International Window Flat Rate Envelope'), 'INT_20' => __('Priority Mail International Small Flat Rate Envelope'), 'INT_21' => __('First-Class Mail International Postcard'), 'INT_22' => __('Priority Mail International Legal Flat Rate Envelope'), 'INT_23' => __('Priority Mail International Padded Flat Rate Envelope'), 'INT_24' => __('Priority Mail International DVD Flat Rate priced box'), 'INT_25' => __('Priority Mail International Large Video Flat Rate priced box'), 'INT_27' => __('Priority Mail Express International Padded Flat Rate Envelope'), ], 'service_to_code' => [ '0_FCLE' => 'First Class', '0_FCL' => 'First Class', '0_FCP' => 'First Class', '0_FCPC' => 'First Class', '1' => 'Priority', '2' => 'Priority Express', '3' => 'Priority Express', '4' => 'Retail Ground', '6' => 'Media', '7' => 'Library', '13' => 'Priority Express', '15' => 'First Class', '16' => 'Priority', '17' => 'Priority', '22' => 'Priority', '23' => 'Priority Express', '25' => 'Priority Express', '27' => 'Priority Express', '28' => 'Priority', '29' => 'Priority', '30' => 'Priority Express', '31' => 'Priority Express', '32' => 'Priority Express', '33' => 'Priority', '34' => 'Priority', '35' => 'Priority', '36' => 'Priority', '37' => 'Priority', '38' => 'Priority', '39' => 'Priority', '40' => 'Priority', '41' => 'Priority', '42' => 'Priority', '43' => 'Priority', '44' => 'Priority', '45' => 'Priority', '46' => 'Priority', '47' => 'Priority', '48' => 'Priority', '49' => 'Priority', '50' => 'Priority', '53' => 'First Class', '57' => 'Priority Express', '58' => 'Priority', '59' => 'Priority', '61' => 'First Class', '62' => 'Priority Express', '63' => 'Priority Express', '64' => 'Priority Express', 'INT_1' => 'Priority Express', 'INT_2' => 'Priority', 'INT_4' => 'Priority Express', 'INT_5' => 'Priority Express', 'INT_6' => 'Priority Express', 'INT_7' => 'Priority Express', 'INT_8' => 'Priority', 'INT_9' => 'Priority', 'INT_10' => 'Priority Express', 'INT_11' => 'Priority', 'INT_12' => 'Priority Express', 'INT_13' => 'First Class', 'INT_14' => 'First Class', 'INT_15' => 'First Class', 'INT_16' => 'Priority', 'INT_17' => 'Priority', 'INT_18' => 'Priority', 'INT_19' => 'Priority', 'INT_20' => 'Priority', 'INT_21' => 'First Class', 'INT_22' => 'Priority', 'INT_23' => 'Priority', 'INT_24' => 'Priority', 'INT_25' => 'Priority', 'INT_27' => 'Priority Express', ], 'method_to_code' => [ 'First-Class Mail Large Envelope' => '0_FCLE', 'First-Class Mail Letter' => '0_FCL', 'First-Class Package Service - Retail' => '0_FCP', ], 'first_class_mail_type' => ['LETTER' => __('Letter'), 'FLAT' => __('Flat'), 'PARCEL' => __('Parcel')], 'container' => [ 'VARIABLE' => __('Variable'), 'SM FLAT RATE BOX' => __('Small Flat-Rate Box'), 'MD FLAT RATE BOX' => __('Medium Flat-Rate Box'), 'LG FLAT RATE BOX' => __('Large Flat-Rate Box'), 'FLAT RATE ENVELOPE' => __('Flat-Rate Envelope'), 'SM FLAT RATE ENVELOPE' => __('Small Flat-Rate Envelope'), 'WINDOW FLAT RATE ENVELOPE' => __('Window Flat-Rate Envelope'), 'GIFT CARD FLAT RATE ENVELOPE' => __('Gift Card Flat-Rate Envelope'), 'LEGAL FLAT RATE ENVELOPE' => __('Legal Flat-Rate Envelope'), 'PADDED FLAT RATE ENVELOPE' => __('Padded Flat-Rate Envelope'), 'RECTANGULAR' => __('Rectangular'), 'NONRECTANGULAR' => __('Non-rectangular'), ], 'containers_filter' => [ [ 'containers' => ['VARIABLE'], 'filters' => [ 'within_us' => [ 'method' => [ '13', '27', '16', '22', '17', '28', '2', '3', '1', '33', '34', '35', '36', '37', '42', '43', '53', '4', '6', '15', '23', '25', '57' ], ], 'from_us' => [ 'method' => [ 'INT_10', 'INT_8', 'INT_11', 'INT_9', 'INT_16', 'INT_20', 'INT_4', 'INT_12', 'INT_1', 'INT_2', 'INT_13', 'INT_14', 'INT_15' ], ], ], ], [ 'containers' => ['SM FLAT RATE BOX'], 'filters' => [ 'within_us' => [ 'method' => ['28', '57'], ], 'from_us' => [ 'method' => ['INT_16', 'INT_24'], ], ] ], [ 'containers' => ['MD FLAT RATE BOX'], 'filters' => [ 'within_us' => [ 'method' => ['17', '57'], ], 'from_us' => [ 'method' => ['INT_9', 'INT_24'], ], ] ], [ 'containers' => ['LG FLAT RATE BOX'], 'filters' => [ 'within_us' => [ 'method' => ['22', '57'], ], 'from_us' => [ 'method' => ['INT_11', 'INT_24', 'INT_25'], ], ] ], [ 'containers' => ['SM FLAT RATE ENVELOPE'], 'filters' => [ 'within_us' => [ 'method' => ['42', '43'], ], 'from_us' => [ 'method' => ['INT_20'], ], ] ], [ 'containers' => ['WINDOW FLAT RATE ENVELOPE'], 'filters' => [ 'within_us' => [ 'method' => ['40', '41'], ], 'from_us' => [ 'method' => ['INT_19'], ], ] ], [ 'containers' => ['GIFT CARD FLAT RATE ENVELOPE'], 'filters' => [ 'within_us' => [ 'method' => ['38', '39'], ], 'from_us' => [ 'method' => ['INT_18'], ], ] ], [ 'containers' => ['PADDED FLAT RATE ENVELOPE'], 'filters' => [ 'within_us' => [ 'method' => ['62', '63', '64', '46', '29'], ], 'from_us' => [ 'method' => ['INT_27', 'INT_23'], ], ] ], [ 'containers' => ['LEGAL FLAT RATE ENVELOPE'], 'filters' => [ 'within_us' => [ 'method' => ['44', '45', '30', '31', '32'], ], 'from_us' => [ 'method' => ['INT_17', 'INT_22'], ], ] ], [ 'containers' => ['FLAT RATE ENVELOPE'], 'filters' => [ 'within_us' => [ 'method' => ['16', '13', '27', '16', '15', '37', '42', '43', '25', '62'], ], 'from_us' => [ 'method' => [ 'INT_10', 'INT_8', 'INT_14', 'INT_20', 'INT_17', 'INT_18', 'INT_19', 'INT_22', 'INT_27' ], ], ] ], [ 'containers' => ['RECTANGULAR'], 'filters' => [ 'within_us' => [ 'method' => ['3', '1', '4', '6', '7', '61'], ], 'from_us' => [ 'method' => ['INT_12', 'INT_1', 'INT_2', 'INT_15'], ], ] ], [ 'containers' => ['NONRECTANGULAR'], 'filters' => [ 'within_us' => [ 'method' => ['3', '1', '4', '6', '7'], ], 'from_us' => [ 'method' => ['INT_4', 'INT_1', 'INT_2', 'INT_15'], ], ] ], ], 'size' => ['REGULAR' => __('Regular'), 'LARGE' => __('Large')], 'machinable' => ['true' => __('Yes'), 'false' => __('No')], 'delivery_confirmation_types' => ['True' => __('Not Required'), 'False' => __('Required')], ]; if (!isset($codes[$type])) { return false; } elseif ('' === $code) { return $codes[$type]; } if (!isset($codes[$type][$code])) { return false; } else { return $codes[$type][$code]; } } /** * Get tracking * * @param string|string[] $trackings * @return Result|null */ public function getTracking($trackings) { $this->setTrackingReqeust(); if (!is_array($trackings)) { $trackings = [$trackings]; } $this->_getXmlTracking($trackings); return $this->_result; } /** * Set tracking request * * @return void */ protected function setTrackingReqeust() { $r = new \Magento\Framework\DataObject(); $userId = $this->getConfigData('userid'); $r->setUserId($userId); $this->_rawTrackRequest = $r; } /** * Send request for tracking * * @param string[] $trackings * @return void */ protected function _getXmlTracking($trackings) { $r = $this->_rawTrackRequest; foreach ($trackings as $tracking) { $xml = $this->_xmlElFactory->create( ['data' => ''] ); $xml->addAttribute('USERID', $r->getUserId()); $trackid = $xml->addChild('TrackID'); $trackid->addAttribute('ID', $tracking); $api = 'TrackV2'; $request = $xml->asXML(); $debugData = ['request' => $this->filterDebugData($request)]; try { $url = $this->getConfigData('gateway_url'); if (!$url) { $url = $this->_defaultGatewayUrl; } $client = $this->_httpClientFactory->create(); $client->setUri($url); $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); $client->setParameterGet('API', $api); $client->setParameterGet('XML', $request); $response = $client->request(); $responseBody = $response->getBody(); $debugData['result'] = $responseBody; } catch (\Exception $e) { $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()]; $responseBody = ''; } $this->_debug($debugData); $this->_parseXmlTrackingResponse($tracking, $responseBody); } } /** * Parse xml tracking response * * @param string $trackingvalue * @param string $response * @return void * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ protected function _parseXmlTrackingResponse($trackingvalue, $response) { $errorTitle = __('For some reason we can\'t retrieve tracking info right now.'); $resultArr = []; if (strlen(trim($response)) > 0) { if (strpos(trim($response), 'parseXml($response); if (is_object($xml)) { if (isset($xml->Number) && isset($xml->Description) && (string)$xml->Description != '') { $errorTitle = (string)$xml->Description; } elseif (isset($xml->TrackInfo) && isset($xml->TrackInfo->Error) && isset($xml->TrackInfo->Error->Description) && (string)$xml->TrackInfo->Error->Description != '' ) { $errorTitle = (string)$xml->TrackInfo->Error->Description; } else { $errorTitle = __( 'Sorry, something went wrong. Please try again or contact us and we\'ll try to help.' ); } if (isset($xml->TrackInfo) && isset($xml->TrackInfo->TrackSummary)) { $resultArr['tracksummary'] = (string)$xml->TrackInfo->TrackSummary; } } } } if (!$this->_result) { $this->_result = $this->_trackFactory->create(); } $defaults = $this->getDefaults(); if ($resultArr) { $tracking = $this->_trackStatusFactory->create(); $tracking->setCarrier('usps'); $tracking->setCarrierTitle($this->getConfigData('title')); $tracking->setTracking($trackingvalue); $tracking->setTrackSummary($resultArr['tracksummary']); $this->_result->append($tracking); } else { $error = $this->_trackErrorFactory->create(); $error->setCarrier('usps'); $error->setCarrierTitle($this->getConfigData('title')); $error->setTracking($trackingvalue); $error->setErrorMessage($errorTitle); $this->_result->append($error); } } /** * Get tracking response * * @return string */ public function getResponse() { $statuses = ''; if ($this->_result instanceof \Magento\Shipping\Model\Tracking\Result) { if ($trackings = $this->_result->getAllTrackings()) { foreach ($trackings as $tracking) { if ($data = $tracking->getAllData()) { if (!empty($data['track_summary'])) { $statuses .= __($data['track_summary']); } else { $statuses .= __('Empty response'); } } } } } if (empty($statuses)) { $statuses = __('Empty response'); } return $statuses; } /** * Get allowed shipping methods * * @return array */ public function getAllowedMethods() { $allowed = explode(',', $this->getConfigData('allowed_methods')); $arr = []; foreach ($allowed as $k) { $arr[$k] = $this->getCode('method', $k); } return $arr; } /** * Return USPS county name by country ISO 3166-1-alpha-2 code * * Return false for unknown countries * * @param string $countryId * @return string|false * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function _getCountryName($countryId) { $countries = [ 'AD' => 'Andorra', 'AE' => 'United Arab Emirates', 'AF' => 'Afghanistan', 'AG' => 'Antigua and Barbuda', 'AI' => 'Anguilla', 'AL' => 'Albania', 'AM' => 'Armenia', 'AN' => 'Netherlands Antilles', 'AO' => 'Angola', 'AR' => 'Argentina', 'AT' => 'Austria', 'AU' => 'Australia', 'AW' => 'Aruba', 'AX' => 'Aland Island (Finland)', 'AZ' => 'Azerbaijan', 'BA' => 'Bosnia-Herzegovina', 'BB' => 'Barbados', 'BD' => 'Bangladesh', 'BE' => 'Belgium', 'BF' => 'Burkina Faso', 'BG' => 'Bulgaria', 'BH' => 'Bahrain', 'BI' => 'Burundi', 'BJ' => 'Benin', 'BM' => 'Bermuda', 'BN' => 'Brunei Darussalam', 'BO' => 'Bolivia', 'BR' => 'Brazil', 'BS' => 'Bahamas', 'BT' => 'Bhutan', 'BW' => 'Botswana', 'BY' => 'Belarus', 'BZ' => 'Belize', 'CA' => 'Canada', 'CC' => 'Cocos Island (Australia)', 'CD' => 'Congo, Democratic Republic of the', 'CF' => 'Central African Republic', 'CG' => 'Congo, Republic of the', 'CH' => 'Switzerland', 'CI' => 'Ivory Coast (Cote d Ivoire)', 'CK' => 'Cook Islands (New Zealand)', 'CL' => 'Chile', 'CM' => 'Cameroon', 'CN' => 'China', 'CO' => 'Colombia', 'CR' => 'Costa Rica', 'CU' => 'Cuba', 'CV' => 'Cape Verde', 'CX' => 'Christmas Island (Australia)', 'CY' => 'Cyprus', 'CZ' => 'Czech Republic', 'DE' => 'Germany', 'DJ' => 'Djibouti', 'DK' => 'Denmark', 'DM' => 'Dominica', 'DO' => 'Dominican Republic', 'DZ' => 'Algeria', 'EC' => 'Ecuador', 'EE' => 'Estonia', 'EG' => 'Egypt', 'ER' => 'Eritrea', 'ES' => 'Spain', 'ET' => 'Ethiopia', 'FI' => 'Finland', 'FJ' => 'Fiji', 'FK' => 'Falkland Islands', 'FM' => 'Micronesia, Federated States of', 'FO' => 'Faroe Islands', 'FR' => 'France', 'GA' => 'Gabon', 'GB' => 'United Kingdom of Great Britain and Northern Ireland', 'GD' => 'Grenada', 'GE' => 'Georgia, Republic of', 'GF' => 'French Guiana', 'GH' => 'Ghana', 'GI' => 'Gibraltar', 'GL' => 'Greenland', 'GM' => 'Gambia', 'GN' => 'Guinea', 'GP' => 'Guadeloupe', 'GQ' => 'Equatorial Guinea', 'GR' => 'Greece', 'GS' => 'South Georgia (Falkland Islands)', 'GT' => 'Guatemala', 'GW' => 'Guinea-Bissau', 'GY' => 'Guyana', 'HK' => 'Hong Kong', 'HN' => 'Honduras', 'HR' => 'Croatia', 'HT' => 'Haiti', 'HU' => 'Hungary', 'ID' => 'Indonesia', 'IE' => 'Ireland', 'IL' => 'Israel', 'IN' => 'India', 'IQ' => 'Iraq', 'IR' => 'Iran', 'IS' => 'Iceland', 'IT' => 'Italy', 'JM' => 'Jamaica', 'JO' => 'Jordan', 'JP' => 'Japan', 'KE' => 'Kenya', 'KG' => 'Kyrgyzstan', 'KH' => 'Cambodia', 'KI' => 'Kiribati', 'KM' => 'Comoros', 'KN' => 'Saint Kitts (Saint Christopher and Nevis)', 'KP' => 'North Korea (Korea, Democratic People\'s Republic of)', 'KR' => 'South Korea (Korea, Republic of)', 'KW' => 'Kuwait', 'KY' => 'Cayman Islands', 'KZ' => 'Kazakhstan', 'LA' => 'Laos', 'LB' => 'Lebanon', 'LC' => 'Saint Lucia', 'LI' => 'Liechtenstein', 'LK' => 'Sri Lanka', 'LR' => 'Liberia', 'LS' => 'Lesotho', 'LT' => 'Lithuania', 'LU' => 'Luxembourg', 'LV' => 'Latvia', 'LY' => 'Libya', 'MA' => 'Morocco', 'MC' => 'Monaco (France)', 'MD' => 'Moldova', 'MG' => 'Madagascar', 'MK' => 'Macedonia, Republic of', 'ML' => 'Mali', 'MM' => 'Burma', 'MN' => 'Mongolia', 'MO' => 'Macao', 'MQ' => 'Martinique', 'MR' => 'Mauritania', 'MS' => 'Montserrat', 'MT' => 'Malta', 'MU' => 'Mauritius', 'MV' => 'Maldives', 'MW' => 'Malawi', 'MX' => 'Mexico', 'MY' => 'Malaysia', 'MZ' => 'Mozambique', 'NA' => 'Namibia', 'NC' => 'New Caledonia', 'NE' => 'Niger', 'NG' => 'Nigeria', 'NI' => 'Nicaragua', 'NL' => 'Netherlands', 'NO' => 'Norway', 'NP' => 'Nepal', 'NR' => 'Nauru', 'NZ' => 'New Zealand', 'OM' => 'Oman', 'PA' => 'Panama', 'PE' => 'Peru', 'PF' => 'French Polynesia', 'PG' => 'Papua New Guinea', 'PH' => 'Philippines', 'PK' => 'Pakistan', 'PL' => 'Poland', 'PM' => 'Saint Pierre and Miquelon', 'PN' => 'Pitcairn Island', 'PT' => 'Portugal', 'PY' => 'Paraguay', 'QA' => 'Qatar', 'RE' => 'Reunion', 'RO' => 'Romania', 'RS' => 'Serbia', 'RU' => 'Russia', 'RW' => 'Rwanda', 'SA' => 'Saudi Arabia', 'SB' => 'Solomon Islands', 'SC' => 'Seychelles', 'SD' => 'Sudan', 'SE' => 'Sweden', 'SG' => 'Singapore', 'SH' => 'Saint Helena', 'SI' => 'Slovenia', 'SK' => 'Slovak Republic', 'SL' => 'Sierra Leone', 'SM' => 'San Marino', 'SN' => 'Senegal', 'SO' => 'Somalia', 'SR' => 'Suriname', 'ST' => 'Sao Tome and Principe', 'SV' => 'El Salvador', 'SY' => 'Syrian Arab Republic', 'SZ' => 'Eswatini', 'TC' => 'Turks and Caicos Islands', 'TD' => 'Chad', 'TG' => 'Togo', 'TH' => 'Thailand', 'TJ' => 'Tajikistan', 'TK' => 'Tokelau (Union Group) (Western Samoa)', 'TL' => 'East Timor (Timor-Leste, Democratic Republic of)', 'TM' => 'Turkmenistan', 'TN' => 'Tunisia', 'TO' => 'Tonga', 'TR' => 'Turkey', 'TT' => 'Trinidad and Tobago', 'TV' => 'Tuvalu', 'TW' => 'Taiwan', 'TZ' => 'Tanzania', 'UA' => 'Ukraine', 'UG' => 'Uganda', 'UY' => 'Uruguay', 'UZ' => 'Uzbekistan', 'VA' => 'Vatican City', 'VC' => 'Saint Vincent and the Grenadines', 'VE' => 'Venezuela', 'VG' => 'British Virgin Islands', 'VN' => 'Vietnam', 'VU' => 'Vanuatu', 'WF' => 'Wallis and Futuna Islands', 'WS' => 'Western Samoa', 'YE' => 'Yemen', 'YT' => 'Mayotte (France)', 'ZA' => 'South Africa', 'ZM' => 'Zambia', 'ZW' => 'Zimbabwe', 'US' => 'United States', ]; if (isset($countries[$countryId])) { return $countries[$countryId]; } return false; } /** * Clean service name from unsupported strings and characters * * @param string $name * @return string */ protected function _filterServiceName($name) { $name = (string)preg_replace( ['~<[^/!][^>]+>.*]+>~sU', '~\