Skip to content

Commit 93810b1

Browse files
committed
Added forceToken support for pricing endpoints
1 parent adbb569 commit 93810b1

10 files changed

Lines changed: 129 additions & 31 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## 4.2.0 - 2022-02-10
8+
9+
### Added
10+
11+
- support for `forceToken` parameter for `updateProductPricing` and `updateVariantPricing` methods of `Article` client
12+
- new `PriceProtectionException` thrown when API returns error with `PRICE_PROTECTION_ERROR` code, used to obtain force token using `getForceToken` method
13+
714
## 4.1.0 - 2021-12-16
815

916
### Added

doc/Article.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ Example above prints out
317317

318318
## Update product pricing
319319

320-
Method expects `product` ID and [Pricing](../src/Article/Entity/Common/Pricing.php) entity and does not return anything.
320+
Method expects `product` ID, [Pricing](../src/Article/Entity/Common/Pricing.php) entity and an optional `forceToken` and does not return anything.
321321

322322
```php
323323
/** @var MpApiClient\Common\Interfaces\ArticleClientInterface $articleClient */
@@ -638,14 +638,16 @@ Example above prints out
638638

639639
## Update variant pricing
640640

641-
Method expects `product` and `variant` IDs and [Pricing](../src/Article/Entity/Common/Pricing.php) entity and does not return anything.
641+
Method expects `product` and `variant` IDs, [Pricing](../src/Article/Entity/Common/Pricing.php) entity and an optional `forceToken` and does not return anything.
642642

643643
```php
644644
/** @var MpApiClient\Common\Interfaces\ArticleClientInterface $articleClient */
645+
/** @var MpApiClient\Exception\PriceProtectionException $e */
645646
$articleClient->updateVariantPricing(
646647
'my-product-id',
647648
'my-variant-id',
648-
new Pricing(99.9, 112.0, 80.5)
649+
new Pricing(99.9, 112.0, 80.5),
650+
$e->getForceToken()
649651
);
650652
```
651653

doc/Exception.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,36 @@ appropriate `@throws` tags.
1313

1414
## [IncorrectDataTypeException](../src/Exception/IncorrectDataTypeException.php)
1515

16+
- Extends [MpApiException](#mpapiexception)
1617
- Thrown when method called expects data of a specific type, but received a different one
1718

1819
## [BadResponseException](../src/Exception/BadResponseException.php)
1920

21+
- Extends [MpApiException](#mpapiexception)
2022
- Thrown when API responded with `4xx` or `5xx` status code that could not be translated to more specific exceptions
21-
- Usually indicates an unknown/unexpected error occurred
23+
- Usually indicates, that an unknown/unexpected error occurred
24+
25+
## [PriceProtectionException](../src/Exception/PriceProtectionException.php)
26+
27+
- Extends [BadResponseException](#badresponseexception)
28+
- Thrown when price protection mechanism is tripped during an article price update
29+
- Contains `getForceToken` method, that may be used to force the price change using a provided token
2230

2331
## [ForbiddenException](../src/Exception/ForbiddenException.php)
2432

33+
- Extends [BadResponseException](#badresponseexception)
2534
- Thrown when API returns `403` status code
2635
- Usually returned on endpoints your account does not have access to
2736

2837
## [NotFoundException](../src/Exception/NotFoundException.php)
2938

39+
- Extends [BadResponseException](#badresponseexception)
3040
- Thrown when API returns `404` status code
3141
- This exception should never be thrown for endpoints with static url (i.e., enums/lists)
3242

3343
## [UnauthorizedException](../src/Exception/UnauthorizedException.php)
3444

45+
- Extends [BadResponseException](#badresponseexception)
3546
- Thrown when API returns `401` status code
3647
- Reasons might include
3748
- you forgot to provide authenticator middleware
@@ -40,16 +51,18 @@ appropriate `@throws` tags.
4051

4152
## [TooManyRequestsException](../src/Exception/TooManyRequestsException.php)
4253

54+
- Extends [BadResponseException](#badresponseexception)
4355
- Thrown when API returns `429` status code
4456
- In that case, you have been rate limited by the API and should slow down your request rate
45-
- API returns rate limit information as part of response headers, which you can easily check
57+
- API returns rate limit information as part of response headers, which can be easily checked
4658

4759
### Example of handling some errors
4860

4961
```php
5062
<?php declare(strict_types=1);
5163

52-
use MpApiClient\Common\Interfaces\ChecksClientInterface;use MpApiClient\Exception\BadResponseException;
64+
use MpApiClient\Common\Interfaces\ChecksClientInterface;
65+
use MpApiClient\Exception\BadResponseException;
5366
use MpApiClient\Exception\IncorrectDataTypeException;
5467
use MpApiClient\Exception\MpApiException;
5568
use MpApiClient\Exception\TooManyRequestsException;

example/Article.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use MpApiClient\Article\Entity\Common\StatusEnum;
1616
use MpApiClient\Common\Authenticators\ClientIdAuthenticator;
1717
use MpApiClient\Exception\MpApiException;
18+
use MpApiClient\Exception\PriceProtectionException;
1819
use MpApiClient\Filter\Filter;
1920
use MpApiClient\Filter\FilterItem;
2021
use MpApiClient\Filter\FilterOperatorEnum;
@@ -231,6 +232,16 @@
231232
'my-product-id',
232233
new Pricing(99.9, 112.0, 80.5)
233234
);
235+
} catch (PriceProtectionException $e) {
236+
try {
237+
$client->article()->updateProductPricing(
238+
'my-product-id',
239+
new Pricing(99.9, 112.0, 80.5),
240+
$e->getForceToken()
241+
);
242+
} catch (MpApiException $e) {
243+
echo 'Unexpected error occurred during product pricing update with force token: ' . $e->getMessage();
244+
}
234245
} catch (MpApiException $e) {
235246
echo 'Unexpected error occurred during product pricing update: ' . $e->getMessage();
236247
}
@@ -429,6 +440,17 @@
429440
'my-variant-id',
430441
new Pricing(99.9, 112.0, 80.5)
431442
);
443+
} catch (PriceProtectionException $e) {
444+
try {
445+
$client->article()->updateVariantPricing(
446+
'my-product-id',
447+
'my-variant-id',
448+
new Pricing(99.9, 112.0, 80.5),
449+
$e->getForceToken()
450+
);
451+
} catch (MpApiException $e) {
452+
echo 'Unexpected error occurred during variant pricing update with force token: ' . $e->getMessage();
453+
}
432454
} catch (MpApiException $e) {
433455
echo 'Unexpected error occurred during variant pricing update: ' . $e->getMessage();
434456
}

src/Article/ArticleClient.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,13 @@ public function getProductPricing(string $productId): Pricing
8787
);
8888
}
8989

90-
public function updateProductPricing(string $productId, Pricing $pricing): void
90+
public function updateProductPricing(string $productId, Pricing $pricing, ?string $forceToken = null): void
9191
{
92-
$this->sendJson('PUT', sprintf(self::PRODUCT_PRICING, $productId), $pricing->getArrayForApi());
92+
$url = sprintf(self::PRODUCT_PRICING, $productId);
93+
if ($forceToken !== null) {
94+
$url = sprintf('%s?force_token=%s', $url, $forceToken);
95+
}
96+
$this->sendJson('PUT', $url, $pricing->getArrayForApi());
9397
}
9498

9599
public function listProductVariants(string $productId, ?Filter $filter): BasicVariantList
@@ -144,9 +148,13 @@ public function getVariantPricing(string $productId, string $variantId): Pricing
144148
);
145149
}
146150

147-
public function updateVariantPricing(string $productId, string $variantId, Pricing $pricing): void
151+
public function updateVariantPricing(string $productId, string $variantId, Pricing $pricing, ?string $forceToken = null): void
148152
{
149-
$this->sendJson('PUT', sprintf(self::VARIANT_PRICING, $productId, $variantId), $pricing->getArrayForApi());
153+
$url = sprintf(self::VARIANT_PRICING, $productId, $variantId);
154+
if ($forceToken !== null) {
155+
$url = sprintf('%s?force_token=%s', $url, $forceToken);
156+
}
157+
$this->sendJson('PUT', $url, $pricing->getArrayForApi());
150158
}
151159

152160
public function updateBatchAvailability(BatchAvailabilityIterator $availability): void

src/Common/Interfaces/ArticleClientInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function getProductPricing(string $productId): Pricing;
5959
* @throws MpApiException
6060
* @deprecated Will be replaced with batch endpoint, similar to BatchAvailability
6161
*/
62-
public function updateProductPricing(string $productId, Pricing $pricing): void;
62+
public function updateProductPricing(string $productId, Pricing $pricing, ?string $forceToken = null): void;
6363

6464
/**
6565
* @throws MpApiException
@@ -102,7 +102,7 @@ public function getVariantPricing(string $productId, string $variantId): Pricing
102102
* @throws MpApiException
103103
* @deprecated Will be replaced with batch endpoint, similar to BatchAvailability
104104
*/
105-
public function updateVariantPricing(string $productId, string $variantId, Pricing $pricing): void;
105+
public function updateVariantPricing(string $productId, string $variantId, Pricing $pricing, ?string $forceToken = null): void;
106106

107107
/**
108108
* @throws MpApiException

src/Exception/BadResponseException.php

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,54 @@ class BadResponseException extends MpApiException
1616
private array $errorCodes;
1717

1818
/**
19-
* @param string $message
20-
* @param int $code
21-
* @param Throwable|null $previous
22-
* @param ErrorCode[] $errorCodes
19+
* @var array<string, mixed>
2320
*/
24-
final private function __construct(string $message = '', int $code = 0, Throwable $previous = null, array $errorCodes = [])
21+
private array $body;
22+
23+
/**
24+
* @param string $message
25+
* @param int $code
26+
* @param Throwable|null $previous
27+
* @param array<string, mixed> $body
28+
* @param ErrorCode[] $errorCodes
29+
*/
30+
final private function __construct(string $message = '', int $code = 0, Throwable $previous = null, array $body = [], array $errorCodes = [])
2531
{
2632
parent::__construct($message, $code, $previous);
33+
$this->body = $body;
2734
$this->errorCodes = $errorCodes;
2835
}
2936

3037
/**
31-
* @param string $message
32-
* @param int $code
33-
* @param GuzzleBadResponseException $previous
34-
* @param array<int, array<string, mixed>> $errorCodes
35-
* @return static
38+
* @param string $message
39+
* @param int $code
40+
* @param GuzzleBadResponseException $previous
41+
* @param array<string, mixed> $body
42+
* @return BadResponseException
43+
*
44+
* @internal
45+
*/
46+
public static function createFromGuzzle(string $message, int $code, GuzzleBadResponseException $previous, array $body = []): BadResponseException
47+
{
48+
$errorCodes = array_map(fn(array $item): ErrorCode => ErrorCode::createFromApi($item), $body['errorCodes'] ?? []);
49+
if ($errorCodes === []) {
50+
return new static($message, $code, $previous, $body);
51+
}
52+
53+
switch ($errorCodes[0]->getCode()) {
54+
case PriceProtectionException::ERROR_CODE:
55+
return new PriceProtectionException($message, $code, $previous, $body, $errorCodes);
56+
default:
57+
return new static($message, $code, $previous, $body, $errorCodes);
58+
}
59+
}
60+
61+
/**
62+
* @return array<string, mixed>
3663
*/
37-
public static function createFromGuzzle(string $message, int $code, GuzzleBadResponseException $previous, array $errorCodes = []): BadResponseException
64+
public function getBody(): array
3865
{
39-
return new static(
40-
$message,
41-
$code,
42-
$previous,
43-
array_map(fn(array $item): ErrorCode => ErrorCode::createFromApi($item), $errorCodes),
44-
);
66+
return $this->body;
4567
}
4668

4769
/**

src/Exception/ExceptionFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public static function fromGuzzleBadResponse(GuzzleBadResponseException $e): MpA
3939
return TooManyRequestsException::createFromGuzzle($message, $code, $e);
4040
default:
4141
/** @psalm-suppress PossiblyInvalidArgument - https://github.com/vimeo/psalm/issues/4295 */
42-
return BadResponseException::createFromGuzzle($message, $code, $e, $body['errorCodes'] ?? []);
42+
return BadResponseException::createFromGuzzle($message, $code, $e, $body);
4343
}
4444
}
4545

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace MpApiClient\Exception;
4+
5+
use LogicException;
6+
7+
final class PriceProtectionException extends BadResponseException
8+
{
9+
10+
public const ERROR_CODE = 'PRICE_PROTECTION_ERROR';
11+
12+
/**
13+
* @throws LogicException
14+
*/
15+
public function getForceToken(): string
16+
{
17+
if (!isset($this->getBody()['data']['data']['forceToken'])) {
18+
throw new LogicException('forceToken not present in response');
19+
}
20+
21+
return (string) $this->getBody()['data']['data']['forceToken'];
22+
}
23+
24+
}

src/MpApiClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ final class MpApiClient implements ClientInterface, MpApiClientInterface
2929
{
3030

3131
const APP_NAME = 'mp-api-client';
32-
const APP_VERSION = '4.1.0';
32+
const APP_VERSION = '4.2.0';
3333

3434
private BrandClientInterface $brandClient;
3535
private CategoryClientInterface $categoryClient;

0 commit comments

Comments
 (0)