diff --git a/.gitignore b/.gitignore index e7c1d61..29da043 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,9 @@ -vendor/ -.idea/ +vendor composer.lock - +coverage_report +.idea/*.iws +.idea/*.iml +.idea/workspace.xml +.idea/tasks.xml +.DS_Store +live_phpunit.sh diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..12940c6 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +shipping \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..59f68b5 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..1162f43 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..7dc8243 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..8ce43b9 --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..c80f219 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..dc191a2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: php +php: + - 5.4 + +before_script: + - composer install --prefer-dist + +script: + - vendor/bin/phpcs --standard=PSR2 src/ tests/ + - vendor/bin/phpunit diff --git a/README.md b/README.md index 6a6928d..3305141 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,31 @@ ## PHP Shipping API -[![Total Downloads](https://poser.pugx.org/pdt256/shipping/downloads.svg)](https://packagist.org/packages/pdt256/shipping) [![Latest Stable Version](https://poser.pugx.org/pdt256/shipping/v/stable.svg)](https://packagist.org/packages/pdt256/shipping) [![Latest Unstable Version](https://poser.pugx.org/pdt256/shipping/v/unstable.svg)](https://packagist.org/packages/pdt256/shipping) [![License](https://poser.pugx.org/pdt256/shipping/license.svg)](https://packagist.org/packages/pdt256/shipping) +[![Test Coverage](http://img.shields.io/badge/coverage-85%25-green.svg)] +[![Build Status](https://travis-ci.org/pdt256/shipping.svg?branch=master)](https://travis-ci.org/pdt256/shipping) +[![Downloads](https://img.shields.io/packagist/dt/pdt256/shipping.svg)](https://packagist.org/packages/pdt256/shipping) +[![License](https://img.shields.io/packagist/l/pdt256/shipping.svg)](https://github.com/pdt256/shipping/blob/master/LICENSE.txt) A shipping rate wrapper for USPS, UPS, and Fedex. +## Introduction + +This is a PHP shipping package that wraps API calls to UPS, FedEx, and USPS for shipping rates. +Multiple packages can be added to get additional rates. + +All code (including tests) conform to the PSR-2 coding standards. +The namespace and autoloader are using the PSR-4 standard. + +All pull requests are processed by Travis CI to conform to PSR-2 and to verify all unit tests pass. + ## Installation Add the following lines to your ``composer.json`` file. ```JSON { - "require": { - "pdt256/shipping": "dev-master" - } + "require": { + "pdt256/shipping": "1.0.*@dev" + } } ``` @@ -23,15 +36,20 @@ Create a shipment object: ```php $shipment = new Shipment; $shipment + ->setFromIsResidential(false) ->setFromStateProvinceCode('IN') ->setFromPostalCode('46205') ->setFromCountryCode('US') + ->setToIsResidential(true); ->setToPostalCode('20101') ->setToCountryCode('US') - ->setToResidential(true); $package = new Package; -$package->setLength(12)->setWidth(4)->setHeight(3)->setWeight(3); +$package + ->setLength(12) + ->setWidth(4) + ->setHeight(3) + ->setWeight(3); $shipment->addPackage($package); ``` @@ -44,7 +62,7 @@ Notice: The below line uses a stub class to fake a response from the UPS API. You can immediately use this method in your code until you get an account with UPS. ```php -'request_adapter' => new RateRequest\StubUPS(), +'requestAdapter' => new RateRequest\StubUPS(), ``` ```php @@ -52,23 +70,23 @@ use pdt256\Shipping\UPS; use pdt256\Shipping\RateRequest; $ups = new UPS\Rate([ - 'prod' => FALSE, - 'access_key' => 'XXXX', - 'user_id' => 'XXXX', - 'password' => 'XXXX', - 'shipper_number' => 'XXXX', - 'shipment' => $shipment, - 'approved_codes' => [ - '03', // 1-5 business days - '02', // 2 business days - '01', // next business day 10:30am - '13', // next business day by 3pm - '14', // next business day by 8am - ], - 'request_adapter' => new RateRequest\StubUPS(), + 'prod' => FALSE, + 'accessKey' => 'XXXX', + 'userId' => 'XXXX', + 'password' => 'XXXX', + 'shipperNumber' => 'XXXX', + 'shipment' => $shipment, + 'approvedCodes' => [ + '03', // 1-5 business days + '02', // 2 business days + '01', // next business day 10:30am + '13', // next business day by 3pm + '14', // next business day by 8am + ], + 'requestAdapter' => new RateRequest\StubUPS(), ]); -$ups_rates = $ups->get_rates(); +$upsRates = $ups->getRates(); ``` Output array sorted by cost: (in cents) @@ -83,9 +101,9 @@ array(4) { string(10) "UPS Ground" protected $cost => int(1900) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(3) "ups" @@ -98,9 +116,9 @@ array(4) { string(15) "UPS 2nd Day Air" protected $cost => int(4900) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(3) "ups" @@ -113,9 +131,9 @@ array(4) { string(22) "UPS Next Day Air Saver" protected $cost => int(8900) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(3) "ups" @@ -128,9 +146,9 @@ array(4) { string(16) "UPS Next Day Air" protected $cost => int(9300) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(3) "ups" @@ -149,14 +167,14 @@ $usps = new USPS\Rate([ 'username' => 'XXXX', 'password' => 'XXXX', 'shipment' => $shipment, - 'approved_codes' => [ + 'approvedCodes' => [ '1', // 1-3 business days '4', // 2-8 business days ], - 'request_adapter' => new RateRequest\StubUSPS(), + 'requestAdapter' => new RateRequest\StubUSPS(), ]); -$usps_rates = $usps->get_rates(); +$uspsRates = $usps->getRates(); ``` Output array sorted by cost: (in cents) @@ -171,9 +189,9 @@ array(2) { string(11) "Parcel Post" protected $cost => int(1001) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(4) "usps" @@ -186,9 +204,9 @@ array(2) { string(13) "Priority Mail" protected $cost => int(1220) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(4) "usps" @@ -206,21 +224,21 @@ $fedex = new Fedex\Rate([ 'prod' => FALSE, 'key' => 'XXXX', 'password' => 'XXXX', - 'account_number' => 'XXXX', - 'meter_number' => 'XXXX', - 'drop_off_type' => 'BUSINESS_SERVICE_CENTER', + 'accountNumber' => 'XXXX', + 'meterNumber' => 'XXXX', + 'dropOffType' => 'BUSINESS_SERVICE_CENTER', 'shipment' => $shipment, - 'approved_codes' => [ + 'approvedCodes' => [ 'FEDEX_EXPRESS_SAVER', // 1-3 business days 'FEDEX_GROUND', // 1-5 business days 'GROUND_HOME_DELIVERY', // 1-5 business days 'FEDEX_2_DAY', // 2 business days 'STANDARD_OVERNIGHT', // overnight ], - 'request_adapter' => new RateRequest\StubFedex(), + 'requestAdapter' => new RateRequest\StubFedex(), ]); -$fedex_rates = $fedex->get_rates(); +$fedexRates = $fedex->getRates(); ``` Output array sorted by cost: (in cents) @@ -235,9 +253,9 @@ array(4) { string(20) "Ground Home Delivery" protected $cost => int(1600) - protected $transit_time => + protected $transitTime => string(10) "THREE_DAYS" - protected $delivery_ts => + protected $deliveryTime => NULL protected $carrier => string(5) "fedex" @@ -250,9 +268,9 @@ array(4) { string(19) "Fedex Express Saver" protected $cost => int(2900) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => class Carbon\Carbon#23 (3) { public $date => string(26) "2014-09-30 20:00:00.000000" @@ -272,9 +290,9 @@ array(4) { string(11) "Fedex 2 Day" protected $cost => int(4000) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => class Carbon\Carbon#26 (3) { public $date => string(26) "2014-09-29 20:00:00.000000" @@ -294,9 +312,9 @@ array(4) { string(18) "Standard Overnight" protected $cost => int(7800) - protected $transit_time => + protected $transitTime => NULL - protected $delivery_ts => + protected $deliveryTime => class Carbon\Carbon#58 (3) { public $date => string(26) "2014-09-26 20:00:00.000000" @@ -311,6 +329,31 @@ array(4) { } ``` +## Unit Tests: + +```bash + vendor/bin/phpunit +``` + +### With Code Coverage: + +```bash + vendor/bin/phpunit --coverage-text --coverage-html coverage_report +``` + +### With Live API Tests: + +```bash + ./live_phpunit.sh +``` + +## Run Coding Standards Test: + +```bash + vendor/bin/phpcs --standard=PSR2 src/ tests/ +``` + + ### License The MIT License (MIT) diff --git a/composer.json b/composer.json index f7694c4..9f61f9d 100644 --- a/composer.json +++ b/composer.json @@ -9,8 +9,17 @@ "email": "pdt256@gmail.com" } ], + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "require-dev": { - "phpunit/phpunit": "4.0.*" + "phpunit/phpunit": "4.0.*", + "squizlabs/php_codesniffer": "1.5.5" + }, + "require": { + "php": ">=5.4" }, "autoload": { "psr-4": { diff --git a/live_phpunit.sh.example b/live_phpunit.sh.example new file mode 100755 index 0000000..694c601 --- /dev/null +++ b/live_phpunit.sh.example @@ -0,0 +1,16 @@ +#!/bin/bash + +export USPS_USERNAME='XXXXXXXXXXXX' +export USPS_PASSWORD='XXXXXXXXXXXX' + +export UPS_ACCESS_KEY='XXXXXXXXXXXXXXXX' +export UPS_USER_ID='XXXXXX' +export UPS_PASSWORD='XXXX' +export UPS_SHIPPER_NUMBER='XXXXXX' + +export FEDEX_KEY='XXXXXXXXXXXXXXXX' +export FEDEX_PASSWORD='XXXXXXXXXXXXXXXXXXXXXXXXX' +export FEDEX_ACCOUNT_NUMBER='XXXXXXXXX' +export FEDEX_METER_NUMBER='XXXXXXXXX' + +vendor/bin/phpunit diff --git a/phpunit.xml b/phpunit.xml index e23b94a..2dd0ddb 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,17 +1,17 @@ - - - ./tests - - + backupStaticAttributes="false" + bootstrap="vendor/autoload.php" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + processIsolation="false" + stopOnFailure="false" + syntaxCheck="false"> + + + ./tests + + diff --git a/src/Arr.php b/src/Arr.php index aba9ec4..1753894 100644 --- a/src/Arr.php +++ b/src/Arr.php @@ -3,8 +3,8 @@ namespace pdt256\Shipping; class Arr { - public static function get($array, $key, $default = NULL) - { - return isset($array[$key]) ? $array[$key] : $default; - } + public static function get($array, $key, $default = null) + { + return isset($array[$key]) ? $array[$key] : $default; + } } diff --git a/src/Fedex/Rate.php b/src/Fedex/Rate.php index 26022cc..bc4ba01 100644 --- a/src/Fedex/Rate.php +++ b/src/Fedex/Rate.php @@ -12,230 +12,218 @@ use Exception; class Rate extends RateAdapter { - private $url_dev = 'https://gatewaybeta.fedex.com/web-services/'; - private $url_prod = 'https://gateway.fedex.com/web-services/'; - - private $key = 'XXX'; - private $password = 'XXX'; - private $account_number = 'XXX'; - private $meter_number = 'XXX'; - private $drop_off_type = 'BUSINESS_SERVICE_CENTER'; - - public $approved_codes = [ - 'PRIORITY_OVERNIGHT', - 'FEDEX_2_DAY', - 'FEDEX_EXPRESS_SAVER', - 'FEDEX_GROUND', - 'GROUND_HOME_DELIVERY', - ]; - - private $shipping_codes = [ - 'EUROPE_FIRST_INTERNATIONAL_PRIORITY' => 'Europe First International Priority', - 'FEDEX_1_DAY_FREIGHT' => 'Fedex 1 Day Freight', - 'FEDEX_2_DAY' => 'Fedex 2 Day', - 'FEDEX_2_DAY_AM' => 'Fedex 2 Day AM', - 'FEDEX_2_DAY_FREIGHT' => 'Fedex 2 Day Freight', - 'FEDEX_3_DAY_FREIGHT' => 'Fedex 3 Day Freight', - 'FEDEX_EXPRESS_SAVER' => 'Fedex Express Saver', - 'FEDEX_FIRST_FREIGHT' => 'Fedex First Freight', - 'FEDEX_FREIGHT_ECONOMY' => 'Fedex Freight Economy', - 'FEDEX_FREIGHT_PRIORITY' => 'Fedex Freight Priority', - 'FEDEX_GROUND' => 'Fedex Ground', - 'FIRST_OVERNIGHT' => 'First Overnight', - 'GROUND_HOME_DELIVERY' => 'Ground Home Delivery', - 'INTERNATIONAL_ECONOMY' => 'International Economy', - 'INTERNATIONAL_ECONOMY_FREIGHT' => 'International Economy Freight', - 'INTERNATIONAL_FIRST' => 'International First', - 'INTERNATIONAL_PRIORITY' => 'International Priority', - 'INTERNATIONAL_PRIORITY_FREIGHT' => 'International Priority Freight', - 'PRIORITY_OVERNIGHT' => 'Priority Overnight', - 'SMART_POST' => 'Smart Post', - 'STANDARD_OVERNIGHT' => 'Standard Overnight', - ]; - - public function __construct($options = []) - { - parent::__construct($options); - - if (isset($options['key'])) { - $this->key = $options['key']; - } - - if (isset($options['password'])) { - $this->password = $options['password']; - } - - if (isset($options['account_number'])) { - $this->account_number = $options['account_number']; - } - - if (isset($options['meter_number'])) { - $this->meter_number = $options['meter_number']; - } - - if (isset($options['approved_codes'])) { - $this->approved_codes = $options['approved_codes']; - } - - if (isset($options['drop_off_type'])) { - $this->drop_off_type = $options['drop_off_type']; - } - - if (isset($options['request_adapter'])) { - $this->set_request_adapter($options['request_adapter']); - } else { - $this->set_request_adapter(new RateRequest\Post()); - } - } - - protected function prepare() - { - $date = time(); - $day_name = date('l', $date); - - if ($day_name == 'Saturday') { - $date += 172800; - } elseif ($day_name == 'Sunday') { - $date += 86400; - } - - // http://www.fedex.com/templates/components/apps/wpor/secure/downloads/pdf/Aug13/PropDevGuide.pdf - // http://www.fedex.com/us/developer/product/WebServices/MyWebHelp_August2010/Content/Proprietary_Developer_Guide/Rate_Services_conditionalized.htm - - - $packages = ''; - $sequence_number = 0; - foreach ($this->shipment->getPackages() as $p) { - $sequence_number++; - - $packages .= ' - ' . $sequence_number . ' - 1 - - LB - ' . $p->getWeight() . ' - - - ' . $p->getLength() . ' - ' . $p->getWidth() . ' - ' . $p->getHeight() . ' - IN - - '; - } - - $this->data = -' - - - - - - ' . $this->key . ' - ' . $this->password . ' - - - - ' . $this->account_number . ' - ' . $this->meter_number . ' - - - crs - 13 - 0 - 0 - - true - - ' . date('c') . ' - ' . $this->drop_off_type . ' - YOUR_PACKAGING - -
- ' . $this->shipment->getFromPostalCode() . ' - ' . $this->shipment->getFromCountryCode() . ' - ' . (($this->shipment->isFromResidential()) ? '1' : '') . ' -
-
- -
- ' . $this->shipment->getToPostalCode() . ' - ' . $this->shipment->getToCountryCode() . ' - ' . (($this->shipment->isToResidential()) ? '1' : '') . ' -
-
- LIST - ' . $this->shipment->packageCount() . ' - ' . $packages . ' -
-
-
-
'; - - return $this; - } - - protected function execute() - { - if ($this->is_prod) { - $url = $this->url_prod; - } else { - $url = $this->url_dev; - } - - $this->response = $this->rate_request->execute($url, $this->data); - - return $this; - } - - protected function process() - { - try { - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->loadXml($this->response); - $rate_reply = $dom->getElementsByTagName('RateReplyDetails'); - - if (empty($rate_reply->length)) { - throw new Exception('Unable to get FedEx Rates.'); - } - } catch (Exception $e) { - // StatsD::increment('error.shipping.get_fedex_rate'); - // Kohana::$log->add(Log::ERROR, $e)->write(); - throw $e; - } - - foreach ($rate_reply as $rate) { - $code = $rate->getElementsByTagName('ServiceType')->item(0)->nodeValue; - - if ( ! empty($this->approved_codes) AND ! in_array($code, $this->approved_codes)) { - continue; - } - - $name = Arr::get($this->shipping_codes, $code); - - $delivery_ts = @$rate->getElementsByTagName('DeliveryTimestamp')->item(0)->nodeValue; - $transit_time = @$rate->getElementsByTagName('TransitTime')->item(0)->nodeValue; - - $cost = $rate - ->getElementsByTagName('RatedShipmentDetails')->item(0) - ->getElementsByTagName('ShipmentRateDetail')->item(0) - ->getElementsByTagName('TotalNetCharge')->item(0) - ->getElementsByTagName('Amount')->item(0)->nodeValue; - - $quote = new Quote; - $quote - ->setCarrier('fedex') - ->setCode($code) - ->setName($name) - ->setCost((int) $cost * 100) - ->setTransitTime($transit_time); - if ($delivery_ts) { - $quote->setDeliveryEstimate(new DateTime($delivery_ts)); - } - - $this->rates[] = $quote; - } - - return $this; - } + private $urlDev = 'https://gatewaybeta.fedex.com/web-services/'; + private $urlProd = 'https://gateway.fedex.com/web-services/'; + + private $key = 'XXX'; + private $password = 'XXX'; + private $accountNumber = 'XXX'; + private $meterNumber = 'XXX'; + private $dropOffType = 'BUSINESS_SERVICE_CENTER'; + + public $approvedCodes = [ + 'PRIORITY_OVERNIGHT', + 'FEDEX_2_DAY', + 'FEDEX_EXPRESS_SAVER', + 'FEDEX_GROUND', + 'GROUND_HOME_DELIVERY', + ]; + + private $shippingCodes = [ + 'EUROPE_FIRST_INTERNATIONAL_PRIORITY' => 'Europe First International Priority', + 'FEDEX_1_DAY_FREIGHT' => 'Fedex 1 Day Freight', + 'FEDEX_2_DAY' => 'Fedex 2 Day', + 'FEDEX_2_DAY_AM' => 'Fedex 2 Day AM', + 'FEDEX_2_DAY_FREIGHT' => 'Fedex 2 Day Freight', + 'FEDEX_3_DAY_FREIGHT' => 'Fedex 3 Day Freight', + 'FEDEX_EXPRESS_SAVER' => 'Fedex Express Saver', + 'FEDEX_FIRST_FREIGHT' => 'Fedex First Freight', + 'FEDEX_FREIGHT_ECONOMY' => 'Fedex Freight Economy', + 'FEDEX_FREIGHT_PRIORITY' => 'Fedex Freight Priority', + 'FEDEX_GROUND' => 'Fedex Ground', + 'FIRST_OVERNIGHT' => 'First Overnight', + 'GROUND_HOME_DELIVERY' => 'Ground Home Delivery', + 'INTERNATIONAL_ECONOMY' => 'International Economy', + 'INTERNATIONAL_ECONOMY_FREIGHT' => 'International Economy Freight', + 'INTERNATIONAL_FIRST' => 'International First', + 'INTERNATIONAL_PRIORITY' => 'International Priority', + 'INTERNATIONAL_PRIORITY_FREIGHT' => 'International Priority Freight', + 'PRIORITY_OVERNIGHT' => 'Priority Overnight', + 'SMART_POST' => 'Smart Post', + 'STANDARD_OVERNIGHT' => 'Standard Overnight', + ]; + + public function __construct($options = []) + { + parent::__construct($options); + + $this->key = Arr::get($options, 'key'); + $this->password = Arr::get($options, 'password'); + $this->accountNumber = Arr::get($options, 'accountNumber'); + $this->meterNumber = Arr::get($options, 'meterNumber'); + $this->approvedCodes = Arr::get($options, 'approvedCodes'); + $this->dropOffType = Arr::get($options, 'dropOffType'); + + $this->setRequestAdapter(Arr::get($options, 'requestAdapter', new RateRequest\Post())); + } + + protected function prepare() + { + $date = time(); + $day_name = date('l', $date); + + if ($day_name == 'Saturday') { + $date += 172800; + } elseif ($day_name == 'Sunday') { + $date += 86400; + } + + // http://www.fedex.com/templates/components/apps/wpor/secure/downloads/pdf/Aug13/PropDevGuide.pdf + // http://www.fedex.com/us/developer/product/WebServices/MyWebHelp_August2010/Content/ + // Proprietary_Developer_Guide/Rate_Services_conditionalized.htm + + $packages = ''; + $sequence_number = 0; + foreach ($this->shipment->getPackages() as $package) { + $sequence_number++; + + $packages .= + '' . + '' . $sequence_number . '' . + '1' . + '' . + 'LB' . + '' . $package->getWeight() . '' . + '' . + '' . + '' . $package->getLength() . '' . + '' . $package->getWidth() . '' . + '' . $package->getHeight() . '' . + 'IN' . + '' . + ''; + } + + $this->data = '' . + '' . + '' . + '' . + '' . + '' . + '' . $this->key . '' . + '' . $this->password . '' . + '' . + '' . + '' . + '' . $this->accountNumber . '' . + '' . $this->meterNumber . '' . + '' . + '' . + 'crs' . + '13' . + '0' . + '0' . + '' . + 'true' . + '' . + '' . date('c') . '' . + '' . $this->dropOffType . '' . + 'YOUR_PACKAGING' . + '' . + '
' . + '' . $this->shipment->getFromPostalCode() . '' . + '' . $this->shipment->getFromCountryCode() . '' . + ( + $this->shipment->getFromIsResidential() ? + '1' : + '' + ) . + '
' . + '
' . + '' . + '
' . + '' . $this->shipment->getToPostalCode() . '' . + '' . $this->shipment->getToCountryCode() . '' . + ( + $this->shipment->getToIsResidential() ? + '1' : + '' + ) . + '
' . + '
' . + 'LIST' . + '' . $this->shipment->packageCount() . '' . + $packages . + '
' . + '
' . + '
' . + '
'; + + return $this; + } + + protected function execute() + { + if ($this->isProduction) { + $url = $this->urlProd; + } else { + $url = $this->urlDev; + } + + $this->response = $this->rateRequest->execute($url, $this->data); + + return $this; + } + + protected function process() + { + try { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->loadXml($this->response); + $rate_reply = $dom->getElementsByTagName('RateReplyDetails'); + + if (empty($rate_reply->length)) { + throw new Exception('Unable to get FedEx Rates.'); + } + } catch (Exception $e) { + // StatsD::increment('error.shipping.get_fedex_rate'); + // Kohana::$log->add(Log::ERROR, $e)->write(); + throw $e; + } + + foreach ($rate_reply as $rate) { + $code = $rate->getElementsByTagName('ServiceType')->item(0)->nodeValue; + + if (! empty($this->approvedCodes) && ! in_array($code, $this->approvedCodes)) { + continue; + } + + $name = Arr::get($this->shippingCodes, $code); + + $delivery_ts = @$rate->getElementsByTagName('DeliveryTimestamp')->item(0)->nodeValue; + $transit_time = @$rate->getElementsByTagName('TransitTime')->item(0)->nodeValue; + + $cost = $rate + ->getElementsByTagName('RatedShipmentDetails')->item(0) + ->getElementsByTagName('ShipmentRateDetail')->item(0) + ->getElementsByTagName('TotalNetCharge')->item(0) + ->getElementsByTagName('Amount')->item(0)->nodeValue; + + $quote = new Quote; + $quote + ->setCarrier('fedex') + ->setCode($code) + ->setName($name) + ->setCost((int) ($cost * 100)) + ->setTransitTime($transit_time); + if ($delivery_ts) { + $quote->setDeliveryEstimate(new DateTime($delivery_ts)); + } + + $this->rates[] = $quote; + } + + return $this; + } } diff --git a/src/Quote.php b/src/Quote.php index 0daf8d4..cfe37ba 100644 --- a/src/Quote.php +++ b/src/Quote.php @@ -7,10 +7,18 @@ class Quote protected $code; protected $name; protected $cost; - protected $transit_time; - protected $delivery_ts; + protected $transitTime; + protected $deliveryEstimate; protected $carrier; + public function __construct($carrier = null, $code = null, $name = null, $cost = null) + { + $this->setCarrier($carrier); + $this->setCode($code); + $this->setName($name); + $this->setCost($cost); + } + /** * @return mixed */ @@ -25,7 +33,7 @@ class Quote */ public function setCarrier($carrier) { - $this->carrier = $carrier; + $this->carrier = (string) $carrier; return $this; } @@ -43,7 +51,7 @@ class Quote */ public function setCode($code) { - $this->code = $code; + $this->code = (string) $code; return $this; } @@ -61,7 +69,7 @@ class Quote */ public function setName($name) { - $this->name = $name; + $this->name = (string) $name; return $this; } @@ -81,7 +89,7 @@ class Quote */ public function setCost($cost) { - $this->cost = $cost; + $this->cost = (int) $cost; return $this; } @@ -90,16 +98,16 @@ class Quote */ public function getTransitTime() { - return $this->transit_time; + return $this->transitTime; } /** - * @param mixed $transit_time + * @param mixed $transitTime * @return $this */ - public function setTransitTime($transit_time) + public function setTransitTime($transitTime) { - $this->transit_time = $transit_time; + $this->transitTime = $transitTime; return $this; } @@ -108,16 +116,16 @@ class Quote */ public function getDeliveryEstimate() { - return $this->delivery_ts; + return $this->deliveryEstimate; } /** - * @param DateTime $estimate + * @param DateTime $deliveryEstimate * @return $this */ - public function setDeliveryEstimate(DateTime $estimate) + public function setDeliveryEstimate(DateTime $deliveryEstimate) { - $this->delivery_ts = $estimate; + $this->deliveryEstimate = $deliveryEstimate; return $this; } } diff --git a/src/RateAdapter.php b/src/RateAdapter.php index de2d17a..0a334cd 100644 --- a/src/RateAdapter.php +++ b/src/RateAdapter.php @@ -5,49 +5,58 @@ use Exception; abstract class RateAdapter { - protected $is_prod = FALSE; - - /** @var Shipment */ - protected $shipment; - protected $data; - protected $response; - protected $rates = []; - - protected $rate_request; - - abstract protected function prepare(); // Prepare XML - abstract protected function execute(); // Curl Request - abstract protected function process(); // Convert to shipping rates array - - public function __construct($options = []) - { - if (isset($options['prod'])) { - $this->is_prod = (bool) $options['prod']; - } - - if (isset($options['shipment'])) { - $this->shipment = $options['shipment']; - } - } - - public function set_request_adapter(RateRequest\Adapter $rate_request) - { - $this->rate_request = $rate_request; - } - - public function get_rates() - { - $this - ->prepare() - ->execute() - ->process() - ->sort_by_cost(); - - return array_values($this->rates); - } - - protected function sort_by_cost() - { - uasort($this->rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());')); - } + protected $isProduction; + + /** @var Shipment */ + protected $shipment; + protected $data; + protected $response; + protected $rates; + + /** @var @var RateRequest\Adapter */ + protected $rateRequest; + + /** + * Prepare XML + */ + abstract protected function prepare(); + + /** + * Curl Request + */ + abstract protected function execute(); + + /** + * Convert to shipping rates array + */ + abstract protected function process(); + + public function __construct($options = []) + { + $this->rates = []; + + $this->isProduction = (bool) Arr::get($options, 'prod', false); + $this->shipment = Arr::get($options, 'shipment'); + } + + public function setRequestAdapter(RateRequest\Adapter $rateRequest) + { + $this->rateRequest = $rateRequest; + } + + public function getRates() + { + $this + ->prepare() + ->execute() + ->process() + ->sortByCost(); + + return array_values($this->rates); + } + + protected function sortByCost() + { + uasort($this->rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());')); + } } diff --git a/src/RateRequest/Adapter.php b/src/RateRequest/Adapter.php index 1e432ef..6913f12 100644 --- a/src/RateRequest/Adapter.php +++ b/src/RateRequest/Adapter.php @@ -3,8 +3,8 @@ namespace pdt256\Shipping\RateRequest; abstract class Adapter { - protected $curl_connect_timeout_ms = 1000; // milliseconds - protected $curl_dl_timeout = 11; // seconds + protected $curlConnectTimeoutInMilliseconds = 1000; + protected $curlDownloadTimeoutInSeconds = 11; - abstract public function execute($url, $data = NULL); + abstract public function execute($url, $data = null); } diff --git a/src/RateRequest/FedexResponse.xml b/src/RateRequest/FedexResponse.xml new file mode 100644 index 0000000..7ad915f --- /dev/null +++ b/src/RateRequest/FedexResponse.xml @@ -0,0 +1,3440 @@ + + + + + NOTE + + NOTE + crs + 819 + The origin state/province code has been changed. + The origin state/province code has been changed. + + + NOTE + crs + 820 + The destination state/province code has been changed. + The destination state/province code has been changed. + + + crs + 13 + 0 + 0 + + + PRIORITY_OVERNIGHT + YOUR_PACKAGING + ACTA + FRI + 2014-09-26T12:00:00 + + PRIORITY_OVERNIGHT + 2014-09-26T12:00:00 + FRI + AM + 0 + NON_DOCUMENTS + + AUS + false + A1 + AM + SERVICE_DEFAULT + PAYOR_ACCOUNT_PACKAGE + + + USD + 44.63 + + + PAYOR_ACCOUNT_PACKAGE + 1 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 31.25 + + + USD + 0.0 + + + USD + 31.25 + + + USD + 10.63 + + + USD + 41.88 + + + USD + 0.0 + + + USD + 41.88 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.63 + + + + + 0 + + USD + 44.63 + + + PAYOR_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 31.25 + + + USD + 0.0 + + + USD + 31.25 + + + USD + 10.63 + + + USD + 41.88 + + + USD + 0.0 + + + USD + 41.88 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.63 + + + + + + + + USD + 44.63 + + + RATED_ACCOUNT_PACKAGE + 1 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 31.25 + + + USD + 0.0 + + + USD + 31.25 + + + USD + 10.63 + + + USD + 41.88 + + + USD + 0.0 + + + USD + 41.88 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.63 + + + + + 0 + + USD + 44.63 + + + RATED_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 31.25 + + + USD + 0.0 + + + USD + 31.25 + + + USD + 10.63 + + + USD + 41.88 + + + USD + 0.0 + + + USD + 41.88 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.63 + + + + + + + + PAYOR_LIST_PACKAGE + 1574 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 72.0 + + + USD + 0.0 + + + USD + 72.0 + + + USD + 14.51 + + + USD + 86.51 + + + USD + 0.0 + + + USD + 86.51 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.51 + + + + + 0 + + PAYOR_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 72.0 + + + USD + 0.0 + + + USD + 72.0 + + + USD + 14.51 + + + USD + 86.51 + + + USD + 0.0 + + + USD + 86.51 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.51 + + + + + + + + RATED_LIST_PACKAGE + 1574 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 72.0 + + + USD + 0.0 + + + USD + 72.0 + + + USD + 14.51 + + + USD + 86.51 + + + USD + 0.0 + + + USD + 86.51 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.51 + + + + + 0 + + RATED_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 72.0 + + + USD + 0.0 + + + USD + 72.0 + + + USD + 14.51 + + + USD + 86.51 + + + USD + 0.0 + + + USD + 86.51 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.51 + + + + + + + + STANDARD_OVERNIGHT + YOUR_PACKAGING + ACTA + FRI + 2014-09-26T20:00:00 + + STANDARD_OVERNIGHT + 2014-09-26T20:00:00 + FRI + AM + 0 + NON_DOCUMENTS + + AUS + false + A1 + AM + SERVICE_DEFAULT + PAYOR_ACCOUNT_PACKAGE + + + USD + 4.71 + + + PAYOR_ACCOUNT_PACKAGE + 1371 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 64.55 + + + USD + 0.0 + + + USD + 64.55 + + + USD + 13.8 + + + USD + 78.35 + + + USD + 0.0 + + + USD + 78.35 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 6.8 + + + + + 0 + + USD + 4.71 + + + PAYOR_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 64.55 + + + USD + 0.0 + + + USD + 64.55 + + + USD + 13.8 + + + USD + 78.35 + + + USD + 0.0 + + + USD + 78.35 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 6.8 + + + + + + + + USD + 4.71 + + + RATED_ACCOUNT_PACKAGE + 1371 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 64.55 + + + USD + 0.0 + + + USD + 64.55 + + + USD + 13.8 + + + USD + 78.35 + + + USD + 0.0 + + + USD + 78.35 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 6.8 + + + + + 0 + + USD + 4.71 + + + RATED_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 64.55 + + + USD + 0.0 + + + USD + 64.55 + + + USD + 13.8 + + + USD + 78.35 + + + USD + 0.0 + + + USD + 78.35 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 6.8 + + + + + + + + PAYOR_LIST_PACKAGE + 1371 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 68.85 + + + USD + 0.0 + + + USD + 68.85 + + + USD + 14.21 + + + USD + 83.06 + + + USD + 0.0 + + + USD + 83.06 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.21 + + + + + 0 + + PAYOR_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 68.85 + + + USD + 0.0 + + + USD + 68.85 + + + USD + 14.21 + + + USD + 83.06 + + + USD + 0.0 + + + USD + 83.06 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.21 + + + + + + + + RATED_LIST_PACKAGE + 1371 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 68.85 + + + USD + 0.0 + + + USD + 68.85 + + + USD + 14.21 + + + USD + 83.06 + + + USD + 0.0 + + + USD + 83.06 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.21 + + + + + 0 + + RATED_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 68.85 + + + USD + 0.0 + + + USD + 68.85 + + + USD + 14.21 + + + USD + 83.06 + + + USD + 0.0 + + + USD + 83.06 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 7.21 + + + + + + + + FEDEX_2_DAY_AM + YOUR_PACKAGING + ACTA + MON + 2014-09-29T12:00:00 + + FEDEX_2_DAY_AM + 2014-09-29T12:00:00 + MON + AM + 0 + NON_DOCUMENTS + + AUS + false + A1 + AM + SERVICE_DEFAULT + PAYOR_ACCOUNT_PACKAGE + + + USD + 4.42 + + + PAYOR_ACCOUNT_PACKAGE + 12 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 34.73 + + + USD + 0.0 + + + USD + 34.73 + + + USD + 10.96 + + + USD + 45.69 + + + USD + 0.0 + + + USD + 45.69 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.96 + + + + + 0 + + USD + 4.42 + + + PAYOR_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 34.73 + + + USD + 0.0 + + + USD + 34.73 + + + USD + 10.96 + + + USD + 45.69 + + + USD + 0.0 + + + USD + 45.69 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.96 + + + + + + + + USD + 4.42 + + + RATED_ACCOUNT_PACKAGE + 12 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 34.73 + + + USD + 0.0 + + + USD + 34.73 + + + USD + 10.96 + + + USD + 45.69 + + + USD + 0.0 + + + USD + 45.69 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.96 + + + + + 0 + + USD + 4.42 + + + RATED_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 34.73 + + + USD + 0.0 + + + USD + 34.73 + + + USD + 10.96 + + + USD + 45.69 + + + USD + 0.0 + + + USD + 45.69 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.96 + + + + + + + + PAYOR_LIST_PACKAGE + 12 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 38.76 + + + USD + 0.0 + + + USD + 38.76 + + + USD + 11.35 + + + USD + 50.11 + + + USD + 0.0 + + + USD + 50.11 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 4.35 + + + + + 0 + + PAYOR_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 38.76 + + + USD + 0.0 + + + USD + 38.76 + + + USD + 11.35 + + + USD + 50.11 + + + USD + 0.0 + + + USD + 50.11 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 4.35 + + + + + + + + RATED_LIST_PACKAGE + 12 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 38.76 + + + USD + 0.0 + + + USD + 38.76 + + + USD + 11.35 + + + USD + 50.11 + + + USD + 0.0 + + + USD + 50.11 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 4.35 + + + + + 0 + + RATED_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 38.76 + + + USD + 0.0 + + + USD + 38.76 + + + USD + 11.35 + + + USD + 50.11 + + + USD + 0.0 + + + USD + 50.11 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 4.35 + + + + + + + + FEDEX_2_DAY + YOUR_PACKAGING + ACTA + MON + 2014-09-29T20:00:00 + + FEDEX_2_DAY + 2014-09-29T20:00:00 + MON + AM + 0 + NON_DOCUMENTS + + AUS + false + A1 + AM + SERVICE_DEFAULT + PAYOR_ACCOUNT_PACKAGE + + + USD + 3.84 + + + PAYOR_ACCOUNT_PACKAGE + 6068 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 30.2 + + + USD + 0.0 + + + USD + 30.2 + + + USD + 10.53 + + + USD + 40.73 + + + USD + 0.0 + + + USD + 40.73 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.53 + + + + + 0 + + USD + 3.84 + + + PAYOR_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 30.2 + + + USD + 0.0 + + + USD + 30.2 + + + USD + 10.53 + + + USD + 40.73 + + + USD + 0.0 + + + USD + 40.73 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.53 + + + + + + + + USD + 3.84 + + + RATED_ACCOUNT_PACKAGE + 6068 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 30.2 + + + USD + 0.0 + + + USD + 30.2 + + + USD + 10.53 + + + USD + 40.73 + + + USD + 0.0 + + + USD + 40.73 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.53 + + + + + 0 + + USD + 3.84 + + + RATED_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 30.2 + + + USD + 0.0 + + + USD + 30.2 + + + USD + 10.53 + + + USD + 40.73 + + + USD + 0.0 + + + USD + 40.73 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.53 + + + + + + + + PAYOR_LIST_PACKAGE + 6068 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 33.7 + + + USD + 0.0 + + + USD + 33.7 + + + USD + 10.87 + + + USD + 44.57 + + + USD + 0.0 + + + USD + 44.57 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.87 + + + + + 0 + + PAYOR_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 33.7 + + + USD + 0.0 + + + USD + 33.7 + + + USD + 10.87 + + + USD + 44.57 + + + USD + 0.0 + + + USD + 44.57 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.87 + + + + + + + + RATED_LIST_PACKAGE + 6068 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 33.7 + + + USD + 0.0 + + + USD + 33.7 + + + USD + 10.87 + + + USD + 44.57 + + + USD + 0.0 + + + USD + 44.57 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.87 + + + + + 0 + + RATED_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 33.7 + + + USD + 0.0 + + + USD + 33.7 + + + USD + 10.87 + + + USD + 44.57 + + + USD + 0.0 + + + USD + 44.57 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 3.87 + + + + + + + + FEDEX_EXPRESS_SAVER + YOUR_PACKAGING + ACTA + TUE + 2014-09-30T20:00:00 + + FEDEX_EXPRESS_SAVER + 2014-09-30T20:00:00 + TUE + AM + 0 + NON_DOCUMENTS + + AUS + false + A1 + AM + SERVICE_DEFAULT + PAYOR_ACCOUNT_PACKAGE + + + USD + 3.01 + + + PAYOR_ACCOUNT_PACKAGE + 7175 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 20.3 + + + USD + 0.0 + + + USD + 20.3 + + + USD + 9.59 + + + USD + 29.89 + + + USD + 0.0 + + + USD + 29.89 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.59 + + + + + 0 + + USD + 3.01 + + + PAYOR_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 20.3 + + + USD + 0.0 + + + USD + 20.3 + + + USD + 9.59 + + + USD + 29.89 + + + USD + 0.0 + + + USD + 29.89 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.59 + + + + + + + + USD + 3.01 + + + RATED_ACCOUNT_PACKAGE + 7175 + 6 + PACKAGE + DIM + 194 + 9.5 + + LB + 4.0 + + + LB + 4.0 + + + USD + 20.3 + + + USD + 0.0 + + + USD + 20.3 + + + USD + 9.59 + + + USD + 29.89 + + + USD + 0.0 + + + USD + 29.89 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.59 + + + + + 0 + + USD + 3.01 + + + RATED_ACCOUNT_PACKAGE + DIM + + LB + 4.0 + + + LB + 4.0 + + + USD + 20.3 + + + USD + 0.0 + + + USD + 20.3 + + + USD + 9.59 + + + USD + 29.89 + + + USD + 0.0 + + + USD + 29.89 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.59 + + + + + + + + PAYOR_LIST_PACKAGE + 7175 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 23.05 + + + USD + 0.0 + + + USD + 23.05 + + + USD + 9.85 + + + USD + 32.9 + + + USD + 0.0 + + + USD + 32.9 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.85 + + + + + 0 + + PAYOR_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 23.05 + + + USD + 0.0 + + + USD + 23.05 + + + USD + 9.85 + + + USD + 32.9 + + + USD + 0.0 + + + USD + 32.9 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.85 + + + + + + + + RATED_LIST_PACKAGE + 7175 + 6 + PACKAGE + DIM + 166 + 9.5 + + LB + 5.0 + + + LB + 5.0 + + + USD + 23.05 + + + USD + 0.0 + + + USD + 23.05 + + + USD + 9.85 + + + USD + 32.9 + + + USD + 0.0 + + + USD + 32.9 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.85 + + + + + 0 + + RATED_LIST_PACKAGE + DIM + + LB + 5.0 + + + LB + 5.0 + + + USD + 23.05 + + + USD + 0.0 + + + USD + 23.05 + + + USD + 9.85 + + + USD + 32.9 + + + USD + 0.0 + + + USD + 32.9 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + Residential delivery + + USD + 3.35 + + + + DELIVERY_AREA + Delivery Area Surcharge Extended Residential + + USD + 3.65 + + + + FUEL + Fuel + + USD + 2.85 + + + + + + + + GROUND_HOME_DELIVERY + YOUR_PACKAGING + ACTA + + GROUND_HOME_DELIVERY + THREE_DAYS + 0 + + AUS + false + A1 + AM + THREE_DAYS + SERVICE_DEFAULT + PAYOR_ACCOUNT_PACKAGE + + + USD + 0.0 + + + PAYOR_ACCOUNT_PACKAGE + 6 + ACTUAL + 0 + 6.5 + + LB + 3.0 + + + USD + 9.01 + + + USD + 0.0 + + + USD + 9.01 + + + USD + 7.54 + + + USD + 16.55 + + + USD + 0.0 + + + USD + 16.55 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + PACKAGE + FedEx Home Delivery Urban/Rural Charge + + USD + 2.9 + + + + DELIVERY_AREA + PACKAGE + Delivery Area Surcharge Extended Residential + + USD + 3.62 + + + + FUEL + PACKAGE + FedEx Ground Fuel + + USD + 1.02 + + + + + 0 + + USD + 0.0 + + + PAYOR_ACCOUNT_PACKAGE + ACTUAL + + LB + 3.0 + + + USD + 9.01 + + + USD + 0.0 + + + USD + 9.01 + + + USD + 7.54 + + + USD + 16.55 + + + USD + 0.0 + + + USD + 16.55 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + PACKAGE + FedEx Home Delivery Urban/Rural Charge + + USD + 2.9 + + + + DELIVERY_AREA + PACKAGE + Delivery Area Surcharge Extended Residential + + USD + 3.62 + + + + FUEL + PACKAGE + FedEx Ground Fuel + + USD + 1.02 + + + + + + + + PAYOR_LIST_PACKAGE + 6 + ACTUAL + 0 + 6.5 + + LB + 3.0 + + + USD + 9.01 + + + USD + 0.0 + + + USD + 9.01 + + + USD + 7.54 + + + USD + 16.55 + + + USD + 0.0 + + + USD + 16.55 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + PACKAGE + FedEx Home Delivery Urban/Rural Charge + + USD + 2.9 + + + + DELIVERY_AREA + PACKAGE + Delivery Area Surcharge Extended Residential + + USD + 3.62 + + + + FUEL + PACKAGE + FedEx Ground Fuel + + USD + 1.02 + + + + + 0 + + PAYOR_LIST_PACKAGE + ACTUAL + + LB + 3.0 + + + USD + 9.01 + + + USD + 0.0 + + + USD + 9.01 + + + USD + 7.54 + + + USD + 16.55 + + + USD + 0.0 + + + USD + 16.55 + + + USD + 0.0 + + + RESIDENTIAL_DELIVERY + PACKAGE + FedEx Home Delivery Urban/Rural Charge + + USD + 2.9 + + + + DELIVERY_AREA + PACKAGE + Delivery Area Surcharge Extended Residential + + USD + 3.62 + + + + FUEL + PACKAGE + FedEx Ground Fuel + + USD + 1.02 + + + + + + + + + diff --git a/src/RateRequest/Get.php b/src/RateRequest/Get.php index 6d64ad4..4e087b7 100644 --- a/src/RateRequest/Get.php +++ b/src/RateRequest/Get.php @@ -3,22 +3,23 @@ namespace pdt256\Shipping\RateRequest; class Get extends Adapter { - public function execute($url, $data = NULL) - { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HEADER, FALSE); - curl_setopt($ch, CURLOPT_HTTPGET, TRUE); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $this->curl_connect_timeout_ms); - curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_dl_timeout); - $response = curl_exec($ch); - curl_close($ch); - if ($response === false) { - throw new RequestException(curl_error($ch)); - } - return $response; - } + public function execute($url, $data = null) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_HTTPGET, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1'); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $this->curlConnectTimeoutInMilliseconds); + curl_setopt($ch, CURLOPT_TIMEOUT, $this->curlDownloadTimeoutInSeconds); + $response = curl_exec($ch); + curl_close($ch); + if ($response === false) { + throw new RequestException(curl_error($ch)); + } + return $response; + } } diff --git a/src/RateRequest/Post.php b/src/RateRequest/Post.php index 17edd11..88ebd2a 100644 --- a/src/RateRequest/Post.php +++ b/src/RateRequest/Post.php @@ -3,24 +3,25 @@ namespace pdt256\Shipping\RateRequest; class Post extends Adapter { - public function execute($url, $data = NULL) - { - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HEADER, FALSE); - curl_setopt($ch, CURLOPT_POST, TRUE); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $this->curl_connect_timeout_ms); - curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_dl_timeout); - $response = curl_exec($ch); - if ($response === false) { - throw new RequestException(curl_error($ch)); - } - curl_close($ch); + public function execute($url, $data = null) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1'); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $this->curlConnectTimeoutInMilliseconds); + curl_setopt($ch, CURLOPT_TIMEOUT, $this->curlDownloadTimeoutInSeconds); + $response = curl_exec($ch); + if ($response === false) { + throw new RequestException(curl_error($ch)); + } + curl_close($ch); - return $response; - } + return $response; + } } diff --git a/src/RateRequest/RequestException.php b/src/RateRequest/RequestException.php index 7df98c7..1e4dd40 100644 --- a/src/RateRequest/RequestException.php +++ b/src/RateRequest/RequestException.php @@ -1,6 +1,6 @@ artificial_delay = $artificial_delay; - } + public function __construct($artificial_delay = 0) + { + $this->artificialDelay = $artificial_delay; + } - public function execute($url, $data = NULL) - { - if ($this->artificial_delay > 0) { - sleep($this->artificial_delay); - } + public function execute($url, $data = null) + { + if ($this->artificialDelay > 0) { + sleep($this->artificialDelay); + } - $response = 'NOTENOTEcrs819The origin state/province code has been changed. The origin state/province code has been changed. NOTEcrs820The destination state/province code has been changed. The destination state/province code has been changed. crs1300PRIORITY_OVERNIGHTYOUR_PACKAGINGACTA FRI2014-09-26T12:00:00PRIORITY_OVERNIGHT2014-09-26T12:00:00FRIAM0NON_DOCUMENTSAUSfalseA1AMSERVICE_DEFAULTPAYOR_ACCOUNT_PACKAGEUSD44.63PAYOR_ACCOUNT_PACKAGE1PACKAGEDIM1949.5LB4.0LB4.0USD31.25USD0.0USD31.25USD10.63USD41.88USD0.0USD41.88USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.630USD44.63PAYOR_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD31.25USD0.0USD31.25USD10.63USD41.88USD0.0USD41.88USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.63USD44.63RATED_ACCOUNT_PACKAGE1PACKAGEDIM1949.5LB4.0LB4.0USD31.25USD0.0USD31.25USD10.63USD41.88USD0.0USD41.88USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.630USD44.63RATED_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD31.25USD0.0USD31.25USD10.63USD41.88USD0.0USD41.88USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.63PAYOR_LIST_PACKAGE15746PACKAGEDIM1669.5LB5.0LB5.0USD72.0USD0.0USD72.0USD14.51USD86.51USD0.0USD86.51USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.510PAYOR_LIST_PACKAGEDIMLB5.0LB5.0USD72.0USD0.0USD72.0USD14.51USD86.51USD0.0USD86.51USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.51RATED_LIST_PACKAGE15746PACKAGEDIM1669.5LB5.0LB5.0USD72.0USD0.0USD72.0USD14.51USD86.51USD0.0USD86.51USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.510RATED_LIST_PACKAGEDIMLB5.0LB5.0USD72.0USD0.0USD72.0USD14.51USD86.51USD0.0USD86.51USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.51STANDARD_OVERNIGHTYOUR_PACKAGINGACTA FRI2014-09-26T20:00:00STANDARD_OVERNIGHT2014-09-26T20:00:00FRIAM0NON_DOCUMENTSAUSfalseA1AMSERVICE_DEFAULTPAYOR_ACCOUNT_PACKAGEUSD4.71PAYOR_ACCOUNT_PACKAGE13716PACKAGEDIM1949.5LB4.0LB4.0USD64.55USD0.0USD64.55USD13.8USD78.35USD0.0USD78.35USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD6.80USD4.71PAYOR_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD64.55USD0.0USD64.55USD13.8USD78.35USD0.0USD78.35USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD6.8USD4.71RATED_ACCOUNT_PACKAGE13716PACKAGEDIM1949.5LB4.0LB4.0USD64.55USD0.0USD64.55USD13.8USD78.35USD0.0USD78.35USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD6.80USD4.71RATED_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD64.55USD0.0USD64.55USD13.8USD78.35USD0.0USD78.35USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD6.8PAYOR_LIST_PACKAGE13716PACKAGEDIM1669.5LB5.0LB5.0USD68.85USD0.0USD68.85USD14.21USD83.06USD0.0USD83.06USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.210PAYOR_LIST_PACKAGEDIMLB5.0LB5.0USD68.85USD0.0USD68.85USD14.21USD83.06USD0.0USD83.06USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.21RATED_LIST_PACKAGE13716PACKAGEDIM1669.5LB5.0LB5.0USD68.85USD0.0USD68.85USD14.21USD83.06USD0.0USD83.06USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.210RATED_LIST_PACKAGEDIMLB5.0LB5.0USD68.85USD0.0USD68.85USD14.21USD83.06USD0.0USD83.06USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD7.21FEDEX_2_DAY_AMYOUR_PACKAGINGACTA MON2014-09-29T12:00:00FEDEX_2_DAY_AM2014-09-29T12:00:00MONAM0NON_DOCUMENTSAUSfalseA1AMSERVICE_DEFAULTPAYOR_ACCOUNT_PACKAGEUSD4.42PAYOR_ACCOUNT_PACKAGE126PACKAGEDIM1949.5LB4.0LB4.0USD34.73USD0.0USD34.73USD10.96USD45.69USD0.0USD45.69USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.960USD4.42PAYOR_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD34.73USD0.0USD34.73USD10.96USD45.69USD0.0USD45.69USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.96USD4.42RATED_ACCOUNT_PACKAGE126PACKAGEDIM1949.5LB4.0LB4.0USD34.73USD0.0USD34.73USD10.96USD45.69USD0.0USD45.69USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.960USD4.42RATED_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD34.73USD0.0USD34.73USD10.96USD45.69USD0.0USD45.69USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.96PAYOR_LIST_PACKAGE126PACKAGEDIM1669.5LB5.0LB5.0USD38.76USD0.0USD38.76USD11.35USD50.11USD0.0USD50.11USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD4.350PAYOR_LIST_PACKAGEDIMLB5.0LB5.0USD38.76USD0.0USD38.76USD11.35USD50.11USD0.0USD50.11USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD4.35RATED_LIST_PACKAGE126PACKAGEDIM1669.5LB5.0LB5.0USD38.76USD0.0USD38.76USD11.35USD50.11USD0.0USD50.11USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD4.350RATED_LIST_PACKAGEDIMLB5.0LB5.0USD38.76USD0.0USD38.76USD11.35USD50.11USD0.0USD50.11USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD4.35FEDEX_2_DAYYOUR_PACKAGINGACTA MON2014-09-29T20:00:00FEDEX_2_DAY2014-09-29T20:00:00MONAM0NON_DOCUMENTSAUSfalseA1AMSERVICE_DEFAULTPAYOR_ACCOUNT_PACKAGEUSD3.84PAYOR_ACCOUNT_PACKAGE60686PACKAGEDIM1949.5LB4.0LB4.0USD30.2USD0.0USD30.2USD10.53USD40.73USD0.0USD40.73USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.530USD3.84PAYOR_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD30.2USD0.0USD30.2USD10.53USD40.73USD0.0USD40.73USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.53USD3.84RATED_ACCOUNT_PACKAGE60686PACKAGEDIM1949.5LB4.0LB4.0USD30.2USD0.0USD30.2USD10.53USD40.73USD0.0USD40.73USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.530USD3.84RATED_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD30.2USD0.0USD30.2USD10.53USD40.73USD0.0USD40.73USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.53PAYOR_LIST_PACKAGE60686PACKAGEDIM1669.5LB5.0LB5.0USD33.7USD0.0USD33.7USD10.87USD44.57USD0.0USD44.57USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.870PAYOR_LIST_PACKAGEDIMLB5.0LB5.0USD33.7USD0.0USD33.7USD10.87USD44.57USD0.0USD44.57USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.87RATED_LIST_PACKAGE60686PACKAGEDIM1669.5LB5.0LB5.0USD33.7USD0.0USD33.7USD10.87USD44.57USD0.0USD44.57USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.870RATED_LIST_PACKAGEDIMLB5.0LB5.0USD33.7USD0.0USD33.7USD10.87USD44.57USD0.0USD44.57USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD3.87FEDEX_EXPRESS_SAVERYOUR_PACKAGINGACTA TUE2014-09-30T20:00:00FEDEX_EXPRESS_SAVER2014-09-30T20:00:00TUEAM0NON_DOCUMENTSAUSfalseA1AMSERVICE_DEFAULTPAYOR_ACCOUNT_PACKAGEUSD3.01PAYOR_ACCOUNT_PACKAGE71756PACKAGEDIM1949.5LB4.0LB4.0USD20.3USD0.0USD20.3USD9.59USD29.89USD0.0USD29.89USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.590USD3.01PAYOR_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD20.3USD0.0USD20.3USD9.59USD29.89USD0.0USD29.89USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.59USD3.01RATED_ACCOUNT_PACKAGE71756PACKAGEDIM1949.5LB4.0LB4.0USD20.3USD0.0USD20.3USD9.59USD29.89USD0.0USD29.89USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.590USD3.01RATED_ACCOUNT_PACKAGEDIMLB4.0LB4.0USD20.3USD0.0USD20.3USD9.59USD29.89USD0.0USD29.89USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.59PAYOR_LIST_PACKAGE71756PACKAGEDIM1669.5LB5.0LB5.0USD23.05USD0.0USD23.05USD9.85USD32.9USD0.0USD32.9USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.850PAYOR_LIST_PACKAGEDIMLB5.0LB5.0USD23.05USD0.0USD23.05USD9.85USD32.9USD0.0USD32.9USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.85RATED_LIST_PACKAGE71756PACKAGEDIM1669.5LB5.0LB5.0USD23.05USD0.0USD23.05USD9.85USD32.9USD0.0USD32.9USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.850RATED_LIST_PACKAGEDIMLB5.0LB5.0USD23.05USD0.0USD23.05USD9.85USD32.9USD0.0USD32.9USD0.0RESIDENTIAL_DELIVERYResidential deliveryUSD3.35DELIVERY_AREADelivery Area Surcharge Extended ResidentialUSD3.65FUELFuelUSD2.85GROUND_HOME_DELIVERYYOUR_PACKAGINGACTA GROUND_HOME_DELIVERYTHREE_DAYS0AUSfalseA1AMTHREE_DAYSSERVICE_DEFAULTPAYOR_ACCOUNT_PACKAGEUSD0.0PAYOR_ACCOUNT_PACKAGE6ACTUAL06.5LB3.0USD9.01USD0.0USD9.01USD7.54USD16.55USD0.0USD16.55USD0.0RESIDENTIAL_DELIVERYPACKAGEFedEx Home Delivery Urban/Rural ChargeUSD2.9DELIVERY_AREAPACKAGEDelivery Area Surcharge Extended ResidentialUSD3.62FUELPACKAGEFedEx Ground FuelUSD1.020USD0.0PAYOR_ACCOUNT_PACKAGEACTUALLB3.0USD9.01USD0.0USD9.01USD7.54USD16.55USD0.0USD16.55USD0.0RESIDENTIAL_DELIVERYPACKAGEFedEx Home Delivery Urban/Rural ChargeUSD2.9DELIVERY_AREAPACKAGEDelivery Area Surcharge Extended ResidentialUSD3.62FUELPACKAGEFedEx Ground FuelUSD1.02PAYOR_LIST_PACKAGE6ACTUAL06.5LB3.0USD9.01USD0.0USD9.01USD7.54USD16.55USD0.0USD16.55USD0.0RESIDENTIAL_DELIVERYPACKAGEFedEx Home Delivery Urban/Rural ChargeUSD2.9DELIVERY_AREAPACKAGEDelivery Area Surcharge Extended ResidentialUSD3.62FUELPACKAGEFedEx Ground FuelUSD1.020PAYOR_LIST_PACKAGEACTUALLB3.0USD9.01USD0.0USD9.01USD7.54USD16.55USD0.0USD16.55USD0.0RESIDENTIAL_DELIVERYPACKAGEFedEx Home Delivery Urban/Rural ChargeUSD2.9DELIVERY_AREAPACKAGEDelivery Area Surcharge Extended ResidentialUSD3.62FUELPACKAGEFedEx Ground FuelUSD1.02'; - - return $response; - } + return file_get_contents(__DIR__ . '/FedexResponse.xml'); + } } diff --git a/src/RateRequest/StubUPS.php b/src/RateRequest/StubUPS.php index 67f16e3..03aa70c 100644 --- a/src/RateRequest/StubUPS.php +++ b/src/RateRequest/StubUPS.php @@ -3,22 +3,19 @@ namespace pdt256\Shipping\RateRequest; class StubUPS extends Adapter { - private $artificial_delay = 0; + private $artificialDelay = 0; - public function __construct($artificial_delay = 0) - { - $this->artificial_delay = $artificial_delay; - } + public function __construct($artificial_delay = 0) + { + $this->artificialDelay = $artificial_delay; + } - public function execute($url, $data = NULL) - { - if ($this->artificial_delay > 0) { - sleep($this->artificial_delay); - } + public function execute($url, $data = null) + { + if ($this->artificialDelay > 0) { + sleep($this->artificialDelay); + } - $response = ' -1Success03Your invoice may vary from the displayed reference ratesMissing / Invalid Shipper Number. Returned rates are Retail Rates.LBS3.0USD19.10USD0.00USD19.10USD19.10USD0.00USD19.103.0LBS3.012Your invoice may vary from the displayed reference ratesMissing / Invalid Shipper Number. Returned rates are Retail Rates.LBS5.0USD37.18USD0.00USD37.183USD37.18USD0.00USD37.183.0LBS5.002Your invoice may vary from the displayed reference ratesMissing / Invalid Shipper Number. Returned rates are Retail Rates.LBS5.0USD49.23USD0.00USD49.232USD49.23USD0.00USD49.233.0LBS5.013Your invoice may vary from the displayed reference ratesMissing / Invalid Shipper Number. Returned rates are Retail Rates.LBS5.0USD89.54USD0.00USD89.541USD89.54USD0.00USD89.543.0LBS5.001Your invoice may vary from the displayed reference ratesMissing / Invalid Shipper Number. Returned rates are Retail Rates.LBS5.0USD93.28USD0.00USD93.28112:00 NoonUSD93.28USD0.00USD93.283.0LBS5.0'; - - return $response; - } + return file_get_contents(__DIR__ . '/UPSResponse.xml'); + } } diff --git a/src/RateRequest/StubUSPS.php b/src/RateRequest/StubUSPS.php index b879abf..03d9eaa 100644 --- a/src/RateRequest/StubUSPS.php +++ b/src/RateRequest/StubUSPS.php @@ -3,22 +3,19 @@ namespace pdt256\Shipping\RateRequest; class StubUSPS extends Adapter { - private $artificial_delay = 0; + private $artificialDelay = 0; - public function __construct($artificial_delay = 0) - { - $this->artificial_delay = $artificial_delay; - } + public function __construct($artificial_delay = 0) + { + $this->artificialDelay = $artificial_delay; + } - public function execute($url, $data = NULL) - { - if ($this->artificial_delay > 0) { - sleep($this->artificial_delay); - } + public function execute($url, $data = null) + { + if ($this->artificialDelay > 0) { + sleep($this->artificialDelay); + } - $response = ' -904017666730LARGEFALSE6Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;42.25Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup42.25Priority Mail 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;12.20Standard Post&lt;sup&gt;&#174;&lt;/sup&gt;10.01Media Mail Parcel3.65Library Mail Parcel3.48'; - - return $response; - } + return file_get_contents(__DIR__ . '/USPSResponse.xml'); + } } diff --git a/src/RateRequest/UPSResponse.xml b/src/RateRequest/UPSResponse.xml new file mode 100644 index 0000000..94e1b0a --- /dev/null +++ b/src/RateRequest/UPSResponse.xml @@ -0,0 +1,247 @@ + + + + 1 + Success + + + + 03 + + Your invoice may vary from the displayed reference rates + Missing / Invalid Shipper Number. Returned rates are Retail Rates. + + + LBS + + 3.0 + + + USD + 19.10 + + + USD + 0.00 + + + USD + 19.10 + + + + + + USD + 19.10 + + + USD + 0.00 + + + USD + 19.10 + + 3.0 + + + LBS + + 3.0 + + + + + + 12 + + Your invoice may vary from the displayed reference rates + Missing / Invalid Shipper Number. Returned rates are Retail Rates. + + + LBS + + 5.0 + + + USD + 37.18 + + + USD + 0.00 + + + USD + 37.18 + + 3 + + + + USD + 37.18 + + + USD + 0.00 + + + USD + 37.18 + + 3.0 + + + LBS + + 5.0 + + + + + + 02 + + Your invoice may vary from the displayed reference rates + Missing / Invalid Shipper Number. Returned rates are Retail Rates. + + + LBS + + 5.0 + + + USD + 49.23 + + + USD + 0.00 + + + USD + 49.23 + + 2 + + + + USD + 49.23 + + + USD + 0.00 + + + USD + 49.23 + + 3.0 + + + LBS + + 5.0 + + + + + + 13 + + Your invoice may vary from the displayed reference rates + Missing / Invalid Shipper Number. Returned rates are Retail Rates. + + + LBS + + 5.0 + + + USD + 89.54 + + + USD + 0.00 + + + USD + 89.54 + + 1 + + + + USD + 89.54 + + + USD + 0.00 + + + USD + 89.54 + + 3.0 + + + LBS + + 5.0 + + + + + + 01 + + Your invoice may vary from the displayed reference rates + Missing / Invalid Shipper Number. Returned rates are Retail Rates. + + + LBS + + 5.0 + + + USD + 93.28 + + + USD + 0.00 + + + USD + 93.28 + + 1 + 12:00 Noon + + + USD + 93.28 + + + USD + 0.00 + + + USD + 93.28 + + 3.0 + + + LBS + + 5.0 + + + + diff --git a/src/RateRequest/USPSResponse.xml b/src/RateRequest/USPSResponse.xml new file mode 100644 index 0000000..0c8f784 --- /dev/null +++ b/src/RateRequest/USPSResponse.xml @@ -0,0 +1,37 @@ + + + + 90401 + 76667 + 3 + 0 + LARGE + FALSE + 6 + + Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; + 42.25 + + + Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup + + 42.25 + + + Priority Mail 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; + 12.20 + + + Standard Post&lt;sup&gt;&#174;&lt;/sup&gt; + 10.01 + + + Media Mail Parcel + 3.65 + + + Library Mail Parcel + 3.48 + + + diff --git a/src/Ship.php b/src/Ship.php index 06e5363..dde40f8 100644 --- a/src/Ship.php +++ b/src/Ship.php @@ -3,145 +3,149 @@ namespace pdt256\Shipping; class Ship { - protected $shipping_options = [ - 'Standard Shipping' => [ - 'ups' => [ - '03' => '1-5 business days', - ], - 'fedex' => [ - 'FEDEX_EXPRESS_SAVER' => '1-3 business days', - 'FEDEX_GROUND' => '1-5 business days', - 'GROUND_HOME_DELIVERY' => '1-5 business days', - ], - 'usps' => [ - '1' => '1-3 business days', - '4' => '2-8 business days', - ], - ], - 'Two-Day Shipping' => [ - 'ups' => [ - '02' => '2 business days', - ], - 'fedex' => [ - 'FEDEX_2_DAY' => '2 business days', - ], - ], - 'One-Day Shipping' => [ - 'ups' => [ - '01' => 'next business day 10:30am', - '13' => 'next business day by 3pm', - '14' => 'next business day by 8am', - ], - 'fedex' => [ - 'STANDARD_OVERNIGHT' => 'overnight', - ], - ], - ]; - - public static function factory($shipping_options = []) - { - $object = new self(); - - if ( ! empty($shipping_options)) { - $object->shipping_options = $shipping_options; - } - - return $object; - } - - public function get_approved_codes($carrier = NULL) { - $approved_codes = []; - - // Build approved_codes - foreach ($this->shipping_options as $shipping_group => $row) { - - foreach ($row as $_carrier => $row2) { - if ( ! isset($approved_codes[$_carrier])) { - $approved_codes[$_carrier] = []; - } - - foreach ($row2 as $code => $display) { - $approved_codes[$_carrier][] = $code; - } - } - } - - if ($carrier !== NULL AND isset($approved_codes[$carrier])) { - return $approved_codes[$carrier]; - } - - return $approved_codes; - } - - public function get_display_rates($rates) - { - // Build output array with cheapest shipping option for each group - $display_rates = []; - foreach ($this->shipping_options as $shipping_group => $row) { - $display_rates[$shipping_group] = []; - $cheapest_row = NULL; - - foreach ($row as $carrier => $row2) { - $group_codes = array_keys($row2); - - if ( ! empty($rates[$carrier])) { - - foreach ($rates[$carrier] as $row3) { - - if (in_array($row3->getCode(), $group_codes)) { - $row3->setCarrier($carrier); - - if ($cheapest_row === NULL) { - $cheapest_row = $row3; - } else { - if ($row3->getCost() < $cheapest_row->getCost()) { - $cheapest_row = $row3; - } - } - } - } - } - } - - // Add row if it exists - if ( ! empty($cheapest_row)) { - $display_rates[$shipping_group][] = $cheapest_row; - } - } - - return $display_rates; - } - - public function get_all_display_rates($rates) - { - // Build output array listing all group options - $display_rates = []; - foreach ($this->shipping_options as $shipping_group => $row) { - $display_rates[$shipping_group] = []; - - foreach ($row as $carrier => $row2) { - $group_codes = array_keys($row2); - - if ( ! empty($rates[$carrier])) { - - foreach ($rates[$carrier] as $row3) { - - if (in_array($row3->getCode(), $group_codes)) { - $row3->setCarrier($carrier); - $display_rates[$shipping_group][] = $row3; - } - } - } - } - - $this->sort_by_cost($display_rates[$shipping_group]); - } - - return $display_rates; - } - - protected function sort_by_cost( & $rates) - { - uasort($rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());')); - } + protected $shipping_options = [ + 'Standard Shipping' => [ + 'ups' => [ + '03' => '1-5 business days', + ], + 'fedex' => [ + 'FEDEX_EXPRESS_SAVER' => '1-3 business days', + 'FEDEX_GROUND' => '1-5 business days', + 'GROUND_HOME_DELIVERY' => '1-5 business days', + ], + 'usps' => [ + '1' => '1-3 business days', + '4' => '2-8 business days', + ], + ], + 'Two-Day Shipping' => [ + 'ups' => [ + '02' => '2 business days', + ], + 'fedex' => [ + 'FEDEX_2_DAY' => '2 business days', + ], + ], + 'One-Day Shipping' => [ + 'ups' => [ + '01' => 'next business day 10:30am', + '13' => 'next business day by 3pm', + '14' => 'next business day by 8am', + ], + 'fedex' => [ + 'STANDARD_OVERNIGHT' => 'overnight', + ], + ], + ]; + + public static function factory($shipping_options = []) + { + $object = new self(); + + if (!empty($shipping_options)) { + $object->shipping_options = $shipping_options; + } + + return $object; + } + + /** + * @return array + */ + public function getApprovedCodes($carrier = null) + { + $approvedCodes = []; + + // Build approvedCodes + foreach ($this->shipping_options as $shipping_group => $row) { + + foreach ($row as $_carrier => $row2) { + if (!isset($approvedCodes[$_carrier])) { + $approvedCodes[$_carrier] = []; + } + + foreach ($row2 as $code => $display) { + $approvedCodes[$_carrier][] = $code; + } + } + } + + if ($carrier !== null && isset($approvedCodes[$carrier])) { + return $approvedCodes[$carrier]; + } + + return $approvedCodes; + } + + public function getDisplayRates($rates) + { + // Build output array with cheapest shipping option for each group + $display_rates = []; + foreach ($this->shipping_options as $shipping_group => $row) { + $display_rates[$shipping_group] = []; + $cheapest_row = null; + + foreach ($row as $carrier => $row2) { + $group_codes = array_keys($row2); + + if (! empty($rates[$carrier])) { + + foreach ($rates[$carrier] as $row3) { + + if (in_array($row3->getCode(), $group_codes)) { + $row3->setCarrier($carrier); + + if ($cheapest_row === null) { + $cheapest_row = $row3; + } else { + if ($row3->getCost() < $cheapest_row->getCost()) { + $cheapest_row = $row3; + } + } + } + } + } + } + + // Add row if it exists + if (! empty($cheapest_row)) { + $display_rates[$shipping_group][] = $cheapest_row; + } + } + + return $display_rates; + } + + public function getAllDisplayRates($rates) + { + // Build output array listing all group options + $display_rates = []; + foreach ($this->shipping_options as $shipping_group => $row) { + $display_rates[$shipping_group] = []; + + foreach ($row as $carrier => $row2) { + $group_codes = array_keys($row2); + + if (!empty($rates[$carrier])) { + + foreach ($rates[$carrier] as $row3) { + + if (in_array($row3->getCode(), $group_codes)) { + $row3->setCarrier($carrier); + $display_rates[$shipping_group][] = $row3; + } + } + } + } + + $this->sortByCost($display_rates[$shipping_group]); + } + + return $display_rates; + } + + protected function sortByCost(& $rates) + { + uasort($rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());')); + } } diff --git a/src/Shipment.php b/src/Shipment.php index c7f2a9d..2f5235f 100644 --- a/src/Shipment.php +++ b/src/Shipment.php @@ -5,15 +5,16 @@ class Shipment /** @var Package[] */ protected $packages = []; - protected $from_postal_code; - protected $from_country_code; - protected $to_postal_code; - protected $to_country_code; /** @var bool */ - protected $to_is_residential; + protected $fromIsResidential; + protected $fromPostalCode; + protected $fromCountryCode; + protected $fromStateProvince; + /** @var bool */ - protected $from_is_residential; - protected $from_state_province; + protected $toIsResidential; + protected $toPostalCode; + protected $toCountryCode; /** * @param Package $package @@ -46,16 +47,16 @@ class Shipment */ public function getFromPostalCode() { - return $this->from_postal_code; + return $this->fromPostalCode; } /** - * @param mixed $from_postal_code + * @param mixed $fromPostalCode * @return $this */ - public function setFromPostalCode($from_postal_code) + public function setFromPostalCode($fromPostalCode) { - $this->from_postal_code = $from_postal_code; + $this->fromPostalCode = $fromPostalCode; return $this; } @@ -64,16 +65,16 @@ class Shipment */ public function getFromCountryCode() { - return $this->from_country_code; + return $this->fromCountryCode; } /** - * @param mixed $from_country_code + * @param mixed $fromCountryCode * @return $this */ - public function setFromCountryCode($from_country_code) + public function setFromCountryCode($fromCountryCode) { - $this->from_country_code = $from_country_code; + $this->fromCountryCode = $fromCountryCode; return $this; } @@ -82,16 +83,16 @@ class Shipment */ public function getToPostalCode() { - return $this->to_postal_code; + return $this->toPostalCode; } /** - * @param mixed $to_postal_code + * @param mixed $toPostalCode * @return $this */ - public function setToPostalCode($to_postal_code) + public function setToPostalCode($toPostalCode) { - $this->to_postal_code = $to_postal_code; + $this->toPostalCode = $toPostalCode; return $this; } @@ -100,52 +101,52 @@ class Shipment */ public function getToCountryCode() { - return $this->to_country_code; + return $this->toCountryCode; } /** - * @param mixed $to_country_code + * @param mixed $toCountryCode * @return $this */ - public function setToCountryCode($to_country_code) + public function setToCountryCode($toCountryCode) { - $this->to_country_code = $to_country_code; + $this->toCountryCode = $toCountryCode; return $this; } /** * @return boolean */ - public function isToResidential() + public function getToIsResidential() { - return $this->to_is_residential; + return $this->toIsResidential; } /** - * @param boolean $to_is_residential + * @param boolean $toIsResidential * @return $this */ - public function setToResidential($to_is_residential) + public function setToIsResidential($toIsResidential) { - $this->to_is_residential = $to_is_residential; + $this->toIsResidential = $toIsResidential; return $this; } /** * @return bool */ - public function isFromResidential() + public function getFromIsResidential() { - return $this->from_is_residential; + return $this->fromIsResidential; } /** - * @param $from_is_residential + * @param $fromIsResidential * @return $this */ - public function setFromResidential($from_is_residential) + public function setFromIsResidential($fromIsResidential) { - $this->from_is_residential = $from_is_residential; + $this->fromIsResidential = $fromIsResidential; return $this; } @@ -154,16 +155,16 @@ class Shipment */ public function getFromStateProvinceCode() { - return $this->from_state_province; + return $this->fromStateProvince; } /** - * @param $from_state_province + * @param $fromStateProvince * @return $this */ - public function setFromStateProvinceCode($from_state_province) + public function setFromStateProvinceCode($fromStateProvince) { - $this->from_state_province = $from_state_province; + $this->fromStateProvince = $fromStateProvince; return $this; } } diff --git a/src/UPS/Rate.php b/src/UPS/Rate.php index bb33c50..0e98561 100644 --- a/src/UPS/Rate.php +++ b/src/UPS/Rate.php @@ -11,238 +11,239 @@ use Exception; class Rate extends RateAdapter { - private $url_dev = 'https://wwwcie.ups.com/ups.app/xml/Rate'; - private $url_prod = 'https://www.ups.com/ups.app/xml/Rate'; - - private $access_key = 'XXX'; - private $user_id = 'XXX'; - private $password = 'XXX'; - private $shipper_number = 'XXX'; - - public $approved_codes = [ - '03', - '12', - ]; - - private $shipping_codes = [ - 'US' => [ // United States - '01' => 'UPS Next Day Air', - '02' => 'UPS 2nd Day Air', - '03' => 'UPS Ground', - '07' => 'UPS Worldwide Express', - '08' => 'UPS Worldwide Expedited', - '11' => 'UPS Standard', - '12' => 'UPS 3 Day Select', - '13' => 'UPS Next Day Air Saver', - '14' => 'UPS Next Day Air Early A.M.', - '54' => 'UPS Worldwide Express Plus', - '59' => 'UPS 2nd Day Air A.M.', - '65' => 'UPS Saver', - ], - 'CA' => [ // Canada - '01' => 'UPS Express', - '02' => 'UPS Expedited', - '07' => 'UPS Worldwide Express', - '08' => 'UPS Worldwide Expedited', - '11' => 'UPS Standard', - '12' => 'UPS 3 Day Select', - '13' => 'UPS Saver', - '14' => 'UPS Express Early A.M.', - '54' => 'UPS Worldwide Express Plus', - '65' => 'UPS Saver', - ], - 'EU' => [ // European Union - '07' => 'UPS Express', - '08' => 'UPS Expedited', - '11' => 'UPS Standard', - '54' => 'UPS Worldwide Express Plus', - '65' => 'UPS Saver', - '82' => 'UPS Today Standard', - '83' => 'UPS Today Dedicated Courier', - '84' => 'UPS Today Intercity', - '85' => 'UPS Today Express', - '86' => 'UPS Today Express Saver', - '01' => 'UPS Next Day Air', - '02' => 'UPS 2nd Day Air', - '03' => 'UPS Ground', - '14' => 'UPS Next Day Air Early A.M.', - ], - 'MX' => [ // Mexico - '07' => 'UPS Express', - '08' => 'UPS Expedited', - '54' => 'UPS Express Plus', - '65' => 'UPS Saver', - ], - 'other' => [ // Other - '07' => 'UPS Express', - '08' => 'UPS Worldwide Expedited', - '11' => 'UPS Standard', - '54' => 'UPS Worldwide Express Plus', - '65' => 'UPS Saver', - ], - ]; - - public function __construct($options = []) - { - parent::__construct($options); - - if (isset($options['access_key'])) { - $this->access_key = $options['access_key']; - } - - if (isset($options['user_id'])) { - $this->user_id = $options['user_id']; - } - - if (isset($options['password'])) { - $this->password = $options['password']; - } - - if (isset($options['shipper_number'])) { - $this->shipper_number = $options['shipper_number']; - } - - if (isset($options['approved_codes'])) { - $this->approved_codes = $options['approved_codes']; - } - - if (isset($options['request_adapter'])) { - $this->set_request_adapter($options['request_adapter']); - } else { - $this->set_request_adapter(new RateRequest\Post()); - } - } - - protected function prepare() - { - $service_code = '03'; - - $packages = ''; - foreach ($this->shipment->getPackages() as $p) { - $packages .= ' - - 02 - - - - IN - - ' . $p->getLength() . ' - ' . $p->getWidth() . ' - ' . $p->getHeight() . ' - - - - LBS - - ' . $p->getWeight() . ' - - '; - } - - $this->data = -' - - ' . $this->access_key . ' - ' . $this->user_id . ' - ' . $this->password . ' - - - - Rate - shop - - - -
- ' . $this->shipment->getFromPostalCode() . ' - ' . $this->shipment->getFromCountryCode() . ' - ' . (($this->shipment->isFromResidential()) ? '1' : '') . ' -
- ' . $this->shipper_number . ' -
- -
- ' . $this->shipment->getToPostalCode() . ' - ' . $this->shipment->getToCountryCode() . ' - ' . (($this->shipment->isToResidential()) ? '1' : '') . ' -
-
- -
- ' . $this->shipment->getFromStateProvinceCode() . ' - ' . $this->shipment->getFromPostalCode() . ' - ' . $this->shipment->getFromCountryCode() . ' - ' . (($this->shipment->isFromResidential()) ? '1' : '') . ' -
-
- - ' . $service_code . ' - - ' . $packages . ' - - - -
-
'; - - return $this; - } - - protected function execute() - { - if ($this->is_prod) { - $url = $this->url_prod; - } else { - $url = $this->url_dev; - } - - $this->response = $this->rate_request->execute($url, $this->data); - - return $this; - } - - protected function process() - { - try { - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->loadXml($this->response); - - $rate_list = @$dom->getElementsByTagName('RatedShipment'); - - if (empty($rate_list->length)) { - throw new Exception('Unable to get UPS Rates.'); - } - } catch (Exception $e) { - // StatsD::increment('error.shipping.get_ups_rate'); - // Kohana::$log->add(Log::ERROR, $e)->write(); - throw $e; - } - - foreach ($rate_list as $rate) { - $code = @$rate - ->getElementsByTagName('Service')->item(0) - ->getElementsByTagName('Code')->item(0)->nodeValue; - - $name = Arr::get($this->shipping_codes['US'], $code); - - $cost = @$rate - ->getElementsByTagName('TotalCharges')->item(0) - ->getElementsByTagName('MonetaryValue')->item(0)->nodeValue; - - if ( ! empty($this->approved_codes) AND ! in_array($code, $this->approved_codes)) { - continue; - } - - $quote = new Quote; - $quote - ->setCarrier('ups') - ->setCode($code) - ->setName($name) - ->setCost((int) $cost * 100); - $this->rates[] = $quote; - } - - return $this; - } + private $urlDev = 'https://wwwcie.ups.com/ups.app/xml/Rate'; + private $urlProd = 'https://www.ups.com/ups.app/xml/Rate'; + + private $accessKey = 'XXX'; + private $userId = 'XXX'; + private $password = 'XXX'; + private $shipperNumber = 'XXX'; + + public $approvedCodes = [ + '03', + '12', + ]; + + private $shippingCodes = [ + 'US' => [ // United States + '01' => 'UPS Next Day Air', + '02' => 'UPS 2nd Day Air', + '03' => 'UPS Ground', + '07' => 'UPS Worldwide Express', + '08' => 'UPS Worldwide Expedited', + '11' => 'UPS Standard', + '12' => 'UPS 3 Day Select', + '13' => 'UPS Next Day Air Saver', + '14' => 'UPS Next Day Air Early A.M.', + '54' => 'UPS Worldwide Express Plus', + '59' => 'UPS 2nd Day Air A.M.', + '65' => 'UPS Saver', + ], + 'CA' => [ // Canada + '01' => 'UPS Express', + '02' => 'UPS Expedited', + '07' => 'UPS Worldwide Express', + '08' => 'UPS Worldwide Expedited', + '11' => 'UPS Standard', + '12' => 'UPS 3 Day Select', + '13' => 'UPS Saver', + '14' => 'UPS Express Early A.M.', + '54' => 'UPS Worldwide Express Plus', + '65' => 'UPS Saver', + ], + 'EU' => [ // European Union + '07' => 'UPS Express', + '08' => 'UPS Expedited', + '11' => 'UPS Standard', + '54' => 'UPS Worldwide Express Plus', + '65' => 'UPS Saver', + '82' => 'UPS Today Standard', + '83' => 'UPS Today Dedicated Courier', + '84' => 'UPS Today Intercity', + '85' => 'UPS Today Express', + '86' => 'UPS Today Express Saver', + '01' => 'UPS Next Day Air', + '02' => 'UPS 2nd Day Air', + '03' => 'UPS Ground', + '14' => 'UPS Next Day Air Early A.M.', + ], + 'MX' => [ // Mexico + '07' => 'UPS Express', + '08' => 'UPS Expedited', + '54' => 'UPS Express Plus', + '65' => 'UPS Saver', + ], + 'other' => [ // Other + '07' => 'UPS Express', + '08' => 'UPS Worldwide Expedited', + '11' => 'UPS Standard', + '54' => 'UPS Worldwide Express Plus', + '65' => 'UPS Saver', + ], + ]; + + public function __construct($options = []) + { + parent::__construct($options); + + $this->accessKey = Arr::get($options, 'accessKey'); + $this->userId = Arr::get($options, 'userId'); + $this->password = Arr::get($options, 'password'); + $this->shipperNumber = Arr::get($options, 'shipperNumber'); + $this->approvedCodes = Arr::get($options, 'approvedCodes'); + + $this->setRequestAdapter(Arr::get($options, 'requestAdapter', new RateRequest\Post())); + + } + + protected function prepare() + { + $service_code = '03'; + + $this->data = '' . "\n" . + '' . + '' . $this->accessKey . ''. + '' . $this->userId . '' . + '' . $this->password . '' . + '' . + '' . + '' . + 'Rate' . + 'shop' . + '' . + '' . + '' . + '
' . + '' . $this->shipment->getFromPostalCode() . '' . + '' . $this->shipment->getFromCountryCode() . '' . + ( + $this->shipment->getFromIsResidential() ? + '1' : + '' + ) . + '
' . + '' . $this->shipperNumber . '' . + '
' . + '' . + '
' . + '' . $this->shipment->getToPostalCode() . '' . + '' . $this->shipment->getToCountryCode() . '' . + ( + $this->shipment->getToIsResidential() ? + '1' : + '' + ) . + '
' . + '
' . + '' . + '
' . + '' . + $this->shipment->getFromStateProvinceCode() . + '' . + '' . $this->shipment->getFromPostalCode() . '' . + '' . $this->shipment->getFromCountryCode() . '' . + ( + $this->shipment->getFromIsResidential() ? + '1' : + '' + ) . + '
' . + '
' . + '' . + '' . $service_code . '' . + '' . + $this->getPackagesXmlString() . + '' . + '' . + '' . + '
' . + '
'; + + return $this; + } + + private function getPackagesXmlString() + { + $packages = ''; + foreach ($this->shipment->getPackages() as $p) { + $packages .= + '' . + '' . + '02' . + '' . + '' . + '' . + 'IN' . + '' . + '' . $p->getLength() . '' . + '' . $p->getWidth() . '' . + '' . $p->getHeight() . '' . + '' . + '' . + '' . + 'LBS' . + '' . + '' . $p->getWeight() . '' . + '' . + ''; + } + + return $packages; + } + + protected function execute() + { + if ($this->isProduction) { + $url = $this->urlProd; + } else { + $url = $this->urlDev; + } + + $this->response = $this->rateRequest->execute($url, $this->data); + + return $this; + } + + protected function process() + { + try { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->loadXml($this->response); + + $rate_list = $dom->getElementsByTagName('RatedShipment'); + + if (empty($rate_list->length)) { + throw new Exception('Unable to get UPS Rates.'); + } + } catch (Exception $e) { + echo $this->response; + throw $e; + } + + foreach ($rate_list as $rate) { + $code = @$rate + ->getElementsByTagName('Service')->item(0) + ->getElementsByTagName('Code')->item(0)->nodeValue; + + $name = Arr::get($this->shippingCodes['US'], $code); + + $cost = @$rate + ->getElementsByTagName('TotalCharges')->item(0) + ->getElementsByTagName('MonetaryValue')->item(0)->nodeValue; + + if (! empty($this->approvedCodes) && ! in_array($code, $this->approvedCodes)) { + continue; + } + + $quote = new Quote; + $quote + ->setCarrier('ups') + ->setCode($code) + ->setName($name) + ->setCost($cost * 100); + $this->rates[] = $quote; + } + + return $this; + } } diff --git a/src/USPS/Rate.php b/src/USPS/Rate.php index fe39462..f5e4887 100644 --- a/src/USPS/Rate.php +++ b/src/USPS/Rate.php @@ -11,207 +11,188 @@ use Exception; class Rate extends RateAdapter { - private $url_dev = 'http://production.shippingapis.com/ShippingAPI.dll'; - private $url_prod = 'http://production.shippingapis.com/ShippingAPI.dll'; - - private $username = 'XXX'; - private $password = 'XXX'; - - public $approved_codes = [ - '1', - '4', - ]; - - private $shipping_codes = [ - 'domestic' => [ - '00' => 'First-Class Mail Parcel', - '01' => 'First-Class Mail Large Envelope', - '02' => 'First-Class Mail Letter', - '03' => 'First-Class Mail Postcards', - '1' => 'Priority Mail', - '2' => 'Express Mail Hold for Pickup', - '3' => 'Express Mail', - '4' => 'Parcel Post', // Standard Post - '5' => 'Bound Printed Matter', - '6' => 'Media Mail', - '7' => 'Library', - '12' => 'First-Class Postcard Stamped', - '13' => 'Express Mail Flat-Rate Envelope', - '16' => 'Priority Mail Flat-Rate Envelope', - '17' => 'Priority Mail Regular Flat-Rate Box', - '18' => 'Priority Mail Keys and IDs', - '19' => 'First-Class Keys and IDs', - '22' => 'Priority Mail Flat-Rate Large Box', - '23' => 'Express Mail Sunday/Holiday', - '25' => 'Express Mail Flat-Rate Envelope Sunday/Holiday', - '27' => 'Express Mail Flat-Rate Envelope Hold For Pickup', - '28' => 'Priority Mail Small Flat-Rate Box', - ], - 'international' => [ - '1' => 'Express Mail International', - '2' => 'Priority Mail International', - '4' => 'Global Express Guaranteed (Document and Non-document)', - '5' => 'Global Express Guaranteed Document used', - '6' => 'Global Express Guaranteed Non-Document Rectangular shape', - '7' => 'Global Express Guaranteed Non-Document Non-Rectangular', - '8' => 'Priority Mail Flat Rate Envelope', - '9' => 'Priority Mail Flat Rate Box', - '10' => 'Express Mail International Flat Rate Envelope', - '11' => 'Priority Mail Flat Rate Large Box', - '12' => 'Global Express Guaranteed Envelope', - '13' => 'First Class Mail International Letters', - '14' => 'First Class Mail International Flats', - '15' => 'First Class Mail International Parcels', - '16' => 'Priority Mail Flat Rate Small Box', - '21' => 'Postcards', - ], - ]; - - public function __construct($options = []) - { - parent::__construct($options); - - if (isset($options['username'])) { - $this->username = $options['username']; - } - - if (isset($options['password'])) { - $this->password = $options['password']; - } - - if (isset($options['username'])) { - $this->username = $options['username']; - } - - if (isset($options['approved_codes'])) { - $this->approved_codes = $options['approved_codes']; - } - - if (isset($options['request_adapter'])) { - $this->set_request_adapter($options['request_adapter']); - } else { - $this->set_request_adapter(new RateRequest\Get()); - } - } - - protected function prepare() - { - - $packages = ''; - $sequence_number = 0; - foreach ($this->shipment->getPackages() as $p) { - $sequence_number++; - - /** - * RateV4Request / Package / Size - required once - Defined as follows: - - REGULAR: Package dimensions are 12’’ or less; - LARGE: Any package dimension is larger than 12’’. - - For example: REGULAR - string - whiteSpace=collapse - enumeration=LARGE - enumeration=REGULAR - - */ - if ($p->getWidth() > 12 or $p->getLength() > 12 or $p->getHeight() > 12) { - $size = 'LARGE'; - $container = 'RECTANGULAR'; - } else { - $size = 'REGULAR'; - $container = 'VARIABLE'; - } - - $packages .= ' - ALL - ' . $this->shipment->getFromPostalCode() . ' - ' . $this->shipment->getToPostalCode() . ' - ' . $p->getWeight() . ' - 0 - ' . $container . ' - ' . $size . ' - ' . $p->getWidth() . ' - ' . $p->getLength() . ' - ' . $p->getHeight() . ' - ' . 'False' . ' - '; - } - - $this->data = -' - - ' . $packages . ' -'; - - return $this; - } - - protected function execute() - { - if ($this->is_prod) { - $url = $this->url_prod; - } else { - $url = $this->url_dev; - } - - $url_request = $url . '?API=RateV4&XML=' . rawurlencode($this->data); - - $this->response = $this->rate_request->execute($url_request); - - return $this; - } - - protected function process() - { - try { - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->loadXml($this->response); - - $postage_list = @$dom->getElementsByTagName('Postage'); - - if (empty($postage_list)) { - throw new Exception('Unable to get USPS Rates.'); - } - } catch (Exception $e) { - // StatsD::increment('error.shipping.get_usps_rate'); - // Kohana::$log->add(Log::ERROR, $e)->write(); - throw $e; - } - - /** @var Quote[] $rates */ - $rates = []; - - foreach ($postage_list as $postage) { - $code = @$postage->getAttribute('CLASSID'); - $cost = @$postage->getElementsByTagName('Rate')->item(0)->nodeValue; - - $name = Arr::get($this->shipping_codes['domestic'], $code); - - if ( ! empty($this->approved_codes) AND ! in_array($code, $this->approved_codes)) { - continue; - } - - if (array_key_exists($code, $rates)) { - $cost = $rates[$code]->getCost() + ($cost * 100); - } else { - $cost = $cost * 100; - } - - $quote = new Quote; - $quote - ->setCarrier('usps') - ->setCode($code) - ->setName($name) - ->setCost((int) $cost); - - $rates[$quote->getCode()] = $quote; - } - - $this->rates = array_values($rates); - - return $this; - } + private $urlDev = 'http://production.shippingapis.com/ShippingAPI.dll'; + private $urlProd = 'http://production.shippingapis.com/ShippingAPI.dll'; + + private $username = 'XXX'; + private $password = 'XXX'; + + public $approvedCodes = [ + '1', + '4', + ]; + + private $shipping_codes = [ + 'domestic' => [ + '00' => 'First-Class Mail Parcel', + '01' => 'First-Class Mail Large Envelope', + '02' => 'First-Class Mail Letter', + '03' => 'First-Class Mail Postcards', + '1' => 'Priority Mail', + '2' => 'Express Mail Hold for Pickup', + '3' => 'Express Mail', + '4' => 'Parcel Post', // Standard Post + '5' => 'Bound Printed Matter', + '6' => 'Media Mail', + '7' => 'Library', + '12' => 'First-Class Postcard Stamped', + '13' => 'Express Mail Flat-Rate Envelope', + '16' => 'Priority Mail Flat-Rate Envelope', + '17' => 'Priority Mail Regular Flat-Rate Box', + '18' => 'Priority Mail Keys and IDs', + '19' => 'First-Class Keys and IDs', + '22' => 'Priority Mail Flat-Rate Large Box', + '23' => 'Express Mail Sunday/Holiday', + '25' => 'Express Mail Flat-Rate Envelope Sunday/Holiday', + '27' => 'Express Mail Flat-Rate Envelope Hold For Pickup', + '28' => 'Priority Mail Small Flat-Rate Box', + ], + 'international' => [ + '1' => 'Express Mail International', + '2' => 'Priority Mail International', + '4' => 'Global Express Guaranteed (Document and Non-document)', + '5' => 'Global Express Guaranteed Document used', + '6' => 'Global Express Guaranteed Non-Document Rectangular shape', + '7' => 'Global Express Guaranteed Non-Document Non-Rectangular', + '8' => 'Priority Mail Flat Rate Envelope', + '9' => 'Priority Mail Flat Rate Box', + '10' => 'Express Mail International Flat Rate Envelope', + '11' => 'Priority Mail Flat Rate Large Box', + '12' => 'Global Express Guaranteed Envelope', + '13' => 'First Class Mail International Letters', + '14' => 'First Class Mail International Flats', + '15' => 'First Class Mail International Parcels', + '16' => 'Priority Mail Flat Rate Small Box', + '21' => 'Postcards', + ], + ]; + + public function __construct($options = []) + { + parent::__construct($options); + + $this->username = Arr::get($options, 'username'); + $this->password = Arr::get($options, 'password'); + $this->approvedCodes = Arr::get($options, 'approvedCodes'); + $this->setRequestAdapter(Arr::get($options, 'requestAdapter', new RateRequest\Get())); + } + + protected function prepare() + { + $packages = ''; + $sequence_number = 0; + foreach ($this->shipment->getPackages() as $p) { + $sequence_number++; + + /** + * RateV4Request / Package / Size + * required once + * Defined as follows: + * + * REGULAR: Package dimensions are 12’’ or less; + * LARGE: Any package dimension is larger than 12’’. + * + * For example: REGULAR + * string + * whiteSpace=collapse + * enumeration=LARGE + * enumeration=REGULAR + + */ + if ($p->getWidth() > 12 or $p->getLength() > 12 or $p->getHeight() > 12) { + $size = 'LARGE'; + $container = 'RECTANGULAR'; + } else { + $size = 'REGULAR'; + $container = 'VARIABLE'; + } + + $packages .= + '' . + 'ALL' . + '' . $this->shipment->getFromPostalCode() . '' . + '' . $this->shipment->getToPostalCode() . '' . + '' . $p->getWeight() . '' . + '0' . + '' . $container . '' . + '' . $size . '' . + '' . $p->getWidth() . '' . + '' . $p->getLength() . '' . + '' . $p->getHeight() . '' . + '' . 'False' . '' . + ''; + } + + $this->data = + '' . + '' . + $packages . + ''; + + return $this; + } + + protected function execute() + { + if ($this->isProduction) { + $url = $this->urlProd; + } else { + $url = $this->urlDev; + } + + $url_request = $url . '?API=RateV4&XML=' . rawurlencode($this->data); + + $this->response = $this->rateRequest->execute($url_request); + + return $this; + } + + protected function process() + { + try { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->loadXml($this->response); + + $postage_list = @$dom->getElementsByTagName('Postage'); + + if (empty($postage_list)) { + throw new Exception('Unable to get USPS Rates.'); + } + } catch (Exception $e) { + throw $e; + } + + /** @var Quote[] $rates */ + $rates = []; + + foreach ($postage_list as $postage) { + $code = @$postage->getAttribute('CLASSID'); + $cost = @$postage->getElementsByTagName('Rate')->item(0)->nodeValue; + + $name = Arr::get($this->shipping_codes['domestic'], $code); + + if (!empty($this->approvedCodes) && !in_array($code, $this->approvedCodes)) { + continue; + } + + if (array_key_exists($code, $rates)) { + $cost = $rates[$code]->getCost() + ($cost * 100); + } else { + $cost = $cost * 100; + } + + $quote = new Quote; + $quote + ->setCarrier('usps') + ->setCode($code) + ->setName($name) + ->setCost((int) $cost); + + $rates[$quote->getCode()] = $quote; + } + + $this->rates = array_values($rates); + + return $this; + } } diff --git a/tests/ArrTest.php b/tests/ArrTest.php new file mode 100644 index 0000000..706f4c9 --- /dev/null +++ b/tests/ArrTest.php @@ -0,0 +1,28 @@ + 'can', 'make' => 'change'), 'we', null, 'can'), + array(array('uno', 'dos', 'tress'), 10, null, null), + array(array('we' => 'can', 'make' => 'change'), 'he', null, null), + array(array('we' => 'can', 'make' => 'change'), 'he', 'who', 'who'), + array(array('we' => 'can', 'make' => 'change'), 'he', array('arrays'), array('arrays')), + ); + } + + /** + * @dataProvider providerGet() + */ + public function testGet(array $array, $key, $default, $expected) + { + $this->assertSame( + $expected, + Arr::get($array, $key, $default) + ); + } +} diff --git a/tests/Fedex/FedexTest.php b/tests/Fedex/FedexTest.php new file mode 100644 index 0000000..01012ba --- /dev/null +++ b/tests/Fedex/FedexTest.php @@ -0,0 +1,110 @@ + [ + 'fedex' => [ + 'FEDEX_EXPRESS_SAVER' => '1-3 business days', + 'FEDEX_GROUND' => '1-5 business days', + 'GROUND_HOME_DELIVERY' => '1-5 business days', + ], + ], + 'Two-Day Shipping' => [ + 'fedex' => [ + 'FEDEX_2_DAY' => '2 business days', + ], + ], + 'One-Day Shipping' => [ + 'fedex' => [ + 'STANDARD_OVERNIGHT' => 'overnight', + ], + ], + ]); + + $this->approvedCodes = $ship->getApprovedCodes('fedex'); + + $package = new Package; + $package->setWeight(3) + ->setWidth(9) + ->setLength(9) + ->setHeight(9); + + $this->shipment = new Shipment; + $this->shipment->setFromStateProvinceCode('CA') + ->setFromPostalCode('90401') + ->setFromCountryCode('US') + ->setToPostalCode('78703') + ->setToCountryCode('US') + ->setToIsResidential(true) + ->addPackage($package); + } + + public function testMockRates() + { + $rateAdapter = new Rate([ + 'prod' => false, + 'drop_off_type' => 'BUSINESS_SERVICE_CENTER', + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + 'requestAdapter' => new StubFedex, + ]); + + $rates = $rateAdapter->getRates(); + + $ground = new Quote('fedex', 'GROUND_HOME_DELIVERY', 'Ground Home Delivery', 1655); + $ground->setTransitTime('THREE_DAYS'); + + $express = new Quote('fedex', 'FEDEX_EXPRESS_SAVER', 'Fedex Express Saver', 2989); + $express->setDeliveryEstimate(new DateTime('2014-09-30T20:00:00')); + + $secondDay = new Quote('fedex', 'FEDEX_2_DAY', 'Fedex 2 Day', 4072); + $secondDay->setDeliveryEstimate(new DateTime('2014-09-29T20:00:00')); + + $overnight = new Quote('fedex', 'STANDARD_OVERNIGHT', 'Standard Overnight', 7834); + $overnight->setDeliveryEstimate(new DateTime('2014-09-26T20:00:00')); + + $expected = [$ground, $express, $secondDay, $overnight]; + + $this->assertEquals($expected, $rates); + } + + public function testLiveRates() + { + if (getenv('FEDEX_KEY') === false) { + $this->markTestSkipped('Live Fedex credentials missing.'); + } + + $rateAdapter = new Rate([ + 'prod' => false, + 'key' => getenv('FEDEX_KEY'), + 'password' => getenv('FEDEX_PASSWORD'), + 'account_number' => getenv('FEDEX_ACCOUNT_NUMBER'), + 'meter_number' => getenv('FEDEX_METER_NUMBER'), + 'drop_off_type' => 'BUSINESS_SERVICE_CENTER', + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + 'requestAdapter' => new StubFedex, + ]); + + $rates = $rateAdapter->getRates(); + + $this->assertTrue(count($rates) > 0); + $this->assertTrue($rates[0] instanceof Quote); + } +} diff --git a/tests/PackageTest.php b/tests/PackageTest.php new file mode 100644 index 0000000..2407da6 --- /dev/null +++ b/tests/PackageTest.php @@ -0,0 +1,19 @@ +setWeight(5); + $package->setWidth(6); + $package->setLength(7); + $package->setHeight(8); + + $this->assertEquals(5, $package->getWeight()); + $this->assertEquals(6, $package->getWidth()); + $this->assertEquals(7, $package->getLength()); + $this->assertEquals(8, $package->getHeight()); + } +} diff --git a/tests/QuoteTest.php b/tests/QuoteTest.php new file mode 100644 index 0000000..34405f5 --- /dev/null +++ b/tests/QuoteTest.php @@ -0,0 +1,25 @@ +setCode('-code-'); + $quote->setName('Test Name'); + $quote->setCost(500); + $quote->setTransitTime('-transit-time-'); + $quote->setDeliveryEstimate(new DateTime); + $quote->setCarrier('-carrier-'); + + $this->assertEquals('-code-', $quote->getCode()); + $this->assertEquals('Test Name', $quote->getName()); + $this->assertEquals(500, $quote->getCost()); + $this->assertEquals('-transit-time-', $quote->getTransitTime()); + $this->assertTrue($quote->getDeliveryEstimate() instanceof DateTime); + $this->assertEquals('-carrier-', $quote->getCarrier()); + } +} diff --git a/tests/RateAdapterTest.php b/tests/RateAdapterTest.php new file mode 100644 index 0000000..c7f351f --- /dev/null +++ b/tests/RateAdapterTest.php @@ -0,0 +1,13 @@ +getMockForAbstractClass('pdt256\Shipping\RateAdapter'); + $mockRequestAdapter = $this->getMockForAbstractClass('pdt256\Shipping\RateRequest\Adapter'); + $mock->setRequestAdapter($mockRequestAdapter); + } +} diff --git a/tests/ShipTest.php b/tests/ShipTest.php index f6cb5ee..7b8bc10 100644 --- a/tests/ShipTest.php +++ b/tests/ShipTest.php @@ -1,277 +1,155 @@ [ - 'ups' => [ - '03' => '1-5 business days', - ], - 'fedex' => [ - 'FEDEX_EXPRESS_SAVER' => '1-3 business days', - 'FEDEX_GROUND' => '1-5 business days', - 'GROUND_HOME_DELIVERY' => '1-5 business days', - ], - 'usps' => [ - '1' => '1-3 business days', - '4' => '2-8 business days', - ], - ], - 'Two-Day Shipping' => [ - 'ups' => [ - '02' => '2 business days', - ], - 'fedex' => [ - 'FEDEX_2_DAY' => '2 business days', - ], - ], - 'One-Day Shipping' => [ - 'ups' => [ - '01' => 'next business day 10:30am', - '13' => 'next business day by 3pm', - '14' => 'next business day by 8am', - ], - 'fedex' => [ - 'STANDARD_OVERNIGHT' => 'overnight', - ], - ], - ]; - - public function setUp() - { - $s = new Shipment; - $s->setFromStateProvinceCode('CA') - ->setFromPostalCode('90401') - ->setFromCountryCode('US') - ->setToPostalCode('78703') - ->setToCountryCode('US') - ->setToResidential(true); - - $p = new Package; - $p->setWeight(3) - ->setWidth(9) - ->setLength(9) - ->setHeight(9); - - $s->addPackage($p); - - $this->shipment = $s; - } - - private function getUSPSOptions() - { - $ship = Ship::factory($this->shipping_options); - $approved_codes = $ship->get_approved_codes('usps'); - - return [ - 'prod' => FALSE, - 'username' => 'XXXX', - 'password' => 'XXXX', - 'shipment' => $this->shipment, - 'approved_codes' => $approved_codes, - 'request_adapter' => new RateRequest\StubUSPS(), - ]; - } - - private function getUPSOptions() - { - $ship = Ship::factory($this->shipping_options); - $approved_codes = $ship->get_approved_codes('ups'); - - return [ - 'prod' => FALSE, - 'access_key' => 'XXXX', - 'user_id' => 'XXXX', - 'password' => 'XXXX', - 'shipper_number' => 'XXXX', - 'shipment' => $this->shipment, - 'approved_codes' => $approved_codes, - 'request_adapter' => new RateRequest\StubUPS(), - ]; - } - - private function getFedexOptions() - { - $ship = Ship::factory($this->shipping_options); - $approved_codes = $ship->get_approved_codes('fedex'); - - return [ - 'prod' => FALSE, - 'key' => 'XXXX', - 'password' => 'XXXX', - 'account_number' => 'XXXX', - 'meter_number' => 'XXXX', - 'drop_off_type' => 'BUSINESS_SERVICE_CENTER', - 'shipment' => $this->shipment, - 'approved_codes' => $approved_codes, - 'request_adapter' => new RateRequest\StubFedex(), - ]; - } - - public function testUSPSRate() - { - $usps = new USPS\Rate($this->getUSPSOptions()); - $usps_rates = $usps->get_rates(); - - $post = new Quote; - $post - ->setCarrier('usps') - ->setCode(4) - ->setName('Parcel Post') - ->setCost(1001); - - $priority = new Quote; - $priority - ->setCarrier('usps') - ->setCode(1) - ->setName('Priority Mail') - ->setCost(1220); - - $expected_return = [$post, $priority]; - - $this->assertEquals($expected_return, $usps_rates); - } - - public function testUPSRate() - { - $ups = new UPS\Rate($this->getUPSOptions()); - $ups_rates = $ups->get_rates(); - - $ground = new Quote; - $ground - ->setCarrier('ups') - ->setCode('03') - ->setName('UPS Ground') - ->setCost(1900); - - $twodayair = new Quote; - $twodayair - ->setCarrier('ups') - ->setCode('02') - ->setName('UPS 2nd Day Air') - ->setCost(4900); +use DateTime; - $nextdaysaver = new Quote; - $nextdaysaver - ->setCarrier('ups') - ->setCode('13') - ->setName('UPS Next Day Air Saver') - ->setCost(8900); - - $nextdayair = new Quote; - $nextdayair - ->setCarrier('ups') - ->setCode('01') - ->setName('UPS Next Day Air') - ->setCost(9300); - - $expected_return = [$ground, $twodayair, $nextdaysaver, $nextdayair]; - - $this->assertEquals($expected_return, $ups_rates); - } - - public function testFedexRate() - { - $fedex = new Fedex\Rate($this->getFedexOptions()); - $fedex_rates = $fedex->get_rates(); - - $ground = new Quote; - $ground - ->setCarrier('fedex') - ->setCode('GROUND_HOME_DELIVERY') - ->setName('Ground Home Delivery') - ->setCost(1600) - ->setTransitTime('THREE_DAYS'); - - $express = new Quote; - $express - ->setCarrier('fedex') - ->setCode('FEDEX_EXPRESS_SAVER') - ->setName('Fedex Express Saver') - ->setCost(2900) - ->setDeliveryEstimate(new DateTime('2014-09-30T20:00:00')) - ->setTransitTime(null); - - $secondday = new Quote; - $secondday - ->setCarrier('fedex') - ->setCode('FEDEX_2_DAY') - ->setName('Fedex 2 Day') - ->setCost(4000) - ->setDeliveryEstimate(new DateTime('2014-09-29T20:00:00')) - ->setTransitTime(null); - - $overnight = new Quote; - $overnight - ->setCarrier('fedex') - ->setCode('STANDARD_OVERNIGHT') - ->setName('Standard Overnight') - ->setCost(7800) - ->setDeliveryEstimate(new DateTime('2014-09-26T20:00:00')) - ->setTransitTime(null); - - $expected_result = [$ground, $express, $secondday, $overnight]; - - $this->assertEquals($expected_result, $fedex_rates); - } - - public function testDisplayOptions() - { - $rates = []; - - $usps = new USPS\Rate($this->getUSPSOptions()); - $rates['usps'] = $usps->get_rates(); - - $ups = new UPS\Rate($this->getUPSOptions()); - $rates['ups'] = $ups->get_rates(); - - $fedex = new Fedex\Rate($this->getFedexOptions()); - $rates['fedex'] = $fedex->get_rates(); - - $ship = Ship::factory($this->shipping_options); - $display_rates = $ship->get_display_rates($rates); - - $post = new Quote; - $post->setCode(4) - ->setName('Parcel Post') - ->setCost(1001) - ->setCarrier('usps'); - - $fedex_two_day = new Quote; - $fedex_two_day->setCode('FEDEX_2_DAY') - ->setName('Fedex 2 Day') - ->setCost(4000) - ->setDeliveryEstimate(new DateTime('2014-09-29T20:00:00')) - ->setCarrier('fedex'); - - $overnight = new Quote; - $overnight->setCode('STANDARD_OVERNIGHT') - ->setName('Standard Overnight') - ->setCost(7800) - ->setDeliveryEstimate(new DateTime('2014-09-26T20:00:00')) - ->setCarrier('fedex'); - - $this->assertEquals([ - 'Standard Shipping' => [ - $post, - ], - 'Two-Day Shipping' => [ - $fedex_two_day, - ], - 'One-Day Shipping' => [ - $overnight, - ], - ], $display_rates); - } +class ShipTest extends \PHPUnit_Framework_TestCase +{ + /** @var Shipment */ + public $shipment; + + public $shipping_options = [ + 'Standard Shipping' => [ + 'ups' => [ + '03' => '1-5 business days', + ], + 'fedex' => [ + 'FEDEX_EXPRESS_SAVER' => '1-3 business days', + 'FEDEX_GROUND' => '1-5 business days', + 'GROUND_HOME_DELIVERY' => '1-5 business days', + ], + 'usps' => [ + '1' => '1-3 business days', + '4' => '2-8 business days', + ], + ], + 'Two-Day Shipping' => [ + 'ups' => [ + '02' => '2 business days', + ], + 'fedex' => [ + 'FEDEX_2_DAY' => '2 business days', + ], + ], + 'One-Day Shipping' => [ + 'ups' => [ + '01' => 'next business day 10:30am', + '13' => 'next business day by 3pm', + '14' => 'next business day by 8am', + ], + 'fedex' => [ + 'STANDARD_OVERNIGHT' => 'overnight', + ], + ], + ]; + + public function setUp() + { + $s = new Shipment; + $s->setFromStateProvinceCode('CA') + ->setFromPostalCode('90401') + ->setFromCountryCode('US') + ->setToPostalCode('78703') + ->setToCountryCode('US') + ->setToIsResidential(true); + + $p = new Package; + $p->setWeight(3) + ->setWidth(9) + ->setLength(9) + ->setHeight(9); + + $s->addPackage($p); + + $this->shipment = $s; + } + + private function getUSPSOptions() + { + $ship = Ship::factory($this->shipping_options); + $approvedCodes = $ship->getApprovedCodes('usps'); + + return [ + 'prod' => false, + 'username' => 'XXXX', + 'password' => 'XXXX', + 'shipment' => $this->shipment, + 'approvedCodes' => $approvedCodes, + 'requestAdapter' => new RateRequest\StubUSPS(), + ]; + } + + private function getUPSOptions() + { + $ship = Ship::factory($this->shipping_options); + $approvedCodes = $ship->getApprovedCodes('ups'); + + return [ + 'prod' => false, + 'accessKey' => 'XXXX', + 'userId' => 'XXXX', + 'password' => 'XXXX', + 'shipperNumber' => 'XXXX', + 'shipment' => $this->shipment, + 'approvedCodes' => $approvedCodes, + 'requestAdapter' => new RateRequest\StubUPS(), + ]; + } + + private function getFedexOptions() + { + $ship = Ship::factory($this->shipping_options); + $approvedCodes = $ship->getApprovedCodes('fedex'); + + return [ + 'prod' => false, + 'key' => 'XXXX', + 'password' => 'XXXX', + 'account_number' => 'XXXX', + 'meter_number' => 'XXXX', + 'drop_off_type' => 'BUSINESS_SERVICE_CENTER', + 'shipment' => $this->shipment, + 'approvedCodes' => $approvedCodes, + 'requestAdapter' => new RateRequest\StubFedex(), + ]; + } + + public function testDisplayOptions() + { + $rates = []; + + $usps = new USPS\Rate($this->getUSPSOptions()); + $rates['usps'] = $usps->getRates(); + + $ups = new UPS\Rate($this->getUPSOptions()); + $rates['ups'] = $ups->getRates(); + + $fedex = new Fedex\Rate($this->getFedexOptions()); + $rates['fedex'] = $fedex->getRates(); + + $ship = Ship::factory($this->shipping_options); + $rates = $ship->getDisplayRates($rates); + + $post = new Quote('usps', '4', 'Parcel Post', 1001); + + $fedexTwoDay = new Quote('fedex', 'FEDEX_2_DAY', 'Fedex 2 Day', 4072); + $fedexTwoDay->setDeliveryEstimate(new DateTime('2014-09-29T20:00:00')); + + $overnight = new Quote('fedex', 'STANDARD_OVERNIGHT', 'Standard Overnight', 7834); + $overnight->setDeliveryEstimate(new DateTime('2014-09-26T20:00:00')); + + $expected = [ + 'Standard Shipping' => [ + $post, + ], + 'Two-Day Shipping' => [ + $fedexTwoDay, + ], + 'One-Day Shipping' => [ + $overnight, + ], + ]; + + $this->assertEquals($expected, $rates); + } } diff --git a/tests/ShipmentTest.php b/tests/ShipmentTest.php new file mode 100644 index 0000000..02dfab7 --- /dev/null +++ b/tests/ShipmentTest.php @@ -0,0 +1,32 @@ +addPackage(new Package); + + $shipment->setFromIsResidential(false); + $shipment->setFromPostalCode('90401'); + $shipment->setFromCountryCode('US'); + $shipment->setFromStateProvinceCode('CA'); + + $shipment->setToIsResidential(true); + $shipment->setToPostalCode('90210'); + $shipment->setToCountryCode('US'); + + $this->assertTrue($shipment->getPackages()[0] instanceof Package); + $this->assertEquals(1, $shipment->packageCount()); + + $this->assertFalse($shipment->getFromIsResidential()); + $this->assertEquals('90401', $shipment->getFromPostalCode()); + $this->assertEquals('US', $shipment->getFromCountryCode()); + $this->assertEquals('CA', $shipment->getFromStateProvinceCode()); + + $this->assertTrue($shipment->getToIsResidential()); + $this->assertEquals('90210', $shipment->getToPostalCode()); + $this->assertEquals('US', $shipment->getToCountryCode()); + } +} diff --git a/tests/UPS/RateTest.php b/tests/UPS/RateTest.php new file mode 100644 index 0000000..e16e015 --- /dev/null +++ b/tests/UPS/RateTest.php @@ -0,0 +1,99 @@ + [ + 'ups' => [ + '03' => '1-5 business days', + ], + ], + 'Two-Day Shipping' => [ + 'ups' => [ + '02' => '2 business days', + ], + ], + 'One-Day Shipping' => [ + 'ups' => [ + '01' => 'next business day 10:30am', + '13' => 'next business day by 3pm', + '14' => 'next business day by 8am', + ], + ], + ]); + + $this->approvedCodes = $ship->getApprovedCodes('ups'); + + $package = new Package; + $package->setWeight(3) + ->setWidth(9) + ->setLength(9) + ->setHeight(9); + + $this->shipment = new Shipment; + $this->shipment->setFromStateProvinceCode('CA') + ->setFromPostalCode('90401') + ->setFromCountryCode('US') + ->setToPostalCode('78703') + ->setToCountryCode('US') + ->setToIsResidential(true) + ->addPackage($package); + } + + public function testMockRates() + { + $rateAdapter = new Rate([ + 'prod' => false, + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + 'requestAdapter' => new StubUPS, + ]); + + $rates = $rateAdapter->getRates(); + + $expected = [ + new Quote('ups', '03', 'UPS Ground', 1910), + new Quote('ups', '02', 'UPS 2nd Day Air', 4923), + new Quote('ups', '13', 'UPS Next Day Air Saver', 8954), + new Quote('ups', '01', 'UPS Next Day Air', 9328), + ]; + + $this->assertEquals($expected, $rates); + } + + public function testLiveRates() + { + if (getenv('UPS_ACCESS_KEY') === false) { + $this->markTestSkipped('Live UPS credentials missing.'); + } + + $rateAdapter = new Rate([ + 'prod' => false, + 'accessKey' => getenv('UPS_ACCESS_KEY'), + 'userId' => getenv('UPS_USER_ID'), + 'password' => getenv('UPS_PASSWORD'), + 'shipperNumber' => getenv('UPS_SHIPPER_NUMBER'), + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + ]); + + $rates = $rateAdapter->getRates(); + + $this->assertTrue(count($rates) > 0); + $this->assertTrue($rates[0] instanceof Quote); + } +} diff --git a/tests/USPS/RateTest.php b/tests/USPS/RateTest.php new file mode 100644 index 0000000..1cf9f67 --- /dev/null +++ b/tests/USPS/RateTest.php @@ -0,0 +1,86 @@ + [ + 'usps' => [ + '1' => '1-3 business days', + '4' => '2-8 business days', + ], + ], + ]); + + $this->approvedCodes = $ship->getApprovedCodes('usps'); + + $package = new Package; + $package->setWeight(3) + ->setWidth(9) + ->setLength(9) + ->setHeight(9); + + $this->shipment = new Shipment; + $this->shipment->setFromStateProvinceCode('CA') + ->setFromPostalCode('90401') + ->setFromCountryCode('US') + ->setToPostalCode('78703') + ->setToCountryCode('US') + ->setToIsResidential(true) + ->addPackage($package); + } + + public function testMockRates() + { + $rateAdapter = new Rate([ + 'prod' => false, + 'username' => 'XXXX', + 'password' => 'XXXX', + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + 'requestAdapter' => new StubUSPS, + ]); + + $rates = $rateAdapter->getRates(); + + $expected = [ + new Quote('usps', '4', 'Parcel Post', 1001), + new Quote('usps', '1', 'Priority Mail', 1220), + ]; + + $this->assertEquals($expected, $rates); + } + + public function testLiveRates() + { + if (getenv('USPS_USERNAME') === false) { + $this->markTestSkipped('Live USPS credentials missing.'); + } + + $rateAdapter = new Rate([ + 'prod' => false, + 'username' => getenv('USPS_USERNAME'), + 'password' => getenv('USPS_PASSWORD'), + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + ]); + + $rates = $rateAdapter->getRates(); + + $this->assertTrue(count($rates) > 0); + $this->assertTrue($rates[0] instanceof Quote); + } +}