From 79a8f951685adc596fba961779a43ee0605343aa Mon Sep 17 00:00:00 2001 From: Kirill Sagan Date: Wed, 3 Aug 2022 00:03:57 +0300 Subject: [PATCH 1/3] Fix encryption when bad response exception --- src/Hyperwallet/Util/ApiClient.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Hyperwallet/Util/ApiClient.php b/src/Hyperwallet/Util/ApiClient.php index f51327dd..7a026fab 100644 --- a/src/Hyperwallet/Util/ApiClient.php +++ b/src/Hyperwallet/Util/ApiClient.php @@ -182,7 +182,8 @@ private function doRequest($method, $url, array $urlParams, array $options) { ))); throw new HyperwalletApiException($errorResponse, $e); } catch (BadResponseException $e) { - $body = \GuzzleHttp\json_decode($e->getResponse()->getBody(), true); + $body = $this->isEncrypted ? \GuzzleHttp\json_decode(\GuzzleHttp\json_encode($this->encryption->decrypt($e->getResponse()->getBody())), true) : + \GuzzleHttp\json_decode($e->getResponse()->getBody(), true); if (is_null($body) || !isset($body['errors']) || empty($body['errors'])) { $body = array('errors' => array( array( From 27b374df05d95bf78eada9ae05f06b6dfb58c79e Mon Sep 17 00:00:00 2001 From: kirillsagan Date: Fri, 26 Jan 2024 10:59:34 +0200 Subject: [PATCH 2/3] Make the decryption of the response a separate function --- src/Hyperwallet/Util/ApiClient.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Hyperwallet/Util/ApiClient.php b/src/Hyperwallet/Util/ApiClient.php index 7a026fab..d0448bc6 100644 --- a/src/Hyperwallet/Util/ApiClient.php +++ b/src/Hyperwallet/Util/ApiClient.php @@ -3,6 +3,7 @@ use GuzzleHttp\Client; use GuzzleHttp\Exception\BadResponseException; use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Exception\GuzzleException; use Hyperwallet\Exception\HyperwalletApiException; use Hyperwallet\Exception\HyperwalletException; use Hyperwallet\Model\BaseModel; @@ -149,6 +150,8 @@ public function doGet($partialUrl, array $uriParams, array $query) { * @return array * * @throws HyperwalletApiException + * @throws HyperwalletException + * @throws GuzzleException */ private function doRequest($method, $url, array $urlParams, array $options) { try { @@ -169,10 +172,8 @@ private function doRequest($method, $url, array $urlParams, array $options) { return array(); } $this->checkResponseHeaderContentType($response); - $body = $this->isEncrypted ? \GuzzleHttp\json_decode(\GuzzleHttp\json_encode($this->encryption->decrypt($response->getBody())), true) : - \GuzzleHttp\json_decode($response->getBody(), true); - return $body; + return $this->getBodyFromResponse($response); } catch (ConnectException $e) { $errorResponse = new ErrorResponse(0, array('errors' => array( array( @@ -182,8 +183,7 @@ private function doRequest($method, $url, array $urlParams, array $options) { ))); throw new HyperwalletApiException($errorResponse, $e); } catch (BadResponseException $e) { - $body = $this->isEncrypted ? \GuzzleHttp\json_decode(\GuzzleHttp\json_encode($this->encryption->decrypt($e->getResponse()->getBody())), true) : - \GuzzleHttp\json_decode($e->getResponse()->getBody(), true); + $body = $this->getBodyFromResponse($e->getResponse()); if (is_null($body) || !isset($body['errors']) || empty($body['errors'])) { $body = array('errors' => array( array( @@ -197,6 +197,17 @@ private function doRequest($method, $url, array $urlParams, array $options) { } } + /** + * Get body from response and decrypt it if necessary + * + * @throws HyperwalletException + */ + private function getBodyFromResponse(ResponseInterface $response) { + return $this->isEncrypted + ? \GuzzleHttp\json_decode(\GuzzleHttp\json_encode($this->encryption->decrypt($response->getBody())), true) + : \GuzzleHttp\json_decode($response->getBody(), true); + } + /** * Checks whether Content-Type header is valid in response * From 698139f860bee00b67369859bffd48bbba1280a1 Mon Sep 17 00:00:00 2001 From: kirillsagan Date: Fri, 26 Jan 2024 12:58:02 +0200 Subject: [PATCH 3/3] Add unit test for throwing bad request exception with encryption --- .../Hyperwallet/Tests/Util/ApiClientTest.php | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tests/Hyperwallet/Tests/Util/ApiClientTest.php b/tests/Hyperwallet/Tests/Util/ApiClientTest.php index 980d42eb..652c6712 100644 --- a/tests/Hyperwallet/Tests/Util/ApiClientTest.php +++ b/tests/Hyperwallet/Tests/Util/ApiClientTest.php @@ -410,6 +410,67 @@ public function testDoPost_throw_exception_bad_request() { $this->validateRequest('POST', '/test', '', array('test2' => 'value2'), true); } + /** + * @throws HyperwalletException + */ + public function testDoPost_throw_exception_bad_request_with_encryption() { + $clientPath = __DIR__ . "/../../../resources/private-jwkset1"; + $hyperwalletPath = __DIR__ . "/../../../resources/public-jwkset1"; + $originalMessage = array( + 'errors' => array( + array( + 'fieldName' => 'testField', + 'code' => 'MY_CODE', + 'message' => 'My test message', + 'relatedResources' => array( + 'trm-f3d38df1-adb7-4127-9858-e72ebe682a79', 'trm-601b1401-4464-4f3f-97b3-09079ee7723b') + ), + array( + 'code' => 'MY_SECOND_CODE', + 'message' => 'My second test message' + ) + ) + ); + + // Setup data + $encryption = new HyperwalletEncryption($clientPath, $hyperwalletPath); + $encryptedMessage = $encryption->encrypt($originalMessage); + + $mockHandler = new MockHandler(array( + new Response(400, array('Content-Type' => 'application/jose+json'), $encryptedMessage) + )); + $this->createApiClientWithEncryption($mockHandler); + + $model = new BaseModel(array(), array('test2' => 'value2')); + + // Execute test + try { + $this->apiClient->doPost('/test', array(), $model, array()); + $this->fail('HyperwalletApiException expected'); + } catch (HyperwalletApiException $e) { + $this->assertEquals('My test message', $e->getMessage()); + $this->assertNotNull($e->getErrorResponse()); + + $this->assertEquals(400, $e->getErrorResponse()->getStatusCode()); + $this->assertCount(2, $e->getErrorResponse()->getErrors()); + + $this->assertEquals('MY_CODE', $e->getErrorResponse()->getErrors()[0]->getCode()); + $this->assertEquals('My test message', $e->getErrorResponse()->getErrors()[0]->getMessage()); + $this->assertEquals('testField', $e->getErrorResponse()->getErrors()[0]->getFieldName()); + + $this->assertEquals('MY_SECOND_CODE', $e->getErrorResponse()->getErrors()[1]->getCode()); + $this->assertEquals('My second test message', $e->getErrorResponse()->getErrors()[1]->getMessage()); + $this->assertNull($e->getErrorResponse()->getErrors()[1]->getFieldName()); + + $this->assertCount(2, $e->getRelatedResources()); + $this->assertEquals('trm-f3d38df1-adb7-4127-9858-e72ebe682a79', $e->getRelatedResources()[0]); + $this->assertEquals('trm-601b1401-4464-4f3f-97b3-09079ee7723b', $e->getRelatedResources()[1]); + } + + // Validate api request + $this->validateRequest('POST', '/test', '', array('test2' => 'value2'), true, array(), true); + } + public function testDoPost_throw_exception_server_error() { // Setup data $mockHandler = new MockHandler(array(