From 4268f9da83f5056cb89cfd7d973ac5b544c6328e Mon Sep 17 00:00:00 2001 From: mrt1m Date: Wed, 7 Jul 2021 19:56:56 +0300 Subject: [PATCH] add data from catalog --- README.md | 29 ++++++++++++++- composer.json | 2 +- src/Actions/Catalog.php | 53 +++++++++++++++++++++++++++ src/Actions/Product.php | 17 ++++----- src/ApiClients/BaseApiClient.php | 49 +++++++++++++++++++++++++ src/ApiClients/Chihiro.php | 32 ++++++++++++++++ src/ApiClients/GraphQL.php | 35 ++++++++++++++++++ src/Client.php | 23 +++++++++--- src/Enum/Category.php | 15 ++++++++ src/Enum/{Regions.php => Region.php} | 2 +- src/Enum/SortingDirection.php | 12 ++++++ src/Query/CatalogProducts.php | 55 ++++++++++++++++++++++++++++ src/Request.php | 47 ------------------------ src/ValueObject/Pagination.php | 26 +++++++++++++ src/ValueObject/Sorting.php | 29 +++++++++++++++ 15 files changed, 360 insertions(+), 66 deletions(-) create mode 100644 src/Actions/Catalog.php create mode 100644 src/ApiClients/BaseApiClient.php create mode 100644 src/ApiClients/Chihiro.php create mode 100644 src/ApiClients/GraphQL.php create mode 100644 src/Enum/Category.php rename src/Enum/{Regions.php => Region.php} (99%) create mode 100644 src/Enum/SortingDirection.php create mode 100644 src/Query/CatalogProducts.php delete mode 100644 src/Request.php create mode 100644 src/ValueObject/Pagination.php create mode 100644 src/ValueObject/Sorting.php diff --git a/README.md b/README.md index f7330d5..4b0b188 100755 --- a/README.md +++ b/README.md @@ -18,9 +18,10 @@ Create Client object using the following code: ```php use PlaystationStoreApi\Client; -use PlaystationStoreApi\Enum\Regions; +use PlaystationStoreApi\Enum\Region; +use \GuzzleHttp\Client as HttpClient; -$clientApi = new Client(new Regions(Regions::RUSSIA)); +$clientApi = new Client(new Region(Region::RUSSIA), new HttpClient()); ``` ## 4. API Requests @@ -29,4 +30,28 @@ $clientApi = new Client(new Regions(Regions::RUSSIA)); ```php $response = $clientApi->product()->get('EP0001-CUSA12042_00-GAME000000000000'); +``` + +### 4.2. Request catalog data + +```php +use PlaystationStoreApi\Query\CatalogProducts; +use \PlaystationStoreApi\Enum\Category; +use PlaystationStoreApi\ValueObject\Pagination; + +$sha256Hash = 'get your code from request in browser'; +$query = new CatalogProducts(new Category(Category::PS4_GAMES), $sha256Hash); +$query->setPagination(new Pagination(10, 0)); + +$response = $clientApi->catalog()->products($query); +``` + +#### 4.2.1 Get sha256Hash + +1) Open the Network panel and find query to https://web.np.playstation.com/api/graphql/v1/op +2) Copy the full request URL and use urldecode +3) sha256Hash is in the extensions parameter, example: + +``` +https://web.np.playstation.com/api/graphql/v1//op?operationName=categoryGridRetrieve&variables={"id":"44d8bb20-653e-431e-8ad0-c0a365f68d2f","pageArgs":{"size":24,"offset":0},"sortBy":{"name":"productReleaseDate","isAscending":false},"filterBy":[],"facetOptions":[]}&extensions={"persistedQuery":{"version":1,"sha256Hash":"9845afc0dbaab4965f6563fffc703f588c8e76792000e8610843b8d3ee9c4c09"}} ``` \ No newline at end of file diff --git a/composer.json b/composer.json index 271c8f8..2ed8f78 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "php": ">7.4", + "php": ">=7.4", "myclabs/php-enum": "1.8.0", "guzzlehttp/guzzle": "7.3.0" }, diff --git a/src/Actions/Catalog.php b/src/Actions/Catalog.php new file mode 100644 index 0000000..1402ea0 --- /dev/null +++ b/src/Actions/Catalog.php @@ -0,0 +1,53 @@ +graphQLApiClient = $graphQLApiClient; + } + + /** + * @throws \Psr\Http\Client\ClientExceptionInterface + * @throws \JsonException + */ + public function products(CatalogProducts $query) : string + { + $params = [ + 'operationName' => 'categoryGridRetrieve', + 'variables' => [ + 'id' => $query->categoryId(), + 'pageArgs' => [ + 'size' => $query->pagination()->size(), + 'offset' => $query->pagination()->offset(), + ], + 'sortBy' => [ + 'name' => $query->sorting()->fieldName(), + 'isAscending' => $query->sorting()->isAscending(), + ], + 'filterBy' => [], + 'facetOptions' => [], + ], + 'extensions' => [ + 'persistedQuery' => [ + 'version' => 1, + 'sha256Hash' => $query->sha256Hash(), + ], + ], + ]; + + $params['variables'] = json_encode($params['variables'], JSON_THROW_ON_ERROR); + $params['extensions'] = json_encode($params['extensions'], JSON_THROW_ON_ERROR); + + return $this->graphQLApiClient->get(new Request('GET', '/op?' . http_build_query($params))); + } +} \ No newline at end of file diff --git a/src/Actions/Product.php b/src/Actions/Product.php index 241cea9..a4ed578 100644 --- a/src/Actions/Product.php +++ b/src/Actions/Product.php @@ -3,25 +3,24 @@ namespace PlaystationStoreApi\Actions; -use PlaystationStoreApi\Request; +use GuzzleHttp\Psr7\Request; +use PlaystationStoreApi\ApiClients\Chihiro; +use Psr\Http\Client\ClientExceptionInterface; class Product { - protected Request $request; + protected Chihiro $chihiroApiCLient; - public function __construct(Request $request) + public function __construct(Chihiro $chihiroApiCLient) { - $this->request = $request; + $this->chihiroApiCLient = $chihiroApiCLient; } /** - * @param string $productId - * - * @return string - * @throws \GuzzleHttp\Exception\GuzzleException + * @throws ClientExceptionInterface */ public function get(string $productId) : string { - return $this->request->get($productId); + return $this->chihiroApiCLient->get(new Request('GET', '/' . $productId)); } } \ No newline at end of file diff --git a/src/ApiClients/BaseApiClient.php b/src/ApiClients/BaseApiClient.php new file mode 100644 index 0000000..8454215 --- /dev/null +++ b/src/ApiClients/BaseApiClient.php @@ -0,0 +1,49 @@ +parseRegion($region); + + $this->client = $client; + $this->uri = new Uri(); + $this->basePath = new Uri(); + } + + protected function parseRegion(Region $region) : void + { + if ($result = explode('-', $region->getValue())) { + $this->region = array_pop($result); + $this->language = implode('-', $result); + } else { + throw new \UnexpectedValueException('The value [' . $region->getValue() . '] is not valid'); + } + } + + protected function mergeBasePath(UriInterface $uri) : UriInterface + { + return $uri + ->withScheme($this->basePath->getScheme()) + ->withHost($this->basePath->getHost()) + ->withPath($this->basePath->getPath() . $uri->getPath()); + } + + abstract public function get(RequestInterface $request) : string; +} \ No newline at end of file diff --git a/src/ApiClients/Chihiro.php b/src/ApiClients/Chihiro.php new file mode 100644 index 0000000..316ded4 --- /dev/null +++ b/src/ApiClients/Chihiro.php @@ -0,0 +1,32 @@ +basePath = new Uri('https://store.playstation.com/store/api/chihiro/00_09_000/container/' . strtoupper($this->region) . '/' . $this->language . '/999/'); + } + + /** + * @throws ClientExceptionInterface + */ + public function get(RequestInterface $request) : string + { + $response = $this->client->sendRequest( + $request->withUri($this->mergeBasePath($request->getUri())) + ); + + return $response->getBody()->getContents(); + } +} \ No newline at end of file diff --git a/src/ApiClients/GraphQL.php b/src/ApiClients/GraphQL.php new file mode 100644 index 0000000..0ef2a12 --- /dev/null +++ b/src/ApiClients/GraphQL.php @@ -0,0 +1,35 @@ +basePath = new Uri('https://web.np.playstation.com/api/graphql/v1/'); + } + + /** + * @throws ClientExceptionInterface + */ + public function get(RequestInterface $request) : string + { + $response = $this->client->sendRequest( + $request + ->withUri($this->mergeBasePath($request->getUri())) + ->withAddedHeader('x-psn-store-locale-override', $this->region . '-' . strtoupper($this->language)) + ); + + return $response->getBody()->getContents(); + } +} \ No newline at end of file diff --git a/src/Client.php b/src/Client.php index 93327e6..6072e60 100644 --- a/src/Client.php +++ b/src/Client.php @@ -3,21 +3,32 @@ namespace PlaystationStoreApi; +use PlaystationStoreApi\Actions\Catalog; use PlaystationStoreApi\Actions\Product; -use PlaystationStoreApi\Enum\Regions; +use PlaystationStoreApi\ApiClients\Chihiro; +use PlaystationStoreApi\ApiClients\GraphQL; +use PlaystationStoreApi\Enum\Region; +use Psr\Http\Client\ClientInterface; class Client { - protected Regions $region; - protected Request $request; + protected Chihiro $chihiroApiCLient; + protected GraphQL $graphQLApiClient; - public function __construct(Regions $region) { + public function __construct(Region $region, ClientInterface $client) + { - $this->request = new Request($region); + $this->chihiroApiCLient = new Chihiro($region, $client); + $this->graphQLApiClient = new GraphQL($region, $client); } public function product() : Product { - return new Product($this->request); + return new Product($this->chihiroApiCLient); + } + + public function catalog() : Catalog + { + return new Catalog($this->graphQLApiClient); } } \ No newline at end of file diff --git a/src/Enum/Category.php b/src/Enum/Category.php new file mode 100644 index 0000000..782f16c --- /dev/null +++ b/src/Enum/Category.php @@ -0,0 +1,15 @@ +categoryId = $category->getValue(); + $this->sha256Hash = $sha256Hash; + $this->pagination = new Pagination(10); + $this->sorting = new Sorting('productReleaseDate'); + } + + public function categoryId() : mixed + { + return $this->categoryId; + } + + public function sha256Hash() : string + { + return $this->sha256Hash; + } + + public function pagination() : Pagination + { + return $this->pagination; + } + + public function setPagination(Pagination $pagination) : void + { + $this->pagination = $pagination; + } + + public function sorting() : Sorting + { + return $this->sorting; + } + + public function setSorting(Sorting $sorting) : self + { + $this->sorting = $sorting; + return $this; + } +} \ No newline at end of file diff --git a/src/Request.php b/src/Request.php deleted file mode 100644 index 9df1c4e..0000000 --- a/src/Request.php +++ /dev/null @@ -1,47 +0,0 @@ -parseRegion($region); - - $this->httpClient = new Client([ - 'base_uri' => 'https://store.playstation.com/store/api/chihiro/00_09_000/container/'.strtoupper($this->region).'/'.$this->language.'/999/', - 'timeout' => 10, - ]); - } - - protected function parseRegion(Regions $region) : void - { - if ($result = explode('-', $region->getValue())) { - $this->region = array_pop($result); - $this->language = implode('-', $result); - } else { - throw new \UnexpectedValueException('The value ['.$region->getValue().'] is not valid'); - } - } - - /** - * @param string $pageId - * @param array $params - * - * @return string - * @throws \GuzzleHttp\Exception\GuzzleException - */ - public function get(string $pageId, array $params = []) : string - { - return $this->httpClient->get($pageId, $params)->getBody()->getContents(); - } -} \ No newline at end of file diff --git a/src/ValueObject/Pagination.php b/src/ValueObject/Pagination.php new file mode 100644 index 0000000..9bbfbbe --- /dev/null +++ b/src/ValueObject/Pagination.php @@ -0,0 +1,26 @@ +size = $size; + $this->offset = $offset; + } + + public function size() : int + { + return $this->size; + } + + public function offset() : int + { + return $this->offset; + } +} \ No newline at end of file diff --git a/src/ValueObject/Sorting.php b/src/ValueObject/Sorting.php new file mode 100644 index 0000000..a09b2d5 --- /dev/null +++ b/src/ValueObject/Sorting.php @@ -0,0 +1,29 @@ +fieldName = $fieldName; + $this->isAscending = (isset($sortingDirection) ? $sortingDirection->getValue() : SortingDirection::DESC) === true; + } + + public function fieldName() : string + { + return $this->fieldName; + } + + public function isAscending() : bool + { + return $this->isAscending; + } + +} \ No newline at end of file