diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e7c1d61
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+vendor/
+.idea/
+composer.lock
+
diff --git a/README.md b/README.md
index cd96df5..6a6928d 100644
--- a/README.md
+++ b/README.md
@@ -21,23 +21,19 @@ Add the following lines to your ``composer.json`` file.
Create a shipment object:
```php
-$shipment = [
- 'weight' => 3, // lbs
- 'dimensions' => [
- 'width' => 9, // inches
- 'length' => 9,
- 'height' => 9,
- ],
- 'from' => [
- 'postal_code' => '90401',
- 'country_code' => 'US',
- ],
- 'to' => [
- 'postal_code' => '78703',
- 'country_code' => 'US',
- 'is_residential' => TRUE,
- ],
-];
+$shipment = new Shipment;
+$shipment
+ ->setFromStateProvinceCode('IN')
+ ->setFromPostalCode('46205')
+ ->setFromCountryCode('US')
+ ->setToPostalCode('20101')
+ ->setToCountryCode('US')
+ ->setToResidential(true);
+
+$package = new Package;
+$package->setLength(12)->setWidth(4)->setHeight(3)->setWeight(3);
+
+$shipment->addPackage($package);
```
## UPS (Stub) Example
@@ -78,32 +74,68 @@ $ups_rates = $ups->get_rates();
Output array sorted by cost: (in cents)
```php
-array (
- 0 =>
- array (
- 'code' => '03',
- 'name' => 'UPS Ground',
- 'cost' => 1900,
- ),
- 1 =>
- array (
- 'code' => '02',
- 'name' => 'UPS 2nd Day Air',
- 'cost' => 4900,
- ),
- 2 =>
- array (
- 'code' => '13',
- 'name' => 'UPS Next Day Air Saver',
- 'cost' => 8900,
- ),
- 3 =>
- array (
- 'code' => '01',
- 'name' => 'UPS Next Day Air',
- 'cost' => 9300,
- ),
-)
+array(4) {
+ [0] =>
+ class pdt256\Shipping\Quote#56 (6) {
+ protected $code =>
+ string(2) "03"
+ protected $name =>
+ string(10) "UPS Ground"
+ protected $cost =>
+ int(1900)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(3) "ups"
+ }
+ [1] =>
+ class pdt256\Shipping\Quote#58 (6) {
+ protected $code =>
+ string(2) "02"
+ protected $name =>
+ string(15) "UPS 2nd Day Air"
+ protected $cost =>
+ int(4900)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(3) "ups"
+ }
+ [2] =>
+ class pdt256\Shipping\Quote#57 (6) {
+ protected $code =>
+ string(2) "13"
+ protected $name =>
+ string(22) "UPS Next Day Air Saver"
+ protected $cost =>
+ int(8900)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(3) "ups"
+ }
+ [3] =>
+ class pdt256\Shipping\Quote#55 (6) {
+ protected $code =>
+ string(2) "01"
+ protected $name =>
+ string(16) "UPS Next Day Air"
+ protected $cost =>
+ int(9300)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(3) "ups"
+ }
+}
```
## USPS (Stub) Example
@@ -116,10 +148,7 @@ $usps = new USPS\Rate([
'prod' => FALSE,
'username' => 'XXXX',
'password' => 'XXXX',
- 'shipment' => array_merge($shipment, [
- 'size' => 'LARGE',
- 'container' => 'RECTANGULAR',
- ]),
+ 'shipment' => $shipment,
'approved_codes' => [
'1', // 1-3 business days
'4', // 2-8 business days
@@ -133,20 +162,38 @@ $usps_rates = $usps->get_rates();
Output array sorted by cost: (in cents)
```php
-array (
- 1 =>
- array (
- 'code' => '4',
- 'name' => 'Parcel Post',
- 'cost' => 1000,
- ),
- 0 =>
- array (
- 'code' => '1',
- 'name' => 'Priority Mail',
- 'cost' => 1200,
- ),
-)
+array(2) {
+ [0] =>
+ class pdt256\Shipping\Quote#30 (6) {
+ protected $code =>
+ string(1) "4"
+ protected $name =>
+ string(11) "Parcel Post"
+ protected $cost =>
+ int(1001)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(4) "usps"
+ }
+ [1] =>
+ class pdt256\Shipping\Quote#26 (6) {
+ protected $code =>
+ string(1) "1"
+ protected $name =>
+ string(13) "Priority Mail"
+ protected $cost =>
+ int(1220)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(4) "usps"
+ }
+}
```
## Fedex (Stub) Example
@@ -162,9 +209,7 @@ $fedex = new Fedex\Rate([
'account_number' => 'XXXX',
'meter_number' => 'XXXX',
'drop_off_type' => 'BUSINESS_SERVICE_CENTER',
- 'shipment' => array_merge($shipment, [
- 'packaging_type' => 'YOUR_PACKAGING',
- ]),
+ 'shipment' => $shipment,
'approved_codes' => [
'FEDEX_EXPRESS_SAVER', // 1-3 business days
'FEDEX_GROUND', // 1-5 business days
@@ -181,40 +226,89 @@ $fedex_rates = $fedex->get_rates();
Output array sorted by cost: (in cents)
```php
-array (
- 3 =>
- array (
- 'code' => 'GROUND_HOME_DELIVERY',
- 'name' => 'Ground Home Delivery',
- 'cost' => 1600,
- 'delivery_ts' => NULL,
- 'transit_time' => 'THREE_DAYS',
- ),
- 2 =>
- array (
- 'code' => 'FEDEX_EXPRESS_SAVER',
- 'name' => 'Fedex Express Saver',
- 'cost' => 2900,
- 'delivery_ts' => '2014-09-30T20:00:00',
- 'transit_time' => NULL,
- ),
- 1 =>
- array (
- 'code' => 'FEDEX_2_DAY',
- 'name' => 'Fedex 2 Day',
- 'cost' => 4000,
- 'delivery_ts' => '2014-09-29T20:00:00',
- 'transit_time' => NULL,
- ),
- 0 =>
- array (
- 'code' => 'STANDARD_OVERNIGHT',
- 'name' => 'Standard Overnight',
- 'cost' => 7800,
- 'delivery_ts' => '2014-09-26T20:00:00',
- 'transit_time' => NULL,
- ),
-)
+array(4) {
+ [0] =>
+ class pdt256\Shipping\Quote#65 (6) {
+ protected $code =>
+ string(20) "GROUND_HOME_DELIVERY"
+ protected $name =>
+ string(20) "Ground Home Delivery"
+ protected $cost =>
+ int(1600)
+ protected $transit_time =>
+ string(10) "THREE_DAYS"
+ protected $delivery_ts =>
+ NULL
+ protected $carrier =>
+ string(5) "fedex"
+ }
+ [1] =>
+ class pdt256\Shipping\Quote#63 (6) {
+ protected $code =>
+ string(19) "FEDEX_EXPRESS_SAVER"
+ protected $name =>
+ string(19) "Fedex Express Saver"
+ protected $cost =>
+ int(2900)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ class Carbon\Carbon#23 (3) {
+ public $date =>
+ string(26) "2014-09-30 20:00:00.000000"
+ public $timezone_type =>
+ int(3)
+ public $timezone =>
+ string(16) "America/New_York"
+ }
+ protected $carrier =>
+ string(5) "fedex"
+ }
+ [2] =>
+ class pdt256\Shipping\Quote#61 (6) {
+ protected $code =>
+ string(11) "FEDEX_2_DAY"
+ protected $name =>
+ string(11) "Fedex 2 Day"
+ protected $cost =>
+ int(4000)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ class Carbon\Carbon#26 (3) {
+ public $date =>
+ string(26) "2014-09-29 20:00:00.000000"
+ public $timezone_type =>
+ int(3)
+ public $timezone =>
+ string(16) "America/New_York"
+ }
+ protected $carrier =>
+ string(5) "fedex"
+ }
+ [3] =>
+ class pdt256\Shipping\Quote#60 (6) {
+ protected $code =>
+ string(18) "STANDARD_OVERNIGHT"
+ protected $name =>
+ string(18) "Standard Overnight"
+ protected $cost =>
+ int(7800)
+ protected $transit_time =>
+ NULL
+ protected $delivery_ts =>
+ class Carbon\Carbon#58 (3) {
+ public $date =>
+ string(26) "2014-09-26 20:00:00.000000"
+ public $timezone_type =>
+ int(3)
+ public $timezone =>
+ string(16) "America/New_York"
+ }
+ protected $carrier =>
+ string(5) "fedex"
+ }
+}
```
### License
diff --git a/composer.json b/composer.json
index 58cef70..f7694c4 100644
--- a/composer.json
+++ b/composer.json
@@ -9,7 +9,6 @@
"email": "pdt256@gmail.com"
}
],
- "require": {},
"require-dev": {
"phpunit/phpunit": "4.0.*"
},
diff --git a/src/Fedex/Rate.php b/src/Fedex/Rate.php
index 85f26f4..26022cc 100644
--- a/src/Fedex/Rate.php
+++ b/src/Fedex/Rate.php
@@ -1,8 +1,10 @@
shipment, 'to');
- $shipper = Arr::get($this->shipment, 'from');
- $dimensions = Arr::get($this->shipment, 'dimensions');
-
- $pounds = (int) Arr::get($this->shipment, 'weight');
- $ounces = 0;
-
- if ($pounds < 1) {
- throw new Exception('Weight missing');
- }
-
$date = time();
$day_name = date('l', $date);
@@ -111,6 +102,28 @@ class Rate extends RateAdapter
// 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 =
'
@@ -136,37 +149,24 @@ class Rate extends RateAdapter
' . date('c') . '
' . $this->drop_off_type . '
- ' . Arr::get($this->shipment, 'packaging_type') . '
+ YOUR_PACKAGING
- ' . Arr::get($shipper, 'postal_code') . '
- ' . Arr::get($shipper, 'country_code') . '
- ' . ((Arr::get($shipper, 'is_residential')) ? '1' : '') . '
+ ' . $this->shipment->getFromPostalCode() . '
+ ' . $this->shipment->getFromCountryCode() . '
+ ' . (($this->shipment->isFromResidential()) ? '1' : '') . '
- ' . Arr::get($to, 'postal_code') . '
- ' . Arr::get($to, 'country_code') . '
- ' . ((Arr::get($to, 'is_residential')) ? '1' : '') . '
+ ' . $this->shipment->getToPostalCode() . '
+ ' . $this->shipment->getToCountryCode() . '
+ ' . (($this->shipment->isToResidential()) ? '1' : '') . '
LIST
- 1
-
- 1
- 1
-
- LB
- ' . $pounds . '
-
-
- ' . Arr::get($dimensions, 'length') . '
- ' . Arr::get($dimensions, 'width') . '
- ' . Arr::get($dimensions, 'height') . '
- IN
-
-
+ ' . $this->shipment->packageCount() . '
+ ' . $packages . '
@@ -222,13 +222,18 @@ class Rate extends RateAdapter
->getElementsByTagName('TotalNetCharge')->item(0)
->getElementsByTagName('Amount')->item(0)->nodeValue;
- $this->rates[] = array(
- 'code' => $code,
- 'name' => $name,
- 'cost' => (int) ($cost * 100),
- 'delivery_ts' => $delivery_ts,
- 'transit_time' => $transit_time,
- );
+ $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/Package.php b/src/Package.php
new file mode 100644
index 0000000..b873fb1
--- /dev/null
+++ b/src/Package.php
@@ -0,0 +1,81 @@
+weight;
+ }
+
+ /**
+ * @param mixed $weight
+ * @return $this
+ */
+ public function setWeight($weight)
+ {
+ $this->weight = $weight;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getWidth()
+ {
+ return $this->width;
+ }
+
+ /**
+ * @param mixed $width
+ * @return $this
+ */
+ public function setWidth($width)
+ {
+ $this->width = $width;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getLength()
+ {
+ return $this->length;
+ }
+
+ /**
+ * @param mixed $length
+ * @return $this
+ */
+ public function setLength($length)
+ {
+ $this->length = $length;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getHeight()
+ {
+ return $this->height;
+ }
+
+ /**
+ * @param mixed $height
+ * @return $this
+ */
+ public function setHeight($height)
+ {
+ $this->height = $height;
+ return $this;
+ }
+}
diff --git a/src/Quote.php b/src/Quote.php
new file mode 100644
index 0000000..0daf8d4
--- /dev/null
+++ b/src/Quote.php
@@ -0,0 +1,123 @@
+carrier;
+ }
+
+ /**
+ * @param mixed $carrier
+ * @return $this
+ */
+ public function setCarrier($carrier)
+ {
+ $this->carrier = $carrier;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCode()
+ {
+ return $this->code;
+ }
+
+ /**
+ * @param string $code
+ * @return $this
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * @param string $name
+ * @return $this
+ */
+ public function setName($name)
+ {
+ $this->name = $name;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getCost()
+ {
+ return $this->cost;
+ }
+
+ /**
+ * Quoted cost of this service, in pennies
+ *
+ * @param int $cost
+ * @return $this
+ */
+ public function setCost($cost)
+ {
+ $this->cost = $cost;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getTransitTime()
+ {
+ return $this->transit_time;
+ }
+
+ /**
+ * @param mixed $transit_time
+ * @return $this
+ */
+ public function setTransitTime($transit_time)
+ {
+ $this->transit_time = $transit_time;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getDeliveryEstimate()
+ {
+ return $this->delivery_ts;
+ }
+
+ /**
+ * @param DateTime $estimate
+ * @return $this
+ */
+ public function setDeliveryEstimate(DateTime $estimate)
+ {
+ $this->delivery_ts = $estimate;
+ return $this;
+ }
+}
diff --git a/src/RateAdapter.php b/src/RateAdapter.php
index 430305b..de2d17a 100644
--- a/src/RateAdapter.php
+++ b/src/RateAdapter.php
@@ -7,6 +7,7 @@ abstract class RateAdapter
{
protected $is_prod = FALSE;
+ /** @var Shipment */
protected $shipment;
protected $data;
protected $response;
@@ -27,18 +28,6 @@ abstract class RateAdapter
if (isset($options['shipment'])) {
$this->shipment = $options['shipment'];
}
-
- if (empty($this->shipment['to'])) {
- throw new Exception('Shipment "to" missing');
- }
-
- if (empty($this->shipment['from'])) {
- throw new Exception('Shipment "from" missing');
- }
-
- if (empty($this->shipment['dimensions'])) {
- throw new Exception('Shipment "dimensions" missing');
- }
}
public function set_request_adapter(RateRequest\Adapter $rate_request)
@@ -54,11 +43,11 @@ abstract class RateAdapter
->process()
->sort_by_cost();
- return $this->rates;
+ return array_values($this->rates);
}
protected function sort_by_cost()
{
- uasort($this->rates, create_function('$a, $b', 'return ($a["cost"] > $b["cost"]);'));
+ uasort($this->rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());'));
}
}
diff --git a/src/Ship.php b/src/Ship.php
index d176c0c..06e5363 100644
--- a/src/Ship.php
+++ b/src/Ship.php
@@ -88,13 +88,13 @@ class Ship
foreach ($rates[$carrier] as $row3) {
- if (in_array($row3['code'], $group_codes)) {
- $row3['carrier'] = $carrier;
+ if (in_array($row3->getCode(), $group_codes)) {
+ $row3->setCarrier($carrier);
if ($cheapest_row === NULL) {
$cheapest_row = $row3;
} else {
- if ($row3['cost'] < $cheapest_row['cost']) {
+ if ($row3->getCost() < $cheapest_row->getCost()) {
$cheapest_row = $row3;
}
}
@@ -126,8 +126,8 @@ class Ship
foreach ($rates[$carrier] as $row3) {
- if (in_array($row3['code'], $group_codes)) {
- $row3['carrier'] = $carrier;
+ if (in_array($row3->getCode(), $group_codes)) {
+ $row3->setCarrier($carrier);
$display_rates[$shipping_group][] = $row3;
}
}
@@ -142,6 +142,6 @@ class Ship
protected function sort_by_cost( & $rates)
{
- uasort($rates, create_function('$a, $b', 'return ($a["cost"] > $b["cost"]);'));
+ uasort($rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());'));
}
}
diff --git a/src/Shipment.php b/src/Shipment.php
new file mode 100644
index 0000000..c7f2a9d
--- /dev/null
+++ b/src/Shipment.php
@@ -0,0 +1,169 @@
+packages[] = $package;
+ return $this;
+ }
+
+ /**
+ * @return Package[]
+ */
+ public function getPackages()
+ {
+ return $this->packages;
+ }
+
+ /**
+ * @return int
+ */
+ public function packageCount()
+ {
+ return count($this->getPackages());
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFromPostalCode()
+ {
+ return $this->from_postal_code;
+ }
+
+ /**
+ * @param mixed $from_postal_code
+ * @return $this
+ */
+ public function setFromPostalCode($from_postal_code)
+ {
+ $this->from_postal_code = $from_postal_code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFromCountryCode()
+ {
+ return $this->from_country_code;
+ }
+
+ /**
+ * @param mixed $from_country_code
+ * @return $this
+ */
+ public function setFromCountryCode($from_country_code)
+ {
+ $this->from_country_code = $from_country_code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getToPostalCode()
+ {
+ return $this->to_postal_code;
+ }
+
+ /**
+ * @param mixed $to_postal_code
+ * @return $this
+ */
+ public function setToPostalCode($to_postal_code)
+ {
+ $this->to_postal_code = $to_postal_code;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getToCountryCode()
+ {
+ return $this->to_country_code;
+ }
+
+ /**
+ * @param mixed $to_country_code
+ * @return $this
+ */
+ public function setToCountryCode($to_country_code)
+ {
+ $this->to_country_code = $to_country_code;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isToResidential()
+ {
+ return $this->to_is_residential;
+ }
+
+ /**
+ * @param boolean $to_is_residential
+ * @return $this
+ */
+ public function setToResidential($to_is_residential)
+ {
+ $this->to_is_residential = $to_is_residential;
+ return $this;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isFromResidential()
+ {
+ return $this->from_is_residential;
+ }
+
+ /**
+ * @param $from_is_residential
+ * @return $this
+ */
+ public function setFromResidential($from_is_residential)
+ {
+ $this->from_is_residential = $from_is_residential;
+ return $this;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getFromStateProvinceCode()
+ {
+ return $this->from_state_province;
+ }
+
+ /**
+ * @param $from_state_province
+ * @return $this
+ */
+ public function setFromStateProvinceCode($from_state_province)
+ {
+ $this->from_state_province = $from_state_province;
+ return $this;
+ }
+}
diff --git a/src/UPS/Rate.php b/src/UPS/Rate.php
index 8e469c7..bb33c50 100644
--- a/src/UPS/Rate.php
+++ b/src/UPS/Rate.php
@@ -3,6 +3,7 @@ namespace pdt256\Shipping\UPS;
use pdt256\Ship;
use pdt256\Shipping\Arr;
+use pdt256\Shipping\Quote;
use pdt256\Shipping\RateAdapter;
use pdt256\Shipping\RateRequest;
use DOMDocument;
@@ -114,19 +115,31 @@ class Rate extends RateAdapter
protected function prepare()
{
- $to = Arr::get($this->shipment, 'to');
- $shipper = Arr::get($this->shipment, 'from');
- $dimensions = Arr::get($this->shipment, 'dimensions');
-
- $pounds = (int) Arr::get($this->shipment, 'weight');
- $ounces = 0;
+ $service_code = '03';
- if ($pounds < 1) {
- throw new Exception('Weight missing');
+ $packages = '';
+ foreach ($this->shipment->getPackages() as $p) {
+ $packages .= '
+
+ 02
+
+
+
+ IN
+
+ ' . $p->getLength() . '
+ ' . $p->getWidth() . '
+ ' . $p->getHeight() . '
+
+
+
+ LBS
+
+ ' . $p->getWeight() . '
+
+ ';
}
- $service_code = '03';
-
$this->data =
'
@@ -142,48 +155,34 @@ class Rate extends RateAdapter
- ' . Arr::get($shipper, 'postal_code') . '
- ' . Arr::get($shipper, 'country_code') . '
- ' . ((Arr::get($shipper, 'is_residential')) ? '1' : '') . '
+ ' . $this->shipment->getFromPostalCode() . '
+ ' . $this->shipment->getFromCountryCode() . '
+ ' . (($this->shipment->isFromResidential()) ? '1' : '') . '
' . $this->shipper_number . '
- ' . Arr::get($to, 'postal_code') . '
- ' . Arr::get($to, 'country_code') . '
- ' . ((Arr::get($to, 'is_residential')) ? '1' : '') . '
+ ' . $this->shipment->getToPostalCode() . '
+ ' . $this->shipment->getToCountryCode() . '
+ ' . (($this->shipment->isToResidential()) ? '1' : '') . '
- ' . Arr::get($shipper, 'postal_code') . '
- ' . Arr::get($shipper, 'country_code') . '
- ' . ((Arr::get($shipper, 'is_residential')) ? '1' : '') . '
+ ' . $this->shipment->getFromStateProvinceCode() . '
+ ' . $this->shipment->getFromPostalCode() . '
+ ' . $this->shipment->getFromCountryCode() . '
+ ' . (($this->shipment->isFromResidential()) ? '1' : '') . '
' . $service_code . '
-
-
- 02
-
-
-
- IN
-
- ' . Arr::get($dimensions, 'length') . '
- ' . Arr::get($dimensions, 'width') . '
- ' . Arr::get($dimensions, 'height') . '
-
-
-
- LBS
-
- ' . $pounds . '
-
-
+ ' . $packages . '
+
+
+
';
@@ -235,11 +234,13 @@ class Rate extends RateAdapter
continue;
}
- $this->rates[] = array(
- 'code' => $code,
- 'name' => $name,
- 'cost' => (int) ($cost * 100),
- );
+ $quote = new Quote;
+ $quote
+ ->setCarrier('ups')
+ ->setCode($code)
+ ->setName($name)
+ ->setCost((int) $cost * 100);
+ $this->rates[] = $quote;
}
return $this;
diff --git a/src/USPS/Rate.php b/src/USPS/Rate.php
index e9dbc35..fe39462 100644
--- a/src/USPS/Rate.php
+++ b/src/USPS/Rate.php
@@ -3,6 +3,7 @@ namespace pdt256\Shipping\USPS;
use pdt256\Shipping;
use pdt256\Shipping\Arr;
+use pdt256\Shipping\Quote;
use pdt256\Shipping\RateAdapter;
use pdt256\Shipping\RateRequest;
use DOMDocument;
@@ -78,6 +79,10 @@ class Rate extends RateAdapter
$this->password = $options['password'];
}
+ if (isset($options['username'])) {
+ $this->username = $options['username'];
+ }
+
if (isset($options['approved_codes'])) {
$this->approved_codes = $options['approved_codes'];
}
@@ -91,50 +96,54 @@ class Rate extends RateAdapter
protected function prepare()
{
- $to = Arr::get($this->shipment, 'to');
- $shipper = Arr::get($this->shipment, 'from');
- $dimensions = Arr::get($this->shipment, 'dimensions');
- // https://www.usps.com/business/web-tools-apis/rate-calculators-v1-7a.htm
- $pounds = (int) Arr::get($this->shipment, 'weight');
- $ounces = 0;
-
- if ($pounds < 1) {
- throw new Exception('Weight missing');
- }
-
- $size = Arr::get($this->shipment, 'size');
-
- // If user has not specified size, determine it automatically
- // https://www.usps.com/business/web-tools-apis/rate-calculator-api.htm#_Toc378922331
- if ($size === null) {
- // Size is considered large if any dimension is larger than 12 inches
- foreach ($dimensions as $dimension) {
- if ($dimension > 12) {
- $size = 'LARGE';
- break;
- }
- }
- if (!isset($size)) {
+ $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 =
'
-
- ALL
- ' . Arr::get($shipper, 'postal_code') . '
- ' . Arr::get($to, 'postal_code') . '
- ' . $pounds . '
- ' . $ounces . '
- ' . Arr::get($this->shipment, 'container') . '
- ' . $size . '
- ' . Arr::get($dimensions, 'width') . '
- ' . Arr::get($dimensions, 'length') . '
- ' . Arr::get($dimensions, 'height') . '
- ' . 'False' . '
-
+ ' . $packages . '
';
return $this;
@@ -172,6 +181,9 @@ class Rate extends RateAdapter
throw $e;
}
+ /** @var Quote[] $rates */
+ $rates = [];
+
foreach ($postage_list as $postage) {
$code = @$postage->getAttribute('CLASSID');
$cost = @$postage->getElementsByTagName('Rate')->item(0)->nodeValue;
@@ -182,13 +194,24 @@ class Rate extends RateAdapter
continue;
}
- $this->rates[] = array(
- 'code' => $code,
- 'name' => $name,
- 'cost' => (int) ($cost * 100),
- );
+ 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/ShipTest.php b/tests/ShipTest.php
index 700d0ae..f6cb5ee 100644
--- a/tests/ShipTest.php
+++ b/tests/ShipTest.php
@@ -1,5 +1,8 @@
3, // lbs
- 'dimensions' => [
- 'width' => 9,
- 'length' => 9,
- 'height' => 9,
- ],
- 'from' => [
- 'postal_code' => '90401',
- 'country_code' => 'US',
- ],
- 'to' => [
- 'postal_code' => '78703',
- 'country_code' => 'US',
- 'is_residential' => TRUE,
- ],
- ];
+ /** @var Shipment */
+ public $shipment;
public $shipping_options = [
'Standard Shipping' => [
@@ -60,6 +48,27 @@ class ShipTest extends PHPUnit_Framework_TestCase
],
];
+ 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);
@@ -69,10 +78,7 @@ class ShipTest extends PHPUnit_Framework_TestCase
'prod' => FALSE,
'username' => 'XXXX',
'password' => 'XXXX',
- 'shipment' => array_merge($this->shipment, [
- 'size' => 'LARGE',
- 'container' => 'RECTANGULAR',
- ]),
+ 'shipment' => $this->shipment,
'approved_codes' => $approved_codes,
'request_adapter' => new RateRequest\StubUSPS(),
];
@@ -107,9 +113,7 @@ class ShipTest extends PHPUnit_Framework_TestCase
'account_number' => 'XXXX',
'meter_number' => 'XXXX',
'drop_off_type' => 'BUSINESS_SERVICE_CENTER',
- 'shipment' => array_merge($this->shipment, [
- 'packaging_type' => 'YOUR_PACKAGING',
- ]),
+ 'shipment' => $this->shipment,
'approved_codes' => $approved_codes,
'request_adapter' => new RateRequest\StubFedex(),
];
@@ -120,18 +124,23 @@ class ShipTest extends PHPUnit_Framework_TestCase
$usps = new USPS\Rate($this->getUSPSOptions());
$usps_rates = $usps->get_rates();
- $this->assertEquals(json_encode([
- 1 => [
- 'code' => '4',
- 'name' => 'Parcel Post',
- 'cost' => 1001,
- ],
- 0 => [
- 'code' => '1',
- 'name' => 'Priority Mail',
- 'cost' => 1220,
- ],
- ]), json_encode($usps_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()
@@ -139,28 +148,37 @@ class ShipTest extends PHPUnit_Framework_TestCase
$ups = new UPS\Rate($this->getUPSOptions());
$ups_rates = $ups->get_rates();
- $this->assertEquals(json_encode([
- 0 => [
- 'code' => '03',
- 'name' => 'UPS Ground',
- 'cost' => 1910,
- ],
- 1 => [
- 'code' => '02',
- 'name' => 'UPS 2nd Day Air',
- 'cost' => 4923,
- ],
- 2 => [
- 'code' => '13',
- 'name' => 'UPS Next Day Air Saver',
- 'cost' => 8954,
- ],
- 3 => [
- 'code' => '01',
- 'name' => 'UPS Next Day Air',
- 'cost' => 9328,
- ],
- ]), json_encode($ups_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);
+
+ $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()
@@ -168,36 +186,44 @@ class ShipTest extends PHPUnit_Framework_TestCase
$fedex = new Fedex\Rate($this->getFedexOptions());
$fedex_rates = $fedex->get_rates();
- $this->assertEquals(json_encode([
- 3 => [
- 'code' => 'GROUND_HOME_DELIVERY',
- 'name' => 'Ground Home Delivery',
- 'cost' => 1655,
- 'delivery_ts' => NULL,
- 'transit_time' => 'THREE_DAYS',
- ],
- 2 => [
- 'code' => 'FEDEX_EXPRESS_SAVER',
- 'name' => 'Fedex Express Saver',
- 'cost' => 2989,
- 'delivery_ts' => '2014-09-30T20:00:00',
- 'transit_time' => NULL,
- ],
- 1 => [
- 'code' => 'FEDEX_2_DAY',
- 'name' => 'Fedex 2 Day',
- 'cost' => 4072,
- 'delivery_ts' => '2014-09-29T20:00:00',
- 'transit_time' => NULL,
- ],
- 0 => [
- 'code' => 'STANDARD_OVERNIGHT',
- 'name' => 'Standard Overnight',
- 'cost' => 7834,
- 'delivery_ts' => '2014-09-26T20:00:00',
- 'transit_time' => NULL,
- ],
- ]), json_encode($fedex_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()
@@ -216,210 +242,36 @@ class ShipTest extends PHPUnit_Framework_TestCase
$ship = Ship::factory($this->shipping_options);
$display_rates = $ship->get_display_rates($rates);
- $this->assertEquals(json_encode([
+ $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' => [
- 0 => [
- 'code' => '4',
- 'name' => 'Parcel Post',
- 'cost' => 1001,
- 'carrier' => 'usps',
- ],
+ $post,
],
'Two-Day Shipping' => [
- 0 => [
- 'code' => 'FEDEX_2_DAY',
- 'name' => 'Fedex 2 Day',
- 'cost' => 4072,
- 'delivery_ts' => '2014-09-29T20:00:00',
- 'transit_time' => NULL,
- 'carrier' => 'fedex',
- ],
+ $fedex_two_day,
],
'One-Day Shipping' => [
- 0 => [
- 'code' => 'STANDARD_OVERNIGHT',
- 'name' => 'Standard Overnight',
- 'cost' => 7834,
- 'delivery_ts' => '2014-09-26T20:00:00',
- 'transit_time' => NULL,
- 'carrier' => 'fedex',
- ],
+ $overnight,
],
- ]), json_encode($display_rates));
- }
-
- /**
- * @expectedException Exception
- */
- public function testUSPSRateMissingTo()
- {
- $usps_options = $this->getUSPSOptions();
- unset($usps_options['shipment']['to']);
-
- $usps = new USPS\Rate($usps_options);
- $usps_rates = $usps->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testUSPSRateMissingFrom()
- {
- $usps_options = $this->getUSPSOptions();
- unset($usps_options['shipment']['from']);
-
- $usps = new USPS\Rate($usps_options);
- $usps_rates = $usps->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testUSPSRateMissingDimensions()
- {
- $usps_options = $this->getUSPSOptions();
- unset($usps_options['shipment']['dimensions']);
-
- $usps = new USPS\Rate($usps_options);
- $usps_rates = $usps->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testUPSRateMissingTo()
- {
- $ups_options = $this->getUPSOptions();
- unset($ups_options['shipment']['to']);
-
- $ups = new UPS\Rate($ups_options);
- $ups_rates = $ups->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testUPSRateMissingFrom()
- {
- $ups_options = $this->getUPSOptions();
- unset($ups_options['shipment']['from']);
-
- $ups = new UPS\Rate($ups_options);
- $ups_rates = $ups->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testUPSRateMissingDimensions()
- {
- $ups_options = $this->getUPSOptions();
- unset($ups_options['shipment']['dimensions']);
-
- $ups = new UPS\Rate($ups_options);
- $ups_rates = $ups->get_rates();
+ ], $display_rates);
}
-
- /**
- * @expectedException Exception
- */
- public function testFedexRateMissingTo()
- {
- $fedex_options = $this->getFedexOptions();
- unset($fedex_options['shipment']['to']);
-
- $fedex = new Fedex\Rate($fedex_options);
- $fedex_rates = $fedex->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testFedexRateMissingFrom()
- {
- $fedex_options = $this->getFedexOptions();
- unset($fedex_options['shipment']['from']);
-
- $fedex = new Fedex\Rate($fedex_options);
- $fedex_rates = $fedex->get_rates();
- }
-
- /**
- * @expectedException Exception
- */
- public function testFedexRateMissingDimensions()
- {
- $fedex_options = $this->getFedexOptions();
- unset($fedex_options['shipment']['dimensions']);
-
- $fedex = new Fedex\Rate($fedex_options);
- $fedex_rates = $fedex->get_rates();
- }
-
- // // Readme Examples:
- // public function testUSPSReadmeExample()
- // {
- // $usps = new USPS\Rate([
- // 'prod' => FALSE,
- // 'username' => 'XXXX',
- // 'password' => 'XXXX',
- // 'shipment' => array_merge($this->shipment, [
- // 'size' => 'LARGE',
- // 'container' => 'RECTANGULAR',
- // ]),
- // 'approved_codes' => [
- // '1', // 1-3 business days
- // '4', // 2-8 business days
- // ],
- // 'request_adapter' => new RateRequest\StubUSPS(),
- // ]);
- //
- // $usps_rates = $usps->get_rates();
- // var_export($usps_rates);
- // }
- //
- // public function testUPSReadmeExample()
- // {
- // $ups = new UPS\Rate([
- // 'prod' => FALSE,
- // 'shipment' => $this->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(),
- // ]);
- //
- // $ups_rates = $ups->get_rates();
- // var_export($ups_rates);
- // }
- //
- // public function testFedexReadmeExample()
- // {
- // $fedex = new Fedex\Rate([
- // 'prod' => FALSE,
- // 'key' => 'XXXX',
- // 'password' => 'XXXX',
- // 'account_number' => 'XXXX',
- // 'meter_number' => 'XXXX',
- // 'drop_off_type' => 'BUSINESS_SERVICE_CENTER',
- // 'shipment' => array_merge($this->shipment, [
- // 'packaging_type' => 'YOUR_PACKAGING',
- // ]),
- // 'approved_codes' => [
- // '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(),
- // ]);
- //
- // $fedex_rates = $fedex->get_rates();
- // var_export($fedex_rates);
- // }
}