gabrielbull/ups-api
PHP library wrapping UPS APIs (Quantum View, Tracking, Shipping, Rating, Time in Transit, Address Validation) with simple classes and examples. Helps fetch rates, create shipments, validate addresses, and track packages.
Installation:
composer require gabrielbull/ups-api
Ensure your Laravel project meets the PHP 7.1+ requirement.
First Use Case:
use Ups\Tracking;
$tracking = new Tracking(
config('services.ups.access_key'),
config('services.ups.user_id'),
config('services.ups.password')
);
$shipment = $tracking->track('1Z999AA10123456784');
return $shipment->Package->Activity;
Configuration:
Add to config/services.php:
'ups' => [
'access_key' => env('UPS_ACCESS_KEY'),
'user_id' => env('UPS_USER_ID'),
'password' => env('UPS_PASSWORD'),
]
Rate & Ship:
$rate = new Ups\Rate($accessKey, $userId, $password);
$shipment = $this->buildShipmentEntity(); // Your method to create Ups\Entity\Shipment
$rates = $rate->getRate($shipment);
$shipping = new Ups\Shipping($accessKey, $userId, $password);
$response = $shipping->createShipment($rates[0]->Rate->SelectedRate->Shipment);
return $response->getTrackingNumber();
Build Shipment Entity:
private function buildShipmentEntity()
{
$shipment = new \Ups\Entity\Shipment();
$shipment->setShipperNumber('123456789');
$shipFrom = $shipment->getShipFrom();
$shipFrom->getAddress()->setPostalCode('90210');
$shipTo = $shipment->getShipTo();
$shipTo->setCompanyName('Recipient');
$shipTo->getAddress()->setPostalCode('10001');
$package = new \Ups\Entity\Package();
$package->getPackagingType()->setCode(\Ups\Entity\PackagingType::PT_PACKAGE);
$package->getPackageWeight()->setWeight(2.5);
$package->setDimensions($this->buildDimensions());
$shipment->addPackage($package);
return $shipment;
}
$address = new \Ups\Entity\Address();
$address->setPostalCode('10001')
->setCity('New York')
->setCountryCode('US');
$xav = new \Ups\AddressValidation($accessKey, $userId, $password);
$xav->activateReturnObjectOnValidate();
$response = $xav->validate($address);
if ($response->isValid()) {
return $response->getValidatedAddress();
}
return $response->getCandidateAddressList();
$tracking = new Ups\Tracking($accessKey, $userId, $password);
$shipment = $tracking->track('1Z999AA10123456784');
$activities = collect($shipment->Package->Activity)
->map(fn($activity) => [
'date' => $activity->Date,
'status' => $activity->Status->StatusType->Description,
'location' => $activity->Location->City ?? null,
]);
return $activities;
$tnT = new Ups\TimeInTransit($accessKey, $userId, $password);
$shipment = $this->buildShipmentEntity(); // Reuse from above
$response = $tnT->getTimeInTransit($shipment);
return [
'earliest' => $response->getEarliestDeliveryDate(),
'latest' => $response->getLatestDeliveryDate(),
'guaranteed' => $response->isGuaranteed(),
];
Register the UPS client as a singleton:
// app/Providers/UpsServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Ups\Tracking;
use Ups\Rate;
use Ups\Shipping;
class UpsServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Tracking::class, function ($app) {
return new Tracking(
config('services.ups.access_key'),
config('services.ups.user_id'),
config('services.ups.password')
);
});
$this->app->singleton(Rate::class, function ($app) {
return new Rate(
config('services.ups.access_key'),
config('services.ups.user_id'),
config('services.ups.password')
);
});
$this->app->singleton(Shipping::class, function ($app) {
return new Shipping(
config('services.ups.access_key'),
config('services.ups.user_id'),
config('services.ups.password')
);
});
}
}
Create a facade for cleaner syntax:
// app/Facades/Ups.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Ups extends Facade
{
protected static function getFacadeAccessor()
{
return 'ups';
}
}
Update config/app.php:
'ups' => App\Facades\Ups::class,
Usage:
$trackingNumber = Ups::ship($shipmentEntity);
$status = Ups::track('1Z999AA10123456784');
// app/Jobs/ShipWithUps.php
namespace App\Jobs;
use Ups\Shipping;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class ShipWithUps implements ShouldQueue
{
use Queueable;
protected $shipment;
public function __construct($shipment)
{
$this->shipment = $shipment;
}
public function handle(Shipping $shipping)
{
$response = $shipping->createShipment($this->shipment);
$this->shipment->update(['tracking_number' => $response->getTrackingNumber()]);
}
}
// app/Listeners/TrackShipmentUpdates.php
namespace App\Listeners;
use Ups\Tracking;
use App\Models\Shipment;
class TrackShipmentUpdates
{
public function handle(Shipment $shipment, Tracking $tracking)
{
$status = $tracking->track($shipment->tracking_number);
$shipment->update(['last_status' => $status->Package->Activity[0]->Status->StatusType->Description]);
}
}
AuthenticationFailedException or empty responses.access_key, user_id, and password in .env.$tracking = new Ups\Tracking($accessKey, $userId, $password);
$tracking->setLogger(new \Monolog\Logger('ups'));
RateServiceException with "Invalid Shipper Number".shipperNumber is set in the Shipment entity.getRateOptions() to debug:
$rateOptions = $rate->getRateOptions($shipment);
var_dump($rateOptions);
SimpleAddressValidation returns no candidates for non-US addresses.AddressLine1 is populated.trackByReference() returns no results.How can I help you explore Laravel packages today?