Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Carrier.php
Go to the documentation of this file.
1 <?php
7 namespace Magento\Ups\Model;
8 
18 
25 {
31  const CODE = 'ups';
32 
37 
39 
45  protected $_code = self::CODE;
46 
52  protected $_request;
53 
59  protected $_result;
60 
66  protected $_baseCurrencyRate;
67 
73  protected $_xmlAccessRequest;
74 
80  protected $_defaultCgiGatewayUrl = 'http://www.ups.com:80/using/services/rave/qcostcgi.cgi';
81 
87  protected $_defaultUrls = [
88  'ShipConfirm' => 'https://wwwcie.ups.com/ups.app/xml/ShipConfirm',
89  'ShipAccept' => 'https://wwwcie.ups.com/ups.app/xml/ShipAccept',
90  ];
91 
97  protected $_liveUrls = [
98  'ShipConfirm' => 'https://onlinetools.ups.com/ups.app/xml/ShipConfirm',
99  'ShipAccept' => 'https://onlinetools.ups.com/ups.app/xml/ShipAccept',
100  ];
101 
107  protected $_customizableContainerTypes = ['CP', 'CSP'];
108 
112  protected $_localeFormat;
113 
117  protected $_logger;
118 
122  protected $configHelper;
123 
128  'UserId', 'Password', 'AccessLicenseNumber'
129  ];
130 
134  private $httpClientFactory;
135 
159  public function __construct(
160  \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
161  \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
162  \Psr\Log\LoggerInterface $logger,
164  \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
165  \Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
166  \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
167  \Magento\Shipping\Model\Tracking\ResultFactory $trackFactory,
168  \Magento\Shipping\Model\Tracking\Result\ErrorFactory $trackErrorFactory,
169  \Magento\Shipping\Model\Tracking\Result\StatusFactory $trackStatusFactory,
170  \Magento\Directory\Model\RegionFactory $regionFactory,
171  \Magento\Directory\Model\CountryFactory $countryFactory,
172  \Magento\Directory\Model\CurrencyFactory $currencyFactory,
173  \Magento\Directory\Helper\Data $directoryData,
174  \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
175  \Magento\Framework\Locale\FormatInterface $localeFormat,
177  ClientFactory $httpClientFactory,
178  array $data = []
179  ) {
180  parent::__construct(
181  $scopeConfig,
182  $rateErrorFactory,
183  $logger,
184  $xmlSecurity,
185  $xmlElFactory,
186  $rateFactory,
187  $rateMethodFactory,
188  $trackFactory,
189  $trackErrorFactory,
190  $trackStatusFactory,
191  $regionFactory,
192  $countryFactory,
193  $currencyFactory,
194  $directoryData,
196  $data
197  );
198  $this->httpClientFactory = $httpClientFactory;
199  $this->_localeFormat = $localeFormat;
200  $this->configHelper = $configHelper;
201  }
202 
210  {
211  $this->setRequest($request);
212  if (!$this->canCollectRates()) {
213  return $this->getErrorMessage();
214  }
215 
216  $this->setRequest($request);
217  $this->_result = $this->_getQuotes();
218  $this->_updateFreeMethodQuote($request);
219 
220  return $this->getResult();
221  }
222 
232  public function setRequest(RateRequest $request)
233  {
234  $this->_request = $request;
235 
236  $rowRequest = new \Magento\Framework\DataObject();
237 
238  if ($request->getLimitMethod()) {
239  $rowRequest->setAction($this->configHelper->getCode('action', 'single'));
240  $rowRequest->setProduct($request->getLimitMethod());
241  } else {
242  $rowRequest->setAction($this->configHelper->getCode('action', 'all'));
243  $rowRequest->setProduct('GND' . $this->getConfigData('dest_type'));
244  }
245 
246  if ($request->getUpsPickup()) {
247  $pickup = $request->getUpsPickup();
248  } else {
249  $pickup = $this->getConfigData('pickup');
250  }
251  $rowRequest->setPickup($this->configHelper->getCode('pickup', $pickup));
252 
253  if ($request->getUpsContainer()) {
254  $container = $request->getUpsContainer();
255  } else {
256  $container = $this->getConfigData('container');
257  }
258  $rowRequest->setContainer($this->configHelper->getCode('container', $container));
259 
260  if ($request->getUpsDestType()) {
261  $destType = $request->getUpsDestType();
262  } else {
263  $destType = $this->getConfigData('dest_type');
264  }
265  $rowRequest->setDestType($this->configHelper->getCode('dest_type', $destType));
266 
267  if ($request->getOrigCountry()) {
268  $origCountry = $request->getOrigCountry();
269  } else {
270  $origCountry = $this->_scopeConfig->getValue(
271  \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_COUNTRY_ID,
272  \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
273  $request->getStoreId()
274  );
275  }
276 
277  $rowRequest->setOrigCountry($this->_countryFactory->create()->load($origCountry)->getData('iso2_code'));
278 
279  if ($request->getOrigRegionCode()) {
280  $origRegionCode = $request->getOrigRegionCode();
281  } else {
282  $origRegionCode = $this->_scopeConfig->getValue(
283  \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_REGION_ID,
284  \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
285  $request->getStoreId()
286  );
287  }
288  if (is_numeric($origRegionCode)) {
289  $origRegionCode = $this->_regionFactory->create()->load($origRegionCode)->getCode();
290  }
291  $rowRequest->setOrigRegionCode($origRegionCode);
292 
293  if ($request->getOrigPostcode()) {
294  $rowRequest->setOrigPostal($request->getOrigPostcode());
295  } else {
296  $rowRequest->setOrigPostal(
297  $this->_scopeConfig->getValue(
298  \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP,
299  \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
300  $request->getStoreId()
301  )
302  );
303  }
304 
305  if ($request->getOrigCity()) {
306  $rowRequest->setOrigCity($request->getOrigCity());
307  } else {
308  $rowRequest->setOrigCity(
309  $this->_scopeConfig->getValue(
310  \Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_CITY,
311  \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
312  $request->getStoreId()
313  )
314  );
315  }
316 
317  if ($request->getDestCountryId()) {
318  $destCountry = $request->getDestCountryId();
319  } else {
320  $destCountry = self::USA_COUNTRY_ID;
321  }
322 
323  //for UPS, puero rico state for US will assume as puerto rico country
324  if ($destCountry == self::USA_COUNTRY_ID && ($request->getDestPostcode() == '00912' ||
325  $request->getDestRegionCode() == self::PUERTORICO_COUNTRY_ID)
326  ) {
327  $destCountry = self::PUERTORICO_COUNTRY_ID;
328  }
329 
330  // For UPS, Guam state of the USA will be represented by Guam country
331  if ($destCountry == self::USA_COUNTRY_ID && $request->getDestRegionCode() == self::GUAM_REGION_CODE) {
332  $destCountry = self::GUAM_COUNTRY_ID;
333  }
334 
335  $country = $this->_countryFactory->create()->load($destCountry);
336  $rowRequest->setDestCountry($country->getData('iso2_code') ?: $destCountry);
337 
338  $rowRequest->setDestRegionCode($request->getDestRegionCode());
339 
340  if ($request->getDestPostcode()) {
341  $rowRequest->setDestPostal($request->getDestPostcode());
342  }
343 
344  $weight = $this->getTotalNumOfBoxes($request->getPackageWeight());
345 
346  $weight = $this->_getCorrectWeight($weight);
347 
348  $rowRequest->setWeight($weight);
349  if ($request->getFreeMethodWeight() != $request->getPackageWeight()) {
350  $rowRequest->setFreeMethodWeight($request->getFreeMethodWeight());
351  }
352 
353  $rowRequest->setValue($request->getPackageValue());
354  $rowRequest->setValueWithDiscount($request->getPackageValueWithDiscount());
355 
356  if ($request->getUpsUnitMeasure()) {
357  $unit = $request->getUpsUnitMeasure();
358  } else {
359  $unit = $this->getConfigData('unit_of_measure');
360  }
361  $rowRequest->setUnitMeasure($unit);
362  $rowRequest->setIsReturn($request->getIsReturn());
363  $rowRequest->setBaseSubtotalInclTax($request->getBaseSubtotalInclTax());
364 
365  $this->_rawRequest = $rowRequest;
366 
367  return $this;
368  }
369 
380  protected function _getCorrectWeight($weight)
381  {
382  $minWeight = $this->getConfigData('min_package_weight');
383 
384  if ($weight < $minWeight) {
385  $weight = $minWeight;
386  }
387 
388  //rounds a number to one significant figure
389  $weight = ceil($weight * 10) / 10;
390 
391  return $weight;
392  }
393 
399  public function getResult()
400  {
401  return $this->_result;
402  }
403 
409  protected function _getQuotes()
410  {
411  switch ($this->getConfigData('type')) {
412  case 'UPS':
413  return $this->_getCgiQuotes();
414  case 'UPS_XML':
415  return $this->_getXmlQuotes();
416  default:
417  break;
418  }
419 
420  return null;
421  }
422 
429  protected function _setFreeMethodRequest($freeMethod)
430  {
431  $r = $this->_rawRequest;
432 
433  $weight = $this->getTotalNumOfBoxes($r->getFreeMethodWeight());
434  $weight = $this->_getCorrectWeight($weight);
435  $r->setWeight($weight);
436  $r->setAction($this->configHelper->getCode('action', 'single'));
437  $r->setProduct($freeMethod);
438  }
439 
445  protected function _getCgiQuotes()
446  {
447  $rowRequest = $this->_rawRequest;
448  if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) {
449  $destPostal = substr($rowRequest->getDestPostal(), 0, 5);
450  } else {
451  $destPostal = $rowRequest->getDestPostal();
452  }
453 
454  $params = [
455  'accept_UPS_license_agreement' => 'yes',
456  '10_action' => $rowRequest->getAction(),
457  '13_product' => $rowRequest->getProduct(),
458  '14_origCountry' => $rowRequest->getOrigCountry(),
459  '15_origPostal' => $rowRequest->getOrigPostal(),
460  'origCity' => $rowRequest->getOrigCity(),
461  '19_destPostal' => $destPostal,
462  '22_destCountry' => $rowRequest->getDestCountry(),
463  '23_weight' => $rowRequest->getWeight(),
464  '47_rate_chart' => $rowRequest->getPickup(),
465  '48_container' => $rowRequest->getContainer(),
466  '49_residential' => $rowRequest->getDestType(),
467  'weight_std' => strtolower($rowRequest->getUnitMeasure()),
468  ];
469  $params['47_rate_chart'] = $params['47_rate_chart']['label'];
470 
471  $responseBody = $this->_getCachedQuotes($params);
472  if ($responseBody === null) {
473  $debugData = ['request' => $params];
474  try {
475  $url = $this->getConfigData('gateway_url');
476  if (!$url) {
478  }
479  $client = new \Zend_Http_Client();
480  $client->setUri($url);
481  $client->setConfig(['maxredirects' => 0, 'timeout' => 30]);
482  $client->setParameterGet($params);
483  $response = $client->request();
484  $responseBody = $response->getBody();
485 
486  $debugData['result'] = $responseBody;
487  $this->_setCachedQuotes($params, $responseBody);
488  } catch (\Throwable $e) {
489  $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
490  $responseBody = '';
491  }
492  $this->_debug($debugData);
493  }
494 
495  return $this->_parseCgiResponse($responseBody);
496  }
497 
505  public function getShipmentByCode($code, $origin = null)
506  {
507  if ($origin === null) {
508  $origin = $this->getConfigData('origin_shipment');
509  }
510  $arr = $this->configHelper->getCode('originShipment', $origin);
511  if (isset($arr[$code])) {
512  return $arr[$code];
513  } else {
514  return false;
515  }
516  }
517 
525  protected function _parseCgiResponse($response)
526  {
527  $costArr = [];
528  $priceArr = [];
529  if (strlen(trim($response)) > 0) {
530  $rRows = explode("\n", $response);
531  $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
532  foreach ($rRows as $rRow) {
533  $row = explode('%', $rRow);
534  switch (substr($row[0], -1)) {
535  case 3:
536  case 4:
537  if (in_array($row[1], $allowedMethods)) {
538  $responsePrice = $this->_localeFormat->getNumber($row[8]);
539  $costArr[$row[1]] = $responsePrice;
540  $priceArr[$row[1]] = $this->getMethodPrice($responsePrice, $row[1]);
541  }
542  break;
543  case 5:
544  $errorTitle = $row[1];
545  $message = __(
546  'Sorry, something went wrong. Please try again or contact us and we\'ll try to help.'
547  );
548  $this->_logger->debug($message . ': ' . $errorTitle);
549  break;
550  case 6:
551  if (in_array($row[3], $allowedMethods)) {
552  $responsePrice = $this->_localeFormat->getNumber($row[10]);
553  $costArr[$row[3]] = $responsePrice;
554  $priceArr[$row[3]] = $this->getMethodPrice($responsePrice, $row[3]);
555  }
556  break;
557  default:
558  break;
559  }
560  }
561  asort($priceArr);
562  }
563 
564  $result = $this->_rateFactory->create();
565 
566  if (empty($priceArr)) {
567  $error = $this->_rateErrorFactory->create();
568  $error->setCarrier('ups');
569  $error->setCarrierTitle($this->getConfigData('title'));
570  $error->setErrorMessage($this->getConfigData('specificerrmsg'));
571  $result->append($error);
572  } else {
573  foreach ($priceArr as $method => $price) {
574  $rate = $this->_rateMethodFactory->create();
575  $rate->setCarrier('ups');
576  $rate->setCarrierTitle($this->getConfigData('title'));
577  $rate->setMethod($method);
578  $methodArray = $this->configHelper->getCode('method', $method);
579  $rate->setMethodTitle($methodArray);
580  $rate->setCost($costArr[$method]);
581  $rate->setPrice($price);
582  $result->append($rate);
583  }
584  }
585 
586  return $result;
587  }
588 
597  protected function _getXmlQuotes()
598  {
599  $url = $this->getConfigData('gateway_xml_url');
600 
601  $this->setXMLAccessRequest();
602  $xmlRequest = $this->_xmlAccessRequest;
603  $debugData['accessRequest'] = $this->filterDebugData($xmlRequest);
604 
605  $rowRequest = $this->_rawRequest;
606  if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) {
607  $destPostal = substr($rowRequest->getDestPostal(), 0, 5);
608  } else {
609  $destPostal = $rowRequest->getDestPostal();
610  }
611  $params = [
612  'accept_UPS_license_agreement' => 'yes',
613  '10_action' => $rowRequest->getAction(),
614  '13_product' => $rowRequest->getProduct(),
615  '14_origCountry' => $rowRequest->getOrigCountry(),
616  '15_origPostal' => $rowRequest->getOrigPostal(),
617  'origCity' => $rowRequest->getOrigCity(),
618  'origRegionCode' => $rowRequest->getOrigRegionCode(),
619  '19_destPostal' => $destPostal,
620  '22_destCountry' => $rowRequest->getDestCountry(),
621  'destRegionCode' => $rowRequest->getDestRegionCode(),
622  '23_weight' => $rowRequest->getWeight(),
623  '47_rate_chart' => $rowRequest->getPickup(),
624  '48_container' => $rowRequest->getContainer(),
625  '49_residential' => $rowRequest->getDestType(),
626  ];
627 
628  if ($params['10_action'] == '4') {
629  $params['10_action'] = 'Shop';
630  $serviceCode = null;
631  } else {
632  $params['10_action'] = 'Rate';
633  $serviceCode = $rowRequest->getProduct() ? $rowRequest->getProduct() : null;
634  }
635  $serviceDescription = $serviceCode ? $this->getShipmentByCode($serviceCode) : '';
636 
637  $xmlParams = <<<XMLRequest
638 <?xml version="1.0"?>
639 <RatingServiceSelectionRequest xml:lang="en-US">
640  <Request>
641  <TransactionReference>
642  <CustomerContext>Rating and Service</CustomerContext>
643  <XpciVersion>1.0</XpciVersion>
644  </TransactionReference>
645  <RequestAction>Rate</RequestAction>
646  <RequestOption>{$params['10_action']}</RequestOption>
647  </Request>
648  <PickupType>
649  <Code>{$params['47_rate_chart']['code']}</Code>
650  <Description>{$params['47_rate_chart']['label']}</Description>
651  </PickupType>
652 
653  <Shipment>
654 XMLRequest;
655 
656  if ($serviceCode !== null) {
657  $xmlParams .= "<Service>" .
658  "<Code>{$serviceCode}</Code>" .
659  "<Description>{$serviceDescription}</Description>" .
660  "</Service>";
661  }
662 
663  $xmlParams .= <<<XMLRequest
664  <Shipper>
665 XMLRequest;
666 
667  if ($this->getConfigFlag('negotiated_active') && ($shipperNumber = $this->getConfigData('shipper_number'))) {
668  $xmlParams .= "<ShipperNumber>{$shipperNumber}</ShipperNumber>";
669  }
670 
671  if ($rowRequest->getIsReturn()) {
672  $shipperCity = '';
673  $shipperPostalCode = $params['19_destPostal'];
674  $shipperCountryCode = $params['22_destCountry'];
675  $shipperStateProvince = $params['destRegionCode'];
676  } else {
677  $shipperCity = $params['origCity'];
678  $shipperPostalCode = $params['15_origPostal'];
679  $shipperCountryCode = $params['14_origCountry'];
680  $shipperStateProvince = $params['origRegionCode'];
681  }
682 
683  $xmlParams .= <<<XMLRequest
684  <Address>
685  <City>{$shipperCity}</City>
686  <PostalCode>{$shipperPostalCode}</PostalCode>
687  <CountryCode>{$shipperCountryCode}</CountryCode>
688  <StateProvinceCode>{$shipperStateProvince}</StateProvinceCode>
689  </Address>
690  </Shipper>
691 
692  <ShipTo>
693  <Address>
694  <PostalCode>{$params['19_destPostal']}</PostalCode>
695  <CountryCode>{$params['22_destCountry']}</CountryCode>
696  <ResidentialAddress>{$params['49_residential']}</ResidentialAddress>
697  <StateProvinceCode>{$params['destRegionCode']}</StateProvinceCode>
698 XMLRequest;
699 
700  if ($params['49_residential'] === '01') {
701  $xmlParams .= "<ResidentialAddressIndicator>{$params['49_residential']}</ResidentialAddressIndicator>";
702  }
703 
704  $xmlParams .= <<<XMLRequest
705  </Address>
706  </ShipTo>
707 
708  <ShipFrom>
709  <Address>
710  <PostalCode>{$params['15_origPostal']}</PostalCode>
711  <CountryCode>{$params['14_origCountry']}</CountryCode>
712  <StateProvinceCode>{$params['origRegionCode']}</StateProvinceCode>
713  </Address>
714  </ShipFrom>
715 
716  <Package>
717  <PackagingType>
718  <Code>{$params['48_container']}</Code>
719  </PackagingType>
720  <PackageWeight>
721  <UnitOfMeasurement>
722  <Code>{$rowRequest->getUnitMeasure()}</Code>
723  </UnitOfMeasurement>
724  <Weight>{$params['23_weight']}</Weight>
725  </PackageWeight>
726  </Package>
727 XMLRequest;
728 
729  if ($this->getConfigFlag('negotiated_active')) {
730  $xmlParams .= "<RateInformation><NegotiatedRatesIndicator/></RateInformation>";
731  }
732  if ($this->getConfigFlag('include_taxes')) {
733  $xmlParams .= "<TaxInformationIndicator/>";
734  }
735 
736  $xmlParams .= <<<XMLRequest
737  </Shipment>
738  </RatingServiceSelectionRequest>
739 XMLRequest;
740 
741  $xmlRequest .= $xmlParams;
742 
743  $xmlResponse = $this->_getCachedQuotes($xmlRequest);
744  if ($xmlResponse === null) {
745  $debugData['request'] = $xmlParams;
746  try {
747  $client = $this->httpClientFactory->create();
748  $client->post($url, $xmlRequest);
749  $xmlResponse = $client->getBody();
750  $debugData['result'] = $xmlResponse;
751  $this->_setCachedQuotes($xmlRequest, $xmlResponse);
752  } catch (\Throwable $e) {
753  $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
754  $xmlResponse = '';
755  }
756  $this->_debug($debugData);
757  }
758 
759  return $this->_parseXmlResponse($xmlResponse);
760  }
761 
768  protected function _getBaseCurrencyRate($code)
769  {
770  if (!$this->_baseCurrencyRate) {
771  $this->_baseCurrencyRate = $this->_currencyFactory->create()->load(
772  $code
773  )->getAnyRate(
774  $this->_request->getBaseCurrency()->getCode()
775  );
776  }
777 
779  }
780 
787  private function mapCurrencyCode($code)
788  {
789  $currencyMapping = [
790  'RMB' => 'CNY',
791  'CNH' => 'CNY'
792  ];
793 
794  return isset($currencyMapping[$code]) ? $currencyMapping[$code] : $code;
795  }
796 
806  protected function _parseXmlResponse($xmlResponse)
807  {
808  $costArr = [];
809  $priceArr = [];
810  if (strlen(trim($xmlResponse)) > 0) {
811  $xml = new \Magento\Framework\Simplexml\Config();
812  $xml->loadString($xmlResponse);
813  $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/ResponseStatusCode/text()");
814  $success = (int)$arr[0];
815  if ($success === 1) {
816  $arr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment");
817  $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));
818 
819  // Negotiated rates
820  $negotiatedArr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates");
821  $negotiatedActive = $this->getConfigFlag('negotiated_active')
822  && $this->getConfigData('shipper_number')
823  && !empty($negotiatedArr);
824 
825  $allowedCurrencies = $this->_currencyFactory->create()->getConfigAllowCurrencies();
826  foreach ($arr as $shipElement) {
827  $code = (string)$shipElement->Service->Code;
828  if (in_array($code, $allowedMethods)) {
829  //The location of tax information is in a different place
830  // depending on whether we are using negotiated rates or not
831  if ($negotiatedActive) {
832  $includeTaxesArr = $xml->getXpath(
833  "//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates"
834  . "/NetSummaryCharges/TotalChargesWithTaxes"
835  );
836  $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr);
837  if ($includeTaxesActive) {
838  $cost = $shipElement->NegotiatedRates
839  ->NetSummaryCharges
840  ->TotalChargesWithTaxes
841  ->MonetaryValue;
842 
843  $responseCurrencyCode = $this->mapCurrencyCode(
844  (string)$shipElement->NegotiatedRates
845  ->NetSummaryCharges
846  ->TotalChargesWithTaxes
847  ->CurrencyCode
848  );
849  } else {
850  $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue;
851  $responseCurrencyCode = $this->mapCurrencyCode(
852  (string)$shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->CurrencyCode
853  );
854  }
855  } else {
856  $includeTaxesArr = $xml->getXpath(
857  "//RatingServiceSelectionResponse/RatedShipment/TotalChargesWithTaxes"
858  );
859  $includeTaxesActive = $this->getConfigFlag('include_taxes') && !empty($includeTaxesArr);
860  if ($includeTaxesActive) {
861  $cost = $shipElement->TotalChargesWithTaxes->MonetaryValue;
862  $responseCurrencyCode = $this->mapCurrencyCode(
863  (string)$shipElement->TotalChargesWithTaxes->CurrencyCode
864  );
865  } else {
866  $cost = $shipElement->TotalCharges->MonetaryValue;
867  $responseCurrencyCode = $this->mapCurrencyCode(
868  (string)$shipElement->TotalCharges->CurrencyCode
869  );
870  }
871  }
872 
873  //convert price with Origin country currency code to base currency code
874  $successConversion = true;
875  if ($responseCurrencyCode) {
876  if (in_array($responseCurrencyCode, $allowedCurrencies)) {
877  $cost = (double)$cost * $this->_getBaseCurrencyRate($responseCurrencyCode);
878  } else {
879  $errorTitle = __(
880  'We can\'t convert a rate from "%1-%2".',
881  $responseCurrencyCode,
882  $this->_request->getPackageCurrency()->getCode()
883  );
884  $error = $this->_rateErrorFactory->create();
885  $error->setCarrier('ups');
886  $error->setCarrierTitle($this->getConfigData('title'));
887  $error->setErrorMessage($errorTitle);
888  $successConversion = false;
889  }
890  }
891 
892  if ($successConversion) {
893  $costArr[$code] = $cost;
894  $priceArr[$code] = $this->getMethodPrice((float)$cost, $code);
895  }
896  }
897  }
898  } else {
899  $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/Error/ErrorDescription/text()");
900  $errorTitle = (string)$arr[0][0];
901  $error = $this->_rateErrorFactory->create();
902  $error->setCarrier('ups');
903  $error->setCarrierTitle($this->getConfigData('title'));
904  $error->setErrorMessage($this->getConfigData('specificerrmsg'));
905  }
906  }
907 
908  $result = $this->_rateFactory->create();
909 
910  if (empty($priceArr)) {
911  $error = $this->_rateErrorFactory->create();
912  $error->setCarrier('ups');
913  $error->setCarrierTitle($this->getConfigData('title'));
914  if ($this->getConfigData('specificerrmsg') !== '') {
915  $errorTitle = $this->getConfigData('specificerrmsg');
916  }
917  if (!isset($errorTitle)) {
918  $errorTitle = __('Cannot retrieve shipping rates');
919  }
920  $error->setErrorMessage($errorTitle);
921  $result->append($error);
922  } else {
923  foreach ($priceArr as $method => $price) {
924  $rate = $this->_rateMethodFactory->create();
925  $rate->setCarrier('ups');
926  $rate->setCarrierTitle($this->getConfigData('title'));
927  $rate->setMethod($method);
928  $methodArr = $this->getShipmentByCode($method);
929  $rate->setMethodTitle($methodArr);
930  $rate->setCost($costArr[$method]);
931  $rate->setPrice($price);
932  $result->append($rate);
933  }
934  }
935 
936  return $result;
937  }
938 
945  public function getTracking($trackings)
946  {
947  if (!is_array($trackings)) {
948  $trackings = [$trackings];
949  }
950 
951  if ($this->getConfigData('type') == 'UPS') {
952  $this->_getCgiTracking($trackings);
953  } elseif ($this->getConfigData('type') == 'UPS_XML') {
954  $this->setXMLAccessRequest();
955  $this->_getXmlTracking($trackings);
956  }
957 
958  return $this->_result;
959  }
960 
966  protected function setXMLAccessRequest()
967  {
968  $userId = $this->getConfigData('username');
969  $userIdPass = $this->getConfigData('password');
970  $accessKey = $this->getConfigData('access_license_number');
971 
972  $this->_xmlAccessRequest = <<<XMLAuth
973 <?xml version="1.0" ?>
974 <AccessRequest xml:lang="en-US">
975  <AccessLicenseNumber>$accessKey</AccessLicenseNumber>
976  <UserId>$userId</UserId>
977  <Password>$userIdPass</Password>
978 </AccessRequest>
979 XMLAuth;
980  }
981 
988  protected function _getCgiTracking($trackings)
989  {
990  //ups no longer support tracking for data streaming version
991  //so we can only reply the popup window to ups.
992  $result = $this->_trackFactory->create();
993  foreach ($trackings as $tracking) {
994  $status = $this->_trackStatusFactory->create();
995  $status->setCarrier('ups');
996  $status->setCarrierTitle($this->getConfigData('title'));
997  $status->setTracking($tracking);
998  $status->setPopup(1);
999  $status->setUrl(
1000  "http://wwwapps.ups.com/WebTracking/processInputRequest?HTMLVersion=5.0&error_carried=true" .
1001  "&tracknums_displayed=5&TypeOfInquiryNumber=T&loc=en_US&InquiryNumber1={$tracking}" .
1002  "&AgreeToTermsAndConditions=yes"
1003  );
1004  $result->append($status);
1005  }
1006 
1007  $this->_result = $result;
1008 
1009  return $result;
1010  }
1011 
1018  protected function _getXmlTracking($trackings)
1019  {
1020  $url = $this->getConfigData('tracking_xml_url');
1021 
1022  foreach ($trackings as $tracking) {
1026  $xmlRequest = <<<XMLAuth
1027 <?xml version="1.0" ?>
1028 <TrackRequest xml:lang="en-US">
1029  <Request>
1030  <RequestAction>Track</RequestAction>
1031  <RequestOption>1</RequestOption>
1032  </Request>
1033  <TrackingNumber>$tracking</TrackingNumber>
1034  <IncludeFreight>01</IncludeFreight>
1035 </TrackRequest>
1036 XMLAuth;
1037  $debugData['request'] = $this->filterDebugData($this->_xmlAccessRequest) . $xmlRequest;
1038  try {
1039  $client = $this->httpClientFactory->create();
1040  $client->post($url, $this->_xmlAccessRequest . $xmlRequest);
1041  $xmlResponse = $client->getBody();
1042  $debugData['result'] = $xmlResponse;
1043  } catch (\Throwable $e) {
1044  $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
1045  $xmlResponse = '';
1046  }
1047 
1048  $this->_debug($debugData);
1049  $this->_parseXmlTrackingResponse($tracking, $xmlResponse);
1050  }
1051 
1052  return $this->_result;
1053  }
1054 
1064  protected function _parseXmlTrackingResponse($trackingValue, $xmlResponse)
1065  {
1066  $errorTitle = 'For some reason we can\'t retrieve tracking info right now.';
1067  $resultArr = [];
1068  $packageProgress = [];
1069 
1070  if ($xmlResponse) {
1071  $xml = new \Magento\Framework\Simplexml\Config();
1072  $xml->loadString($xmlResponse);
1073  $arr = $xml->getXpath("//TrackResponse/Response/ResponseStatusCode/text()");
1074  $success = (int)$arr[0][0];
1075 
1076  if ($success === 1) {
1077  $arr = $xml->getXpath("//TrackResponse/Shipment/Service/Description/text()");
1078  $resultArr['service'] = (string)$arr[0];
1079 
1080  $arr = $xml->getXpath("//TrackResponse/Shipment/PickupDate/text()");
1081  $resultArr['shippeddate'] = (string)$arr[0];
1082 
1083  $arr = $xml->getXpath("//TrackResponse/Shipment/Package/PackageWeight/Weight/text()");
1084  $weight = (string)$arr[0];
1085 
1086  $arr = $xml->getXpath("//TrackResponse/Shipment/Package/PackageWeight/UnitOfMeasurement/Code/text()");
1087  $unit = (string)$arr[0];
1088 
1089  $resultArr['weight'] = "{$weight} {$unit}";
1090 
1091  $activityTags = $xml->getXpath("//TrackResponse/Shipment/Package/Activity");
1092  if ($activityTags) {
1093  $index = 1;
1094  foreach ($activityTags as $activityTag) {
1095  $addressArr = [];
1096  if (isset($activityTag->ActivityLocation->Address->City)) {
1097  $addressArr[] = (string)$activityTag->ActivityLocation->Address->City;
1098  }
1099  if (isset($activityTag->ActivityLocation->Address->StateProvinceCode)) {
1100  $addressArr[] = (string)$activityTag->ActivityLocation->Address->StateProvinceCode;
1101  }
1102  if (isset($activityTag->ActivityLocation->Address->CountryCode)) {
1103  $addressArr[] = (string)$activityTag->ActivityLocation->Address->CountryCode;
1104  }
1105  $dateArr = [];
1106  $date = (string)$activityTag->Date;
1107  //YYYYMMDD
1108  $dateArr[] = substr($date, 0, 4);
1109  $dateArr[] = substr($date, 4, 2);
1110  $dateArr[] = substr($date, -2, 2);
1111 
1112  $timeArr = [];
1113  $time = (string)$activityTag->Time;
1114  //HHMMSS
1115  $timeArr[] = substr($time, 0, 2);
1116  $timeArr[] = substr($time, 2, 2);
1117  $timeArr[] = substr($time, -2, 2);
1118 
1119  if ($index === 1) {
1120  $resultArr['status'] = (string)$activityTag->Status->StatusType->Description;
1121  $resultArr['deliverydate'] = implode('-', $dateArr);
1122  //YYYY-MM-DD
1123  $resultArr['deliverytime'] = implode(':', $timeArr);
1124  //HH:MM:SS
1125  $resultArr['deliverylocation'] = (string)$activityTag->ActivityLocation->Description;
1126  $resultArr['signedby'] = (string)$activityTag->ActivityLocation->SignedForByName;
1127  if ($addressArr) {
1128  $resultArr['deliveryto'] = implode(', ', $addressArr);
1129  }
1130  } else {
1131  $tempArr = [];
1132  $tempArr['activity'] = (string)$activityTag->Status->StatusType->Description;
1133  $tempArr['deliverydate'] = implode('-', $dateArr);
1134  //YYYY-MM-DD
1135  $tempArr['deliverytime'] = implode(':', $timeArr);
1136  //HH:MM:SS
1137  if ($addressArr) {
1138  $tempArr['deliverylocation'] = implode(', ', $addressArr);
1139  }
1140  $packageProgress[] = $tempArr;
1141  }
1142  $index++;
1143  }
1144  $resultArr['progressdetail'] = $packageProgress;
1145  }
1146  } else {
1147  $arr = $xml->getXpath("//TrackResponse/Response/Error/ErrorDescription/text()");
1148  $errorTitle = (string)$arr[0][0];
1149  }
1150  }
1151 
1152  if (!$this->_result) {
1153  $this->_result = $this->_trackFactory->create();
1154  }
1155 
1156  if ($resultArr) {
1157  $tracking = $this->_trackStatusFactory->create();
1158  $tracking->setCarrier('ups');
1159  $tracking->setCarrierTitle($this->getConfigData('title'));
1160  $tracking->setTracking($trackingValue);
1161  $tracking->addData($resultArr);
1162  $this->_result->append($tracking);
1163  } else {
1164  $error = $this->_trackErrorFactory->create();
1165  $error->setCarrier('ups');
1166  $error->setCarrierTitle($this->getConfigData('title'));
1167  $error->setTracking($trackingValue);
1168  $error->setErrorMessage($errorTitle);
1169  $this->_result->append($error);
1170  }
1171 
1172  return $this->_result;
1173  }
1174 
1180  public function getResponse()
1181  {
1182  $statuses = '';
1183  if ($this->_result instanceof \Magento\Shipping\Model\Tracking\Result) {
1184  $trackings = $this->_result->getAllTrackings();
1185  if ($trackings) {
1186  foreach ($trackings as $tracking) {
1187  $data = $tracking->getAllData();
1188  if ($data) {
1189  if (isset($data['status'])) {
1190  $statuses .= __($data['status']);
1191  } else {
1192  $statuses .= __($data['error_message']);
1193  }
1194  }
1195  }
1196  }
1197  }
1198  if (empty($statuses)) {
1199  $statuses = __('Empty response');
1200  }
1201 
1202  return $statuses;
1203  }
1204 
1210  public function getAllowedMethods()
1211  {
1212  $allowed = explode(',', $this->getConfigData('allowed_methods'));
1213  $arr = [];
1214  $isByCode = $this->getConfigData('type') == 'UPS_XML';
1215  foreach ($allowed as $code) {
1216  $arr[$code] = $isByCode ? $this->getShipmentByCode($code) : $this->configHelper->getCode('method', $code);
1217  }
1218 
1219  return $arr;
1220  }
1221 
1231  protected function _formShipmentRequest(\Magento\Framework\DataObject $request)
1232  {
1233  $packageParams = $request->getPackageParams();
1234  $height = $packageParams->getHeight();
1235  $width = $packageParams->getWidth();
1236  $length = $packageParams->getLength();
1237  $weightUnits = $packageParams->getWeightUnits() == \Zend_Measure_Weight::POUND ? 'LBS' : 'KGS';
1238  $dimensionsUnits = $packageParams->getDimensionUnits() == \Zend_Measure_Length::INCH ? 'IN' : 'CM';
1239 
1240  $itemsDesc = [];
1241  $itemsShipment = $request->getPackageItems();
1242  foreach ($itemsShipment as $itemShipment) {
1243  $item = new \Magento\Framework\DataObject();
1244  $item->setData($itemShipment);
1245  $itemsDesc[] = $item->getName();
1246  }
1247 
1248  $xmlRequest = $this->_xmlElFactory->create(
1249  ['data' => '<?xml version = "1.0" ?><ShipmentConfirmRequest xml:lang="en-US"/>']
1250  );
1251  $requestPart = $xmlRequest->addChild('Request');
1252  $requestPart->addChild('RequestAction', 'ShipConfirm');
1253  $requestPart->addChild('RequestOption', 'nonvalidate');
1254 
1255  $shipmentPart = $xmlRequest->addChild('Shipment');
1256  if ($request->getIsReturn()) {
1257  $returnPart = $shipmentPart->addChild('ReturnService');
1258  // UPS Print Return Label
1259  $returnPart->addChild('Code', '9');
1260  }
1261  $shipmentPart->addChild('Description', substr(implode(' ', $itemsDesc), 0, 35));
1262  //empirical
1263 
1264  $shipperPart = $shipmentPart->addChild('Shipper');
1265  if ($request->getIsReturn()) {
1266  $shipperPart->addChild('Name', $request->getRecipientContactCompanyName());
1267  $shipperPart->addChild('AttentionName', $request->getRecipientContactPersonName());
1268  $shipperPart->addChild('ShipperNumber', $this->getConfigData('shipper_number'));
1269  $shipperPart->addChild('PhoneNumber', $request->getRecipientContactPhoneNumber());
1270 
1271  $addressPart = $shipperPart->addChild('Address');
1272  $addressPart->addChild('AddressLine1', $request->getRecipientAddressStreet());
1273  $addressPart->addChild('AddressLine2', $request->getRecipientAddressStreet2());
1274  $addressPart->addChild('City', $request->getRecipientAddressCity());
1275  $addressPart->addChild('CountryCode', $request->getRecipientAddressCountryCode());
1276  $addressPart->addChild('PostalCode', $request->getRecipientAddressPostalCode());
1277  if ($request->getRecipientAddressStateOrProvinceCode()) {
1278  $addressPart->addChild('StateProvinceCode', $request->getRecipientAddressStateOrProvinceCode());
1279  }
1280  } else {
1281  $shipperPart->addChild('Name', $request->getShipperContactCompanyName());
1282  $shipperPart->addChild('AttentionName', $request->getShipperContactPersonName());
1283  $shipperPart->addChild('ShipperNumber', $this->getConfigData('shipper_number'));
1284  $shipperPart->addChild('PhoneNumber', $request->getShipperContactPhoneNumber());
1285 
1286  $addressPart = $shipperPart->addChild('Address');
1287  $addressPart->addChild('AddressLine1', $request->getShipperAddressStreet());
1288  $addressPart->addChild('AddressLine2', $request->getShipperAddressStreet2());
1289  $addressPart->addChild('City', $request->getShipperAddressCity());
1290  $addressPart->addChild('CountryCode', $request->getShipperAddressCountryCode());
1291  $addressPart->addChild('PostalCode', $request->getShipperAddressPostalCode());
1292  if ($request->getShipperAddressStateOrProvinceCode()) {
1293  $addressPart->addChild('StateProvinceCode', $request->getShipperAddressStateOrProvinceCode());
1294  }
1295  }
1296 
1297  $shipToPart = $shipmentPart->addChild('ShipTo');
1298  $shipToPart->addChild('AttentionName', $request->getRecipientContactPersonName());
1299  $shipToPart->addChild(
1300  'CompanyName',
1301  $request->getRecipientContactCompanyName() ? $request->getRecipientContactCompanyName() : 'N/A'
1302  );
1303  $shipToPart->addChild('PhoneNumber', $request->getRecipientContactPhoneNumber());
1304 
1305  $addressPart = $shipToPart->addChild('Address');
1306  $addressPart->addChild('AddressLine1', $request->getRecipientAddressStreet1());
1307  $addressPart->addChild('AddressLine2', $request->getRecipientAddressStreet2());
1308  $addressPart->addChild('City', $request->getRecipientAddressCity());
1309  $addressPart->addChild('CountryCode', $request->getRecipientAddressCountryCode());
1310  $addressPart->addChild('PostalCode', $request->getRecipientAddressPostalCode());
1311  if ($request->getRecipientAddressStateOrProvinceCode()) {
1312  $addressPart->addChild('StateProvinceCode', $request->getRecipientAddressRegionCode());
1313  }
1314  if ($this->getConfigData('dest_type') == 'RES') {
1315  $addressPart->addChild('ResidentialAddress');
1316  }
1317 
1318  if ($request->getIsReturn()) {
1319  $shipFromPart = $shipmentPart->addChild('ShipFrom');
1320  $shipFromPart->addChild('AttentionName', $request->getShipperContactPersonName());
1321  $shipFromPart->addChild(
1322  'CompanyName',
1323  $request->getShipperContactCompanyName() ? $request
1324  ->getShipperContactCompanyName() : $request
1325  ->getShipperContactPersonName()
1326  );
1327  $shipFromAddress = $shipFromPart->addChild('Address');
1328  $shipFromAddress->addChild('AddressLine1', $request->getShipperAddressStreet1());
1329  $shipFromAddress->addChild('AddressLine2', $request->getShipperAddressStreet2());
1330  $shipFromAddress->addChild('City', $request->getShipperAddressCity());
1331  $shipFromAddress->addChild('CountryCode', $request->getShipperAddressCountryCode());
1332  $shipFromAddress->addChild('PostalCode', $request->getShipperAddressPostalCode());
1333  if ($request->getShipperAddressStateOrProvinceCode()) {
1334  $shipFromAddress->addChild('StateProvinceCode', $request->getShipperAddressStateOrProvinceCode());
1335  }
1336 
1337  $addressPart = $shipToPart->addChild('Address');
1338  $addressPart->addChild('AddressLine1', $request->getShipperAddressStreet1());
1339  $addressPart->addChild('AddressLine2', $request->getShipperAddressStreet2());
1340  $addressPart->addChild('City', $request->getShipperAddressCity());
1341  $addressPart->addChild('CountryCode', $request->getShipperAddressCountryCode());
1342  $addressPart->addChild('PostalCode', $request->getShipperAddressPostalCode());
1343  if ($request->getShipperAddressStateOrProvinceCode()) {
1344  $addressPart->addChild('StateProvinceCode', $request->getShipperAddressStateOrProvinceCode());
1345  }
1346  if ($this->getConfigData('dest_type') == 'RES') {
1347  $addressPart->addChild('ResidentialAddress');
1348  }
1349  }
1350 
1351  $servicePart = $shipmentPart->addChild('Service');
1352  $servicePart->addChild('Code', $request->getShippingMethod());
1353  $packagePart = $shipmentPart->addChild('Package');
1354  $packagePart->addChild('Description', substr(implode(' ', $itemsDesc), 0, 35));
1355  //empirical
1356  $packagePart->addChild('PackagingType')->addChild('Code', $request->getPackagingType());
1357  $packageWeight = $packagePart->addChild('PackageWeight');
1358  $packageWeight->addChild('Weight', $request->getPackageWeight());
1359  $packageWeight->addChild('UnitOfMeasurement')->addChild('Code', $weightUnits);
1360 
1361  // set dimensions
1362  if ($length || $width || $height) {
1363  $packageDimensions = $packagePart->addChild('Dimensions');
1364  $packageDimensions->addChild('UnitOfMeasurement')->addChild('Code', $dimensionsUnits);
1365  $packageDimensions->addChild('Length', $length);
1366  $packageDimensions->addChild('Width', $width);
1367  $packageDimensions->addChild('Height', $height);
1368  }
1369 
1370  // ups support reference number only for domestic service
1371  if ($this->_isUSCountry($request->getRecipientAddressCountryCode())
1372  && $this->_isUSCountry($request->getShipperAddressCountryCode())
1373  ) {
1374  if ($request->getReferenceData()) {
1375  $referenceData = $request->getReferenceData() . $request->getPackageId();
1376  } else {
1377  $referenceData = 'Order #' .
1378  $request->getOrderShipment()->getOrder()->getIncrementId() .
1379  ' P' .
1380  $request->getPackageId();
1381  }
1382  $referencePart = $packagePart->addChild('ReferenceNumber');
1383  $referencePart->addChild('Code', '02');
1384  $referencePart->addChild('Value', $referenceData);
1385  }
1386 
1387  $deliveryConfirmation = $packageParams->getDeliveryConfirmation();
1388  if ($deliveryConfirmation) {
1390  $serviceOptionsNode = null;
1391  switch ($this->_getDeliveryConfirmationLevel($request->getRecipientAddressCountryCode())) {
1393  $serviceOptionsNode = $packagePart->addChild('PackageServiceOptions');
1394  break;
1396  $serviceOptionsNode = $shipmentPart->addChild('ShipmentServiceOptions');
1397  break;
1398  default:
1399  break;
1400  }
1401  if ($serviceOptionsNode !== null) {
1402  $serviceOptionsNode->addChild(
1403  'DeliveryConfirmation'
1404  )->addChild(
1405  'DCISType',
1406  $packageParams->getDeliveryConfirmation()
1407  );
1408  }
1409  }
1410 
1411  $shipmentPart->addChild('PaymentInformation')
1412  ->addChild('Prepaid')
1413  ->addChild('BillShipper')
1414  ->addChild('AccountNumber', $this->getConfigData('shipper_number'));
1415 
1416  if ($request->getPackagingType() != $this->configHelper->getCode('container', 'ULE')
1417  && $request->getShipperAddressCountryCode() == self::USA_COUNTRY_ID
1418  && ($request->getRecipientAddressCountryCode() == 'CA'
1419  || $request->getRecipientAddressCountryCode() == 'PR')
1420  ) {
1421  $invoiceLineTotalPart = $shipmentPart->addChild('InvoiceLineTotal');
1422  $invoiceLineTotalPart->addChild('CurrencyCode', $request->getBaseCurrencyCode());
1423  $invoiceLineTotalPart->addChild('MonetaryValue', ceil($packageParams->getCustomsValue()));
1424  }
1425 
1426  $labelPart = $xmlRequest->addChild('LabelSpecification');
1427  $labelPart->addChild('LabelPrintMethod')->addChild('Code', 'GIF');
1428  $labelPart->addChild('LabelImageFormat')->addChild('Code', 'GIF');
1429 
1430  return $xmlRequest->asXml();
1431  }
1432 
1439  protected function _sendShipmentAcceptRequest(Element $shipmentConfirmResponse)
1440  {
1441  $xmlRequest = $this->_xmlElFactory->create(
1442  ['data' => '<?xml version = "1.0" ?><ShipmentAcceptRequest/>']
1443  );
1444  $request = $xmlRequest->addChild('Request');
1445  $request->addChild('RequestAction', 'ShipAccept');
1446  $xmlRequest->addChild('ShipmentDigest', $shipmentConfirmResponse->ShipmentDigest);
1447  $debugData = ['request' => $this->filterDebugData($this->_xmlAccessRequest) . $xmlRequest->asXML()];
1448 
1449  try {
1450  $client = $this->httpClientFactory->create();
1451  $client->post($this->getShipAcceptUrl(), $this->_xmlAccessRequest . $xmlRequest->asXML());
1452  $xmlResponse = $client->getBody();
1453  $debugData['result'] = $xmlResponse;
1454  $this->_setCachedQuotes($xmlRequest, $xmlResponse);
1455  } catch (\Throwable $e) {
1456  $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
1457  $xmlResponse = '';
1458  }
1459 
1460  try {
1461  $response = $this->_xmlElFactory->create(['data' => $xmlResponse]);
1462  } catch (\Throwable $e) {
1463  $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
1464  }
1465 
1466  $result = new \Magento\Framework\DataObject();
1467  if (isset($response->Error)) {
1468  $result->setErrors((string)$response->Error->ErrorDescription);
1469  } else {
1470  $shippingLabelContent = (string)$response->ShipmentResults->PackageResults->LabelImage->GraphicImage;
1471  $trackingNumber = (string)$response->ShipmentResults->PackageResults->TrackingNumber;
1472 
1473  $result->setShippingLabelContent(base64_decode($shippingLabelContent));
1474  $result->setTrackingNumber($trackingNumber);
1475  }
1476 
1477  $this->_debug($debugData);
1478 
1479  return $result;
1480  }
1481 
1487  public function getShipAcceptUrl()
1488  {
1489  if ($this->getConfigData('is_account_live')) {
1490  $url = $this->_liveUrls['ShipAccept'];
1491  } else {
1492  $url = $this->_defaultUrls['ShipAccept'];
1493  }
1494 
1495  return $url;
1496  }
1497 
1504  protected function _doShipmentRequest(\Magento\Framework\DataObject $request)
1505  {
1506  $this->_prepareShipmentRequest($request);
1507  $result = new \Magento\Framework\DataObject();
1508  $rawXmlRequest = $this->_formShipmentRequest($request);
1509  $this->setXMLAccessRequest();
1510  $xmlRequest = $this->_xmlAccessRequest . $rawXmlRequest;
1511  $xmlResponse = $this->_getCachedQuotes($xmlRequest);
1512 
1513  if ($xmlResponse === null) {
1514  $debugData['request'] = $this->filterDebugData($this->_xmlAccessRequest) . $rawXmlRequest;
1515  $url = $this->getShipConfirmUrl();
1516  $client = $this->httpClientFactory->create();
1517  try {
1518  $client->post($url, $xmlRequest);
1519  $xmlResponse = $client->getBody();
1520  $debugData['result'] = $xmlResponse;
1521  $this->_setCachedQuotes($xmlRequest, $xmlResponse);
1522  } catch (\Throwable $e) {
1523  $debugData['result'] = ['code' => $e->getCode(), 'error' => $e->getMessage()];
1524  }
1525  }
1526 
1527  try {
1528  $response = $this->_xmlElFactory->create(['data' => $xmlResponse]);
1529  } catch (\Throwable $e) {
1530  $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
1531  $result->setErrors($e->getMessage());
1532  }
1533 
1534  if (isset($response->Response->Error)
1535  && in_array($response->Response->Error->ErrorSeverity, ['Hard', 'Transient'])
1536  ) {
1537  $result->setErrors((string)$response->Response->Error->ErrorDescription);
1538  }
1539 
1540  $this->_debug($debugData);
1541 
1542  if ($result->hasErrors() || empty($response)) {
1543  return $result;
1544  } else {
1545  return $this->_sendShipmentAcceptRequest($response);
1546  }
1547  }
1548 
1554  public function getShipConfirmUrl()
1555  {
1556  $url = $this->getConfigData('url');
1557  if (!$url) {
1558  if ($this->getConfigData('is_account_live')) {
1559  $url = $this->_liveUrls['ShipConfirm'];
1560 
1561  return $url;
1562  } else {
1563  $url = $this->_defaultUrls['ShipConfirm'];
1564 
1565  return $url;
1566  }
1567  }
1568 
1569  return $url;
1570  }
1571 
1579  public function getContainerTypes(\Magento\Framework\DataObject $params = null)
1580  {
1581  if ($params === null) {
1582  return $this->_getAllowedContainers($params);
1583  }
1584  $method = $params->getMethod();
1585  $countryShipper = $params->getCountryShipper();
1586  $countryRecipient = $params->getCountryRecipient();
1587 
1588  if ($countryShipper == self::USA_COUNTRY_ID && $countryRecipient == self::CANADA_COUNTRY_ID ||
1589  $countryShipper == self::CANADA_COUNTRY_ID && $countryRecipient == self::USA_COUNTRY_ID ||
1590  $countryShipper == self::MEXICO_COUNTRY_ID && $countryRecipient == self::USA_COUNTRY_ID && $method == '11'
1591  ) {
1592  $containerTypes = [];
1593  if ($method == '07' || $method == '08' || $method == '65') {
1594  // Worldwide Expedited
1595  if ($method != '08') {
1596  $containerTypes = [
1597  '01' => __('UPS Letter Envelope'),
1598  '24' => __('UPS Worldwide 25 kilo'),
1599  '25' => __('UPS Worldwide 10 kilo'),
1600  ];
1601  }
1602  $containerTypes = $containerTypes + [
1603  '03' => __('UPS Tube'),
1604  '04' => __('PAK'),
1605  '2a' => __('Small Express Box'),
1606  '2b' => __('Medium Express Box'),
1607  '2c' => __('Large Express Box'),
1608  ];
1609  }
1610 
1611  return ['00' => __('Customer Packaging')] + $containerTypes;
1612  } elseif ($countryShipper == self::USA_COUNTRY_ID &&
1613  $countryRecipient == self::PUERTORICO_COUNTRY_ID &&
1614  ($method == '03' ||
1615  $method == '02' ||
1616  $method == '01')
1617  ) {
1618  // Container types should be the same as for domestic
1619  $params->setCountryRecipient(self::USA_COUNTRY_ID);
1620  $containerTypes = $this->_getAllowedContainers($params);
1621  $params->setCountryRecipient($countryRecipient);
1622 
1623  return $containerTypes;
1624  }
1625 
1626  return $this->_getAllowedContainers($params);
1627  }
1628 
1634  public function getContainerTypesAll()
1635  {
1636  $codes = $this->configHelper->getCode('container');
1637  $descriptions = $this->configHelper->getCode('container_description');
1638  $result = [];
1639  foreach ($codes as $key => &$code) {
1640  $result[$code] = $descriptions[$key];
1641  }
1642 
1643  return $result;
1644  }
1645 
1651  public function getContainerTypesFilter()
1652  {
1653  return $this->configHelper->getCode('containers_filter');
1654  }
1655 
1662  public function getDeliveryConfirmationTypes(\Magento\Framework\DataObject $params = null)
1663  {
1664  $countryRecipient = $params != null ? $params->getCountryRecipient() : null;
1665  $deliveryConfirmationTypes = [];
1666  switch ($this->_getDeliveryConfirmationLevel($countryRecipient)) {
1668  $deliveryConfirmationTypes = [
1669  1 => __('Delivery Confirmation'),
1670  2 => __('Signature Required'),
1671  3 => __('Adult Signature Required'),
1672  ];
1673  break;
1675  $deliveryConfirmationTypes = [1 => __('Signature Required'), 2 => __('Adult Signature Required')];
1676  break;
1677  default:
1678  break;
1679  }
1680  array_unshift($deliveryConfirmationTypes, __('Not Required'));
1681 
1682  return $deliveryConfirmationTypes;
1683  }
1684 
1691  {
1692  $result = [];
1693  $containerTypes = $this->configHelper->getCode('container');
1694  foreach (parent::getCustomizableContainerTypes() as $containerType) {
1695  $result[$containerType] = $containerTypes[$containerType];
1696  }
1697 
1698  return $result;
1699  }
1700 
1708  protected function _getDeliveryConfirmationLevel($countyDestination = null)
1709  {
1710  if ($countyDestination === null) {
1711  return null;
1712  }
1713 
1714  if ($countyDestination == self::USA_COUNTRY_ID) {
1716  }
1717 
1719  }
1720 }
_prepareShipmentRequest(\Magento\Framework\DataObject $request)
$response
Definition: 404.php:11
if(!defined( 'PHP_VERSION_ID')||!(PHP_VERSION_ID===70002||PHP_VERSION_ID===70004||PHP_VERSION_ID >=70006))
Definition: bootstrap.php:14
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
_parseXmlResponse($xmlResponse)
Definition: Carrier.php:806
getTracking($trackings)
Definition: Carrier.php:945
__()
Definition: __.php:13
const DELIVERY_CONFIRMATION_PACKAGE
Definition: Carrier.php:38
$price
$message
$logger
_sendShipmentAcceptRequest(Element $shipmentConfirmResponse)
Definition: Carrier.php:1439
const DELIVERY_CONFIRMATION_SHIPMENT
Definition: Carrier.php:36
_getCgiTracking($trackings)
Definition: Carrier.php:988
$status
Definition: order_status.php:8
setRequest(RateRequest $request)
Definition: Carrier.php:232
_parseXmlTrackingResponse($trackingValue, $xmlResponse)
Definition: Carrier.php:1064
getDeliveryConfirmationTypes(\Magento\Framework\DataObject $params=null)
Definition: Carrier.php:1662
$method
Definition: info.phtml:13
_getAllowedContainers(\Magento\Framework\DataObject $params=null)
_parseCgiResponse($response)
Definition: Carrier.php:525
getShipmentByCode($code, $origin=null)
Definition: Carrier.php:505
_getDeliveryConfirmationLevel($countyDestination=null)
Definition: Carrier.php:1708
_getXmlTracking($trackings)
Definition: Carrier.php:1018
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE]
Definition: website.php:18
_doShipmentRequest(\Magento\Framework\DataObject $request)
Definition: Carrier.php:1504
_setFreeMethodRequest($freeMethod)
Definition: Carrier.php:429
collectRates(RateRequest $request)
Definition: Carrier.php:209
$index
Definition: list.phtml:44
$code
Definition: info.phtml:12
__construct(\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory, \Psr\Log\LoggerInterface $logger, Security $xmlSecurity, \Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory, \Magento\Shipping\Model\Rate\ResultFactory $rateFactory, \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory, \Magento\Shipping\Model\Tracking\ResultFactory $trackFactory, \Magento\Shipping\Model\Tracking\Result\ErrorFactory $trackErrorFactory, \Magento\Shipping\Model\Tracking\Result\StatusFactory $trackStatusFactory, \Magento\Directory\Model\RegionFactory $regionFactory, \Magento\Directory\Model\CountryFactory $countryFactory, \Magento\Directory\Model\CurrencyFactory $currencyFactory, \Magento\Directory\Helper\Data $directoryData, \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry, \Magento\Framework\Locale\FormatInterface $localeFormat, Config $configHelper, ClientFactory $httpClientFactory, array $data=[])
Definition: Carrier.php:159
getContainerTypes(\Magento\Framework\DataObject $params=null)
Definition: Carrier.php:1579