6

How can I add estimate delivery date for UPS shipping method. I searching over google but not luck and I try to following link for magento 1 UPS estimate delivery date but not work. I also check ups inTransit api but not convert in magento 2 any one know how can I achieve this.

2
  • Looks like the link you provided is for Magento 1 but your question has a magento2 tag Commented Apr 9, 2018 at 18:21
  • Yes i need it in magento 2 not in 1.
    – Pratik
    Commented Apr 10, 2018 at 5:44

3 Answers 3

7
+50

step1:- Override carrier.php file in local module Vendor\module-ups\Model\Carrier.php

Find function setRequest() and add DestCity.

public function setRequest(RateRequest $request)
{
        $rowRequest->setDestCity($request->getDestCity());
        $this->_rawRequest = $rowRequest;
        return $this;
}

step2:- Find function _getXmlQuotes().

protected function _getXmlQuotes()
    {
        $url = $this->getConfigData('gateway_xml_url');

        $this->setXMLAccessRequest();
        $xmlRequest = $this->_xmlAccessRequest;
        $debugData['accessRequest'] = $this->filterDebugData($xmlRequest);

        $rowRequest = $this->_rawRequest;
        if (self::USA_COUNTRY_ID == $rowRequest->getDestCountry()) {
            $destPostal = substr($rowRequest->getDestPostal(), 0, 5);
        } else {
            $destPostal = $rowRequest->getDestPostal();
        }
        $params = [
            'accept_UPS_license_agreement' => 'yes',
            '10_action' => $rowRequest->getAction(),
            '13_product' => $rowRequest->getProduct(),
            '14_origCountry' => $rowRequest->getOrigCountry(),
            '15_origPostal' => $rowRequest->getOrigPostal(),
            'origCity' => $rowRequest->getOrigCity(),
            'origRegionCode' => $rowRequest->getOrigRegionCode(),
            '19_destPostal' => $destPostal,
            '22_destCountry' => $rowRequest->getDestCountry(),
            'destRegionCode' => $rowRequest->getDestRegionCode(),
            '23_weight' => $rowRequest->getWeight(),
            '47_rate_chart' => $rowRequest->getPickup(),
            '48_container' => $rowRequest->getContainer(),
            '49_residential' => $rowRequest->getDestType(),
        ];
        // start change action name Shop to Shoptimeintransit
        if ($params['10_action'] == '4') {
            $params['10_action'] = 'Shoptimeintransit';
            $serviceCode = null;
        } else {
            $params['10_action'] = 'Rate';
            $serviceCode = $rowRequest->getProduct() ? $rowRequest->getProduct() : '';
        }
        // end
        $serviceDescription = $serviceCode ? $this->getShipmentByCode($serviceCode) : '';

        $xmlParams = <<<XMLRequest
<?xml version="1.0"?>
<RatingServiceSelectionRequest xml:lang="en-US">
  <Request>
    <TransactionReference>
      <CustomerContext>Rating and Service</CustomerContext>
      <XpciVersion>1.0</XpciVersion>
    </TransactionReference>
    <RequestAction>Rate</RequestAction>
    <RequestOption>{$params['10_action']}</RequestOption>
  </Request>
  <PickupType>
          <Code>{$params['47_rate_chart']['code']}</Code>
          <Description>{$params['47_rate_chart']['label']}</Description>
  </PickupType>

  <Shipment>
XMLRequest;

        if ($serviceCode !== null) {
            $xmlParams .= "<Service>" .
                "<Code>{$serviceCode}</Code>" .
                "<Description>{$serviceDescription}</Description>" .
                "</Service>";
        }

        $xmlParams .= <<<XMLRequest
      <Shipper>
XMLRequest;

        if ($this->getConfigFlag('negotiated_active') && ($shipper = $this->getConfigData('shipper_number'))) {
            $xmlParams .= "<ShipperNumber>{$shipper}</ShipperNumber>";
        }

        if ($rowRequest->getIsReturn()) {
            $shipperCity = '';
            $shipperPostalCode = $params['19_destPostal'];
            $shipperCountryCode = $params['22_destCountry'];
            $shipperStateProvince = $params['destRegionCode'];
        } else {
            $shipperCity = $params['origCity'];
            $shipperPostalCode = $params['15_origPostal'];
            $shipperCountryCode = $params['14_origCountry'];
            $shipperStateProvince = $params['origRegionCode'];
        }

        $xmlParams .= <<<XMLRequest
      <Address>
          <City>{$shipperCity}</City>
          <PostalCode>{$shipperPostalCode}</PostalCode>
          <CountryCode>{$shipperCountryCode}</CountryCode>
          <StateProvinceCode>{$shipperStateProvince}</StateProvinceCode>
      </Address>
    </Shipper>
    <ShipTo>
      XMLRequest;

/* ------- Start XML Mod to add city ---------*/
$xmlRequest .= <<< XMLRequest
            <City>{$rowRequest->getDestCity()}</City>
XMLRequest;
/* ---------------- End of XML Mod --------------------*/

$xmlRequest .= <<< XMLRequest
          /* ------- XML Mod For Time In Transit Params ---------*/         

          <PostalCode>{$params['19_destPostal']}</PostalCode>
          <CountryCode>{$params['22_destCountry']}</CountryCode>
          <ResidentialAddress>{$params['49_residential']}</ResidentialAddress>
          <StateProvinceCode>{$params['destRegionCode']}</StateProvinceCode>
XMLRequest;

        if ($params['49_residential'] === '01') {
            $xmlParams .= "<ResidentialAddressIndicator>{$params['49_residential']}</ResidentialAddressIndicator>";
        }

        $xmlParams .= <<<XMLRequest
      </Address>
    </ShipTo>


    <ShipFrom>
      <Address>
          <PostalCode>{$params['15_origPostal']}</PostalCode>
          <CountryCode>{$params['14_origCountry']}</CountryCode>
          <StateProvinceCode>{$params['origRegionCode']}</StateProvinceCode>
      </Address>
    </ShipFrom>

    <Package>
      <PackagingType><Code>{$params['48_container']}</Code></PackagingType>
      <PackageWeight>
         <UnitOfMeasurement><Code>{$rowRequest->getUnitMeasure()}</Code></UnitOfMeasurement>
        <Weight>{$params['23_weight']}</Weight>
      </PackageWeight>
    </Package>
        /* ------- XML Mod Start for deliverytime ---------*/
        <DeliveryTimeInformation>
        <PackageBillType>03</PackageBillType>
    </DeliveryTimeInformation>
        /* ---------------- End of XML Mod --------------------*/
XMLRequest;

        if ($this->getConfigFlag('negotiated_active')) {
            $xmlParams .= "<RateInformation><NegotiatedRatesIndicator/></RateInformation>";
        }

/* ---------------- End of XML Mod --------------------*/
        $xmlParams .= <<<XMLRequest
  </Shipment>
</RatingServiceSelectionRequest>
XMLRequest;

        $xmlRequest .= $xmlParams;

        $xmlResponse = $this->_getCachedQuotes($xmlRequest);
        if ($xmlResponse === null) {
            $debugData['request'] = $xmlParams;
            try {
                $ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest);
                curl_setopt($ch, CURLOPT_TIMEOUT, 30);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, (bool)$this->getConfigFlag('mode_xml'));
                $xmlResponse = curl_exec($ch);
                if ($xmlResponse !== false) {
                    $debugData['result'] = $xmlResponse;
                    $this->_setCachedQuotes($xmlRequest, $xmlResponse);
                } else {
                    $debugData['result'] = ['error' => curl_error($ch)];
                }
                curl_close($ch);
            } catch (\Exception $e) {
                $debugData['result'] = ['error' => $e->getMessage(), 'code' => $e->getCode()];
                $xmlResponse = '';
            }

            $this->_debug($debugData);
        }

        return $this->_parseXmlResponse($xmlResponse);
    }

step3:- Find Function _parseXmlResponse()

protected function _parseXmlResponse($xmlResponse)
    {
        $costArr = [];
        $priceArr = [];
        if (strlen(trim($xmlResponse)) > 0) {
            $xml = new \Magento\Framework\Simplexml\Config();
            $xml->loadString($xmlResponse);
            $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/ResponseStatusCode/text()");
            $success = (int)$arr[0];
            if ($success === 1) {
                $arr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment");
                $allowedMethods = explode(",", $this->getConfigData('allowed_methods'));

                // Negotiated rates
                $negotiatedArr = $xml->getXpath("//RatingServiceSelectionResponse/RatedShipment/NegotiatedRates");
                $negotiatedActive = $this->getConfigFlag(
                        'negotiated_active'
                    ) && $this->getConfigData(
                        'shipper_number'
                    ) && !empty($negotiatedArr);

                $allowedCurrencies = $this->_currencyFactory->create()->getConfigAllowCurrencies();
                foreach ($arr as $shipElement) {
                    $code = (string)$shipElement->Service->Code;
                    if (in_array($code, $allowedMethods)) {
                        if ($negotiatedActive) {
                            $cost = $shipElement->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue;
                        } else {
                            $cost = $shipElement->TotalCharges->MonetaryValue;
                        }
                        /* ------------ Time In Transit Mod ------------*/

                        $daysInTransit = $shipElement->TimeInTransit->ServiceSummary->EstimatedArrival->TotalTransitDays;
                        //print_r($daysInTransit);die;
                        $etaDate = $shipElement->TimeInTransit->ServiceSummary->EstimatedArrival->Arrival->Date;
                        $etaTime = $shipElement->TimeInTransit->ServiceSummary->EstimatedArrival->Arrival->Time;
                        $eta = new \DateTime();
                        $eta->setDate(substr($etaDate, 0, 4), substr($etaDate, 4, 2), substr($etaDate, 6, 2));
                        $eta->setTime(substr($etaTime, 0, 2), substr($etaTime, 4, 2), substr($etaTime, 4, 2));

                        /* ----------- End Time In Transit Mod ---------*/
                        //convert price with Origin country currency code to base currency code
                        $successConversion = true;
                        $responseCurrencyCode = $this->mapCurrencyCode(
                            (string)$shipElement->TotalCharges->CurrencyCode
                        );
                        if ($responseCurrencyCode) {
                            if (in_array($responseCurrencyCode, $allowedCurrencies)) {
                                $cost = (double)$cost * $this->_getBaseCurrencyRate($responseCurrencyCode);
                            } else {
                                $errorTitle = __(
                                    'We can\'t convert a rate from "%1-%2".',
                                    $responseCurrencyCode,
                                    $this->_request->getPackageCurrency()->getCode()
                                );
                                $error = $this->_rateErrorFactory->create();
                                $error->setCarrier('ups');
                                $error->setCarrierTitle($this->getConfigData('title'));
                                $error->setErrorMessage($errorTitle);
                                $successConversion = false;
                            }
                        }

                        if ($successConversion) {
                            $costArr[$code] = $cost;
                            $priceArr[$code] = $this->getMethodPrice(floatval($cost), $code);
                             /* ------------ Time In Transit Mod ------------*/

                            $timeInTransitArr[$code] = $daysInTransit;
                            $etaArr[$code] = $eta;

                            /* ----------- End Time In Transit Mod ---------*/  
                        }
                    }
                }
            } else {
                $arr = $xml->getXpath("//RatingServiceSelectionResponse/Response/Error/ErrorDescription/text()");
                $errorTitle = (string)$arr[0][0];
                $error = $this->_rateErrorFactory->create();
                $error->setCarrier('ups');
                $error->setCarrierTitle($this->getConfigData('title'));
                $error->setErrorMessage($this->getConfigData('specificerrmsg'));
            }
        }

        $result = $this->_rateFactory->create();

        if (empty($priceArr)) {
            $error = $this->_rateErrorFactory->create();
            $error->setCarrier('ups');
            $error->setCarrierTitle($this->getConfigData('title'));
            if (!isset($errorTitle)) {
                $errorTitle = __('Cannot retrieve shipping rates');
            }
           $error->setErrorMessage($this->getConfigData('specificerrmsg'));

            /* ------------ Time In Transit Mod ------------*/

            $error->setErrorMessage($errorTitle);

             /* ----------- End Time In Transit Mod ---------*/

            $result->append($error);
        } else {
            foreach ($priceArr as $method => $price) {
                $rate = $this->_rateMethodFactory->create();
                $rate->setCarrier('ups');
                $rate->setCarrierTitle($this->getConfigData('title'));
                $rate->setMethod($method);
                $methodArr = $this->getShipmentByCode($method);
                /* ------------ Time In Transit Mod ------------*/

                //$transitDays = intval($timeInTransitArr[$method]);
                $rate->setMethodTitle($methodArr . ' (ETA: ' . $etaArr[$method]->format('d-m-Y H:i'). ')');

                /* ----------- End Time In Transit Mod ---------*/
               // $rate->setMethodTitle($methodArr);
                $rate->setCost($costArr[$method]);
                $rate->setPrice($price);
                $result->append($rate);
            }
        }

        return $result;
    }
2
  • I get a blank page with:"Estimate Shipping and Tax" when I edit this page. Is there any additional step or maybe I didn't insert the dest city at the right place. Any imput would be appreciated
    – Emili
    Commented May 10, 2019 at 16:45
  • Working fine, also used below line of code also.
    – Soni5041
    Commented Jul 13, 2020 at 13:24
1

Please replace

$daysInTransit = $shipElement->TimeInTransit->ServiceSummary->EstimatedArrival->TotalTransitDays;

with

 $daysInTransit = (string)$shipElement->TimeInTransit->ServiceSummary->EstimatedArrival->BusinessDaysInTransit;
2
  • With above code, i was facing this error also and this code help me.
    – Soni5041
    Commented Jul 13, 2020 at 13:24
  • Then you need to print $shipElement and check the data. Commented Jul 14, 2020 at 12:11
0

I am using Magento 2.4. I modified Carier.php file of UPS Module to fetch Estimate delivery Date and time from UPS API. I used above code but it was throwing error "Invalid weight" so I used additional parameter in <shipment> tag Below code is required because when you pass $params['10_action'] = 'Shoptimeintransit'; ,so you need to add new element ShipmentTotalWeight in shipment container

 <Shipment>
    ........
    <ShipmentTotalWeight>
        <UnitOfMeasurement>
            <Code>{$rowRequest->getUnitMeasure()}</Code>
        </UnitOfMeasurement>
        <Weight>{$params['23_weight']}</Weight>
    </ShipmentTotalWeight>
    .......
 </Shipment>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.