61 'RATED_ACCOUNT_PACKAGE',
62 'PAYOR_ACCOUNT_PACKAGE',
63 'RATED_ACCOUNT_SHIPMENT',
64 'PAYOR_ACCOUNT_SHIPMENT',
67 'RATED_LIST_SHIPMENT',
68 'PAYOR_LIST_SHIPMENT',
127 'Key',
'Password',
'MeterNumber',
134 private static $trackServiceVersion = 10;
140 private static $trackingErrors = [
'FAILURE',
'ERROR'];
150 private $soapClientFactory;
177 \
Magento\Framework\
App\Config\ScopeConfigInterface $scopeConfig,
178 \
Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
179 \Psr\Log\LoggerInterface
$logger,
181 \
Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
182 \
Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
183 \
Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
184 \
Magento\Shipping\Model\Tracking\ResultFactory $trackFactory,
185 \
Magento\Shipping\Model\Tracking\
Result\ErrorFactory $trackErrorFactory,
186 \
Magento\Shipping\Model\Tracking\
Result\StatusFactory $trackStatusFactory,
187 \
Magento\Directory\Model\RegionFactory $regionFactory,
188 \
Magento\Directory\Model\CountryFactory $countryFactory,
189 \
Magento\Directory\Model\CurrencyFactory $currencyFactory,
190 \
Magento\Directory\Helper\Data $directoryData,
196 Json $serializer =
null,
200 $this->_productCollectionFactory = $productCollectionFactory;
219 $wsdlBasePath = $configReader->getModuleDir(
Dir::MODULE_ETC_DIR,
'Magento_Fedex') .
'/wsdl/';
220 $this->_shipServiceWsdl = $wsdlBasePath .
'ShipService_v10.wsdl';
221 $this->_rateServiceWsdl = $wsdlBasePath .
'RateService_v10.wsdl';
222 $this->_trackServiceWsdl = $wsdlBasePath .
'TrackService_v' . self::$trackServiceVersion .
'.wsdl';
236 $client = $this->soapClientFactory->create($wsdl, [
'trace' => $trace]);
237 $client->__setLocation(
307 $r = new \Magento\Framework\DataObject();
310 $r->setService(
$request->getLimitMethod());
314 $account =
$request->getFedexAccount();
318 $r->setAccount($account);
321 $dropoff =
$request->getFedexDropoff();
325 $r->setDropoffType($dropoff);
327 if (
$request->getFedexPackaging()) {
328 $packaging =
$request->getFedexPackaging();
332 $r->setPackaging($packaging);
335 $origCountry =
$request->getOrigCountry();
337 $origCountry = $this->_scopeConfig->getValue(
338 \
Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_COUNTRY_ID,
339 \
Magento\Store\Model\ScopeInterface::SCOPE_STORE,
343 $r->setOrigCountry($this->_countryFactory->create()->load($origCountry)->getData(
'iso2_code'));
346 $r->setOrigPostal(
$request->getOrigPostcode());
349 $this->_scopeConfig->getValue(
350 \
Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_ZIP,
351 \
Magento\Store\Model\ScopeInterface::SCOPE_STORE,
358 $destCountry =
$request->getDestCountryId();
362 $r->setDestCountry($this->_countryFactory->create()->load($destCountry)->getData(
'iso2_code'));
365 $r->setDestPostal(
$request->getDestPostcode());
370 $r->setDestCity(
$request->getDestCity());
374 $r->setWeight($weight);
376 $r->setFreeMethodWeight(
$request->getFreeMethodWeight());
379 $r->setValue(
$request->getPackagePhysicalValue());
380 $r->setValueWithDiscount(
$request->getPackageValueWithDiscount());
386 $r->setIsReturn(
$request->getIsReturn());
388 $r->setBaseSubtotalInclTax(
$request->getBaseSubtotalInclTax());
402 if (!$this->_result) {
403 $this->_result = $this->_trackFactory->create();
415 return [
'ServiceId' =>
'crs',
'Major' =>
'10',
'Intermediate' =>
'0',
'Minor' =>
'0'];
428 'WebAuthenticationDetail' => [
429 'UserCredential' => [
'Key' => $r->getKey(),
'Password' => $r->getPassword()],
431 'ClientDetail' => [
'AccountNumber' => $r->getAccount(),
'MeterNumber' => $r->getMeterNumber()],
433 'RequestedShipment' => [
434 'DropoffType' => $r->getDropoffType(),
435 'ShipTimestamp' => date(
'c'),
436 'PackagingType' => $r->getPackaging(),
437 'TotalInsuredValue' => [
'Amount' => $r->getValue(),
'Currency' => $this->
getCurrencyCode()],
439 'Address' => [
'PostalCode' => $r->getOrigPostal(),
'CountryCode' => $r->getOrigCountry()],
443 'PostalCode' => $r->getDestPostal(),
444 'CountryCode' => $r->getDestCountry(),
445 'Residential' => (bool)$this->
getConfigData(
'residence_delivery'),
448 'ShippingChargesPayment' => [
449 'PaymentType' =>
'SENDER',
450 'Payor' => [
'AccountNumber' => $r->getAccount(),
'CountryCode' => $r->getOrigCountry()],
452 'CustomsClearanceDetail' => [
453 'CustomsValue' => [
'Amount' => $r->getValue(),
'Currency' => $this->
getCurrencyCode()],
455 'RateRequestTypes' =>
'LIST',
456 'PackageCount' =>
'1',
457 'PackageDetail' =>
'INDIVIDUAL_PACKAGES',
458 'RequestedPackageLineItems' => [
461 'Value' => (double)$r->getWeight(),
464 'GroupPackageCount' => 1,
470 if ($r->getDestCity()) {
471 $ratesRequest[
'RequestedShipment'][
'Recipient'][
'Address'][
'City'] = $r->getDestCity();
474 if ($purpose == self::RATE_REQUEST_GENERAL) {
475 $ratesRequest[
'RequestedShipment'][
'RequestedPackageLineItems'][0][
'InsuredValue'] = [
476 'Amount' => $r->getValue(),
480 if ($purpose == self::RATE_REQUEST_SMARTPOST) {
482 $ratesRequest[
'RequestedShipment'][
'SmartPostDetail'] = [
483 'Indicia' => (double)$r->getWeight() >= 1 ?
'PARCEL_SELECT' :
'PRESORTED_STANDARD',
489 return $ratesRequest;
501 $ratesRequestNoShipTimestamp = $ratesRequest;
502 unset($ratesRequestNoShipTimestamp[
'RequestedShipment'][
'ShipTimestamp']);
503 $requestString = $this->serializer->serialize($ratesRequestNoShipTimestamp);
509 $response = $client->getRates($ratesRequest);
512 }
catch (\Exception $e) {
513 $debugData[
'result'] = [
'error' => $e->getMessage(),
'code' => $e->getCode()];
514 $this->_logger->critical($e);
519 $this->
_debug($debugData);
531 $this->_result = $this->_rateFactory->create();
533 $allowedMethods = explode(
',', $this->
getConfigData(
'allowed_methods'));
534 if (in_array(self::RATE_REQUEST_SMARTPOST, $allowedMethods)) {
537 if (!$preparedSmartpost->getError()) {
538 $this->_result->append($preparedSmartpost);
544 if (!$preparedGeneral->getError()
545 || $this->_result->getError() && $preparedGeneral->getError()
546 || empty($this->_result->getAllRates())
548 $this->_result->append($preparedGeneral);
565 $errorTitle =
'For some reason we can\'t retrieve tracking info right now.';
568 if (
$response->HighestSeverity ==
'FAILURE' ||
$response->HighestSeverity ==
'ERROR') {
569 if (is_array(
$response->Notifications)) {
570 $notification = array_pop(
$response->Notifications);
571 $errorTitle = (string)$notification->Message;
573 $errorTitle = (string)
$response->Notifications->Message;
576 $allowedMethods = explode(
",", $this->
getConfigData(
'allowed_methods'));
578 if (is_array(
$response->RateReplyDetails)) {
580 $serviceName = (string)
$rate->ServiceType;
581 if (in_array($serviceName, $allowedMethods)) {
583 $costArr[$serviceName] =
$amount;
590 $serviceName = (string)
$rate->ServiceType;
591 if (in_array($serviceName, $allowedMethods)) {
593 $costArr[$serviceName] =
$amount;
600 $result = $this->_rateFactory->create();
601 if (empty($priceArr)) {
602 $error = $this->_rateErrorFactory->create();
603 $error->setCarrier($this->_code);
605 $error->setErrorMessage($errorTitle);
606 $error->setErrorMessage($this->
getConfigData(
'specificerrmsg'));
610 $rate = $this->_rateMethodFactory->create();
611 $rate->setCarrier($this->_code);
633 $rateTypeAmounts = [];
635 if (is_object(
$rate)) {
637 foreach (
$rate->RatedShipmentDetails as $ratedShipmentDetail) {
638 $netAmount = (string)$ratedShipmentDetail->ShipmentRateDetail->TotalNetCharge->Amount;
639 $rateType = (
string)$ratedShipmentDetail->ShipmentRateDetail->RateType;
640 $rateTypeAmounts[$rateType] = $netAmount;
643 foreach ($this->_ratesOrder as $rateType) {
644 if (!empty($rateTypeAmounts[$rateType])) {
645 $amount = $rateTypeAmounts[$rateType];
651 $amount = (string)
$rate->RatedShipmentDetails[0]->ShipmentRateDetail->TotalNetCharge->Amount;
668 $r->setWeight($weight);
669 $r->setService($freeMethod);
680 $xml = $this->_xmlElFactory->create(
681 [
'data' =>
'<?xml version = "1.0" encoding = "UTF-8"?><FDXRateAvailableServicesRequest/>']
684 $xml->addAttribute(
'xmlns:api',
'http://www.fedex.com/fsmapi');
685 $xml->addAttribute(
'xmlns:xsi',
'http://www.w3.org/2001/XMLSchema-instance');
686 $xml->addAttribute(
'xsi:noNamespaceSchemaLocation',
'FDXRateAvailableServicesRequest.xsd');
688 $requestHeader = $xml->addChild(
'RequestHeader');
689 $requestHeader->addChild(
'AccountNumber', $r->getAccount());
690 $requestHeader->addChild(
'MeterNumber',
'0');
692 $xml->addChild(
'ShipDate', date(
'Y-m-d'));
693 $xml->addChild(
'DropoffType', $r->getDropoffType());
694 if ($r->hasService()) {
695 $xml->addChild(
'Service', $r->getService());
697 $xml->addChild(
'Packaging', $r->getPackaging());
698 $xml->addChild(
'WeightUnits',
'LBS');
699 $xml->addChild(
'Weight', $r->getWeight());
701 $originAddress = $xml->addChild(
'OriginAddress');
702 $originAddress->addChild(
'PostalCode', $r->getOrigPostal());
703 $originAddress->addChild(
'CountryCode', $r->getOrigCountry());
705 $destinationAddress = $xml->addChild(
'DestinationAddress');
706 $destinationAddress->addChild(
'PostalCode', $r->getDestPostal());
707 $destinationAddress->addChild(
'CountryCode', $r->getDestCountry());
709 $payment = $xml->addChild(
'Payment');
710 $payment->addChild(
'PayorType',
'SENDER');
712 $declaredValue = $xml->addChild(
'DeclaredValue');
713 $declaredValue->addChild(
'Value', $r->getValue());
717 $specialServices = $xml->addChild(
'SpecialServices');
718 $specialServices->addChild(
'ResidentialDelivery',
'true');
721 $xml->addChild(
'PackageCount',
'1');
726 if ($responseBody ===
null) {
731 $url = $this->_defaultGatewayUrl;
734 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
735 curl_setopt($ch, CURLOPT_URL,
$url);
736 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,
true);
737 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
738 curl_setopt($ch, CURLOPT_POSTFIELDS,
$request);
744 }
catch (\Exception $e) {
745 $debugData[
'result'] = [
'error' => $e->getMessage(),
'code' => $e->getCode()];
748 $this->
_debug($debugData);
768 if (is_object($xml)) {
769 if (is_object($xml->Error) && is_object($xml->Error->Message)) {
770 $errorTitle = (string)$xml->Error->Message;
771 }
elseif (is_object($xml->SoftError) && is_object($xml->SoftError->Message)) {
772 $errorTitle = (string)$xml->SoftError->Message;
774 $errorTitle =
'Sorry, something went wrong. Please try again or contact us and we\'ll try to help.';
777 $allowedMethods = explode(
",", $this->
getConfigData(
'allowed_methods'));
779 foreach ($xml->Entry as $entry) {
780 if (in_array((
string)$entry->Service, $allowedMethods)) {
781 $costArr[(string)$entry->Service] = (
string)$entry
785 $priceArr[(string)$entry->Service] = $this->getMethodPrice(
786 (
string)$entry->EstimatedCharges->DiscountedCharges->NetCharge,
787 (
string)$entry->Service
794 $errorTitle =
'Response is in the wrong format.';
797 $errorTitle =
'For some reason we can\'t retrieve tracking info right now.';
800 $result = $this->_rateFactory->create();
801 if (empty($priceArr)) {
802 $error = $this->_rateErrorFactory->create();
803 $error->setCarrier(
'fedex');
805 $error->setErrorMessage($this->
getConfigData(
'specificerrmsg'));
809 $rate = $this->_rateMethodFactory->create();
810 $rate->setCarrier(
'fedex');
835 'EUROPE_FIRST_INTERNATIONAL_PRIORITY' =>
__(
'Europe First Priority'),
836 'FEDEX_1_DAY_FREIGHT' =>
__(
'1 Day Freight'),
837 'FEDEX_2_DAY_FREIGHT' =>
__(
'2 Day Freight'),
838 'FEDEX_2_DAY' =>
__(
'2 Day'),
839 'FEDEX_2_DAY_AM' =>
__(
'2 Day AM'),
840 'FEDEX_3_DAY_FREIGHT' =>
__(
'3 Day Freight'),
841 'FEDEX_EXPRESS_SAVER' =>
__(
'Express Saver'),
842 'FEDEX_GROUND' =>
__(
'Ground'),
843 'FIRST_OVERNIGHT' =>
__(
'First Overnight'),
844 'GROUND_HOME_DELIVERY' =>
__(
'Home Delivery'),
845 'INTERNATIONAL_ECONOMY' =>
__(
'International Economy'),
846 'INTERNATIONAL_ECONOMY_FREIGHT' =>
__(
'Intl Economy Freight'),
847 'INTERNATIONAL_FIRST' =>
__(
'International First'),
848 'INTERNATIONAL_GROUND' =>
__(
'International Ground'),
849 'INTERNATIONAL_PRIORITY' =>
__(
'International Priority'),
850 'INTERNATIONAL_PRIORITY_FREIGHT' =>
__(
'Intl Priority Freight'),
851 'PRIORITY_OVERNIGHT' =>
__(
'Priority Overnight'),
852 'SMART_POST' =>
__(
'Smart Post'),
853 'STANDARD_OVERNIGHT' =>
__(
'Standard Overnight'),
854 'FEDEX_FREIGHT' =>
__(
'Freight'),
855 'FEDEX_NATIONAL_FREIGHT' =>
__(
'National Freight'),
858 'REGULAR_PICKUP' =>
__(
'Regular Pickup'),
859 'REQUEST_COURIER' =>
__(
'Request Courier'),
860 'DROP_BOX' =>
__(
'Drop Box'),
861 'BUSINESS_SERVICE_CENTER' =>
__(
'Business Service Center'),
862 'STATION' =>
__(
'Station'),
865 'FEDEX_ENVELOPE' =>
__(
'FedEx Envelope'),
866 'FEDEX_PAK' =>
__(
'FedEx Pak'),
867 'FEDEX_BOX' =>
__(
'FedEx Box'),
868 'FEDEX_TUBE' =>
__(
'FedEx Tube'),
869 'FEDEX_10KG_BOX' =>
__(
'FedEx 10kg Box'),
870 'FEDEX_25KG_BOX' =>
__(
'FedEx 25kg Box'),
871 'YOUR_PACKAGING' =>
__(
'Your Packaging'),
873 'containers_filter' => [
875 'containers' => [
'FEDEX_ENVELOPE',
'FEDEX_PAK'],
879 'FEDEX_EXPRESS_SAVER',
882 'STANDARD_OVERNIGHT',
883 'PRIORITY_OVERNIGHT',
888 'method' => [
'INTERNATIONAL_FIRST',
'INTERNATIONAL_ECONOMY',
'INTERNATIONAL_PRIORITY'],
893 'containers' => [
'FEDEX_BOX',
'FEDEX_TUBE'],
899 'STANDARD_OVERNIGHT',
900 'PRIORITY_OVERNIGHT',
903 'FEDEX_1_DAY_FREIGHT',
904 'FEDEX_2_DAY_FREIGHT',
905 'FEDEX_3_DAY_FREIGHT',
906 'FEDEX_NATIONAL_FREIGHT',
910 'method' => [
'INTERNATIONAL_FIRST',
'INTERNATIONAL_ECONOMY',
'INTERNATIONAL_PRIORITY'],
915 'containers' => [
'FEDEX_10KG_BOX',
'FEDEX_25KG_BOX'],
918 'from_us' => [
'method' => [
'INTERNATIONAL_PRIORITY']],
922 'containers' => [
'YOUR_PACKAGING'],
927 'GROUND_HOME_DELIVERY',
929 'FEDEX_EXPRESS_SAVER',
932 'STANDARD_OVERNIGHT',
933 'PRIORITY_OVERNIGHT',
936 'FEDEX_1_DAY_FREIGHT',
937 'FEDEX_2_DAY_FREIGHT',
938 'FEDEX_3_DAY_FREIGHT',
939 'FEDEX_NATIONAL_FREIGHT',
944 'INTERNATIONAL_FIRST',
945 'INTERNATIONAL_ECONOMY',
946 'INTERNATIONAL_PRIORITY',
947 'INTERNATIONAL_GROUND',
949 'FEDEX_1_DAY_FREIGHT',
950 'FEDEX_2_DAY_FREIGHT',
951 'FEDEX_3_DAY_FREIGHT',
952 'FEDEX_NATIONAL_FREIGHT',
953 'INTERNATIONAL_ECONOMY_FREIGHT',
954 'INTERNATIONAL_PRIORITY_FREIGHT',
960 'delivery_confirmation_types' => [
961 'NO_SIGNATURE_REQUIRED' =>
__(
'Not Required'),
962 'ADULT' =>
__(
'Adult'),
963 'DIRECT' =>
__(
'Direct'),
964 'INDIRECT' =>
__(
'Indirect'),
966 'unit_of_measure' => [
967 'LB' =>
__(
'Pounds'),
968 'KG' =>
__(
'Kilograms'),
972 if (!isset($codes[
$type])) {
975 return $codes[
$type];
1009 $currencyCode = $this->_storeManager->getStore()->getBaseCurrencyCode();
1011 return isset($codes[$currencyCode]) ? $codes[$currencyCode] : $currencyCode;
1024 if (!is_array($trackings)) {
1025 $trackings = [$trackings];
1028 foreach ($trackings as $tracking) {
1042 $r = new \Magento\Framework\DataObject();
1045 $r->setAccount($account);
1047 $this->_rawTrackingRequest = $r;
1059 'WebAuthenticationDetail' => [
1060 'UserCredential' => [
1070 'ServiceId' =>
'trck',
1071 'Major' => self::$trackServiceVersion,
1072 'Intermediate' =>
'0',
1075 'SelectionDetails' => [
1076 'PackageIdentifier' => [
'Type' =>
'TRACKING_NUMBER_OR_DOORTAG',
'Value' => $tracking],
1078 'ProcessingOptions' =>
'INCLUDE_DETAILED_SCANS' 1080 $requestString = $this->serializer->serialize($trackRequest);
1086 $response = $client->track($trackRequest);
1089 }
catch (\Exception $e) {
1090 $debugData[
'result'] = [
'error' => $e->getMessage(),
'code' => $e->getCode()];
1091 $this->_logger->critical($e);
1096 $this->
_debug($debugData);
1111 $this->appendTrackingError($trackingValue,
__(
'Invalid response from carrier'));
1113 }
elseif (in_array(
$response->HighestSeverity, self::$trackingErrors)) {
1114 $this->appendTrackingError($trackingValue, (
string)
$response->Notifications->Message);
1117 $this->appendTrackingError($trackingValue,
__(
'No available tracking items'));
1121 $trackInfo =
$response->CompletedTrackDetails->TrackDetails;
1124 if (is_object($trackInfo)) {
1125 $trackInfo = [$trackInfo];
1131 foreach ($trackInfo as
$item) {
1132 $tracking = $this->_trackStatusFactory->create();
1133 $tracking->setCarrier(self::CODE);
1134 $tracking->setCarrierTitle($carrierTitle);
1135 $tracking->setTracking($trackingValue);
1136 $tracking->addData($this->processTrackingDetails(
$item));
1143 $this->appendTrackingError(
1145 __(
'For some reason we can\'t retrieve tracking info right now.')
1158 if ($this->_result instanceof \
Magento\Shipping\Model\Tracking\
Result) {
1159 if ($trackings = $this->_result->getAllTrackings()) {
1160 foreach ($trackings as $tracking) {
1161 if (
$data = $tracking->getAllData()) {
1162 if (!empty(
$data[
'status'])) {
1163 $statuses .=
__(
$data[
'status']) .
"\n<br/>";
1165 $statuses .=
__(
'Empty response') .
"\n<br/>";
1171 if (empty($statuses)) {
1172 $statuses =
__(
'Empty response');
1185 $allowed = explode(
',', $this->
getConfigData(
'allowed_methods'));
1187 foreach ($allowed as $k) {
1188 $arr[$k] = $this->
getCode(
'method', $k);
1202 'WebAuthenticationDetail' => [
1203 'UserCredential' => [
1212 'TransactionDetail' => [
1213 'CustomerTransactionId' =>
'*** Express Domestic Shipping Request v9 using PHP ***',
1215 'Version' => [
'ServiceId' =>
'ship',
'Major' =>
'10',
'Intermediate' =>
'0',
'Minor' =>
'0'],
1230 if (
$request->getReferenceData()) {
1233 $referenceData =
'Order #' .
1234 $request->getOrderShipment()->getOrder()->getIncrementId() .
1238 $packageParams =
$request->getPackageParams();
1239 $customsValue = $packageParams->getCustomsValue();
1240 $height = $packageParams->getHeight();
1241 $width = $packageParams->getWidth();
1242 $length = $packageParams->getLength();
1247 $countriesOfManufacture = [];
1249 $packageItems =
$request->getPackageItems();
1250 foreach ($packageItems as $itemShipment) {
1251 $item = new \Magento\Framework\DataObject();
1252 $item->setData($itemShipment);
1254 $unitPrice +=
$item->getPrice();
1255 $itemsQty +=
$item->getQty();
1257 $itemsDesc[] =
$item->getName();
1264 )->addFieldToFilter(
1267 )->addAttributeToSelect(
1268 'country_of_manufacture' 1271 $countriesOfManufacture[] =
$product->getCountryOfManufacture();
1274 $paymentType = $this->getPaymentType(
$request);
1275 $optionType =
$request->getShippingMethod() == self::RATE_REQUEST_SMARTPOST
1276 ?
'SERVICE_DEFAULT' : $packageParams->getDeliveryConfirmation();
1278 'RequestedShipment' => [
1279 'ShipTimestamp' =>
time(),
1281 'PackagingType' => $request->getPackagingType(),
1282 'ServiceType' =>
$request->getShippingMethod(),
1285 'PersonName' =>
$request->getShipperContactPersonName(),
1286 'CompanyName' =>
$request->getShipperContactCompanyName(),
1287 'PhoneNumber' =>
$request->getShipperContactPhoneNumber(),
1290 'StreetLines' => [
$request->getShipperAddressStreet()],
1291 'City' =>
$request->getShipperAddressCity(),
1292 'StateOrProvinceCode' =>
$request->getShipperAddressStateOrProvinceCode(),
1293 'PostalCode' =>
$request->getShipperAddressPostalCode(),
1294 'CountryCode' =>
$request->getShipperAddressCountryCode(),
1299 'PersonName' =>
$request->getRecipientContactPersonName(),
1300 'CompanyName' =>
$request->getRecipientContactCompanyName(),
1301 'PhoneNumber' =>
$request->getRecipientContactPhoneNumber(),
1304 'StreetLines' => [
$request->getRecipientAddressStreet()],
1305 'City' =>
$request->getRecipientAddressCity(),
1306 'StateOrProvinceCode' =>
$request->getRecipientAddressStateOrProvinceCode(),
1307 'PostalCode' =>
$request->getRecipientAddressPostalCode(),
1308 'CountryCode' =>
$request->getRecipientAddressCountryCode(),
1309 'Residential' => (bool)$this->
getConfigData(
'residence_delivery'),
1312 'ShippingChargesPayment' => [
1313 'PaymentType' => $paymentType,
1316 'CountryCode' => $this->_scopeConfig->getValue(
1317 \
Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_COUNTRY_ID,
1318 \
Magento\Store\Model\ScopeInterface::SCOPE_STORE,
1323 'LabelSpecification' => [
1324 'LabelFormatType' =>
'COMMON2D',
1325 'ImageType' =>
'PNG',
1326 'LabelStockType' =>
'PAPER_8.5X11_TOP_HALF_LABEL',
1328 'RateRequestTypes' => [
'ACCOUNT'],
1329 'PackageCount' => 1,
1330 'RequestedPackageLineItems' => [
1331 'SequenceNumber' =>
'1',
1332 'Weight' => [
'Units' => $weightUnits,
'Value' =>
$request->getPackageWeight()],
1333 'CustomerReferences' => [
1334 'CustomerReferenceType' =>
'CUSTOMER_REFERENCE',
1335 'Value' => $referenceData,
1337 'SpecialServicesRequested' => [
1338 'SpecialServiceTypes' =>
'SIGNATURE_OPTION',
1339 'SignatureOptionDetail' => [
'OptionType' => $optionType],
1346 if (
$request->getShipperAddressCountryCode() !=
$request->getRecipientAddressCountryCode()) {
1347 $requestClient[
'RequestedShipment'][
'CustomsClearanceDetail'] = [
1348 'CustomsValue' => [
'Currency' =>
$request->getBaseCurrencyCode(),
'Amount' => $customsValue],
1349 'DutiesPayment' => [
1350 'PaymentType' => $paymentType,
1353 'CountryCode' => $this->_scopeConfig->getValue(
1354 \
Magento\Sales\Model\Order\Shipment::XML_PATH_STORE_COUNTRY_ID,
1355 \
Magento\Store\Model\ScopeInterface::SCOPE_STORE,
1361 'Weight' => [
'Units' => $weightUnits,
'Value' =>
$request->getPackageWeight()],
1362 'NumberOfPieces' => 1,
1363 'CountryOfManufacture' => implode(
',', array_unique($countriesOfManufacture)),
1364 'Description' => implode(
', ', $itemsDesc),
1365 'Quantity' => ceil($itemsQty),
1366 'QuantityUnits' =>
'pcs',
1367 'UnitPrice' => [
'Currency' =>
$request->getBaseCurrencyCode(),
'Amount' => $unitPrice],
1368 'CustomsValue' => [
'Currency' =>
$request->getBaseCurrencyCode(),
'Amount' => $customsValue],
1373 if (
$request->getMasterTrackingId()) {
1374 $requestClient[
'RequestedShipment'][
'MasterTrackingId'] =
$request->getMasterTrackingId();
1378 $requestClient[
'RequestedShipment'][
'SmartPostDetail'] = [
1379 'Indicia' => (double)
$request->getPackageWeight() >= 1 ?
'PARCEL_SELECT' :
'PRESORTED_STANDARD',
1385 if ($length || $width || $height) {
1386 $requestClient[
'RequestedShipment'][
'RequestedPackageLineItems'][
'Dimensions'] = [
1387 'Length' => $length,
1389 'Height' => $height,
1406 $result = new \Magento\Framework\DataObject();
1410 $response = $client->processShipment($requestClient);
1412 if (
$response->HighestSeverity !=
'FAILURE' &&
$response->HighestSeverity !=
'ERROR') {
1413 $shippingLabelContent =
$response->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image;
1414 $trackingNumber = $this->getTrackingNumber(
1415 $response->CompletedShipmentDetail->CompletedPackageDetails->TrackingIds
1417 $result->setShippingLabelContent($shippingLabelContent);
1418 $result->setTrackingNumber($trackingNumber);
1419 $debugData[
'result'] = $client->__getLastResponse();
1420 $this->
_debug($debugData);
1422 $debugData[
'result'] = [
'error' =>
'',
'code' =>
'',
'xml' => $client->__getLastResponse()];
1423 if (is_array(
$response->Notifications)) {
1424 foreach (
$response->Notifications as $notification) {
1425 $debugData[
'result'][
'code'] .= $notification->Code .
'; ';
1426 $debugData[
'result'][
'error'] .= $notification->Message .
'; ';
1429 $debugData[
'result'][
'code'] =
$response->Notifications->Code .
' ';
1430 $debugData[
'result'][
'error'] =
$response->Notifications->Message .
' ';
1432 $this->
_debug($debugData);
1433 $result->setErrors($debugData[
'result'][
'error']);
1435 $result->setGatewayResponse($client->__getLastResponse());
1444 private function getTrackingNumber($trackingIds)
1446 return is_array($trackingIds) ? array_map(
1448 return $val->TrackingNumber;
1451 ) : $trackingIds->TrackingNumber;
1464 $requestData[
'DeletionControl'] =
'DELETE_ONE_PACKAGE';
1487 $countryShipper =
$params->getCountryShipper();
1488 $countryRecipient =
$params->getCountryRecipient();
1490 if (($countryShipper == self::USA_COUNTRY_ID && $countryRecipient == self::CANADA_COUNTRY_ID ||
1491 $countryShipper == self::CANADA_COUNTRY_ID &&
1492 $countryRecipient == self::USA_COUNTRY_ID) &&
1495 return [
'YOUR_PACKAGING' =>
__(
'Your Packaging')];
1497 if (
$method ==
'INTERNATIONAL_ECONOMY' ||
$method ==
'INTERNATIONAL_FIRST') {
1499 $exclude = [
'FEDEX_10KG_BOX' =>
'',
'FEDEX_25KG_BOX' =>
''];
1501 return array_diff_key($allTypes, $exclude);
1503 if (
$method ==
'EUROPE_FIRST_INTERNATIONAL_PRIORITY') {
1505 $exclude = [
'FEDEX_BOX' =>
'',
'FEDEX_TUBE' =>
''];
1507 return array_diff_key($allTypes, $exclude);
1509 if ($countryShipper == self::CANADA_COUNTRY_ID && $countryRecipient == self::CANADA_COUNTRY_ID) {
1511 $params->setCountryShipper(self::USA_COUNTRY_ID);
1512 $params->setCountryRecipient(self::USA_COUNTRY_ID);
1528 return $this->
getCode(
'packaging');
1538 return $this->
getCode(
'containers_filter');
1550 return $this->
getCode(
'delivery_confirmation_types');
1560 foreach (array_keys(
$data) as $key) {
1561 if (is_array(
$data[$key])) {
1563 }
elseif (in_array($key, $this->_debugReplacePrivateDataKeys)) {
1577 private function processTrackingDetails(\stdClass $trackInfo)
1580 'shippeddate' =>
null,
1581 'deliverydate' =>
null,
1582 'deliverytime' =>
null,
1583 'deliverylocation' =>
null,
1585 'progressdetail' => [],
1588 $datetime = $this->parseDate(!empty($trackInfo->ShipTimestamp) ? $trackInfo->ShipTimestamp :
null);
1590 $result[
'shippeddate'] =
gmdate(
'Y-m-d', $datetime->getTimestamp());
1593 $result[
'signedby'] = !empty($trackInfo->DeliverySignatureName) ?
1594 (string) $trackInfo->DeliverySignatureName :
1597 $result[
'status'] = (!empty($trackInfo->StatusDetail) && !empty($trackInfo->StatusDetail->Description)) ?
1598 (
string) $trackInfo->StatusDetail->Description :
1600 $result[
'service'] = (!empty($trackInfo->Service) && !empty($trackInfo->Service->Description)) ?
1601 (
string) $trackInfo->Service->Description :
1604 $datetime = $this->getDeliveryDateTime($trackInfo);
1606 $result[
'deliverydate'] =
gmdate(
'Y-m-d', $datetime->getTimestamp());
1607 $result[
'deliverytime'] =
gmdate(
'H:i:s', $datetime->getTimestamp());
1611 if (!empty($trackInfo->EstimatedDeliveryAddress)) {
1612 $address = $trackInfo->EstimatedDeliveryAddress;
1613 }
elseif (!empty($trackInfo->ActualDeliveryAddress)) {
1614 $address = $trackInfo->ActualDeliveryAddress;
1621 if (!empty($trackInfo->PackageWeight)) {
1624 (
string) $trackInfo->PackageWeight->Value,
1625 (
string) $trackInfo->PackageWeight->Units
1629 if (!empty($trackInfo->Events)) {
1630 $events = $trackInfo->Events;
1631 if (is_object($events)) {
1632 $events = [$trackInfo->Events];
1634 $result[
'progressdetail'] = $this->processTrackDetailsEvents($events);
1645 private function getDeliveryDateTime(\stdClass $trackInfo)
1648 if (!empty($trackInfo->EstimatedDeliveryTimestamp)) {
1649 $timestamp = $trackInfo->EstimatedDeliveryTimestamp;
1650 }
elseif (!empty($trackInfo->ActualDeliveryTimestamp)) {
1651 $timestamp = $trackInfo->ActualDeliveryTimestamp;
1654 return $timestamp ? $this->parseDate($timestamp) : null;
1664 private function getDeliveryAddress(\stdClass
$address)
1672 if (!empty(
$address->StateOrProvinceCode)) {
1676 if (!empty(
$address->CountryCode)) {
1691 private function processTrackDetailsEvents(array $events)
1695 foreach ($events as $event) {
1697 'activity' => (string) $event->EventDescription,
1698 'deliverydate' =>
null,
1699 'deliverytime' =>
null,
1700 'deliverylocation' =>
null 1703 $datetime = $this->parseDate(!empty($event->Timestamp) ? $event->Timestamp :
null);
1705 $item[
'deliverydate'] =
gmdate(
'Y-m-d', $datetime->getTimestamp());
1706 $item[
'deliverytime'] =
gmdate(
'H:i:s', $datetime->getTimestamp());
1709 if (!empty($event->Address)) {
1710 $item[
'deliverylocation'] = $this->getDeliveryAddress($event->Address);
1724 private function appendTrackingError($trackingValue, $errorMessage)
1726 $error = $this->_trackErrorFactory->create();
1727 $error->setCarrier(
'fedex');
1729 $error->setTracking($trackingValue);
1730 $error->setErrorMessage($errorMessage);
1732 $result->append($error);
1743 private function parseDate($timestamp)
1745 if ($timestamp ===
null) {
1748 $formats = [\DateTime::ATOM,
'Y-m-d\TH:i:s'];
1749 foreach ($formats as
$format) {
1751 $utcTimezone = new \DateTimeZone(
'UTC');
1752 $dateTime = \DateTime::createFromFormat(
$format, $timestamp, $utcTimezone);
1768 private function getPaymentType(DataObject
$request): string
1770 return $request->getIsReturn() &&
$request->getShippingMethod() !== self::RATE_REQUEST_SMARTPOST
_prepareShipmentRequest(\Magento\Framework\DataObject $request)
_prepareRateResponse($response)
$_debugReplacePrivateDataKeys
_parseXmlResponse($response)
if(!defined( 'PHP_VERSION_ID')||!(PHP_VERSION_ID===70002||PHP_VERSION_ID===70004||PHP_VERSION_ID >=70006))
__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\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\Module\Dir\Reader $configReader, \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory, array $data=[], Json $serializer=null, ClientFactory $soapClientFactory=null)
elseif(isset( $params[ 'redirect_parent']))
const RATE_REQUEST_SMARTPOST
_createSoapClient($wsdl, $trace=false)
_formRateRequest($purpose)
getTotalNumOfBoxes($weight)
_getXMLTracking($tracking)
collectRates(RateRequest $request)
_doShipmentRequest(\Magento\Framework\DataObject $request)
const RATE_REQUEST_GENERAL
getMethodPrice($cost, $method='')
getDeliveryConfirmationTypes(\Magento\Framework\DataObject $params=null)
_getCachedQuotes($requestParams)
setRequest(RateRequest $request)
_setCachedQuotes($requestParams, $response)
_parseTrackingResponse($trackingValue, $response)
parseXml($xmlContent, $customSimplexml='SimpleXMLElement')
_getAllowedContainers(\Magento\Framework\DataObject $params=null)
_getRateAmountOriginBased($rate)
_formShipmentRequest(\Magento\Framework\DataObject $request)
getContainerTypes(\Magento\Framework\DataObject $params=null)
_doRatesRequest($purpose)
_updateFreeMethodQuote($request)
_setFreeMethodRequest($freeMethod)
$_customizableContainerTypes
getContainerTypesFilter()
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE]
$_productCollectionFactory