Migrating code to PSR2. Adding optional support for live API calls in unit tests. Adding rounding error bug fix. Adding more tests to get to 85% coverage. Adding phpstorm project. Bumping master for v1.0.x target.
This commit is contained in:
parent
01ddc321ce
commit
ccf447f755
11
.gitignore
vendored
11
.gitignore
vendored
@ -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
|
||||
|
1
.idea/.name
generated
Normal file
1
.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
shipping
|
5
.idea/encodings.xml
generated
Normal file
5
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0" is_locked="false">
|
||||
<option name="myName" value="Project Default" />
|
||||
<option name="myLocal" value="false" />
|
||||
<inspection_tool class="PhpCSValidationInspection" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="CODING_STANDARD" value="PSR2" />
|
||||
<option name="WARNING_HIGHLIGHT_LEVEL_NAME" value="ERROR" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
5
.idea/misc.xml
generated
Normal file
5
.idea/misc.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" />
|
||||
</project>
|
||||
|
9
.idea/modules.xml
generated
Normal file
9
.idea/modules.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/shipping.iml" filepath="$PROJECT_DIR$/.idea/shipping.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
9
.idea/php.xml
generated
Normal file
9
.idea/php.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PhpUnit">
|
||||
<phpunit_settings>
|
||||
<PhpUnitSettings load_method="CUSTOM_LOADER" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" phpunit_phar_path="" />
|
||||
</phpunit_settings>
|
||||
</component>
|
||||
</project>
|
||||
|
5
.idea/scopes/scope_settings.xml
generated
Normal file
5
.idea/scopes/scope_settings.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<state>
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</state>
|
||||
</component>
|
7
.idea/vcs.xml
generated
Normal file
7
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
10
.travis.yml
Normal file
10
.travis.yml
Normal file
@ -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
|
123
README.md
123
README.md
@ -1,9 +1,22 @@
|
||||
## PHP Shipping API
|
||||
|
||||
[](https://packagist.org/packages/pdt256/shipping) [](https://packagist.org/packages/pdt256/shipping) [](https://packagist.org/packages/pdt256/shipping) [](https://packagist.org/packages/pdt256/shipping)
|
||||
[]
|
||||
[](https://travis-ci.org/pdt256/shipping)
|
||||
[](https://packagist.org/packages/pdt256/shipping)
|
||||
[](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.
|
||||
@ -11,7 +24,7 @@ Add the following lines to your ``composer.json`` file.
|
||||
```JSON
|
||||
{
|
||||
"require": {
|
||||
"pdt256/shipping": "dev-master"
|
||||
"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
|
||||
@ -53,22 +71,22 @@ use pdt256\Shipping\RateRequest;
|
||||
|
||||
$ups = new UPS\Rate([
|
||||
'prod' => FALSE,
|
||||
'access_key' => 'XXXX',
|
||||
'user_id' => 'XXXX',
|
||||
'accessKey' => 'XXXX',
|
||||
'userId' => 'XXXX',
|
||||
'password' => 'XXXX',
|
||||
'shipper_number' => 'XXXX',
|
||||
'shipperNumber' => 'XXXX',
|
||||
'shipment' => $shipment,
|
||||
'approved_codes' => [
|
||||
'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
|
||||
],
|
||||
'request_adapter' => new RateRequest\StubUPS(),
|
||||
'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)
|
||||
|
@ -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": {
|
||||
|
16
live_phpunit.sh.example
Executable file
16
live_phpunit.sh.example
Executable file
@ -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
|
@ -3,7 +3,7 @@ namespace pdt256\Shipping;
|
||||
|
||||
class Arr
|
||||
{
|
||||
public static function get($array, $key, $default = NULL)
|
||||
public static function get($array, $key, $default = null)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : $default;
|
||||
}
|
||||
|
@ -12,16 +12,16 @@ 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 $urlDev = 'https://gatewaybeta.fedex.com/web-services/';
|
||||
private $urlProd = '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';
|
||||
private $accountNumber = 'XXX';
|
||||
private $meterNumber = 'XXX';
|
||||
private $dropOffType = 'BUSINESS_SERVICE_CENTER';
|
||||
|
||||
public $approved_codes = [
|
||||
public $approvedCodes = [
|
||||
'PRIORITY_OVERNIGHT',
|
||||
'FEDEX_2_DAY',
|
||||
'FEDEX_EXPRESS_SAVER',
|
||||
@ -29,7 +29,7 @@ class Rate extends RateAdapter
|
||||
'GROUND_HOME_DELIVERY',
|
||||
];
|
||||
|
||||
private $shipping_codes = [
|
||||
private $shippingCodes = [
|
||||
'EUROPE_FIRST_INTERNATIONAL_PRIORITY' => 'Europe First International Priority',
|
||||
'FEDEX_1_DAY_FREIGHT' => 'Fedex 1 Day Freight',
|
||||
'FEDEX_2_DAY' => 'Fedex 2 Day',
|
||||
@ -57,35 +57,14 @@ class Rate extends RateAdapter
|
||||
{
|
||||
parent::__construct($options);
|
||||
|
||||
if (isset($options['key'])) {
|
||||
$this->key = $options['key'];
|
||||
}
|
||||
$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');
|
||||
|
||||
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());
|
||||
}
|
||||
$this->setRequestAdapter(Arr::get($options, 'requestAdapter', new RateRequest\Post()));
|
||||
}
|
||||
|
||||
protected function prepare()
|
||||
@ -100,90 +79,99 @@ 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
|
||||
|
||||
// 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) {
|
||||
foreach ($this->shipment->getPackages() as $package) {
|
||||
$sequence_number++;
|
||||
|
||||
$packages .= '<RequestedPackageLineItems>
|
||||
<SequenceNumber>' . $sequence_number . '</SequenceNumber>
|
||||
<GroupPackageCount>1</GroupPackageCount>
|
||||
<Weight>
|
||||
<Units>LB</Units>
|
||||
<Value>' . $p->getWeight() . '</Value>
|
||||
</Weight>
|
||||
<Dimensions>
|
||||
<Length>' . $p->getLength() . '</Length>
|
||||
<Width>' . $p->getWidth() . '</Width>
|
||||
<Height>' . $p->getHeight() . '</Height>
|
||||
<Units>IN</Units>
|
||||
</Dimensions>
|
||||
</RequestedPackageLineItems>';
|
||||
$packages .=
|
||||
'<RequestedPackageLineItems>' .
|
||||
'<SequenceNumber>' . $sequence_number . '</SequenceNumber>' .
|
||||
'<GroupPackageCount>1</GroupPackageCount>' .
|
||||
'<Weight>' .
|
||||
'<Units>LB</Units>' .
|
||||
'<Value>' . $package->getWeight() . '</Value>' .
|
||||
'</Weight>' .
|
||||
'<Dimensions>' .
|
||||
'<Length>' . $package->getLength() . '</Length>' .
|
||||
'<Width>' . $package->getWidth() . '</Width>' .
|
||||
'<Height>' . $package->getHeight() . '</Height>' .
|
||||
'<Units>IN</Units>' .
|
||||
'</Dimensions>' .
|
||||
'</RequestedPackageLineItems>';
|
||||
}
|
||||
|
||||
$this->data =
|
||||
'<?xml version="1.0"?>
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://fedex.com/ws/rate/v13">
|
||||
<SOAP-ENV:Body>
|
||||
<RateRequest>
|
||||
<WebAuthenticationDetail>
|
||||
<UserCredential>
|
||||
<Key>' . $this->key . '</Key>
|
||||
<Password>' . $this->password . '</Password>
|
||||
</UserCredential>
|
||||
</WebAuthenticationDetail>
|
||||
<ClientDetail>
|
||||
<AccountNumber>' . $this->account_number . '</AccountNumber>
|
||||
<MeterNumber>' . $this->meter_number . '</MeterNumber>
|
||||
</ClientDetail>
|
||||
<Version>
|
||||
<ServiceId>crs</ServiceId>
|
||||
<Major>13</Major>
|
||||
<Intermediate>0</Intermediate>
|
||||
<Minor>0</Minor>
|
||||
</Version>
|
||||
<ReturnTransitAndCommit>true</ReturnTransitAndCommit>
|
||||
<RequestedShipment>
|
||||
<ShipTimestamp>' . date('c') . '</ShipTimestamp>
|
||||
<DropoffType>' . $this->drop_off_type . '</DropoffType>
|
||||
<PackagingType>YOUR_PACKAGING</PackagingType>
|
||||
<Shipper>
|
||||
<Address>
|
||||
<PostalCode>' . $this->shipment->getFromPostalCode() . '</PostalCode>
|
||||
<CountryCode>' . $this->shipment->getFromCountryCode() . '</CountryCode>
|
||||
' . (($this->shipment->isFromResidential()) ? '<Residential>1</Residential>' : '') . '
|
||||
</Address>
|
||||
</Shipper>
|
||||
<Recipient>
|
||||
<Address>
|
||||
<PostalCode>' . $this->shipment->getToPostalCode() . '</PostalCode>
|
||||
<CountryCode>' . $this->shipment->getToCountryCode() . '</CountryCode>
|
||||
' . (($this->shipment->isToResidential()) ? '<Residential>1</Residential>' : '') . '
|
||||
</Address>
|
||||
</Recipient>
|
||||
<RateRequestTypes>LIST</RateRequestTypes>
|
||||
<PackageCount>' . $this->shipment->packageCount() . '</PackageCount>
|
||||
' . $packages . '
|
||||
</RequestedShipment>
|
||||
</RateRequest>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>';
|
||||
$this->data = '<?xml version="1.0"?>' .
|
||||
'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" ' .
|
||||
'xmlns="http://fedex.com/ws/rate/v13">' .
|
||||
'<SOAP-ENV:Body>' .
|
||||
'<RateRequest>' .
|
||||
'<WebAuthenticationDetail>' .
|
||||
'<UserCredential>' .
|
||||
'<Key>' . $this->key . '</Key>' .
|
||||
'<Password>' . $this->password . '</Password>' .
|
||||
'</UserCredential>' .
|
||||
'</WebAuthenticationDetail>' .
|
||||
'<ClientDetail>' .
|
||||
'<AccountNumber>' . $this->accountNumber . '</AccountNumber>' .
|
||||
'<MeterNumber>' . $this->meterNumber . '</MeterNumber>' .
|
||||
'</ClientDetail>' .
|
||||
'<Version>' .
|
||||
'<ServiceId>crs</ServiceId>' .
|
||||
'<Major>13</Major>' .
|
||||
'<Intermediate>0</Intermediate>' .
|
||||
'<Minor>0</Minor>' .
|
||||
'</Version>' .
|
||||
'<ReturnTransitAndCommit>true</ReturnTransitAndCommit>' .
|
||||
'<RequestedShipment>' .
|
||||
'<ShipTimestamp>' . date('c') . '</ShipTimestamp>' .
|
||||
'<DropoffType>' . $this->dropOffType . '</DropoffType>' .
|
||||
'<PackagingType>YOUR_PACKAGING</PackagingType>' .
|
||||
'<Shipper>' .
|
||||
'<Address>' .
|
||||
'<PostalCode>' . $this->shipment->getFromPostalCode() . '</PostalCode>' .
|
||||
'<CountryCode>' . $this->shipment->getFromCountryCode() . '</CountryCode>' .
|
||||
(
|
||||
$this->shipment->getFromIsResidential() ?
|
||||
'<Residential>1</Residential>' :
|
||||
''
|
||||
) .
|
||||
'</Address>' .
|
||||
'</Shipper>' .
|
||||
'<Recipient>' .
|
||||
'<Address>' .
|
||||
'<PostalCode>' . $this->shipment->getToPostalCode() . '</PostalCode>' .
|
||||
'<CountryCode>' . $this->shipment->getToCountryCode() . '</CountryCode>' .
|
||||
(
|
||||
$this->shipment->getToIsResidential() ?
|
||||
'<Residential>1</Residential>' :
|
||||
''
|
||||
) .
|
||||
'</Address>' .
|
||||
'</Recipient>' .
|
||||
'<RateRequestTypes>LIST</RateRequestTypes>' .
|
||||
'<PackageCount>' . $this->shipment->packageCount() . '</PackageCount>' .
|
||||
$packages .
|
||||
'</RequestedShipment>' .
|
||||
'</RateRequest>' .
|
||||
'</SOAP-ENV:Body>' .
|
||||
'</SOAP-ENV:Envelope>';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function execute()
|
||||
{
|
||||
if ($this->is_prod) {
|
||||
$url = $this->url_prod;
|
||||
if ($this->isProduction) {
|
||||
$url = $this->urlProd;
|
||||
} else {
|
||||
$url = $this->url_dev;
|
||||
$url = $this->urlDev;
|
||||
}
|
||||
|
||||
$this->response = $this->rate_request->execute($url, $this->data);
|
||||
$this->response = $this->rateRequest->execute($url, $this->data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -207,11 +195,11 @@ class Rate extends RateAdapter
|
||||
foreach ($rate_reply as $rate) {
|
||||
$code = $rate->getElementsByTagName('ServiceType')->item(0)->nodeValue;
|
||||
|
||||
if ( ! empty($this->approved_codes) AND ! in_array($code, $this->approved_codes)) {
|
||||
if (! empty($this->approvedCodes) && ! in_array($code, $this->approvedCodes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = Arr::get($this->shipping_codes, $code);
|
||||
$name = Arr::get($this->shippingCodes, $code);
|
||||
|
||||
$delivery_ts = @$rate->getElementsByTagName('DeliveryTimestamp')->item(0)->nodeValue;
|
||||
$transit_time = @$rate->getElementsByTagName('TransitTime')->item(0)->nodeValue;
|
||||
@ -227,7 +215,7 @@ class Rate extends RateAdapter
|
||||
->setCarrier('fedex')
|
||||
->setCode($code)
|
||||
->setName($name)
|
||||
->setCost((int) $cost * 100)
|
||||
->setCost((int) ($cost * 100))
|
||||
->setTransitTime($transit_time);
|
||||
if ($delivery_ts) {
|
||||
$quote->setDeliveryEstimate(new DateTime($delivery_ts));
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -5,48 +5,57 @@ use Exception;
|
||||
|
||||
abstract class RateAdapter
|
||||
{
|
||||
protected $is_prod = FALSE;
|
||||
protected $isProduction;
|
||||
|
||||
/** @var Shipment */
|
||||
protected $shipment;
|
||||
protected $data;
|
||||
protected $response;
|
||||
protected $rates = [];
|
||||
protected $rates;
|
||||
|
||||
protected $rate_request;
|
||||
/** @var @var RateRequest\Adapter */
|
||||
protected $rateRequest;
|
||||
|
||||
abstract protected function prepare(); // Prepare XML
|
||||
abstract protected function execute(); // Curl Request
|
||||
abstract protected function process(); // Convert to shipping rates array
|
||||
/**
|
||||
* 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 = [])
|
||||
{
|
||||
if (isset($options['prod'])) {
|
||||
$this->is_prod = (bool) $options['prod'];
|
||||
$this->rates = [];
|
||||
|
||||
$this->isProduction = (bool) Arr::get($options, 'prod', false);
|
||||
$this->shipment = Arr::get($options, 'shipment');
|
||||
}
|
||||
|
||||
if (isset($options['shipment'])) {
|
||||
$this->shipment = $options['shipment'];
|
||||
}
|
||||
}
|
||||
|
||||
public function set_request_adapter(RateRequest\Adapter $rate_request)
|
||||
public function setRequestAdapter(RateRequest\Adapter $rateRequest)
|
||||
{
|
||||
$this->rate_request = $rate_request;
|
||||
$this->rateRequest = $rateRequest;
|
||||
}
|
||||
|
||||
public function get_rates()
|
||||
public function getRates()
|
||||
{
|
||||
$this
|
||||
->prepare()
|
||||
->execute()
|
||||
->process()
|
||||
->sort_by_cost();
|
||||
->sortByCost();
|
||||
|
||||
return array_values($this->rates);
|
||||
}
|
||||
|
||||
protected function sort_by_cost()
|
||||
protected function sortByCost()
|
||||
{
|
||||
uasort($this->rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());'));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
3440
src/RateRequest/FedexResponse.xml
Normal file
3440
src/RateRequest/FedexResponse.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,17 +3,18 @@ namespace pdt256\Shipping\RateRequest;
|
||||
|
||||
class Get extends Adapter
|
||||
{
|
||||
public function execute($url, $data = NULL)
|
||||
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_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);
|
||||
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) {
|
||||
|
@ -3,18 +3,19 @@ namespace pdt256\Shipping\RateRequest;
|
||||
|
||||
class Post extends Adapter
|
||||
{
|
||||
public function execute($url, $data = NULL)
|
||||
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_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_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);
|
||||
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));
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace pdt256\Shipping\RateRequest;
|
||||
|
||||
|
||||
class RequestException extends \Exception {}
|
||||
class RequestException extends \Exception
|
||||
{
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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;
|
||||
$this->artificialDelay = $artificial_delay;
|
||||
}
|
||||
|
||||
public function execute($url, $data = NULL)
|
||||
public function execute($url, $data = null)
|
||||
{
|
||||
if ($this->artificial_delay > 0) {
|
||||
sleep($this->artificial_delay);
|
||||
if ($this->artificialDelay > 0) {
|
||||
sleep($this->artificialDelay);
|
||||
}
|
||||
|
||||
$response = '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RateV4Response><Package ID="1"><ZipOrigination>90401</ZipOrigination><ZipDestination>76667</ZipDestination><Pounds>3</Pounds><Ounces>0</Ounces><Size>LARGE</Size><Machinable>FALSE</Machinable><Zone>6</Zone><Postage CLASSID="3"><MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;</MailService><Rate>42.25</Rate></Postage><Postage CLASSID="2"><MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup</MailService><Rate>42.25</Rate></Postage><Postage CLASSID="1"><MailService>Priority Mail 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;</MailService><Rate>12.20</Rate></Postage><Postage CLASSID="4"><MailService>Standard Post&lt;sup&gt;&#174;&lt;/sup&gt;</MailService><Rate>10.01</Rate></Postage><Postage CLASSID="6"><MailService>Media Mail Parcel</MailService><Rate>3.65</Rate></Postage><Postage CLASSID="7"><MailService>Library Mail Parcel</MailService><Rate>3.48</Rate></Postage></Package></RateV4Response>';
|
||||
|
||||
return $response;
|
||||
return file_get_contents(__DIR__ . '/USPSResponse.xml');
|
||||
}
|
||||
}
|
||||
|
247
src/RateRequest/UPSResponse.xml
Normal file
247
src/RateRequest/UPSResponse.xml
Normal file
@ -0,0 +1,247 @@
|
||||
<?xml version="1.0"?>
|
||||
<RatingServiceSelectionResponse>
|
||||
<Response>
|
||||
<ResponseStatusCode>1</ResponseStatusCode>
|
||||
<ResponseStatusDescription>Success</ResponseStatusDescription>
|
||||
</Response>
|
||||
<RatedShipment>
|
||||
<Service>
|
||||
<Code>03</Code>
|
||||
</Service>
|
||||
<RatedShipmentWarning>Your invoice may vary from the displayed reference rates</RatedShipmentWarning>
|
||||
<RatedShipmentWarning>Missing / Invalid Shipper Number. Returned rates are Retail Rates.</RatedShipmentWarning>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>3.0</Weight>
|
||||
</BillingWeight>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>19.10</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>19.10</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<GuaranteedDaysToDelivery/>
|
||||
<ScheduledDeliveryTime/>
|
||||
<RatedPackage>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>19.10</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>19.10</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<Weight>3.0</Weight>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>3.0</Weight>
|
||||
</BillingWeight>
|
||||
</RatedPackage>
|
||||
</RatedShipment>
|
||||
<RatedShipment>
|
||||
<Service>
|
||||
<Code>12</Code>
|
||||
</Service>
|
||||
<RatedShipmentWarning>Your invoice may vary from the displayed reference rates</RatedShipmentWarning>
|
||||
<RatedShipmentWarning>Missing / Invalid Shipper Number. Returned rates are Retail Rates.</RatedShipmentWarning>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>37.18</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>37.18</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<GuaranteedDaysToDelivery>3</GuaranteedDaysToDelivery>
|
||||
<ScheduledDeliveryTime/>
|
||||
<RatedPackage>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>37.18</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>37.18</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<Weight>3.0</Weight>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
</RatedPackage>
|
||||
</RatedShipment>
|
||||
<RatedShipment>
|
||||
<Service>
|
||||
<Code>02</Code>
|
||||
</Service>
|
||||
<RatedShipmentWarning>Your invoice may vary from the displayed reference rates</RatedShipmentWarning>
|
||||
<RatedShipmentWarning>Missing / Invalid Shipper Number. Returned rates are Retail Rates.</RatedShipmentWarning>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>49.23</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>49.23</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<GuaranteedDaysToDelivery>2</GuaranteedDaysToDelivery>
|
||||
<ScheduledDeliveryTime/>
|
||||
<RatedPackage>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>49.23</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>49.23</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<Weight>3.0</Weight>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
</RatedPackage>
|
||||
</RatedShipment>
|
||||
<RatedShipment>
|
||||
<Service>
|
||||
<Code>13</Code>
|
||||
</Service>
|
||||
<RatedShipmentWarning>Your invoice may vary from the displayed reference rates</RatedShipmentWarning>
|
||||
<RatedShipmentWarning>Missing / Invalid Shipper Number. Returned rates are Retail Rates.</RatedShipmentWarning>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>89.54</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>89.54</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<GuaranteedDaysToDelivery>1</GuaranteedDaysToDelivery>
|
||||
<ScheduledDeliveryTime/>
|
||||
<RatedPackage>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>89.54</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>89.54</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<Weight>3.0</Weight>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
</RatedPackage>
|
||||
</RatedShipment>
|
||||
<RatedShipment>
|
||||
<Service>
|
||||
<Code>01</Code>
|
||||
</Service>
|
||||
<RatedShipmentWarning>Your invoice may vary from the displayed reference rates</RatedShipmentWarning>
|
||||
<RatedShipmentWarning>Missing / Invalid Shipper Number. Returned rates are Retail Rates.</RatedShipmentWarning>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>93.28</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>93.28</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<GuaranteedDaysToDelivery>1</GuaranteedDaysToDelivery>
|
||||
<ScheduledDeliveryTime>12:00 Noon</ScheduledDeliveryTime>
|
||||
<RatedPackage>
|
||||
<TransportationCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>93.28</MonetaryValue>
|
||||
</TransportationCharges>
|
||||
<ServiceOptionsCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>0.00</MonetaryValue>
|
||||
</ServiceOptionsCharges>
|
||||
<TotalCharges>
|
||||
<CurrencyCode>USD</CurrencyCode>
|
||||
<MonetaryValue>93.28</MonetaryValue>
|
||||
</TotalCharges>
|
||||
<Weight>3.0</Weight>
|
||||
<BillingWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>5.0</Weight>
|
||||
</BillingWeight>
|
||||
</RatedPackage>
|
||||
</RatedShipment>
|
||||
</RatingServiceSelectionResponse>
|
37
src/RateRequest/USPSResponse.xml
Normal file
37
src/RateRequest/USPSResponse.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RateV4Response>
|
||||
<Package ID="1">
|
||||
<ZipOrigination>90401</ZipOrigination>
|
||||
<ZipDestination>76667</ZipDestination>
|
||||
<Pounds>3</Pounds>
|
||||
<Ounces>0</Ounces>
|
||||
<Size>LARGE</Size>
|
||||
<Machinable>FALSE</Machinable>
|
||||
<Zone>6</Zone>
|
||||
<Postage CLASSID="3">
|
||||
<MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;</MailService>
|
||||
<Rate>42.25</Rate>
|
||||
</Postage>
|
||||
<Postage CLASSID="2">
|
||||
<MailService>Priority Mail Express 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt; Hold For Pickup
|
||||
</MailService>
|
||||
<Rate>42.25</Rate>
|
||||
</Postage>
|
||||
<Postage CLASSID="1">
|
||||
<MailService>Priority Mail 2-Day&lt;sup&gt;&#8482;&lt;/sup&gt;</MailService>
|
||||
<Rate>12.20</Rate>
|
||||
</Postage>
|
||||
<Postage CLASSID="4">
|
||||
<MailService>Standard Post&lt;sup&gt;&#174;&lt;/sup&gt;</MailService>
|
||||
<Rate>10.01</Rate>
|
||||
</Postage>
|
||||
<Postage CLASSID="6">
|
||||
<MailService>Media Mail Parcel</MailService>
|
||||
<Rate>3.65</Rate>
|
||||
</Postage>
|
||||
<Postage CLASSID="7">
|
||||
<MailService>Library Mail Parcel</MailService>
|
||||
<Rate>3.48</Rate>
|
||||
</Postage>
|
||||
</Package>
|
||||
</RateV4Response>
|
34
src/Ship.php
34
src/Ship.php
@ -49,37 +49,41 @@ class Ship
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function get_approved_codes($carrier = NULL) {
|
||||
$approved_codes = [];
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getApprovedCodes($carrier = null)
|
||||
{
|
||||
$approvedCodes = [];
|
||||
|
||||
// Build approved_codes
|
||||
// Build approvedCodes
|
||||
foreach ($this->shipping_options as $shipping_group => $row) {
|
||||
|
||||
foreach ($row as $_carrier => $row2) {
|
||||
if ( ! isset($approved_codes[$_carrier])) {
|
||||
$approved_codes[$_carrier] = [];
|
||||
if (!isset($approvedCodes[$_carrier])) {
|
||||
$approvedCodes[$_carrier] = [];
|
||||
}
|
||||
|
||||
foreach ($row2 as $code => $display) {
|
||||
$approved_codes[$_carrier][] = $code;
|
||||
$approvedCodes[$_carrier][] = $code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($carrier !== NULL AND isset($approved_codes[$carrier])) {
|
||||
return $approved_codes[$carrier];
|
||||
if ($carrier !== null && isset($approvedCodes[$carrier])) {
|
||||
return $approvedCodes[$carrier];
|
||||
}
|
||||
|
||||
return $approved_codes;
|
||||
return $approvedCodes;
|
||||
}
|
||||
|
||||
public function get_display_rates($rates)
|
||||
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;
|
||||
$cheapest_row = null;
|
||||
|
||||
foreach ($row as $carrier => $row2) {
|
||||
$group_codes = array_keys($row2);
|
||||
@ -91,7 +95,7 @@ class Ship
|
||||
if (in_array($row3->getCode(), $group_codes)) {
|
||||
$row3->setCarrier($carrier);
|
||||
|
||||
if ($cheapest_row === NULL) {
|
||||
if ($cheapest_row === null) {
|
||||
$cheapest_row = $row3;
|
||||
} else {
|
||||
if ($row3->getCost() < $cheapest_row->getCost()) {
|
||||
@ -112,7 +116,7 @@ class Ship
|
||||
return $display_rates;
|
||||
}
|
||||
|
||||
public function get_all_display_rates($rates)
|
||||
public function getAllDisplayRates($rates)
|
||||
{
|
||||
// Build output array listing all group options
|
||||
$display_rates = [];
|
||||
@ -134,13 +138,13 @@ class Ship
|
||||
}
|
||||
}
|
||||
|
||||
$this->sort_by_cost($display_rates[$shipping_group]);
|
||||
$this->sortByCost($display_rates[$shipping_group]);
|
||||
}
|
||||
|
||||
return $display_rates;
|
||||
}
|
||||
|
||||
protected function sort_by_cost( & $rates)
|
||||
protected function sortByCost(& $rates)
|
||||
{
|
||||
uasort($rates, create_function('$a, $b', 'return ($a->getCost() > $b->getCost());'));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
221
src/UPS/Rate.php
221
src/UPS/Rate.php
@ -11,20 +11,20 @@ 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 $urlDev = 'https://wwwcie.ups.com/ups.app/xml/Rate';
|
||||
private $urlProd = 'https://www.ups.com/ups.app/xml/Rate';
|
||||
|
||||
private $access_key = 'XXX';
|
||||
private $user_id = 'XXX';
|
||||
private $accessKey = 'XXX';
|
||||
private $userId = 'XXX';
|
||||
private $password = 'XXX';
|
||||
private $shipper_number = 'XXX';
|
||||
private $shipperNumber = 'XXX';
|
||||
|
||||
public $approved_codes = [
|
||||
public $approvedCodes = [
|
||||
'03',
|
||||
'12',
|
||||
];
|
||||
|
||||
private $shipping_codes = [
|
||||
private $shippingCodes = [
|
||||
'US' => [ // United States
|
||||
'01' => 'UPS Next Day Air',
|
||||
'02' => 'UPS 2nd Day Air',
|
||||
@ -86,118 +86,120 @@ class Rate extends RateAdapter
|
||||
{
|
||||
parent::__construct($options);
|
||||
|
||||
if (isset($options['access_key'])) {
|
||||
$this->access_key = $options['access_key'];
|
||||
}
|
||||
$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');
|
||||
|
||||
if (isset($options['user_id'])) {
|
||||
$this->user_id = $options['user_id'];
|
||||
}
|
||||
$this->setRequestAdapter(Arr::get($options, 'requestAdapter', new RateRequest\Post()));
|
||||
|
||||
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 .= '<Package>
|
||||
<PackagingType>
|
||||
<Code>02</Code>
|
||||
</PackagingType>
|
||||
<Dimensions>
|
||||
<UnitOfMeasurement>
|
||||
<Code>IN</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Length>' . $p->getLength() . '</Length>
|
||||
<Width>' . $p->getWidth() . '</Width>
|
||||
<Height>' . $p->getHeight() . '</Height>
|
||||
</Dimensions>
|
||||
<PackageWeight>
|
||||
<UnitOfMeasurement>
|
||||
<Code>LBS</Code>
|
||||
</UnitOfMeasurement>
|
||||
<Weight>' . $p->getWeight() . '</Weight>
|
||||
</PackageWeight>
|
||||
</Package>';
|
||||
}
|
||||
|
||||
$this->data =
|
||||
'<?xml version="1.0"?>
|
||||
<AccessRequest xml:lang="en-US">
|
||||
<AccessLicenseNumber>' . $this->access_key . '</AccessLicenseNumber>
|
||||
<UserId>' . $this->user_id . '</UserId>
|
||||
<Password>' . $this->password . '</Password>
|
||||
</AccessRequest>
|
||||
<RatingServiceSelectionRequest xml:lang="en-US">
|
||||
<Request>
|
||||
<RequestAction>Rate</RequestAction>
|
||||
<RequestOption>shop</RequestOption>
|
||||
</Request>
|
||||
<Shipment>
|
||||
<Shipper>
|
||||
<Address>
|
||||
<PostalCode>' . $this->shipment->getFromPostalCode() . '</PostalCode>
|
||||
<CountryCode>' . $this->shipment->getFromCountryCode() . '</CountryCode>
|
||||
' . (($this->shipment->isFromResidential()) ? '<ResidentialAddressIndicator>1</ResidentialAddressIndicator>' : '') . '
|
||||
</Address>
|
||||
<ShipperNumber>' . $this->shipper_number . '</ShipperNumber>
|
||||
</Shipper>
|
||||
<ShipTo>
|
||||
<Address>
|
||||
<PostalCode>' . $this->shipment->getToPostalCode() . '</PostalCode>
|
||||
<CountryCode>' . $this->shipment->getToCountryCode() . '</CountryCode>
|
||||
' . (($this->shipment->isToResidential()) ? '<ResidentialAddressIndicator>1</ResidentialAddressIndicator>' : '') . '
|
||||
</Address>
|
||||
</ShipTo>
|
||||
<ShipFrom>
|
||||
<Address>
|
||||
<StateProvinceCode>' . $this->shipment->getFromStateProvinceCode() . '</StateProvinceCode>
|
||||
<PostalCode>' . $this->shipment->getFromPostalCode() . '</PostalCode>
|
||||
<CountryCode>' . $this->shipment->getFromCountryCode() . '</CountryCode>
|
||||
' . (($this->shipment->isFromResidential()) ? '<ResidentialAddressIndicator>1</ResidentialAddressIndicator>' : '') . '
|
||||
</Address>
|
||||
</ShipFrom>
|
||||
<Service>
|
||||
<Code>' . $service_code . '</Code>
|
||||
</Service>
|
||||
' . $packages . '
|
||||
<RateInformation>
|
||||
<NegotiatedRatesIndicator/>
|
||||
</RateInformation>
|
||||
</Shipment>
|
||||
</RatingServiceSelectionRequest>';
|
||||
$this->data = '<?xml version="1.0"?>' . "\n" .
|
||||
'<AccessRequest xml:lang="en-US">' .
|
||||
'<AccessLicenseNumber>' . $this->accessKey . '</AccessLicenseNumber>'.
|
||||
'<UserId>' . $this->userId . '</UserId>' .
|
||||
'<Password>' . $this->password . '</Password>' .
|
||||
'</AccessRequest>' .
|
||||
'<RatingServiceSelectionRequest xml:lang="en-US">' .
|
||||
'<Request>' .
|
||||
'<RequestAction>Rate</RequestAction>' .
|
||||
'<RequestOption>shop</RequestOption>' .
|
||||
'</Request>' .
|
||||
'<Shipment>' .
|
||||
'<Shipper>' .
|
||||
'<Address>' .
|
||||
'<PostalCode>' . $this->shipment->getFromPostalCode() . '</PostalCode>' .
|
||||
'<CountryCode>' . $this->shipment->getFromCountryCode() . '</CountryCode>' .
|
||||
(
|
||||
$this->shipment->getFromIsResidential() ?
|
||||
'<ResidentialAddressIndicator>1</ResidentialAddressIndicator>' :
|
||||
''
|
||||
) .
|
||||
'</Address>' .
|
||||
'<ShipperNumber>' . $this->shipperNumber . '</ShipperNumber>' .
|
||||
'</Shipper>' .
|
||||
'<ShipTo>' .
|
||||
'<Address>' .
|
||||
'<PostalCode>' . $this->shipment->getToPostalCode() . '</PostalCode>' .
|
||||
'<CountryCode>' . $this->shipment->getToCountryCode() . '</CountryCode>' .
|
||||
(
|
||||
$this->shipment->getToIsResidential() ?
|
||||
'<ResidentialAddressIndicator>1</ResidentialAddressIndicator>' :
|
||||
''
|
||||
) .
|
||||
'</Address>' .
|
||||
'</ShipTo>' .
|
||||
'<ShipFrom>' .
|
||||
'<Address>' .
|
||||
'<StateProvinceCode>' .
|
||||
$this->shipment->getFromStateProvinceCode() .
|
||||
'</StateProvinceCode>' .
|
||||
'<PostalCode>' . $this->shipment->getFromPostalCode() . '</PostalCode>' .
|
||||
'<CountryCode>' . $this->shipment->getFromCountryCode() . '</CountryCode>' .
|
||||
(
|
||||
$this->shipment->getFromIsResidential() ?
|
||||
'<ResidentialAddressIndicator>1</ResidentialAddressIndicator>' :
|
||||
''
|
||||
) .
|
||||
'</Address>' .
|
||||
'</ShipFrom>' .
|
||||
'<Service>' .
|
||||
'<Code>' . $service_code . '</Code>' .
|
||||
'</Service>' .
|
||||
$this->getPackagesXmlString() .
|
||||
'<RateInformation>' .
|
||||
'<NegotiatedRatesIndicator/>' .
|
||||
'</RateInformation>' .
|
||||
'</Shipment>' .
|
||||
'</RatingServiceSelectionRequest>';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function execute()
|
||||
private function getPackagesXmlString()
|
||||
{
|
||||
if ($this->is_prod) {
|
||||
$url = $this->url_prod;
|
||||
} else {
|
||||
$url = $this->url_dev;
|
||||
$packages = '';
|
||||
foreach ($this->shipment->getPackages() as $p) {
|
||||
$packages .=
|
||||
'<Package>' .
|
||||
'<PackagingType>' .
|
||||
'<Code>02</Code>' .
|
||||
'</PackagingType>' .
|
||||
'<Dimensions>' .
|
||||
'<UnitOfMeasurement>' .
|
||||
'<Code>IN</Code>' .
|
||||
'</UnitOfMeasurement>' .
|
||||
'<Length>' . $p->getLength() . '</Length>' .
|
||||
'<Width>' . $p->getWidth() . '</Width>' .
|
||||
'<Height>' . $p->getHeight() . '</Height>' .
|
||||
'</Dimensions>' .
|
||||
'<PackageWeight>' .
|
||||
'<UnitOfMeasurement>' .
|
||||
'<Code>LBS</Code>' .
|
||||
'</UnitOfMeasurement>' .
|
||||
'<Weight>' . $p->getWeight() . '</Weight>' .
|
||||
'</PackageWeight>' .
|
||||
'</Package>';
|
||||
}
|
||||
|
||||
$this->response = $this->rate_request->execute($url, $this->data);
|
||||
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;
|
||||
}
|
||||
@ -208,14 +210,13 @@ class Rate extends RateAdapter
|
||||
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$dom->loadXml($this->response);
|
||||
|
||||
$rate_list = @$dom->getElementsByTagName('RatedShipment');
|
||||
$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();
|
||||
echo $this->response;
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@ -224,13 +225,13 @@ class Rate extends RateAdapter
|
||||
->getElementsByTagName('Service')->item(0)
|
||||
->getElementsByTagName('Code')->item(0)->nodeValue;
|
||||
|
||||
$name = Arr::get($this->shipping_codes['US'], $code);
|
||||
$name = Arr::get($this->shippingCodes['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)) {
|
||||
if (! empty($this->approvedCodes) && ! in_array($code, $this->approvedCodes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -239,7 +240,7 @@ class Rate extends RateAdapter
|
||||
->setCarrier('ups')
|
||||
->setCode($code)
|
||||
->setName($name)
|
||||
->setCost((int) $cost * 100);
|
||||
->setCost($cost * 100);
|
||||
$this->rates[] = $quote;
|
||||
}
|
||||
|
||||
|
@ -11,13 +11,13 @@ 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 $urlDev = 'http://production.shippingapis.com/ShippingAPI.dll';
|
||||
private $urlProd = 'http://production.shippingapis.com/ShippingAPI.dll';
|
||||
|
||||
private $username = 'XXX';
|
||||
private $password = 'XXX';
|
||||
|
||||
public $approved_codes = [
|
||||
public $approvedCodes = [
|
||||
'1',
|
||||
'4',
|
||||
];
|
||||
@ -71,32 +71,14 @@ class Rate extends RateAdapter
|
||||
{
|
||||
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());
|
||||
}
|
||||
$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) {
|
||||
@ -104,17 +86,17 @@ class Rate extends RateAdapter
|
||||
|
||||
/**
|
||||
* 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: <Size>REGULAR</Size>
|
||||
string
|
||||
whiteSpace=collapse
|
||||
enumeration=LARGE
|
||||
enumeration=REGULAR
|
||||
* required once
|
||||
* Defined as follows:
|
||||
*
|
||||
* REGULAR: Package dimensions are 12’’ or less;
|
||||
* LARGE: Any package dimension is larger than 12’’.
|
||||
*
|
||||
* For example: <Size>REGULAR</Size>
|
||||
* string
|
||||
* whiteSpace=collapse
|
||||
* enumeration=LARGE
|
||||
* enumeration=REGULAR
|
||||
|
||||
*/
|
||||
if ($p->getWidth() > 12 or $p->getLength() > 12 or $p->getHeight() > 12) {
|
||||
@ -125,41 +107,42 @@ class Rate extends RateAdapter
|
||||
$container = 'VARIABLE';
|
||||
}
|
||||
|
||||
$packages .= '<Package ID="' . $sequence_number .'">
|
||||
<Service>ALL</Service>
|
||||
<ZipOrigination>' . $this->shipment->getFromPostalCode() . '</ZipOrigination>
|
||||
<ZipDestination>' . $this->shipment->getToPostalCode() . '</ZipDestination>
|
||||
<Pounds>' . $p->getWeight() . '</Pounds>
|
||||
<Ounces>0</Ounces>
|
||||
<Container>' . $container . '</Container>
|
||||
<Size>' . $size . '</Size>
|
||||
<Width>' . $p->getWidth() . '</Width>
|
||||
<Length>' . $p->getLength() . '</Length>
|
||||
<Height>' . $p->getHeight() . '</Height>
|
||||
<Machinable>' . 'False' . '</Machinable>
|
||||
</Package>';
|
||||
$packages .=
|
||||
'<Package ID="' . $sequence_number . '">' .
|
||||
'<Service>ALL</Service>' .
|
||||
'<ZipOrigination>' . $this->shipment->getFromPostalCode() . '</ZipOrigination>' .
|
||||
'<ZipDestination>' . $this->shipment->getToPostalCode() . '</ZipDestination>' .
|
||||
'<Pounds>' . $p->getWeight() . '</Pounds>' .
|
||||
'<Ounces>0</Ounces>' .
|
||||
'<Container>' . $container . '</Container>' .
|
||||
'<Size>' . $size . '</Size>' .
|
||||
'<Width>' . $p->getWidth() . '</Width>' .
|
||||
'<Length>' . $p->getLength() . '</Length>' .
|
||||
'<Height>' . $p->getHeight() . '</Height>' .
|
||||
'<Machinable>' . 'False' . '</Machinable>' .
|
||||
'</Package>';
|
||||
}
|
||||
|
||||
$this->data =
|
||||
'<RateV4Request USERID="' . $this->username . '">
|
||||
<Revision/>
|
||||
' . $packages . '
|
||||
</RateV4Request>';
|
||||
'<RateV4Request USERID="' . $this->username . '">' .
|
||||
'<Revision/>' .
|
||||
$packages .
|
||||
'</RateV4Request>';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function execute()
|
||||
{
|
||||
if ($this->is_prod) {
|
||||
$url = $this->url_prod;
|
||||
if ($this->isProduction) {
|
||||
$url = $this->urlProd;
|
||||
} else {
|
||||
$url = $this->url_dev;
|
||||
$url = $this->urlDev;
|
||||
}
|
||||
|
||||
$url_request = $url . '?API=RateV4&XML=' . rawurlencode($this->data);
|
||||
|
||||
$this->response = $this->rate_request->execute($url_request);
|
||||
$this->response = $this->rateRequest->execute($url_request);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -176,8 +159,6 @@ class Rate extends RateAdapter
|
||||
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;
|
||||
}
|
||||
|
||||
@ -190,7 +171,7 @@ class Rate extends RateAdapter
|
||||
|
||||
$name = Arr::get($this->shipping_codes['domestic'], $code);
|
||||
|
||||
if ( ! empty($this->approved_codes) AND ! in_array($code, $this->approved_codes)) {
|
||||
if (!empty($this->approvedCodes) && !in_array($code, $this->approvedCodes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
28
tests/ArrTest.php
Normal file
28
tests/ArrTest.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping;
|
||||
|
||||
class ArrTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function providerGet()
|
||||
{
|
||||
return array(
|
||||
array(array('uno', 'dos', 'tress'), 1, null, 'dos'),
|
||||
array(array('we' => '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)
|
||||
);
|
||||
}
|
||||
}
|
110
tests/Fedex/FedexTest.php
Normal file
110
tests/Fedex/FedexTest.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping\Fedex;
|
||||
|
||||
use pdt256\Shipping\RateRequest\StubFedex;
|
||||
use pdt256\Shipping\Ship;
|
||||
use pdt256\Shipping\Package;
|
||||
use pdt256\Shipping\Shipment;
|
||||
use pdt256\Shipping\Quote;
|
||||
use DateTime;
|
||||
|
||||
class RateTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Shipment */
|
||||
protected $shipment;
|
||||
|
||||
protected $approvedCodes = [];
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$ship = Ship::factory([
|
||||
'Standard Shipping' => [
|
||||
'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);
|
||||
}
|
||||
}
|
19
tests/PackageTest.php
Normal file
19
tests/PackageTest.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping;
|
||||
|
||||
class PackageTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreate()
|
||||
{
|
||||
$package = new Package;
|
||||
$package->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());
|
||||
}
|
||||
}
|
25
tests/QuoteTest.php
Normal file
25
tests/QuoteTest.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class QuoteTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreate()
|
||||
{
|
||||
$quote = new Quote;
|
||||
$quote->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());
|
||||
}
|
||||
}
|
13
tests/RateAdapterTest.php
Normal file
13
tests/RateAdapterTest.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping;
|
||||
|
||||
class RateAdapterTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreate()
|
||||
{
|
||||
/* @var RateAdapter $mock */
|
||||
$mock = $this->getMockForAbstractClass('pdt256\Shipping\RateAdapter');
|
||||
$mockRequestAdapter = $this->getMockForAbstractClass('pdt256\Shipping\RateRequest\Adapter');
|
||||
$mock->setRequestAdapter($mockRequestAdapter);
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
<?php
|
||||
use pdt256\Shipping\Package;
|
||||
use pdt256\Shipping\Quote;
|
||||
use pdt256\Shipping\Ship;
|
||||
use pdt256\Shipping\Shipment;
|
||||
use pdt256\Shipping\USPS;
|
||||
use pdt256\Shipping\UPS;
|
||||
use pdt256\Shipping\Fedex;
|
||||
use pdt256\Shipping\RateRequest;
|
||||
namespace pdt256\Shipping;
|
||||
|
||||
class ShipTest extends PHPUnit_Framework_TestCase
|
||||
use DateTime;
|
||||
|
||||
class ShipTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Shipment */
|
||||
public $shipment;
|
||||
@ -56,7 +51,7 @@ class ShipTest extends PHPUnit_Framework_TestCase
|
||||
->setFromCountryCode('US')
|
||||
->setToPostalCode('78703')
|
||||
->setToCountryCode('US')
|
||||
->setToResidential(true);
|
||||
->setToIsResidential(true);
|
||||
|
||||
$p = new Package;
|
||||
$p->setWeight(3)
|
||||
@ -72,206 +67,89 @@ class ShipTest extends PHPUnit_Framework_TestCase
|
||||
private function getUSPSOptions()
|
||||
{
|
||||
$ship = Ship::factory($this->shipping_options);
|
||||
$approved_codes = $ship->get_approved_codes('usps');
|
||||
$approvedCodes = $ship->getApprovedCodes('usps');
|
||||
|
||||
return [
|
||||
'prod' => FALSE,
|
||||
'prod' => false,
|
||||
'username' => 'XXXX',
|
||||
'password' => 'XXXX',
|
||||
'shipment' => $this->shipment,
|
||||
'approved_codes' => $approved_codes,
|
||||
'request_adapter' => new RateRequest\StubUSPS(),
|
||||
'approvedCodes' => $approvedCodes,
|
||||
'requestAdapter' => new RateRequest\StubUSPS(),
|
||||
];
|
||||
}
|
||||
|
||||
private function getUPSOptions()
|
||||
{
|
||||
$ship = Ship::factory($this->shipping_options);
|
||||
$approved_codes = $ship->get_approved_codes('ups');
|
||||
$approvedCodes = $ship->getApprovedCodes('ups');
|
||||
|
||||
return [
|
||||
'prod' => FALSE,
|
||||
'access_key' => 'XXXX',
|
||||
'user_id' => 'XXXX',
|
||||
'prod' => false,
|
||||
'accessKey' => 'XXXX',
|
||||
'userId' => 'XXXX',
|
||||
'password' => 'XXXX',
|
||||
'shipper_number' => 'XXXX',
|
||||
'shipperNumber' => 'XXXX',
|
||||
'shipment' => $this->shipment,
|
||||
'approved_codes' => $approved_codes,
|
||||
'request_adapter' => new RateRequest\StubUPS(),
|
||||
'approvedCodes' => $approvedCodes,
|
||||
'requestAdapter' => new RateRequest\StubUPS(),
|
||||
];
|
||||
}
|
||||
|
||||
private function getFedexOptions()
|
||||
{
|
||||
$ship = Ship::factory($this->shipping_options);
|
||||
$approved_codes = $ship->get_approved_codes('fedex');
|
||||
$approvedCodes = $ship->getApprovedCodes('fedex');
|
||||
|
||||
return [
|
||||
'prod' => FALSE,
|
||||
'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(),
|
||||
'approvedCodes' => $approvedCodes,
|
||||
'requestAdapter' => 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);
|
||||
|
||||
$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();
|
||||
$rates['usps'] = $usps->getRates();
|
||||
|
||||
$ups = new UPS\Rate($this->getUPSOptions());
|
||||
$rates['ups'] = $ups->get_rates();
|
||||
$rates['ups'] = $ups->getRates();
|
||||
|
||||
$fedex = new Fedex\Rate($this->getFedexOptions());
|
||||
$rates['fedex'] = $fedex->get_rates();
|
||||
$rates['fedex'] = $fedex->getRates();
|
||||
|
||||
$ship = Ship::factory($this->shipping_options);
|
||||
$display_rates = $ship->get_display_rates($rates);
|
||||
$rates = $ship->getDisplayRates($rates);
|
||||
|
||||
$post = new Quote;
|
||||
$post->setCode(4)
|
||||
->setName('Parcel Post')
|
||||
->setCost(1001)
|
||||
->setCarrier('usps');
|
||||
$post = new Quote('usps', '4', 'Parcel Post', 1001);
|
||||
|
||||
$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');
|
||||
$fedexTwoDay = new Quote('fedex', 'FEDEX_2_DAY', 'Fedex 2 Day', 4072);
|
||||
$fedexTwoDay->setDeliveryEstimate(new DateTime('2014-09-29T20:00:00'));
|
||||
|
||||
$overnight = new Quote;
|
||||
$overnight->setCode('STANDARD_OVERNIGHT')
|
||||
->setName('Standard Overnight')
|
||||
->setCost(7800)
|
||||
->setDeliveryEstimate(new DateTime('2014-09-26T20:00:00'))
|
||||
->setCarrier('fedex');
|
||||
$overnight = new Quote('fedex', 'STANDARD_OVERNIGHT', 'Standard Overnight', 7834);
|
||||
$overnight->setDeliveryEstimate(new DateTime('2014-09-26T20:00:00'));
|
||||
|
||||
$this->assertEquals([
|
||||
$expected = [
|
||||
'Standard Shipping' => [
|
||||
$post,
|
||||
],
|
||||
'Two-Day Shipping' => [
|
||||
$fedex_two_day,
|
||||
$fedexTwoDay,
|
||||
],
|
||||
'One-Day Shipping' => [
|
||||
$overnight,
|
||||
],
|
||||
], $display_rates);
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $rates);
|
||||
}
|
||||
}
|
||||
|
32
tests/ShipmentTest.php
Normal file
32
tests/ShipmentTest.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping;
|
||||
|
||||
class ShipmentTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCreate()
|
||||
{
|
||||
$shipment = new Shipment;
|
||||
$shipment->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());
|
||||
}
|
||||
}
|
99
tests/UPS/RateTest.php
Normal file
99
tests/UPS/RateTest.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping\UPS;
|
||||
|
||||
use pdt256\Shipping\RateRequest\StubUPS;
|
||||
use pdt256\Shipping\Ship;
|
||||
use pdt256\Shipping\Package;
|
||||
use pdt256\Shipping\Shipment;
|
||||
use pdt256\Shipping\Quote;
|
||||
|
||||
class RateTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Shipment */
|
||||
protected $shipment;
|
||||
|
||||
protected $approvedCodes = [];
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$ship = Ship::factory([
|
||||
'Standard Shipping' => [
|
||||
'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);
|
||||
}
|
||||
}
|
86
tests/USPS/RateTest.php
Normal file
86
tests/USPS/RateTest.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
namespace pdt256\Shipping\USPS;
|
||||
|
||||
use pdt256\Shipping\RateRequest\StubUSPS;
|
||||
use pdt256\Shipping\Ship;
|
||||
use pdt256\Shipping\Package;
|
||||
use pdt256\Shipping\Shipment;
|
||||
use pdt256\Shipping\Quote;
|
||||
|
||||
class RateTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/** @var Shipment */
|
||||
protected $shipment;
|
||||
|
||||
protected $approvedCodes = [];
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$ship = Ship::factory([
|
||||
'Standard Shipping' => [
|
||||
'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);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user