From 539ea90a146a5968cf535e97e1a0eeb84abc4209 Mon Sep 17 00:00:00 2001 From: Konstantin Pereyaslov Date: Sun, 8 Mar 2015 06:56:47 +0300 Subject: [PATCH] Throw FedexRequestException with message from FedEx when FedEx returns error instead of \Exception with generic error message. --- src/Fedex/FedexRequestException.php | 28 ++++++++ src/Fedex/Rate.php | 70 ++++++++++++++++--- src/RateRequest/FedexErrorResponse.xml | 1 + src/RateRequest/StubFailingFedex.php | 14 ++++ src/RateRequest/StubFedex.php | 2 +- .../StubIncorrectResponseAdapter.php | 21 ++++++ tests/Fedex/FedexTest.php | 47 +++++++++++++ 7 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 src/Fedex/FedexRequestException.php create mode 100644 src/RateRequest/FedexErrorResponse.xml create mode 100644 src/RateRequest/StubFailingFedex.php create mode 100644 src/RateRequest/StubIncorrectResponseAdapter.php diff --git a/src/Fedex/FedexRequestException.php b/src/Fedex/FedexRequestException.php new file mode 100644 index 0000000..148b7ca --- /dev/null +++ b/src/Fedex/FedexRequestException.php @@ -0,0 +1,28 @@ +severity; + } + + /** + * @param string $severity + */ + public function setSeverity($severity) + { + $this->severity = $severity; + } +} diff --git a/src/Fedex/Rate.php b/src/Fedex/Rate.php index 20c2016..55af5af 100644 --- a/src/Fedex/Rate.php +++ b/src/Fedex/Rate.php @@ -196,20 +196,68 @@ class Rate extends RateAdapter return $this; } - protected function process() + /** + * @param $response + * @return FedexRequestException + */ + protected function getIncorrectResponseException($response) { - try { - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->loadXml($this->response); - $rate_reply = $dom->getElementsByTagName('RateReplyDetails'); + return new FedexRequestException('Incorrect response received from FedEx: ' . $response); + } - if (empty($rate_reply->length)) { - throw new Exception('Unable to get FedEx Rates.'); + /** + * @param string $response + * @return FedexRequestException + */ + protected function getExceptionFromResponse($response) + { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->loadXml($response); + $notifications = $dom->getElementsByTagName('Notifications'); + foreach ($notifications as $notification) { + $messages = $notification->getElementsByTagName('Message'); + if ($messages->length === 0) { + break; + } + foreach ($messages as $message) { + $exceptionMessage = $message->textContent; + break; + } + $codes = $notification->getElementsByTagName('Code'); + if ($codes->length === 0) { + break; + } + foreach ($codes as $code) { + $exceptionCode = $code->textContent; + break; } - } catch (Exception $e) { - // StatsD::increment('error.shipping.get_fedex_rate'); - // Kohana::$log->add(Log::ERROR, $e)->write(); - throw $e; + $severities = $notification->getElementsByTagName('Severity'); + if ($severities->length === 0) { + break; + } + foreach ($severities as $severity) { + $exceptionSeverity = $severity->textContent; + break; + } + if (!isset($exceptionMessage) || !isset($exceptionCode) || !isset($exceptionSeverity)) { + return $this->getIncorrectResponseException($response); + } + $exception = new FedexRequestException($exceptionMessage, $exceptionCode); + $exception->setSeverity($exceptionSeverity); + return $exception; + + } + return $this->getIncorrectResponseException($response); + } + + protected function process() + { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->loadXml($this->response); + $rate_reply = $dom->getElementsByTagName('RateReplyDetails'); + + if (empty($rate_reply->length)) { + throw $this->getExceptionFromResponse($this->response); } foreach ($rate_reply as $rate) { diff --git a/src/RateRequest/FedexErrorResponse.xml b/src/RateRequest/FedexErrorResponse.xml new file mode 100644 index 0000000..018bec4 --- /dev/null +++ b/src/RateRequest/FedexErrorResponse.xml @@ -0,0 +1 @@ +WARNINGWARNINGcrs556There are no valid services available. There are no valid services available. crs1300 \ No newline at end of file diff --git a/src/RateRequest/StubFailingFedex.php b/src/RateRequest/StubFailingFedex.php new file mode 100644 index 0000000..841564d --- /dev/null +++ b/src/RateRequest/StubFailingFedex.php @@ -0,0 +1,14 @@ +artificialDelay > 0) { + sleep($this->artificialDelay); + } + + return file_get_contents(__DIR__ . '/FedexErrorResponse.xml'); + } +} diff --git a/src/RateRequest/StubFedex.php b/src/RateRequest/StubFedex.php index ef61376..ba2a1e3 100644 --- a/src/RateRequest/StubFedex.php +++ b/src/RateRequest/StubFedex.php @@ -3,7 +3,7 @@ namespace pdt256\Shipping\RateRequest; class StubFedex extends Adapter { - private $artificialDelay = 0; + protected $artificialDelay = 0; public function __construct($artificial_delay = 0) { diff --git a/src/RateRequest/StubIncorrectResponseAdapter.php b/src/RateRequest/StubIncorrectResponseAdapter.php new file mode 100644 index 0000000..56953f5 --- /dev/null +++ b/src/RateRequest/StubIncorrectResponseAdapter.php @@ -0,0 +1,21 @@ +artificialDelay = $artificial_delay; + } + + public function execute($url, $data = null) + { + if ($this->artificialDelay > 0) { + sleep($this->artificialDelay); + } + + return ''; + } +} diff --git a/tests/Fedex/FedexTest.php b/tests/Fedex/FedexTest.php index e7d09d3..d935a3e 100644 --- a/tests/Fedex/FedexTest.php +++ b/tests/Fedex/FedexTest.php @@ -1,7 +1,9 @@ assertEquals($expected, $rates); } + public function testFail() + { + $rateAdapter = new Rate([ + 'prod' => false, + 'key' => 'XXX', + 'password' => 'XXX', + 'accountNumber' => 'XXX', + 'meterNumber' => 'XXX', + 'dropOffType' => 'BUSINESS_SERVICE_CENTER', + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + 'requestAdapter' => new StubFailingFedex(), + ]); + try { + $rateAdapter->getRates(); + $this->fail('Getting error from fedex should throw an exception'); + } catch (FedexRequestException $ex) { + $this->assertEquals('556', $ex->getCode()); + $this->assertEquals('There are no valid services available. ', $ex->getMessage()); + $this->assertEquals('WARNING', $ex->getSeverity()); + + } + } + + public function testIncorrectResponse() + { + $rateAdapter = new Rate([ + 'prod' => false, + 'key' => 'XXX', + 'password' => 'XXX', + 'accountNumber' => 'XXX', + 'meterNumber' => 'XXX', + 'dropOffType' => 'BUSINESS_SERVICE_CENTER', + 'shipment' => $this->shipment, + 'approvedCodes' => $this->approvedCodes, + 'requestAdapter' => new StubIncorrectResponseAdapter(), + ]); + try { + $rateAdapter->getRates(); + $this->fail('Getting incorrect response should throw an exception'); + } catch (FedexRequestException $ex) { + $this->assertEquals('Incorrect response received from FedEx: ', $ex->getMessage()); + } + } + public function testLiveRates() { if (getenv('FEDEX_KEY') === false) {