diff --git a/README.md b/README.md index 54f539c..6acda6d 100644 --- a/README.md +++ b/README.md @@ -1,159 +1,85 @@ # UPS (United Parcel Service) PHP API -#### Version 0.1.0 (2012-08-22) - ---- - -### Table Of Contents - -1. [About the Project](#about-the-project) -2. [Features](#features) -3. [Setters & Getters](#setters--getters) -4. [Live Shipping Rates](#live-shipping-rates) -5. [Credits](#credits) -6. [License](#license) - ---- - -### About the Project - -So after searching around the Internet, it's apparent that there are no modern OOP UPS (United Parcel Service [www.ups.com](http://www.ups.com)) libraries. This library aims to provide a solid foundation for other developers to fork, contribute, and use for their own projects when interacting with the UPS API. - -*While the live rates API is stable and is encouraged to be used, just know that this project is very early in development. While the goal is to support the entire API, it will take some time, especially since there are no quality examples to use. Please contribute with pull requests to speed things up!* - ---- - -### Features - -1. Consistent and extendible API -2. Live shipping rates between multiple countries -3. Live shipping rates for multiple packages (with unique weights and dimensions) -4. Framework Agnostic. Great for CodeIgniter and Laravel - ---- - -### Setters & Getters - -The setters and getters are dynamic, and included by default in the library using PHP magic method. Meaning, you can set or get any object property using a memorable and consistent syntax. - -#### Setters - -*Setters are used to override default property values.* - - $Ups = new Ups(array( - 'access_key' => 'your-access-key', - 'username' => 'your-username', - 'password' => 'your-password', - 'account_number' => 'your-account-number', - 'origin' => 'your-zipcode' - )); - - $Ups->set_country_code('US'); - $Ups->set_shipping_type('03'); // Use the numberic code for UPS - $Ups->set_shipping_type('UPS Ground'); // OR use the service name - - -#### Getters - -*Getters are used to retrieve property values.* - - $Ups = new Ups(array( - 'access_key' => 'your-access-key', - 'username' => 'your-username', - 'password' => 'your-password', - 'account_number' => 'your-account-number', - 'origin' => 'your-zipcode' - )); - - $country_code = $Ups->get_country_code(); - $shipping_type = $Ups->get_shipping_type(); - ----- - -# Live Shipping Rates - - get_rates(mixed $destination, array $packages); - -**$destination** : An array containing address components or a 5 digit zipcode string. - -**$packages** : An array of arrays that contain indexes and values that give the packages weight and dimension. - -### How to Use - -#### Step 1. Initialize the Library - - // Define your origin - $origin = 'your-zipcode'; - - // OR use the long syntax for non-US locations - $origin = array( - 'state' => 'IN', - 'postal_code' => '46060', - 'country_code' => 'US' - ); - - $auth_params = array( - 'access_key' => 'your-access-key', - 'username' => 'your-username', - 'password' => 'your-password', - 'account_number' => 'your-account-number', - 'origin' => $origin - ); - - // PHP - $Ups = new Ups($auth_params); - - // CodeIgniter - $this->CI->load->library('Ups', $auth_params); - - // ExpressionEngine - $this->EE->load->library('Ups', $auth_params); - -#### Step 2. Set your destination and package data. - - // Height, width, depth are optional. Weight is required. - $packages = array( - array( - 'height' => 12, - 'width' => 12, - 'depth' => 1, - 'weight' => 2 - ), - array( - 'height' => 6, - 'width' => 6, - 'depth' => 2, - 'weight' => 1 - ) - ); - - // Define a destination with a 5 digit zip (US Only) - $destination = '33010'; // Postal code for Miami, FL - - // OR use the long syntax for non-US locations - $destination = array( - 'state' => 'FL', - 'postal_code' => '33010', - 'country_code' => 'US' - ); - - -#### Step 3. Get the live rates - - // PHP - $rate = $Ups->get_rate($destination, $packages); - - // CodeIgniter - $rate = $this->CI->ups->get_rate($destination, $packages); - - // ExpressionEngine - $rate = $this->EE->ups->get_rate($destination, $packages); - ---- +#### Version 0.1.0 (2015-05-23) + + +### Install + +I recommend to use composer for installing. Here is a sample of composer.json file to include UPS library: + + { + "name": "StudyProject", + "repositories": [ + { + "type": "git", + "url": "https://github.com/KoulSlou/UPS.git" + } + ], + "require": { + "KoulSlou/UPS":"dev-master" + } + } + + +### How To Use + +First you need to initialize Ups object with your account credentials: + + + $auth_params = array( + 'access_key' => '1234567890', + 'username' => 'JohnSmith', + 'password' => '*******', + 'account_number' => '123456' + ); + + $Ups = new Ups($auth_params); + +Then you need to specify origin and destination. You can provide only zipcode string for US address, for other countries +provide array with address information. + + + $destination = array( + 'state' => 'FL', + 'postal_code' => '33010', + 'country_code' => 'US', + 'company' => 'test', + 'fax' => '123' + ); + + + $origin = '32548' + +Now define information about packages your going to send: + + // Height, width, depth are optional. Weight is required. + $packages = array( + array( + 'height' => 12, + 'width' => 12, + 'depth' => 1, + 'weight' => 2 + ), + array( + 'height' => 6, + 'width' => 6, + 'depth' => 2, + 'weight' => 1 + ) + ); + +To get rates call get_rate() function: + + $rates = $Ups->rates->get_rate($packages); + +You will receive object of Ups_Live_Rates. In rates property you will have array of available shipping methods (array of +Ups_Rate objects) + + ### Credits -The following URL contains the only library I could find that was of any use was for interacting with UPS. I started from this code, and removed all the hardcoded variables, added a proper setters/getters, and made the packaging system much more robust.[CodeIgniter UPS Rate Tool](https://github.com/EllisLab/CodeIgniter/wiki/UPS-Rate-Tool) +Here is a link to the repository that I used: https://github.com/objectivehtml/UPS --- diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..32997aa --- /dev/null +++ b/composer.json @@ -0,0 +1,12 @@ +{ + "name":"KoulSlou/UPS", + "autoload": { + "files": [ + "libraries/Ups/Ups_Base.php", + "libraries/Ups/Ups_Base_Response.php", + "libraries/Ups/Ups.php", + "libraries/Ups/Ups_Live_Rates.php", + "libraries/Ups/Ups_Rate.php" + ] + } +} diff --git a/libraries/Ups/Ups.php b/libraries/Ups/Ups.php index 6d8ec7c..ca80d80 100644 --- a/libraries/Ups/Ups.php +++ b/libraries/Ups/Ups.php @@ -1,8 +1,5 @@ $obj = new $class($params); } } -} \ No newline at end of file +} diff --git a/libraries/Ups/Ups_Base.php b/libraries/Ups/Ups_Base.php index 0fb78cd..09dfb7b 100644 --- a/libraries/Ups/Ups_Base.php +++ b/libraries/Ups/Ups_Base.php @@ -10,8 +10,6 @@ * @build 20120823 */ -require_once 'Ups_Base_Response.php'; - abstract class Base_Ups { /** @@ -180,4 +178,4 @@ protected function url($endpoint) { return rtrim($this->base_url, '/') . '/' . ltrim($endpoint, '/'); } -} \ No newline at end of file +} diff --git a/libraries/Ups/Ups_Base_Response.php b/libraries/Ups/Ups_Base_Response.php index aabf64f..c1aa2b7 100644 --- a/libraries/Ups/Ups_Base_Response.php +++ b/libraries/Ups/Ups_Base_Response.php @@ -95,6 +95,19 @@ public function __construct($data = array()) } } } + + + public function __set($name, $value) + { + + + if(property_exists($this, $name)) + $this->{$name} = $value; + else if(property_exists($this, ("_".$name))) + $this->{"_".$name} = $value; + else + throw new Exception("Trying to set unexisting property ".$name); + } /** diff --git a/libraries/Ups/Ups_Live_Rates.php b/libraries/Ups/Ups_Live_Rates.php index f0d2e08..36bc8e7 100644 --- a/libraries/Ups/Ups_Live_Rates.php +++ b/libraries/Ups/Ups_Live_Rates.php @@ -218,7 +218,7 @@ class Ups_Live_Rates extends Base_Ups * @var string */ - protected $service_type = 'Rate'; + protected $service_type = 'Shop'; /** @@ -244,13 +244,13 @@ public function __construct($data = array()) parent::__construct($data); } - protected function build_location($var) + protected function build_location($argLocation) { $components = array( 'company', 'attn', - 'phone', - 'fax', + 'phone', + 'fax', 'address' => array( 'street', 'street_2', @@ -261,58 +261,52 @@ protected function build_location($var) 'country_code' ) ); - - if(!is_array($var) && !is_object($var) && preg_match('/\d{5}/', $var)) - { - $var = array( - 'address' => array( - 'state' => $this->get_state($var), - 'postal_code' => $var, - 'country_code' => $this->country_code - ) - ); - } - - foreach($components as $index => $component) - { - $component_name = $component; - - $is_array = TRUE; - - if(!is_array($component)) - { - $is_array = FALSE; - $component = array($component); - } - else - { - $component_name = $index; - } - - foreach($component as $sub_component) - { - $value = NULL; - - if(!isset($var[$sub_component]) && property_exists($this, $sub_component)) - { - $value = $this->$sub_component; - } - - if(!empty($value)) - { - if($is_array) - { - $var[$component_name][$sub_component] = $value; - } - else - { - $var[$sub_component] = $value; - } - } - } - } - - return $var; + + + //If just zip code string is passed + if(is_string($argLocation)) + { + if(!preg_match('/^\d{5}$/', $argLocation)){ + throw new Exception("Bad format for zip code in ".__FUNCTION__."() function in class ".__CLASS__." on line ".__LINE__); + } + + return array('address' => array( + 'state' => $this->get_state($argLocation), + 'postal_code' => $argLocation, + 'country_code' => $this->country_code + )); + + } + + + $location = array(); + + //If address passed in array format + foreach($components as $index=>$addrComponentName){ + + //Work with strings - company, attn, phone, fax + if(is_string($components[$index])){ + if(isset($argLocation[$addrComponentName]) && !empty($argLocation[$addrComponentName])){ + $location[$addrComponentName] = $argLocation[$addrComponentName]; + } + //Work with address inner components - street, city, state, postal_code, country_code + } elseif(is_array($components[$index])){ + + $outerElementName = $index; + foreach($components[$outerElementName] as $innerElement){ + + //If we pass location address WITHOUT outer "address" element + if(isset($argLocation[$innerElement])){ + $location[$outerElementName][$innerElement] = $argLocation[$innerElement]; + } else if (isset($argLocation[$outerElementName][$innerElement])){ + $location[$outerElementName][$innerElement] = $argLocation[$outerElementName][$innerElement]; + } + } + + } + + } + return $location; } protected function key($str) @@ -392,7 +386,7 @@ public function set_destination($var) public function set_shipper($var) { $var = $var ? $var : $this->origin; - + $this->shipper = $this->build_location($var); $this->shipper = isset($this->shipper['address']) ? $this->shipper['address'] : $this->shipper; } @@ -421,7 +415,9 @@ protected function set_default_date($index) public function get_rate($packages = array()) { $this->set_shipper($this->shipper); - + + + $residential_xml = ''; $package_xml = ''; @@ -501,7 +497,7 @@ public function get_rate($packages = array()) - {$this->ship_date} + ".time()." @@ -511,9 +507,9 @@ public function get_rate($packages = array()) "; - + $result = $this->curl($data); - + $xml = new SimpleXMLElement(strstr($result, ' strtotime($this->ship_date), 'formatted_ship_date' => date($this->date_format, strtotime($this->ship_date)) )); - - /* - $return = array( - 'origin' => (object) $this->origin, - 'destination' => (object) $destination, - 'success' => TRUE, - 'error' => FALSE, - 'shipping_type' => $this->shipping_type, - 'package_type' => $this->package_type, - 'pickup_type' => $this->pickup_type, - 'residential' => $this->residential, - 'service_type' => $this->service_type, - 'ship_date' => strtotime($this->ship_date), - 'formatted_ship_date' => date($this->date_format, strtotime($this->ship_date)) - ); - */ - + if ($xml->Response->ResponseStatusCode == '1') { + $response->success(); $data = array(); $warnings = array(); - + $rates = array(); + foreach($xml->RatedShipment as $index => $service) { + + $rates[] = new Ups_Rate($service); + $data[count($data)] = "{$service->TotalCharges->MonetaryValue}"; - + + if(isset($service->RatedShipmentWarning)) { foreach($service->RatedShipmentWarning as $warning) @@ -564,25 +550,10 @@ public function get_rate($packages = array()) } } } - - asort($data); - - foreach($data as $key => $value) - { - $date = ''; - - $service = $xml->RatedShipment[$key]->children(); - - if (!empty($service->GuaranteedDaysToDelivery)) - { - $date = date($this->date_format, strtotime($this->ship_date) + ($service->GuaranteedDaysToDelivery * 86400)); - } - - $rate = number_format((double)($service->TotalCharges->MonetaryValue), 2); - } + $response->warnings = $warnings; - $response->rate = (double) $rate; + $response->setRates($rates); } else { @@ -750,5 +721,26 @@ public function __construct($data = array()) * @var array */ - public $formatted_ship_date; -} \ No newline at end of file + public $formatted_ship_date; + + /** + * + * Delivery rate + * + * @var double + */ + + protected $_rates; + + + public function getRates() + { + return $this->_rates; + } + + public function setRates($value) + { + $this->_rates = $value; + } + +} diff --git a/libraries/Ups/Ups_Rate.php b/libraries/Ups/Ups_Rate.php new file mode 100644 index 0000000..72d7cd3 --- /dev/null +++ b/libraries/Ups/Ups_Rate.php @@ -0,0 +1,93 @@ + 'UPS Express', + '02' => 'UPS Expedited', + '03' => 'UPS Ground', + '07' => 'UPS Express', + '08' => 'UPS Expedited', + '11' => 'UPS Standard', + '12' => 'UPS Three-Day Select', + '13' => 'UPS Saver', + '14' => 'UPS Express Early A.M.', + '54' => 'UPS Worldwide Express Plus', + '59' => 'UPS Second Day Air A.M.', + '65' => 'UPS Saver', + '82' => 'UPS Today Standard', + '83' => 'UPS Today Dedicated Courrier', + '84' => 'UPS Today Intercity', + '85' => 'UPS Today Express', + '86' => 'UPS Today Express Saver', + '308' => 'UPS Freight LTL', + '309' => 'UPS Freight LTL Guaranteed', + '310' => 'UPS Freight LTL Urgent', + 'TDCB' => 'Trade Direct Cross Border', + 'TDA' => 'Trade Direct Air', + 'TDO' => 'Trade Direct Ocean', + ); + + /** + * @param SimpleXMLElement $xmlRateDescription + */ + + public function __construct($xmlRateDescription) + { + + + $this->_code = $xmlRateDescription->Service->Code->__toString(); + + $this->_price = number_format((double)($xmlRateDescription->TotalCharges->MonetaryValue), 2); + + $this->_serviceName = self::$service_codes[$this->_code]; + + if (!empty($xmlRateDescription->GuaranteedDaysToDelivery)) + { + $this->_guaranteedDelivery = $xmlRateDescription->GuaranteedDaysToDelivery->__toString(); + } + + } + + + public function getCode() + { + return $this->_code; + } + + public function getPrice() + { + return $this->_price; + } + + public function getServiceName() + { + return $this->_serviceName; + } + + public function getDays() + { + return $this->_guaranteedDelivery; + } + + + + + + + +} diff --git a/license.txt b/license.txt index 15cf8a7..ac759c1 100644 --- a/license.txt +++ b/license.txt @@ -1,5 +1,5 @@ UPS API for PHP -Copyright (C) 2012 Jusrin Kimbrell +Copyright (C) 2015 Tamara Fedorova This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by