Skip to content

Commit

Permalink
Merge branch 'straversy-xav-api-wrapper'
Browse files Browse the repository at this point in the history
  • Loading branch information
stefandoorn committed Jun 20, 2015
2 parents 9720413 + d3c664b commit 7459612
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 6 deletions.
57 changes: 51 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@ Tracking API, Shipping API, Rating API and Time in Transit API. Feel free to con

1. [Requirements](#requirements)
2. [Installation](#installation)
3. [QuantumView Class](#quantumview-class)
3. [Address Validation Class](#addressvalidation-class)
* [Example](#addressvalidation-class-example)
* [Parameters](#addressvalidation-class-parameters)
4. [QuantumView Class](#quantumview-class)
* [Example](#quantumview-class-example)
* [Parameters](#quantumview-class-parameters)
4. [Tracking Class](#tracking-class)
5. [Tracking Class](#tracking-class)
* [Example](#tracking-class-example)
* [Parameters](#tracking-class-parameters)
5. [Rate Class](#rate-class)
6. [Rate Class](#rate-class)
* [Example](#rate-class-example)
* [Parameters](#rate-class-parameters)
6. [TimeInTransit Class](#timeintransit-class)
7. [TimeInTransit Class](#timeintransit-class)
* [Example](#timeintransit-class-example)
* [Parameters](#timeintransit-class-parameters)
7. [Shipping Class](#shipping-class)
8. [Logging](#logging)
8. [Shipping Class](#shipping-class)
9. [Logging](#logging)

<a name="requirements"></a>
## Requirements
Expand All @@ -50,6 +53,48 @@ add the following lines to your ``composer.json`` file.
}
```

<a name="addressvalidation-class"></a>
## Address Validation Class (Street Level)

The Address Validation Class allow you to validate an address at street level. Suggestions are given when address is invalid.

Note: UPS has two Address Validations. This is Street Level option, which includes all option
of the normal Address Validation class and adds street level validation.

Not all countries are supported, see UPS documentation. Currently US & Puerto Rico are supported.

<a name="addressvalidation-class-example"></a>
### Example

```php
$address = new \Ups\Entity\Address();
$address->setAttentionName('Test Test');
$address->setBuildingName('Test');
$address->setAddressLine1('Address Line 1');
$address->setAddressLine2('Address Line 2');
$address->setAddressLine3('Address Line 3');
$address->setStateProvinceCode('NY');
$address->setCity('New York');
$address->setCountryCode('US');
$address->setPostalCode('10000');

$xav = new \Ups\AddressValidation($accessKey, $userId, $password);
try {
$response = $xav->validate($address, $requestOption = \Ups\AddressValidation::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15);
} catch (Exception $e) {
var_dump($e);
}
```

<a name="addressvalidation-class-parameters"></a>
### Parameters

Adress Validation parameters are:

* `address` Address object as constructed in example
* `requestOption` One of the three request options
* `maxSuggestion` Maximum number of suggestions to be returned. Max =

<a name="quantumview-class"></a>
## QuantumView Class

Expand Down
224 changes: 224 additions & 0 deletions src/Ups/AddressValidation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
<?php
namespace Ups;

use DOMDocument;
use SimpleXMLElement;
use Exception;
use stdClass;

/**
* Address Validation API Wrapper
*
* @package ups
*/
class AddressValidation extends Ups
{
const ENDPOINT = '/XAV';

/**
* @var RequestInterface
*/
private $request;

/**
* @var ResponseInterface
* @todo make private
*/
public $response;

/**
* @var int
*/
private $requestOption;

/**
* @var address
*/
private $address;

/**
* @var int
*/
private $maxSuggestion;

/**
* Request Options
*/
const REQUEST_OPTION_ADDRESS_VALIDATION = 1;
const REQUEST_OPTION_ADDRESS_CLASSIFICATION = 2;
const REQUEST_OPTION_ADDRESS_VALIDATION_AND_CLASSIFICATION = 3;

/**
* @param string|null $accessKey UPS License Access Key
* @param string|null $userId UPS User ID
* @param string|null $password UPS User Password
* @param bool $useIntegration Determine if we should use production or CIE URLs.
* @param RequestInterface $request
* @param LoggerInterface PSR3 compatible logger (optional)
*/
public function __construct($accessKey = null, $userId = null, $password = null, $useIntegration = false, RequestInterface $request = null, LoggerInterface $logger = null)
{
if (null !== $request) {
$this->setRequest($request);
}
parent::__construct($accessKey, $userId, $password, $useIntegration, $logger);
}


/**
* Get address suggestions from UPS
*
* @param $address
* @param int $requestOption
* @param int $maxSuggestion
* @return stdClass
* @throws Exception
*/
public function validate($address, $requestOption = self::REQUEST_OPTION_ADDRESS_VALIDATION, $maxSuggestion = 15)
{
if($maxSuggestion > 50) {
throw new \Exception('Maximum of 50 suggestions allowed');
}

if(!in_array($requestOption, range(1, 3))) {
throw new \Exception('Invalid request option supplied');
}

$this->address = $address;
$this->requestOption = $requestOption;
$this->maxSuggestion = $maxSuggestion;

$access = $this->createAccess();
$request = $this->createRequest();

$this->response = $this->getRequest()->request($access, $request, $this->compileEndpointUrl(self::ENDPOINT));
$response = $this->response->getResponse();

if (null === $response) {
throw new Exception("Failure (0): Unknown error", 0);
}

if ($response instanceof SimpleXMLElement && $response->Response->ResponseStatusCode == 0) {
throw new Exception(
"Failure ({$response->Response->Error->ErrorSeverity}): {$response->Response->Error->ErrorDescription}",
(int)$response->Response->Error->ErrorCode
);
} else {
return $this->formatResponse($response);
}
}


/**
* Create the XAV request
*
* @return string
*/
private function createRequest()
{
$xml = new DOMDocument();
$xml->formatOutput = true;

$avRequest = $xml->appendChild($xml->createElement("AddressValidationRequest"));
$avRequest->setAttribute('xml:lang', 'en-US');

$request = $avRequest->appendChild($xml->createElement("Request"));

$node = $xml->importNode($this->createTransactionNode(), true);
$request->appendChild($node);

$request->appendChild($xml->createElement("RequestAction", "XAV"));

if (null !== $this->requestOption) {
$request->appendChild($xml->createElement("RequestOption", $this->requestOption));
}

if (null !== $this->maxSuggestion) {
$avRequest->appendChild($xml->createElement("MaximumListSize", $this->maxSuggestion));
}

if (null !== $this->address) {
$addressNode = $avRequest->appendChild($xml->createElement("AddressKeyFormat"));

if($this->address->getAttentionName()) {
$addressNode->appendChild($xml->createElement("ConsigneeName", $this->address->getAttentionName()));
}
if($this->address->getBuildingName()) {
$addressNode->appendChild($xml->createElement("BuildingName", $this->address->getBuildingName()));
}
if($this->address->getAddressLine1()) {
$addressNode->appendChild($xml->createElement("AddressLine", $this->address->getAddressLine1()));
}
if($this->address->getAddressLine2()) {
$addressNode->appendChild($xml->createElement("AddressLine", $this->address->getAddressLine2()));
}
if($this->address->getAddressLine3()) {
$addressNode->appendChild($xml->createElement("AddressLine", $this->address->getAddressLine3()));
}
if($this->address->getStateProvinceCode()) {
$addressNode->appendChild($xml->createElement("PoliticalDivision2", $this->address->getStateProvinceCode()));
}
if($this->address->getCity()) {
$addressNode->appendChild($xml->createElement("PoliticalDivision1", $this->address->getCity()));
}
if($this->address->getCountryCode()) {
$addressNode->appendChild($xml->createElement("CountryCode", $this->address->getCountryCode()));
}
if($this->address->getPostalCode()) {
$addressNode->appendChild($xml->createElement("PostcodePrimaryLow", $this->address->getPostalCode()));
}
}

return $xml->saveXML();
}

/**
* Format the response
*
* @param SimpleXMLElement $response
* @return stdClass
*/
private function formatResponse(SimpleXMLElement $response)
{
return $this->convertXmlObject($response->AddressKeyFormat);
}

/**
* @return RequestInterface
*/
public function getRequest()
{
if (null === $this->request) {
$this->request = new Request;
}
return $this->request;
}

/**
* @param RequestInterface $request
* @return $this
*/
public function setRequest(RequestInterface $request)
{
$this->request = $request;
return $this;
}

/**
* @return ResponseInterface
*/
public function getResponse()
{
return $this->response;
}

/**
* @param ResponseInterface $response
* @return $this
*/
public function setResponse(ResponseInterface $response)
{
$this->response = $response;
return $this;
}
}
38 changes: 38 additions & 0 deletions tests/Ups/Tests/AddressValidationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
namespace Ups\Tests;

use Ups;
use Exception;
use PHPUnit_Framework_TestCase;

// @todo Include also request test
class AddressValidationTest extends PHPUnit_Framework_TestCase
{
public function testCreateRequest()
{
$xavRequest = new \Ups\AddressValidation;
$xavRequest->setRequest($request = new RequestMock);

$address = new \Ups\Entity\Address;
$address->setAttentionName('Test Test');
$address->setBuildingName('Building 1');
$address->setAddressLine1('Times Square 1');
$address->setAddressLine2('First Corner');
$address->setAddressLine3('Second Corner');
$address->setStateProvinceCode('NY');
$address->setCity('New York');
$address->setCountryCode('US');
$address->setPostalCode('50000');

try {
// Get data
$response = $xavRequest->validate($address);
} catch (Exception $e) {}

$this->assertEquals(
$request->getRequestXml(),
$request->getExpectedRequestXml('/AddressValidation/Request1.xml')
);
}

}
20 changes: 20 additions & 0 deletions tests/Ups/Tests/_files/requests/AddressValidation/Request1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<AddressValidationRequest xml:lang="en-US">
<Request>
<TransactionReference/>
<RequestAction>XAV</RequestAction>
<RequestOption>1</RequestOption>
</Request>
<MaximumListSize>15</MaximumListSize>
<AddressKeyFormat>
<ConsigneeName>Test Test</ConsigneeName>
<BuildingName>Building 1</BuildingName>
<AddressLine>Times Square 1</AddressLine>
<AddressLine>First Corner</AddressLine>
<AddressLine>Second Corner</AddressLine>
<PoliticalDivision2>NY</PoliticalDivision2>
<PoliticalDivision1>New York</PoliticalDivision1>
<CountryCode>US</CountryCode>
<PostcodePrimaryLow>50000</PostcodePrimaryLow>
</AddressKeyFormat>
</AddressValidationRequest>

0 comments on commit 7459612

Please sign in to comment.