diff --git a/.phan/config.php b/.phan/config.php index e138932..9679218 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -26,6 +26,7 @@ // use Phan\Config; return [ + "minimum_target_php_version" => "7.4", // If true, missing properties will be created when // they are first seen. If false, we'll report an // error message. @@ -65,7 +66,7 @@ return [ 'directory_list' => [ // Change this to include the folders you wish to analyze // (and the folders of their dependencies) - '.' + 'src/' // 'www', // To speed up analysis, we recommend going back later and // limiting this to only the vendor/ subdirectories your diff --git a/phpstan.neon b/phpstan.neon index a1ca077..b5185b7 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -2,7 +2,7 @@ parameters: tmpDir: %currentWorkingDirectory%/tmp/phpstan-codeblocks-amazon-incentives - level: 8 + level: 9 paths: - %currentWorkingDirectory%/src excludePaths: diff --git a/phpunit.xml b/phpunit.xml index 1132d19..b004c68 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,6 +1,6 @@ diff --git a/src/AWS/AWS.php b/src/AWS/AWS.php index 7689f5f..f6340e8 100644 --- a/src/AWS/AWS.php +++ b/src/AWS/AWS.php @@ -1,5 +1,7 @@ getCanonicalRequest($service_operation, $payload); $date_time_string = $this->getTimestamp(); AmazonDebug::writeLog(['call' => __METHOD__]); - $result = json_decode($this->makeRequest( + $result = Json::jsonDecode($this->makeRequest( $payload, $canonical_request, $service_operation, $date_time_string - ), true); + )); return new CreateResponse($result); } @@ -97,12 +100,12 @@ class AWS $canonical_request = $this->getCanonicalRequest($service_operation, $payload); $date_time_string = $this->getTimestamp(); AmazonDebug::writeLog(['call' => __METHOD__]); - $result = json_decode($this->makeRequest( + $result = Json::jsonDecode($this->makeRequest( $payload, $canonical_request, $service_operation, $date_time_string - ), true); + )); return new CancelResponse($result); } @@ -120,12 +123,12 @@ class AWS $canonical_request = $this->getCanonicalRequest($service_operation, $payload); $date_time_string = $this->getTimestamp(); AmazonDebug::writeLog(['call' => __METHOD__]); - $result = json_decode($this->makeRequest( + $result = Json::jsonDecode($this->makeRequest( $payload, $canonical_request, $service_operation, $date_time_string - ), true); + )); return new CreateBalanceResponse($result); } @@ -212,7 +215,7 @@ class AWS * @param string $date_time_string Ymd\THis\Z encoded timestamp, getTimestamp() * @param string $service_target Target service in the agcod string: * Value like com.amazonaws.agcod.. - * @return array Header data as array for curl request + * @return array Header data as array for curl request */ public function buildHeaders( string $payload, diff --git a/src/AmazonIncentives.php b/src/AmazonIncentives.php index af5005d..848956b 100644 --- a/src/AmazonIncentives.php +++ b/src/AmazonIncentives.php @@ -30,12 +30,12 @@ final class AmazonIncentives * @param bool|null $debug Debug flag */ public function __construct( - string $key = null, - string $secret = null, - string $partner = null, - string $endpoint = null, - string $currency = null, - bool $debug = null + ?string $key = null, + ?string $secret = null, + ?string $partner = null, + ?string $endpoint = null, + ?string $currency = null, + ?bool $debug = null ) { // load AWS settings // fail here if settings missing @@ -65,7 +65,7 @@ final class AmazonIncentives * * @throws AmazonErrors */ - public function buyGiftCard(float $value, string $creation_request_id = null): Response\CreateResponse + public function buyGiftCard(float $value, ?string $creation_request_id = null): Response\CreateResponse { return ($this->newAWS())->getCode($value, $creation_request_id); } @@ -109,12 +109,12 @@ final class AmazonIncentives * @return AmazonIncentives self class */ public static function make( - string $key = null, - string $secret = null, - string $partner = null, - string $endpoint = null, - string $currency = null, - bool $debug = null + ?string $key = null, + ?string $secret = null, + ?string $partner = null, + ?string $endpoint = null, + ?string $currency = null, + ?bool $debug = null ): AmazonIncentives { return new static($key, $secret, $partner, $endpoint, $currency, $debug); } diff --git a/src/Client/Client.php b/src/Client/Client.php index abea497..1fa02b1 100644 --- a/src/Client/Client.php +++ b/src/Client/Client.php @@ -1,9 +1,12 @@ $headers Headers to be used in the request + * @param array $headers Headers to be used in the request * @param array|string $params Can be nested for arrays and hashes * @return string Result as json string */ @@ -50,7 +53,12 @@ class Client implements ClientInterface $err = curl_errno($handle); AmazonDebug::writeLog(['CURL_REQUEST_RESULT' => $result]); // extract all the error codes from Amazon - $result_ar = json_decode((string)$result, true); + // note we do not care about result errors here, if json decode fails, just set to empty + try { + $result_ar = Json::jsonDecode((string)$result); + } catch (AmazonErrors $e) { + $result_ar = []; + } // if message is 'Rate exceeded', set different error if (($result_ar['message'] ?? '') == 'Rate exceeded') { $error_status = 'RESEND'; diff --git a/src/Client/ClientInterface.php b/src/Client/ClientInterface.php index 8cf67c7..c0c1425 100644 --- a/src/Client/ClientInterface.php +++ b/src/Client/ClientInterface.php @@ -1,5 +1,7 @@ Log data array log id -> array of log entries */ + /** @var array>> Log data array log id -> array of log entries */ private static $log = []; /** @var bool debug flag */ private static $debug = false; diff --git a/src/Exceptions/AmazonErrors.php b/src/Exceptions/AmazonErrors.php index b07612e..aa4baec 100644 --- a/src/Exceptions/AmazonErrors.php +++ b/src/Exceptions/AmazonErrors.php @@ -1,5 +1,7 @@ '', 'code' => '', diff --git a/src/Handle/Json.php b/src/Handle/Json.php new file mode 100644 index 0000000..c8eea53 --- /dev/null +++ b/src/Handle/Json.php @@ -0,0 +1,42 @@ + + * @throws AmazonErrors + */ + public static function jsonDecode(string $json): array + { + $result = json_decode($json, true); + if ( + ($json_last_error = json_last_error()) || + $result === null || + !is_array($result) + ) { + throw AmazonErrors::getError( + 'FAILURE', + 'J-' . $json_last_error, + 'jsonDecoreError', + 'Failed to decode json data', + 0 + ); + } + return $result; + } +} + +// __END__ diff --git a/src/Response/CancelResponse.php b/src/Response/CancelResponse.php index effd540..49b3309 100644 --- a/src/Response/CancelResponse.php +++ b/src/Response/CancelResponse.php @@ -1,5 +1,7 @@ amount; } @@ -98,10 +100,18 @@ class CreateBalanceResponse */ public function parseJsonResponse(array $json_response): self { - if (array_key_exists('amount', $json_response['availableFunds'])) { - $this->amount = $json_response['availableFunds']['amount']; + if ( + is_array($json_response['availableFunds']) && + array_key_exists('amount', $json_response['availableFunds']) && + is_numeric($json_response['availableFunds']['amount']) + ) { + $this->amount = (float)$json_response['availableFunds']['amount']; } - if (array_key_exists('currencyCode', $json_response['availableFunds'])) { + if ( + is_array($json_response['availableFunds']) && + array_key_exists('currencyCode', $json_response['availableFunds']) && + is_string($json_response['availableFunds']['currencyCode']) + ) { $this->currency = $json_response['availableFunds']['currencyCode']; } // SUCCESS, FAILURE, RESEND diff --git a/src/Response/CreateResponse.php b/src/Response/CreateResponse.php index f22813e..f85029c 100644 --- a/src/Response/CreateResponse.php +++ b/src/Response/CreateResponse.php @@ -1,5 +1,7 @@ assertIsNumeric( $funds->getAmount(), - 'Assert amoount is numerc' + 'Assert amoount is numeric' ); // USD, JPY, etc $this->assertIsString(