PHP: UPS API, UPS 运费计算, UPS接口

项目地址: https://github.com/gabrielbull/php-ups-api

安装:(了解composer看这里:PHP: Composer 依赖管理 Composer Cheat Sheet for developers 安装和用法

composer require gabrielbull/ups-api

 

前提

需要申请 UPS ACCESS KEY:

PHP: UPS API, UPS 运费计算, UPS接口
PHP: UPS API, UPS 运费计算, UPS接口
PHP: UPS API, UPS 运费计算, UPS接口
PHP: UPS API, UPS 运费计算, UPS接口

用法:(完整整合类见最下方

1. 地址验证 Address Validation Class (Street Level)

$address = new \Ups\Entity\Address();
$address->setAttentionName('Test Test');
$address->setBuildingName('Test');
$address->setAddressLine1('Address Line 1');
$address->setAddressLine2('Address Line 2');
$address->setAddressLine3('Address Line 3');
$address->setStateProvinceCode('NY');
$address->setCity('New York');
$address->setCountryCode('US');
$address->setPostalCode('10000');

$xav = new \Ups\AddressValidation($accessKey, $userId, $password);
$xav->activateReturnObjectOnValidate(); //This is optional
try {
    $response = $xav->validate($address, $requestOption = \Ups\AddressValidation::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15);
} catch (Exception $e) {
    var_dump($e);
}

其他选项:

if ($response->noCandidates()) {
    //Do something clever and helpful to let the use know the address is invalid
}
if ($response->isAmbiguous()) {
    $candidateAddresses = $response->getCandidateAddressList();
    foreach($candidateAddresses as $address) {
        //Present user with list of candidate addresses so they can pick the correct one        
    }
}
if ($response->isValid()) {
    $validAddress = $response->getValidatedAddress();
    
    //Show user validated address or update their address with the 'official' address
    //Or do something else helpful...
}

2. 简单地址验证 Simple Address Validation Class

$address = new \Ups\Entity\Address();
$address->setStateProvinceCode('NY');
$address->setCity('New York');
$address->setCountryCode('US');
$address->setPostalCode('10000');

$av = new \Ups\SimpleAddressValidation($accessKey, $userId, $password);
try {
 $response = $av->validate($address);
 var_dump($response);
} catch (Exception $e) {
 var_dump($e);
}

3. QuantumView Class

The QuantumView Class allow you to request a Quantum View Data subscription

$quantumView = new Ups\QuantumView($accessKey, $userId, $password);

try {
	// Get the subscription for all events for the last hour
	$events = $quantumView->getSubscription(null, (time() - 3600));

	foreach($events as $event) {
		// Your code here
		echo $event->Type;
	}

} catch (Exception $e) {
	var_dump($e);
}

 

4. 追踪 Tracking Class

The Tracking Class allow you to track a shipment using the UPS Tracking API.

$tracking = new Ups\Tracking($accessKey, $userId, $password);

try {
	$shipment = $tracking->track('TRACKING NUMBER');

	foreach($shipment->Package->Activity as $activity) {
		var_dump($activity);
	}

} catch (Exception $e) {
	var_dump($e);
}

Example using Reference Number

$tracking = new Ups\Tracking($accessKey, $userId, $password);

try {
    $shipment = $tracking->trackByReference('REFERENCE NUMBER');

    foreach($shipment->Package->Activity as $activity) {
        var_dump($activity);
    }

} catch (Exception $e) {
    var_dump($e);
}

Example using Reference Number with additional parameters

$tracking = new Ups\Tracking($accessKey, $userId, $password);

$tracking->setShipperNumber('SHIPPER NUMBER');

$beginDate = new \DateTime('2016-01-01');
$endDate = new \DateTime('2016-01-31');

$tracking->setBeginDate($beginDate);
$tracking->setEndDate($endDate);

try {
    $shipment = $tracking->trackByReference('REFERENCE NUMBER');

    foreach($shipment->Package->Activity as $activity) {
        var_dump($activity);
    }

} catch (Exception $e) {
    var_dump($e);
}

5. 价格运算 Rate Class

The Rate Class allow you to get shipment rates using the UPS Rate API.

$rate = new Ups\Rate(
	$accessKey,
	$userId,
	$password
);

try {
    $shipment = new \Ups\Entity\Shipment();

    $shipperAddress = $shipment->getShipper()->getAddress();
    $shipperAddress->setPostalCode('99205');

    $address = new \Ups\Entity\Address();
    $address->setPostalCode('99205');
    $shipFrom = new \Ups\Entity\ShipFrom();
    $shipFrom->setAddress($address);

    $shipment->setShipFrom($shipFrom);

    $shipTo = $shipment->getShipTo();
    $shipTo->setCompanyName('Test Ship To');
    $shipToAddress = $shipTo->getAddress();
    $shipToAddress->setPostalCode('99205');

    $package = new \Ups\Entity\Package();
    $package->getPackagingType()->setCode(\Ups\Entity\PackagingType::PT_PACKAGE);
    $package->getPackageWeight()->setWeight(10);
    
    // if you need this (depends of the shipper country)
    $weightUnit = new \Ups\Entity\UnitOfMeasurement;
    $weightUnit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_KGS);
    $package->getPackageWeight()->setUnitOfMeasurement($weightUnit);

    $dimensions = new \Ups\Entity\Dimensions();
    $dimensions->setHeight(10);
    $dimensions->setWidth(10);
    $dimensions->setLength(10);

    $unit = new \Ups\Entity\UnitOfMeasurement;
    $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_IN);

    $dimensions->setUnitOfMeasurement($unit);
    $package->setDimensions($dimensions);

    $shipment->addPackage($package);

    var_dump($rate->getRate($shipment));
} catch (Exception $e) {
    var_dump($e);
}

 

6. 价格和时间计算 RateTimeInTransit Class

The RateTimeInTransit Class allow you to get shipment rates like the Rate Class, but the response will also include TimeInTransit data.

$rate = new Ups\RateTimeInTransit(
	$accessKey,
	$userId,
	$password
);

try {
    $shipment = new \Ups\Entity\Shipment();

    $shipperAddress = $shipment->getShipper()->getAddress();
    $shipperAddress->setPostalCode('99205');

    $address = new \Ups\Entity\Address();
    $address->setPostalCode('99205');
    $shipFrom = new \Ups\Entity\ShipFrom();
    $shipFrom->setAddress($address);

    $shipment->setShipFrom($shipFrom);

    $shipTo = $shipment->getShipTo();
    $shipTo->setCompanyName('Test Ship To');
    $shipToAddress = $shipTo->getAddress();
    $shipToAddress->setPostalCode('99205');

    $package = new \Ups\Entity\Package();
    $package->getPackagingType()->setCode(\Ups\Entity\PackagingType::PT_PACKAGE);
    $package->getPackageWeight()->setWeight(10);
    
    // if you need this (depends of the shipper country)
    $weightUnit = new \Ups\Entity\UnitOfMeasurement;
    $weightUnit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_KGS);
    $package->getPackageWeight()->setUnitOfMeasurement($weightUnit);

    $dimensions = new \Ups\Entity\Dimensions();
    $dimensions->setHeight(10);
    $dimensions->setWidth(10);
    $dimensions->setLength(10);

    $unit = new \Ups\Entity\UnitOfMeasurement;
    $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_IN);

    $dimensions->setUnitOfMeasurement($unit);
    $package->setDimensions($dimensions);

    $shipment->addPackage($package);

    $deliveryTimeInformation = new \Ups\Entity\DeliveryTimeInformation();
    $deliveryTimeInformation->setPackageBillType(\Ups\Entity\DeliveryTimeInformation::PBT_NON_DOCUMENT);
    
    $pickup = new \Ups\Entity\Pickup();
    $pickup->setDate("20170520");
    $pickup->setTime("160000");
    $shipment->setDeliveryTimeInformation($deliveryTimeInformation);

    var_dump($rate->shopRatesTimeInTransit($shipment));
} catch (Exception $e) {
    var_dump($e);
}

7. 时间估算 TimeInTransit Class

The TimeInTransit Class allow you to get all transit times using the UPS TimeInTransit API.

$timeInTransit = new Ups\TimeInTransit($access, $userid, $passwd);

try {
    $request = new \Ups\Entity\TimeInTransitRequest;

    // Addresses
    $from = new \Ups\Entity\AddressArtifactFormat;
    $from->setPoliticalDivision3('Amsterdam');
    $from->setPostcodePrimaryLow('1000AA');
    $from->setCountryCode('NL');
    $request->setTransitFrom($from);

    $to = new \Ups\Entity\AddressArtifactFormat;
    $to->setPoliticalDivision3('Amsterdam');
    $to->setPostcodePrimaryLow('1000AA');
    $to->setCountryCode('NL');
    $request->setTransitTo($to);

    // Weight
    $shipmentWeight = new \Ups\Entity\ShipmentWeight;
    $shipmentWeight->setWeight($totalWeight);
    $unit = new \Ups\Entity\UnitOfMeasurement;
    $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_KGS);
    $shipmentWeight->setUnitOfMeasurement($unit);
    $request->setShipmentWeight($shipmentWeight);

    // Packages
    $request->setTotalPackagesInShipment(2);

    // InvoiceLines
    $invoiceLineTotal = new \Ups\Entity\InvoiceLineTotal;
    $invoiceLineTotal->setMonetaryValue(100.00);
    $invoiceLineTotal->setCurrencyCode('EUR');
    $request->setInvoiceLineTotal($invoiceLineTotal);

    // Pickup date
    $request->setPickupDate(new DateTime);

    // Get data
    $times = $timeInTransit->getTimeInTransit($request);

	foreach($times->ServiceSummary as $serviceSummary) {
		var_dump($serviceSummary);
	}

} catch (Exception $e) {
    var_dump($e);
}

8. Locator Class

The Locator class allows you to search for UPS Access Point locations.

$locatorRequest = new \Ups\Entity\LocatorRequest;

$originAddress = new \Ups\Entity\OriginAddress;
$address = new \Ups\Entity\AddressKeyFormat;
$address->setCountryCode('NL');
$originAddress->setAddressKeyFormat($address);

$geocode = new \Ups\Entity\GeoCode;
$geocode->setLatitude(52.0000);
$geocode->setLongitude(4.0000);
$originAddress->setGeoCode($geocode);
$locatorRequest->setOriginAddress($originAddress);

$translate = new \Ups\Entity\Translate;
$translate->setLanguageCode('ENG');
$locatorRequest->setTranslate($translate);

$acccessPointSearch = new \Ups\Entity\AccessPointSearch;
$acccessPointSearch->setAccessPointStatus(\Ups\Entity\AccessPointSearch::STATUS_ACTIVE_AVAILABLE);

$locationSearch = new \Ups\Entity\LocationSearchCriteria;
$locationSearch->setAccessPointSearch($acccessPointSearch);
$locationSearch->setMaximumListSize(25);

$locatorRequest->setLocationSearchCriteria($locationSearch);

$unitOfMeasurement = new \Ups\Entity\UnitOfMeasurement;
$unitOfMeasurement->setCode(\Ups\Entity\UnitOfMeasurement::UOM_KM);
$unitOfMeasurement->setDescription('Kilometers');
$locatorRequest->setUnitOfMeasurement($unitOfMeasurement);

try {
    // Get the locations
    $locator = new Ups\Locator($accessKey, $userId, $password);
    $locations = $locator->getLocations($locatorRequest, \Ups\Locator::OPTION_UPS_ACCESS_POINT_LOCATIONS);

	foreach($locations->SearchResults->DropLocation as $location) {
		// Your code here
		var_dump($location);
	}

} catch (Exception $e) {
	var_dump($e);
}

9. 国际单 Tradeability Class

The Tradeability class allows you to get data for international shipments:

  • Landed Costs (e.g. duties)
  • Denied Party Screener
  • Import Compliance
  • Export License Detection

Note: only the Landed Costs API is currently implemented.

WARNING: Tradeability is only available through a SOAP API. Therefore you are required to have the SOAP extension installed on your system.

// Build request
$landedCostRequest = new \Ups\Entity\Tradeability\LandedCostRequest;

// Build shipment
$shipment = new \Ups\Entity\Tradeability\Shipment;
$shipment->setOriginCountryCode('NL');
$shipment->setDestinationCountryCode('US');
$shipment->setDestinationStateProvinceCode('TX');
$shipment->setResultCurrencyCode('EUR');
$shipment->setTariffCodeAlert(1);
$shipment->setTransportationMode(\Ups\Entity\Tradeability\Shipment::TRANSPORT_MODE_AIR);
$shipment->setTransactionReferenceId('1');

// Build product
$product = new \Ups\Entity\Tradeability\Product;
$product->setProductName('Test');
$tariffInfo = new \Ups\Entity\Tradeability\TariffInfo;
$tariffInfo->setTariffCode('5109.90.80.00');
$product->setTariffInfo($tariffInfo);
$product->setProductCountryCodeOfOrigin('BD');
$unitPrice = new \Ups\Entity\Tradeability\UnitPrice;
$unitPrice->setMonetaryValue(250);
$unitPrice->setCurrencyCode('EUR');
$product->setUnitPrice($unitPrice);
$weight = new Ups\Entity\Tradeability\Weight;
$weight->setValue(0.83);
$unitOfMeasurement = new \Ups\Entity\Tradeability\UnitOfMeasurement;
$unitOfMeasurement->setCode('kg');
$weight->setUnitOfMeasurement($unitOfMeasurement);
$product->setWeight($weight);
$quantity = new \Ups\Entity\Tradeability\Quantity;
$quantity->setValue(5);
$unitOfMeasurement = new \Ups\Entity\Tradeability\UnitOfMeasurement;
$unitOfMeasurement->setCode(\Ups\Entity\Tradeability\UnitOfMeasurement::PROD_PIECES);
$quantity->setUnitOfMeasurement($unitOfMeasurement);
$product->setQuantity($quantity);
$product->setTariffCodeAlert(1);

// Add product to shipment
$shipment->addProduct($product);

// Query request
$queryRequest = new \Ups\Entity\Tradeability\QueryRequest;
$queryRequest->setShipment($shipment);
$queryRequest->setSuppressQuestionIndicator(true);

// Build
$landedCostRequest->setQueryRequest($queryRequest);

try {
    // Get the data
    $api = new Ups\Tradeability($accessKey, $userId, $password);
    $result = $api->getLandedCosts($landedCostRequest);

    var_dump($result);
} catch (Exception $e) {
    var_dump($e);
}

10 . Shipping Class

The Shipping class allows you to register shipments. This also includes return shipments.

The shipping flow consists of 2 steps:

  • Confirm: Send information to UPS to get it validated and get a digest you can use to accept the shipment.
  • Accept: Finalise the shipment, mark it as it will be shipped. Get label and additional information.
    // Start shipment
    $shipment = new Ups\Entity\Shipment;

    // Set shipper
    $shipper = $shipment->getShipper();
    $shipper->setShipperNumber('XX');
    $shipper->setName('XX');
    $shipper->setAttentionName('XX');
    $shipperAddress = $shipper->getAddress();
    $shipperAddress->setAddressLine1('XX');
    $shipperAddress->setPostalCode('XX');
    $shipperAddress->setCity('XX');
    $shipperAddress->setStateProvinceCode('XX'); // required in US
    $shipperAddress->setCountryCode('XX');
    $shipper->setAddress($shipperAddress);
    $shipper->setEmailAddress('XX'); 
    $shipper->setPhoneNumber('XX');
    $shipment->setShipper($shipper);

    // To address
    $address = new \Ups\Entity\Address();
    $address->setAddressLine1('XX');
    $address->setPostalCode('XX');
    $address->setCity('XX');
    $address->setStateProvinceCode('XX');  // Required in US
    $address->setCountryCode('XX');
    $shipTo = new \Ups\Entity\ShipTo();
    $shipTo->setAddress($address);
    $shipTo->setCompanyName('XX');
    $shipTo->setAttentionName('XX');
    $shipTo->setEmailAddress('XX'); 
    $shipTo->setPhoneNumber('XX');
    $shipment->setShipTo($shipTo);

    // From address
    $address = new \Ups\Entity\Address();
    $address->setAddressLine1('XX');
    $address->setPostalCode('XX');
    $address->setCity('XX');
    $address->setStateProvinceCode('XX');  
    $address->setCountryCode('XX');
    $shipFrom = new \Ups\Entity\ShipFrom();
    $shipFrom->setAddress($address);
    $shipFrom->setName('XX');
    $shipFrom->setAttentionName($shipFrom->getName());
    $shipFrom->setCompanyName($shipFrom->getName());
    $shipFrom->setEmailAddress('XX');
    $shipFrom->setPhoneNumber('XX');
    $shipment->setShipFrom($shipFrom);

    // Sold to
    $address = new \Ups\Entity\Address();
    $address->setAddressLine1('XX');
    $address->setPostalCode('XX');
    $address->setCity('XX');
    $address->setCountryCode('XX');
    $address->setStateProvinceCode('XX');
    $soldTo = new \Ups\Entity\SoldTo;
    $soldTo->setAddress($address);
    $soldTo->setAttentionName('XX');
    $soldTo->setCompanyName($soldTo->getAttentionName());
    $soldTo->setEmailAddress('XX');
    $soldTo->setPhoneNumber('XX');
    $shipment->setSoldTo($soldTo);

    // Set service
    $service = new \Ups\Entity\Service;
    $service->setCode(\Ups\Entity\Service::S_STANDARD);
    $service->setDescription($service->getName());
    $shipment->setService($service);

    // Mark as a return (if return)
    if ($return) {
        $returnService = new \Ups\Entity\ReturnService;
        $returnService->setCode(\Ups\Entity\ReturnService::PRINT_RETURN_LABEL_PRL);
        $shipment->setReturnService($returnService);
    }

    // Set description
    $shipment->setDescription('XX');

    // Add Package
    $package = new \Ups\Entity\Package();
    $package->getPackagingType()->setCode(\Ups\Entity\PackagingType::PT_PACKAGE);
    $package->getPackageWeight()->setWeight(10);
    $unit = new \Ups\Entity\UnitOfMeasurement;
    $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_KGS);
    $package->getPackageWeight()->setUnitOfMeasurement($unit);

    // Set dimensions
    $dimensions = new \Ups\Entity\Dimensions();
    $dimensions->setHeight(50);
    $dimensions->setWidth(50);
    $dimensions->setLength(50);
    $unit = new \Ups\Entity\UnitOfMeasurement;
    $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_CM);
    $dimensions->setUnitOfMeasurement($unit);
    $package->setDimensions($dimensions);

    // Add descriptions because it is a package
    $package->setDescription('XX');

    // Add this package
    $shipment->addPackage($package);

    // Set Reference Number
    $referenceNumber = new \Ups\Entity\ReferenceNumber;
    if ($return) {
        $referenceNumber->setCode(\Ups\Entity\ReferenceNumber::CODE_RETURN_AUTHORIZATION_NUMBER);
        $referenceNumber->setValue($return_id);
    } else {
        $referenceNumber->setCode(\Ups\Entity\ReferenceNumber::CODE_INVOICE_NUMBER);
        $referenceNumber->setValue($order_id);
    }
    $shipment->setReferenceNumber($referenceNumber);

    // Set payment information
    $shipment->setPaymentInformation(new \Ups\Entity\PaymentInformation('prepaid', (object)array('AccountNumber' => 'XX')));

    // Ask for negotiated rates (optional)
    $rateInformation = new \Ups\Entity\RateInformation;
    $rateInformation->setNegotiatedRatesIndicator(1);
    $shipment->setRateInformation($rateInformation);

    // Get shipment info
    try {
        $api = new Ups\Shipping($accessKey, $userId, $password); 
    
        $confirm = $api->confirm(\Ups\Shipping::REQ_VALIDATE, $shipment);
        var_dump($confirm); // Confirm holds the digest you need to accept the result
        
        if ($confirm) {
            $accept = $api->accept($confirm->ShipmentDigest);
            var_dump($accept); // Accept holds the label and additional information
        }
    } catch (\Exception $e) {
        var_dump($e);
    }

If you wanted to create a printable file from the UPS Shipping label image data that came back with $accept, you would use something like the following:

    $label_file = $order_id . ".gif"; 
    $base64_string = $accept->PackageResults->LabelImage->GraphicImage;
    $ifp = fopen($label_file, 'wb');
    fwrite($ifp, base64_decode($base64_string));
    fclose($ifp);

 

11. 报错日志 Logging

All constructors take a PSR-3 compatible logger.

Besides that, the main UPS class has a public method setLogger to set it after the constructor ran.

Requests & responses (including XML, no access keys) are logged at DEBUG level. At INFO level only the event is reported, not the XML content. More severe problems (e.g. no connection) are logged with higher severity.

Example using Monolog

// Create logger
$log = new \Monolog\Logger('ups');
$log->pushHandler(new \Monolog\Handler\StreamHandler('logs/ups.log', \Monolog\Logger::DEBUG));

// Create Rate object + insert logger
$rate = new Ups\Rate($key, $username, $password, $useIntegration, $log);

 

12. 个人的小小整合实例:

<?php
/**
 * @filesource  :  ups.php
 * @Author      :  justcode.ikeepstudying.com
 * @copyright   :  Copyright (C) 2017-2018 GLS IT Studio NY
 * @version     :  Created on Dec 6, 2017 10:12:19 AM
 * @Github      :  https://github.com/gabrielbull/php-ups-api
 *
 */

include_once rtrim(dirname(__FILE__), '/').'/vendor/autoload.php';

class UPS
{
    private $ups_account;
    private $ups_access_key;
    private $ups_user_id;
    private $ups_user_password;
    private $shipment;
    private $service;
    private $package;
    private $dimensions;
    private $address_from;
    private $address_to;
    private $ship_from;
    private $ship_to;
    private $pickup;
    private $request;
    private $type;
    private $services = array(
                '01' => 'UPS Next Day Air',
                '02' => 'UPS Second Day Air',
                '03' => 'UPS Ground',
                '07' => 'UPS Worldwide Express',
                '08' => 'UPS Worldwide Expedited',
                '11' => 'UPS Standard',
                '12' => 'UPS Three-Day Select',
                '13' => 'Next Day Air Saver',
                '14' => 'UPS Next Day Air Early AM',
                '54' => 'UPS Worldwide Express Plus',
                '59' => 'UPS Second Day Air AM',
                '65' => 'UPS Saver',
                '70' => 'UPS Access Point Economy',
                '93' => 'UPS Sure Post',
            );

    function __construct($param = array())
    {
        $this->ups_account       = $param['ups_account']       ?? UPS_ACCOUNT;
        $this->ups_access_key    = $param['ups_access_key']    ?? UPS_ACCESS_KEY;
        $this->ups_user_id       = $param['ups_user_id']       ?? UPS_USER_ID;
        $this->ups_user_password = $param['ups_user_password'] ?? UPS_USER_PASSWORD;

        $this->request    = new \Ups\Entity\TimeInTransitRequest;
        $this->shipment   = new \Ups\Entity\Shipment();
        $this->ship_from  = new \Ups\Entity\ShipFrom();
        $this->ship_to    = new \Ups\Entity\ShipTo();
        $this->service    = new \Ups\Entity\Service;
        $this->package    = new \Ups\Entity\Package();
        $this->dimensions = new \Ups\Entity\Dimensions();

        return $this;
    }

    public function __set($property, $value)
    {
        $this->{$property} = $value;
    }

    function shipper($param=array())
    {
        $shipper = $this->shipment->getShipper();
        if(isset($param['number'])) $shipper->setShipperNumber($param['number']);
        if(isset($param['att']))    $shipper->setAttentionName($param['att']);
        if(isset($param['name']))   $shipper->setName($param['name']);
        $shipperAddress = $shipper->getAddress();
        $shipper->setAddress($shipperAddress);
        $this->shipment->setShipper($shipper);

        return $this;

    }

    function type($type = '')
    {
        $this->type = $type;
        return $this;
    }

    function from($param=array(), $type = '')
    {
        $type = $type ? $type : $this->type;

        switch ($type)
        {
            case 'artifact':

                $address_from = new \Ups\Entity\AddressArtifactFormat;
                if(isset($param['city']))     $address_from->setPoliticalDivision3($param['city']);
                if(isset($param['zip']))      $address_from->setPostcodePrimaryLow($param['zip']);
                if(isset($param['country']))  $address_from->setCountryCode($param['country']);
                $this->request->setTransitFrom($address_from);

            break;

            default:

                $address_from = new \Ups\Entity\Address();
                if(isset($param['name']))     $address_from->setAttentionName($param['name']);
                if(isset($param['address1'])) $address_from->setAddressLine1($param['address1']);
                if(isset($param['address2'])) $address_from->setAddressLine2($param['address2']);
                if(isset($param['address3'])) $address_from->setAddressLine3($param['address3']);
                if(isset($param['state']))    $address_from->setStateProvinceCode($param['state']);  // Required in US
                if(isset($param['city']))     $address_from->setCity($param['city']);
                if(isset($param['country']))  $address_from->setCountryCode($param['country']);
                if(isset($param['zip']))      $address_from->setPostalCode($param['zip']);

                $this->address_from = $address_from;
                $this->ship_from->setAddress($address_from);
                $this->shipment->setShipFrom($this->ship_from);

            break;
        }

        return $this;
    }

    function to($param=array(), $type = '')
    {
        $type = $type ? $type : $this->type;

        switch ($type)
        {
            case 'artifact':

                $address_to = new \Ups\Entity\AddressArtifactFormat;
                if(isset($param['city']))     $address_to->setPoliticalDivision3($param['city']);
                if(isset($param['zip']))      $address_to->setPostcodePrimaryLow($param['zip']);
                if(isset($param['country']))  $address_to->setCountryCode($param['country']);
                $this->request->setTransitTo($address_to);

            break;

            default:

                $address_to = new \Ups\Entity\Address();
                if(isset($param['name']))     $address_to->setAttentionName($param['name']);
                if(isset($param['address1'])) $address_to->setAddressLine1($param['address1']);
                if(isset($param['address2'])) $address_to->setAddressLine2($param['address2']);
                if(isset($param['address3'])) $address_to->setAddressLine3($param['address3']);
                if(isset($param['state']))    $address_to->setStateProvinceCode($param['state']);  // Required in US
                if(isset($param['city']))     $address_to->setCity($param['city']);
                if(isset($param['country']))  $address_to->setCountryCode($param['country']);
                if(isset($param['zip']))      $address_to->setPostalCode($param['zip']);

                $this->address_to = $address_to;
                $this->ship_to->setAddress($address_to);
                $this->shipment->setShipTo($this->ship_to);

            break;
        }

        return $this;
    }

    /**
     * ups/vendor/gabrielbull/ups-api/src/Entity/Service.php
        $services = array(
        '1' => S_AIR_1DAY,
        '2' => S_AIR_2DAY,
        '3' => S_GROUND,
        '7' => S_WW_EXPRESS,
        '8' => S_WW_EXPEDITED,
        '11' => S_STANDARD,
        '12' => S_3DAYSELECT,
        '13' => S_AIR_1DAYSAVER,
        '14' => S_AIR_1DAYEARLYAM,
        '54' => S_WW_EXPRESSPLUS,
        '59' => S_AIR_2DAYAM,
        '65' => S_SAVER,
        '70' => S_ACCESS_POINT,
        '93' => S_SURE_POST,
        );
    */
    function service($class = '03')
    {
        if($class*1<10) $class = '0'.abs($class);
        $this->service->setCode($class);
        $this->service->setDescription($this->service->getName());
        $this->shipment->setService($this->service);

        return $this;
    }

    function weight($lbs, $type = '')
    {
        $type = $type ? $type : $this->type;
        $unit = new \Ups\Entity\UnitOfMeasurement;
        $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_LBS);

        switch ($type)
        {
            case 'artifact':

                $shipmentWeight = new \Ups\Entity\ShipmentWeight;
                $shipmentWeight->setWeight($lbs);
                $shipmentWeight->setUnitOfMeasurement($unit);
                $this->request->setShipmentWeight($shipmentWeight);

            break;

            default:

                $this->package->getPackagingType()->setCode(\Ups\Entity\PackagingType::PT_PACKAGE);
                $this->package->getPackageWeight()->setWeight($lbs);
                $this->package->getPackageWeight()->setUnitOfMeasurement($unit);

            break;
        }

        return $this;
    }

    function size($length = '', $width = '', $height = '')
    {
        if(is_array($length) AND $length)
        {
            $length = $length['length'] ?? $length;
            $width  = $length['width']  ?? $width;
            $height = $length['height'] ?? $height;
        }

        $this->dimensions->setLength($length);
        $this->dimensions->setWidth($width);
        $this->dimensions->setHeight($height);
        $unit = new \Ups\Entity\UnitOfMeasurement;
        $unit->setCode(\Ups\Entity\UnitOfMeasurement::UOM_IN);
        $this->dimensions->setUnitOfMeasurement($unit);

        return $this;
    }

    function packages($number=1)
    {
        $this->request->setTotalPackagesInShipment($number);
        return $this;
    }

    function invoice($amount, $currency = 'USD')
    {
        $invoiceLineTotal = new \Ups\Entity\InvoiceLineTotal;
        $invoiceLineTotal->setMonetaryValue($amount);
        $invoiceLineTotal->setCurrencyCode($currency);
        $this->request->setInvoiceLineTotal($invoiceLineTotal);
        return $this;
    }

    function pickup($date = '')
    {
        $this->pickup = date('Y-m-d', ($date ? strtotime(str_replace('-', '/', $date)) : time()));
        return $this;
    }

    function tracking($tracking_number)
    {
        $tracking = new \Ups\Tracking($this->ups_access_key, $this->ups_user_id, $this->ups_user_password);

        try {
            $shipment = $tracking->track($tracking_number);
            $response = $shipment->Package->Activity;
        }
        catch (Exception $e) { $response = $e->getMessage();  }

        return $response;
    }

    function ratetime($zip_from, $zip_to)
    {
        $rate = new Ups\RateTimeInTransit($this->ups_access_key, $this->ups_user_id, $this->ups_user_password);

        $address = new \Ups\Entity\Address();
        $address->setPostalCode($zip_from);
        $shipFrom = new \Ups\Entity\ShipFrom();
        $shipFrom->setAddress($address);
        $this->shipment->setShipFrom($shipFrom);

        $shipTo = $this->shipment->getShipTo();
        $shipToAddress = $shipTo->getAddress();
        $shipToAddress->setPostalCode($zip_to);

        $this->package->setDimensions($this->dimensions);
        $this->shipment->addPackage($this->package);

        $deliveryTimeInformation = new \Ups\Entity\DeliveryTimeInformation();
        $deliveryTimeInformation->setPackageBillType(\Ups\Entity\DeliveryTimeInformation::PBT_NON_DOCUMENT);

        $this->shipment->setDeliveryTimeInformation($deliveryTimeInformation);

        try
        {
            $response = array();
            $result = $rate->shopRatesTimeInTransit($this->shipment)->RatedShipment;
            if($result) foreach ($result as $row)
            {
                $service_summary = $row->TimeInTransit->ServiceSummary;
                $service_arrival = $service_summary->getEstimatedArrival();
                $response[]     = array(
                                    'service'  => $service_summary->Service->getDescription(),
                                    'fee'      => $row->TotalCharges->MonetaryValue,
                                    'currency' => $row->TotalCharges->CurrencyCode,
                                    'business' => $service_arrival->getBusinessDaysInTransit(),
                                    'delivery' => date('Y-m-d H:i:s', strtotime($service_arrival->getArrival()->getDate().' '.$service_arrival->getArrival()->getTime())),
                                );
            }
        }
        catch (Exception $e) { $response = $e->getMessage();  }

        return $response;
    }

    function rate()
    {
        $rate = new \Ups\Rate($this->ups_access_key, $this->ups_user_id, $this->ups_user_password);
        $this->shipment->addPackage($this->package);

        try
        {
            $response = array();
            $result = $rate->getRate($this->shipment)->RatedShipment;
            if($result) foreach ($result as $row)
            {
                $response[]     = array(
                    'service'  => $this->services[$row->Service->getCode()] ?? '--',
                    'fee'      => $row->TotalCharges->MonetaryValue,
                    'currency' => $row->TotalCharges->CurrencyCode,
                    'business' => $row->GuaranteedDaysToDelivery,
                    'delivery' => date('Y-m-d', strtotime('+'.$row->GuaranteedDaysToDelivery.' days')).' '.$row->ScheduledDeliveryTime,
                );
            }

            $response = count($response) > 1 ? $response : $response[0];
        }
        catch (Exception $e) { $response = $e->getMessage();  }

        return $response;
    }

    /**
     * The TimeInTransit Class allow you to get all transit times using the UPS TimeInTransit API.
     * /var/www/html/system/libraries/calculators/ups/vendor/gabrielbull/ups-api/src/Entity/EstimatedArrival.php
     * you need to manually change private vars to public vars
     *
     * @return array|string
     */
    function timein()
    {
        $timeInTransit = new \Ups\TimeInTransit($this->ups_access_key, $this->ups_user_id, $this->ups_user_password);

        // Pickup date
        $this->request->setPickupDate(new DateTime($this->pickup));

        try
        {
            $response = array();
            $result   = $timeInTransit->getTimeInTransit($this->request)->ServiceSummary;

            if($result) foreach ($result as $row)
            {
                $response[] = array(
                                'service'     => $row->Service->getDescription(),
                                'pickup'      => $row->EstimatedArrival->getPickupDate().' '.$row->EstimatedArrival->getPickupTime(),
                                'business'    => $row->EstimatedArrival->getBusinessTransitDays(),
                                'delivery'    => $row->EstimatedArrival->getDate().' '.$row->EstimatedArrival->getTime(),
                            );
            }
        }
        catch (Exception $e) { $response = $e->getMessage();  }

        return $response;
    }

    function isAddr($param = array())
    {
        $address = new \Ups\Entity\Address();
        if(isset($param['address1'])) $address->setAddressLine1($param['address1']);
        if(isset($param['address2'])) $address->setAddressLine2($param['address2']);
        if(isset($param['address3'])) $address->setAddressLine3($param['address3']);
        if(isset($param['city']))     $address->setCity($param['city']);
        if(isset($param['state']))    $address->setStateProvinceCode($param['state']);
        if(isset($param['country']))  $address->setCountryCode($param['country']);
        if(isset($param['zip']))      $address->setPostalCode($param['zip']);

        $xav = new \Ups\AddressValidation($this->ups_access_key, $this->ups_user_id, $this->ups_user_password);
        $xav->activateReturnObjectOnValidate(); //This is optional
        try { $response = $xav->validate($address, $requestOption = \Ups\AddressValidation::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15); }
        catch (Exception $e) { $response = $e->getMessage();  }

        return $response;
    }

    function __destruct()
    {
        unset($this->request);
        unset($this->shipment);
        unset($this->ship_from);
        unset($this->ship_to);
        unset($this->service);
        unset($this->package);
        unset($this->dimensions);
        unset($this->pickup);
        unset($this->type);
    }

}

调用:

$from = array(
'name'      => 'Lisha',
'address1'  => '412 University St.',
'city'      => 'SF',
'state'     => 'CA',
'country'   => 'US',
'zip'       => '94134',
);
$to = array(
'name'      => 'gideon',
'address1'  => '100 John St.',
'city'      => 'NY',
'state'     => 'NY',
'country'   => 'US',
'zip'       => '10038',
);

$canada = array(
'address1' => "1010 EASY ST",
'city'     => 'OTTAWA',
'state'    => 'ONTARIO',
'country'  => 'CA',
'zip'      => 'K1A 0B1',
);

$uk = array(
'address1' => "10 Downing Street",
'city'     => 'LONDON',
'state'    => '',
'country'  => 'UK',
'zip'      => 'SW1A 2AA',
);

$eur = array(
'address1' => "10 Downing Street",
'city'     => 'Amsterdam',
'state'    => '',
'country'  => 'NL',
'zip'      => '1000AA',
);


$ups = new UPS()

//        dump($ups->weight(10)->size(12, 35, 8)->ratetime(10001, 94134));

//        dump($ups->isAddr($canada));
//        dump($ups->from($from)->to($to)->service()->weight(10)->size(12, 35, 8)->rate());

//        $type = 'artifact';
//        dump($ups->type($type)->from($from)->to($eur)->weight(10, $type)->packages(2)->invoice(100)->timein());
//        dump($ups->from($from, $type)->to($to, $type)->weight(10, $type)->packages(2)->invoice(100)->pickup('2018-5-10')->timein());

 

注意,你需要写入自己的 UPS_ACCOUNT, UPS_ACCESS_KEY, UPS_USER_ID, UPS_USER_PASSWORD 参数,方法见最上面。

 

 

本文:PHP: UPS API, UPS 运费计算, UPS接口