add error response object

This commit is contained in:
David Remer 2020-04-13 11:52:50 +03:00
parent 5ca109ec97
commit 76b3733417
18 changed files with 417 additions and 85 deletions

View file

@ -3,14 +3,14 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
class CacheClearTest extends TestCase
{
public function testClear() {
public function testClear()
{
$testee = new Cache('group');
expect('wp_cache_flush')
->once()
@ -18,11 +18,12 @@ class CacheClearTest extends TestCase
$this->assertTrue($testee->clear());
}
public function testClearReturnsFalseWhenCacheWasNotCleared() {
public function testClearReturnsFalseWhenCacheWasNotCleared()
{
$testee = new Cache('group');
expect('wp_cache_flush')
->once()
->andReturn(false);
$this->assertFalse($testee->clear());
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class CacheDeleteTest extends TestCase
{
public function testDelete() {
public function testDelete()
{
$testee = new Cache('group');
expect('wp_cache_delete')
->once()
@ -20,7 +20,8 @@ class CacheDeleteTest extends TestCase
$this->assertTrue($testee->delete('key'));
}
public function testDeleteFails() {
public function testDeleteFails()
{
$testee = new Cache('group');
expect('wp_cache_delete')
->once()
@ -29,9 +30,10 @@ class CacheDeleteTest extends TestCase
$this->assertFalse($testee->delete('key'));
}
public function testDeleteThrowsErrorIfKeyIsNotAString() {
public function testDeleteThrowsErrorIfKeyIsNotAString()
{
$testee = new Cache('group');
$this->expectException(InvalidCacheArgumentException::class);
$testee->delete(123);
}
}
}

View file

@ -10,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class CacheGetTest extends TestCase
{
public function testGetHasValueInCache() {
public function testGetHasValueInCache()
{
$this->markTestIncomplete(
'This test has not been implemented yet. Problem is the $found reference'
);
@ -18,7 +19,7 @@ class CacheGetTest extends TestCase
$expected = 'value';
expect('wp_cache_get')
->once()
->andReturnUsing(function($key, $group, $force, &$lastFound) use ($expected) {
->andReturnUsing(function ($key, $group, $force, &$lastFound) use ($expected) {
$lastFound = true;
return $expected;
});
@ -26,7 +27,8 @@ class CacheGetTest extends TestCase
$this->assertEquals($expected, $result);
}
public function testGetHasValueNotInCache() {
public function testGetHasValueNotInCache()
{
$this->markTestIncomplete(
'This test has not been implemented yet. Problem is the $found reference'
);
@ -40,10 +42,10 @@ class CacheGetTest extends TestCase
$this->assertEquals($expected, $result);
}
public function testGetThrowsExceptionWhenKeyIsNotAString() {
public function testGetThrowsExceptionWhenKeyIsNotAString()
{
$testee = new Cache('group');
$this->expectException(InvalidCacheArgumentException::class);
$testee->get(123);
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class CacheSetTest extends TestCase
{
public function testSet() {
public function testSet()
{
$testee = new Cache('group');
expect('wp_cache_set')
->once()
@ -21,7 +21,8 @@ class CacheSetTest extends TestCase
$this->assertTrue($setValue);
}
public function testSetReturnsFalseWhenCacheNotSet() {
public function testSetReturnsFalseWhenCacheNotSet()
{
$testee = new Cache('group');
expect('wp_cache_set')
->once()
@ -31,9 +32,10 @@ class CacheSetTest extends TestCase
$this->assertFalse($setValue);
}
public function testSetThrowsErrorWhenKeyIsNotAString() {
public function testSetThrowsErrorWhenKeyIsNotAString()
{
$testee = new Cache('group');
$this->expectException(InvalidCacheArgumentException::class);
$testee->set(123, 'value');
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,8 +10,8 @@ use function Brain\Monkey\Functions\expect;
class DeleteMultipleTest extends TestCase
{
public function testDeleteMultiple() {
public function testDeleteMultiple()
{
$testee = new Transient('group');
$keys = ['key1', 'key2'];
expect('delete_transient')->once()->with('groupkey1')->andReturn(true);
@ -20,18 +19,20 @@ class DeleteMultipleTest extends TestCase
$this->assertTrue($testee->deleteMultiple($keys));
}
public function testDeleteMultipleThrowsErrorIfKeysAreNotIterateable() {
public function testDeleteMultipleThrowsErrorIfKeysAreNotIterateable()
{
$testee = new Transient('group');
$keys = new \stdClass();
$this->expectException(InvalidCacheArgumentException::class);
$testee->deleteMultiple($keys);
}
public function testDeleteMultipleThrowsErrorIfKeysAreNotStrings() {
public function testDeleteMultipleThrowsErrorIfKeysAreNotStrings()
{
$testee = new Transient('group');
$keys = [1];
$this->expectException(InvalidCacheArgumentException::class);
$testee->deleteMultiple($keys);
}
}
}

View file

@ -10,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class GetMultipleTest extends TestCase
{
public function testGetMultiple() {
public function testGetMultiple()
{
$testee = new Transient('group');
expect('get_transient')
->times(3)
@ -27,17 +28,20 @@ class GetMultipleTest extends TestCase
$this->assertTrue($value === 1);
}
}
public function testGetMultipleThrowsErrorIfParamIsNotIterateable() {
public function testGetMultipleThrowsErrorIfParamIsNotIterateable()
{
$testee = new Transient('group');
$this->expectException(InvalidCacheArgumentException::class);
$keys = new \stdClass();
$testee->getMultiple($keys);
}
public function testGetMultipleThrowsErrorIfOneKeyIsNotAString() {
public function testGetMultipleThrowsErrorIfOneKeyIsNotAString()
{
$testee = new Transient('group');
$this->expectException(InvalidCacheArgumentException::class);
$keys = [1];
$testee->getMultiple($keys);
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class SetMultipleTest extends TestCase
{
public function testSetMultiple() {
public function testSetMultiple()
{
$testee = new Transient('group');
$values = [
'key1' => 'value1',
@ -21,7 +21,7 @@ class SetMultipleTest extends TestCase
expect('set_transient')
->times(3)
->andReturnUsing(
function($key, $value) use ($values) {
function ($key, $value) use ($values) {
$key = str_replace('group', '', $key);
return isset($values[$key]) && $values[$key] === $value;
}
@ -30,17 +30,19 @@ class SetMultipleTest extends TestCase
$this->assertTrue($testee->setMultiple($values));
}
public function testSetMultipleThrowsErrorIfNotIterateable() {
public function testSetMultipleThrowsErrorIfNotIterateable()
{
$testee = new Transient('group');
$values = new \stdClass();
$this->expectException(InvalidCacheArgumentException::class);
$testee->setMultiple($values);
}
public function testSetMultipleThrowsErrorIfKeyIsNotString() {
public function testSetMultipleThrowsErrorIfKeyIsNotString()
{
$testee = new Transient('group');
$values = [1];
$this->expectException(InvalidCacheArgumentException::class);
$testee->setMultiple($values);
}
}
}

View file

@ -3,14 +3,14 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
class TransientClearTest extends TestCase
{
public function testClearWithObjectCache() {
public function testClearWithObjectCache()
{
$testee = new Transient('group');
expect('wp_using_ext_object_cache')
->once()
@ -20,7 +20,9 @@ class TransientClearTest extends TestCase
->andReturn(true);
$this->assertTrue($testee->clear());
}
public function testClearWithObjectCacheFails() {
public function testClearWithObjectCacheFails()
{
$testee = new Transient('group');
expect('wp_using_ext_object_cache')
->once()
@ -31,7 +33,8 @@ class TransientClearTest extends TestCase
$this->assertFalse($testee->clear());
}
public function testClearReturnsFalseWhenObjectCacheIsNotUsed() {
public function testClearReturnsFalseWhenObjectCacheIsNotUsed()
{
$testee = new Transient('group');
expect('wp_using_ext_object_cache')
->once()
@ -41,4 +44,4 @@ class TransientClearTest extends TestCase
->andReturn(true);
$this->assertFalse($testee->clear());
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class TransientDeleteTest extends TestCase
{
public function testDelete() {
public function testDelete()
{
$testee = new Transient('group');
expect('delete_transient')
->once()
@ -20,7 +20,8 @@ class TransientDeleteTest extends TestCase
$this->assertTrue($testee->delete('key'));
}
public function testDeleteFails() {
public function testDeleteFails()
{
$testee = new Transient('group');
expect('delete_transient')
->once()
@ -29,10 +30,10 @@ class TransientDeleteTest extends TestCase
$this->assertFalse($testee->delete('key'));
}
public function testDeleteThrowsErrorIfKeyIsNotAString() {
public function testDeleteThrowsErrorIfKeyIsNotAString()
{
$testee = new Transient('group');
$this->expectException(InvalidCacheArgumentException::class);
$testee->delete(123);
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class TransientGetTest extends TestCase
{
public function testGetHasValueInCache() {
public function testGetHasValueInCache()
{
$testee = new Transient('group');
$expected = 'value';
expect('get_transient')
@ -22,7 +22,8 @@ class TransientGetTest extends TestCase
$this->assertEquals($expected, $result);
}
public function testGetHasValueNotInCache() {
public function testGetHasValueNotInCache()
{
$testee = new Transient('group');
$expected = 'value';
expect('get_transient')
@ -33,10 +34,10 @@ class TransientGetTest extends TestCase
$this->assertEquals($expected, $result);
}
public function testGetThrowsExceptionWhenKeyIsNotAString() {
public function testGetThrowsExceptionWhenKeyIsNotAString()
{
$testee = new Transient('group');
$this->expectException(InvalidCacheArgumentException::class);
$testee->get(123);
}
}
}

View file

@ -3,16 +3,16 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
class TransientHasTest extends TestCase
{
public function testHas() {
public function testHas()
{
$testee = new Transient('group');
expect('get_transient')->with('groupkey')->andReturn(1);
$this->assertTrue($testee->has('key'));
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Cache;
use Inpsyde\CacheModule\Exception\InvalidCacheArgumentException;
use PHPUnit\Framework\TestCase;
use function Brain\Monkey\Functions\expect;
@ -11,7 +10,8 @@ use function Brain\Monkey\Functions\expect;
class TransientSetTest extends TestCase
{
public function testSet() {
public function testSet()
{
$testee = new Transient('group');
expect('set_transient')
->once()
@ -21,7 +21,8 @@ class TransientSetTest extends TestCase
$this->assertTrue($setValue);
}
public function testSetReturnsFalseWhenCacheNotSet() {
public function testSetReturnsFalseWhenCacheNotSet()
{
$testee = new Transient('group');
expect('set_transient')
->once()
@ -31,9 +32,10 @@ class TransientSetTest extends TestCase
$this->assertFalse($setValue);
}
public function testSetThrowsErrorWhenKeyIsNotAString() {
public function testSetThrowsErrorWhenKeyIsNotAString()
{
$testee = new Transient('group');
$this->expectException(InvalidCacheArgumentException::class);
$testee->set(123, 'value');
}
}
}

View file

@ -3,7 +3,6 @@ declare(strict_types=1);
namespace Inpsyde\CacheModule\Provider;
use Inpsyde\CacheModule\Cache\Cache;
use Inpsyde\CacheModule\Cache\Transient;
use PHPUnit\Framework\TestCase;
@ -12,7 +11,8 @@ use function Brain\Monkey\Functions\expect;
class CacheProviderTest extends TestCase
{
public function test_transientForKey() {
public function test_transientForKey()
{
$testee = new CacheProvider();
$result = $testee->transientForKey('group');
@ -23,7 +23,9 @@ class CacheProviderTest extends TestCase
$this->assertTrue($result->set('key', 'value'), 'Group has not been set correctly.');
$this->assertTrue(is_a($result, Transient::class));
}
public function test_cacheOrTransientForKeyReturnsCache() {
public function test_cacheOrTransientForKeyReturnsCache()
{
$testee = new CacheProvider();
expect('wp_using_ext_object_cache')
->once()
@ -32,7 +34,9 @@ class CacheProviderTest extends TestCase
$this->assertInstanceOf(Cache::class, $result);
}
public function test_cacheOrTransientForKeyReturnsTransient() {
public function test_cacheOrTransientForKeyReturnsTransient()
{
$testee = new CacheProvider();
expect('wp_using_ext_object_cache')
->once()
@ -41,7 +45,8 @@ class CacheProviderTest extends TestCase
$this->assertInstanceOf(Transient::class, $result);
}
public function test_cacheForKey() {
public function test_cacheForKey()
{
$testee = new CacheProvider();
$result = $testee->cacheForKey('group');
expect('wp_cache_set')
@ -51,4 +56,4 @@ class CacheProviderTest extends TestCase
$this->assertTrue($result->set('key', 'value'), 'Group has not been set correctly.');
$this->assertTrue(is_a($result, Cache::class));
}
}
}

View file

@ -9,6 +9,7 @@ use Inpsyde\PayPalCommerce\ApiClient\Authentication\Bearer;
use Inpsyde\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use Inpsyde\PayPalCommerce\ApiClient\Factory\AddressFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\AmountFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\ErrorResponseCollectionFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\ItemFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\LineItemFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\OrderFactory;
@ -46,11 +47,13 @@ return [
'api.endpoint.order' => function (ContainerInterface $container) : OrderEndpoint {
$orderFactory = $container->get('api.factory.order');
$patchCollectionFactory = $container->get('api.factory.patch-collection-factory');
$errorResponseFactory = $container->get('api.factory.response-error');
return new OrderEndpoint(
$container->get('api.host'),
$container->get('api.bearer'),
$orderFactory,
$patchCollectionFactory
$patchCollectionFactory,
$errorResponseFactory
);
},
'api.cart-repository' => function (ContainerInterface $container) : CartRepository {
@ -107,6 +110,9 @@ return [
'api.factory.address' => function (ContainerInterface $container) : AddressFactory {
return new AddressFactory();
},
'api.factory.response-error' => function (ContainerInterface $container) : ErrorResponseCollectionFactory {
return new ErrorResponseCollectionFactory();
},
'api.factory.order' => function (ContainerInterface $container) : OrderFactory {
$purchaseUnitFactory = $container->get('api.factory.purchase-unit');
$payerFactory = $container->get('api.factory.payer');

View file

@ -4,10 +4,12 @@ declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Endpoint;
use Inpsyde\PayPalCommerce\ApiClient\Authentication\Bearer;
use Inpsyde\PayPalCommerce\ApiClient\Entity\ErrorResponse;
use Inpsyde\PayPalCommerce\ApiClient\Entity\Order;
use Inpsyde\PayPalCommerce\ApiClient\Entity\OrderStatus;
use Inpsyde\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use Inpsyde\PayPalCommerce\ApiClient\Exception\RuntimeException;
use Inpsyde\PayPalCommerce\ApiClient\Factory\ErrorResponseCollectionFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\OrderFactory;
use Inpsyde\PayPalCommerce\ApiClient\Factory\PatchCollectionFactory;
@ -18,17 +20,20 @@ class OrderEndpoint
private $bearer;
private $orderFactory;
private $patchCollectionFactory;
private $errorResponseFactory;
public function __construct(
string $host,
Bearer $bearer,
OrderFactory $orderFactory,
PatchCollectionFactory $patchCollectionFactory
PatchCollectionFactory $patchCollectionFactory,
ErrorResponseCollectionFactory $errorResponseFactory
) {
$this->host = $host;
$this->bearer = $bearer;
$this->orderFactory = $orderFactory;
$this->patchCollectionFactory = $patchCollectionFactory;
$this->errorResponseFactory = $errorResponseFactory;
}
public function createForPurchaseUnits(PurchaseUnit ...$items) : Order
@ -53,10 +58,21 @@ class OrderEndpoint
'body' => json_encode($data),
];
$response = wp_remote_post($url, $args);
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 201) {
if (is_wp_error($response)) {
$this->handleResponseWpError($url, $args);
throw new RuntimeException(__('Could not create order.', 'woocommerce-paypal-commerce-gateway'));
}
$json = json_decode($response['body']);
if (wp_remote_retrieve_response_code($response) !== 201) {
$errors = $this->errorResponseFactory->fromPayPalResponse(
$json,
(int)wp_remote_retrieve_response_code($response),
$url,
$args
);
add_action('woocommerce-paypal-commerce-gateway.error', $errors);
throw new RuntimeException(__('Could not create order.', 'woocommerce-paypal-commerce-gateway'));
}
$order = $this->orderFactory->fromPayPalResponse($json);
return $order;
}
@ -78,22 +94,24 @@ class OrderEndpoint
$response = wp_remote_post($url, $args);
if (is_wp_error($response)) {
$this->handleResponseWpError($url, $args);
throw new RuntimeException(__('Could not capture order.', 'woocommerce-paypal-commerce-gateway'));
}
if (wp_remote_retrieve_response_code($response) !== 422) {
$json = json_decode($response['body']);
if (is_array($json->details) && count(array_filter(
$json->details,
function ($detail) : bool {
return $detail->issue === 'ORDER_ALREADY_CAPTURED';
}
))
) {
$json = json_decode($response['body']);
if (wp_remote_retrieve_response_code($response) !== 201) {
$errors = $this->errorResponseFactory->fromPayPalResponse(
$json,
(int)wp_remote_retrieve_response_code($response),
$url,
$args
);
// If the order has already been captured, we return the updated order.
if ($errors->hasErrorCode(ErrorResponse::ORDER_ALREADY_CAPTURED)) {
return $this->order($order->id());
}
}
if (wp_remote_retrieve_response_code($response) !== 201) {
add_action('woocommerce-paypal-commerce-gateway.error', $errors);
throw new RuntimeException(__('Could not capture order.', 'woocommerce-paypal-commerce-gateway'));
}
$json = json_decode($response['body']);
@ -112,10 +130,21 @@ class OrderEndpoint
],
];
$response = wp_remote_get($url, $args);
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
if (is_wp_error($response)) {
$this->handleResponseWpError($url, $args);
throw new RuntimeException(__('Could not retrieve order.', 'woocommerce-paypal-commerce-gateway'));
}
$json = json_decode($response['body']);
if (wp_remote_retrieve_response_code($response) !== 200) {
$errors = $this->errorResponseFactory->fromPayPalResponse(
$json,
(int) wp_remote_retrieve_response_code($response),
$url,
$args
);
add_action('woocommerce-paypal-commerce-gateway.error', $errors);
throw new RuntimeException(__('Could not retrieve order.', 'woocommerce-paypal-commerce-gateway'));
}
return $this->orderFactory->fromPayPalResponse($json);
}
@ -138,11 +167,33 @@ class OrderEndpoint
'body' => json_encode($patches->toArray()),
];
$response = wp_remote_post($url, $args);
if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 204) {
if (is_wp_error($response)) {
$this->handleResponseWpError($url, $args);
throw new RuntimeException(__('Could not retrieve order.', 'woocommerce-paypal-commerce-gateway'));
}
if (wp_remote_retrieve_response_code($response) !== 204) {
$json = json_decode($response['body']);
$errors = $this->errorResponseFactory->fromPayPalResponse(
$json,
(int)wp_remote_retrieve_response_code($response),
$url,
$args
);
add_action('woocommerce-paypal-commerce-gateway.error', $errors);
throw new RuntimeException(__('Could not patch order.', 'woocommerce-paypal-commerce-gateway'));
}
$newOrder = $this->order($orderToUpdate->id());
return $newOrder;
}
private function handleResponseWpError(string $url, array $args)
{
$errors = $this->errorResponseFactory->unknownError(
$url,
$args
);
add_action('woocommerce-paypal-commerce-gateway.error', $errors);
}
}

View file

@ -0,0 +1,156 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class ErrorResponse
{
/* Order error codes */
const ACTION_DOES_NOT_MATCH_INTENT='ACTION_DOES_NOT_MATCH_INTENT';
const AGREEMENT_ALREADY_CANCELLED='AGREEMENT_ALREADY_CANCELLED';
const AMOUNT_CANNOT_BE_SPECIFIED='AMOUNT_CANNOT_BE_SPECIFIED';
const AMOUNT_MISMATCH='AMOUNT_MISMATCH';
const AMOUNT_NOT_PATCHABLE='AMOUNT_NOT_PATCHABLE';
const AUTH_CAPTURE_NOT_ENABLED='AUTH_CAPTURE_NOT_ENABLED';
const AUTHENTICATION_FAILURE='AUTHENTICATION_FAILURE';
const AUTHORIZATION_AMOUNT_EXCEEDED='AUTHORIZATION_AMOUNT_EXCEEDED';
const AUTHORIZATION_CURRENCY_MISMATCH='AUTHORIZATION_CURRENCY_MISMATCH';
const BILLING_AGREEMENT_NOT_FOUND='BILLING_AGREEMENT_NOT_FOUND';
const CANNOT_BE_NEGATIVE='CANNOT_BE_NEGATIVE';
const CANNOT_BE_ZERO_OR_NEGATIVE='CANNOT_BE_ZERO_OR_NEGATIVE';
const CARD_TYPE_NOT_SUPPORTED='CARD_TYPE_NOT_SUPPORTED';
const INVALID_SECURITY_CODE_LENGTH='INVALID_SECURITY_CODE_LENGTH';
const CITY_REQUIRED='CITY_REQUIRED';
const COMPLIANCE_VIOLATION='COMPLIANCE_VIOLATION';
const CONSENT_NEEDED='CONSENT_NEEDED';
const CURRENCY_NOT_SUPPORTED_FOR_CARD_TYPE='CURRENCY_NOT_SUPPORTED_FOR_CARD_TYPE';
const CURRENCY_NOT_SUPPORTED_FOR_COUNTRY='CURRENCY_NOT_SUPPORTED_FOR_COUNTRY';
const DECIMAL_PRECISION='DECIMAL_PRECISION';
const DOMESTIC_TRANSACTION_REQUIRED='DOMESTIC_TRANSACTION_REQUIRED';
const DUPLICATE_INVOICE_ID='DUPLICATE_INVOICE_ID';
const DUPLICATE_REQUEST_ID='DUPLICATE_REQUEST_ID';
const FIELD_NOT_PATCHABLE='FIELD_NOT_PATCHABLE';
const INSTRUMENT_DECLINED='INSTRUMENT_DECLINED';
const INTERNAL_SERVER_ERROR='INTERNAL_SERVER_ERROR';
const INTERNAL_SERVICE_ERROR='INTERNAL_SERVICE_ERROR';
const INVALID_ACCOUNT_STATUS='INVALID_ACCOUNT_STATUS';
const INVALID_ARRAY_MAX_ITEMS='INVALID_ARRAY_MAX_ITEMS';
const INVALID_ARRAY_MIN_ITEMS='INVALID_ARRAY_MIN_ITEMS';
const INVALID_COUNTRY_CODE='INVALID_COUNTRY_CODE';
const INVALID_CURRENCY_CODE='INVALID_CURRENCY_CODE';
const INVALID_JSON_POINTER_FORMAT='INVALID_JSON_POINTER_FORMAT';
const INVALID_PARAMETER_SYNTAX='INVALID_PARAMETER_SYNTAX';
const INVALID_PARAMETER_VALUE='INVALID_PARAMETER_VALUE';
const INVALID_PARAMETER='INVALID_PARAMETER';
const INVALID_PATCH_OPERATION='INVALID_PATCH_OPERATION';
const INVALID_PAYER_ID='INVALID_PAYER_ID';
const INVALID_RESOURCE_ID='INVALID_RESOURCE_ID';
const INVALID_STRING_LENGTH='INVALID_STRING_LENGTH';
const ITEM_TOTAL_MISMATCH='ITEM_TOTAL_MISMATCH';
const ITEM_TOTAL_REQUIRED='ITEM_TOTAL_REQUIRED';
const MAX_AUTHORIZATION_COUNT_EXCEEDED='MAX_AUTHORIZATION_COUNT_EXCEEDED';
const MAX_NUMBER_OF_PAYMENT_ATTEMPTS_EXCEEDED='MAX_NUMBER_OF_PAYMENT_ATTEMPTS_EXCEEDED';
const MAX_VALUE_EXCEEDED='MAX_VALUE_EXCEEDED';
const MISSING_REQUIRED_PARAMETER='MISSING_REQUIRED_PARAMETER';
const MISSING_SHIPPING_ADDRESS='MISSING_SHIPPING_ADDRESS';
const MULTI_CURRENCY_ORDER='MULTI_CURRENCY_ORDER';
const MULTIPLE_SHIPPING_ADDRESS_NOT_SUPPORTED='MULTIPLE_SHIPPING_ADDRESS_NOT_SUPPORTED';
const MULTIPLE_SHIPPING_OPTION_SELECTED='MULTIPLE_SHIPPING_OPTION_SELECTED';
const INVALID_PICKUP_ADDRESS='INVALID_PICKUP_ADDRESS';
const NOT_AUTHORIZED='NOT_AUTHORIZED';
const NOT_ENABLED_FOR_CARD_PROCESSING='NOT_ENABLED_FOR_CARD_PROCESSING';
const NOT_PATCHABLE='NOT_PATCHABLE';
const NOT_SUPPORTED='NOT_SUPPORTED';
const ORDER_ALREADY_AUTHORIZED='ORDER_ALREADY_AUTHORIZED';
const ORDER_ALREADY_CAPTURED='ORDER_ALREADY_CAPTURED';
const ORDER_ALREADY_COMPLETED='ORDER_ALREADY_COMPLETED';
const ORDER_CANNOT_BE_SAVED='ORDER_CANNOT_BE_SAVED';
const ORDER_COMPLETED_OR_VOIDED='ORDER_COMPLETED_OR_VOIDED';
const ORDER_EXPIRED='ORDER_EXPIRED';
const ORDER_NOT_APPROVED='ORDER_NOT_APPROVED';
const ORDER_NOT_SAVED='ORDER_NOT_SAVED';
const ORDER_PREVIOUSLY_VOIDED='ORDER_PREVIOUSLY_VOIDED';
const PARAMETER_VALUE_NOT_SUPPORTED='PARAMETER_VALUE_NOT_SUPPORTED';
const PATCH_PATH_REQUIRED='PATCH_PATH_REQUIRED';
const PATCH_VALUE_REQUIRED='PATCH_VALUE_REQUIRED';
const PAYEE_ACCOUNT_INVALID='PAYEE_ACCOUNT_INVALID';
const PAYEE_ACCOUNT_LOCKED_OR_CLOSED='PAYEE_ACCOUNT_LOCKED_OR_CLOSED';
const PAYEE_ACCOUNT_RESTRICTED='PAYEE_ACCOUNT_RESTRICTED';
const PAYEE_BLOCKED_TRANSACTION='PAYEE_BLOCKED_TRANSACTION';
const PAYER_ACCOUNT_LOCKED_OR_CLOSED='PAYER_ACCOUNT_LOCKED_OR_CLOSED';
const PAYER_ACCOUNT_RESTRICTED='PAYER_ACCOUNT_RESTRICTED';
const PAYER_CANNOT_PAY='PAYER_CANNOT_PAY';
const PAYER_CONSENT_REQUIRED='PAYER_CONSENT_REQUIRED';
const PAYER_COUNTRY_NOT_SUPPORTED='PAYER_COUNTRY_NOT_SUPPORTED';
const PAYEE_NOT_ENABLED_FOR_CARD_PROCESSING='PAYEE_NOT_ENABLED_FOR_CARD_PROCESSING';
const PAYMENT_INSTRUCTION_REQUIRED='PAYMENT_INSTRUCTION_REQUIRED';
const PERMISSION_DENIED='PERMISSION_DENIED';
const POSTAL_CODE_REQUIRED='POSTAL_CODE_REQUIRED';
const PREFERRED_SHIPPING_OPTION_AMOUNT_MISMATCH='PREFERRED_SHIPPING_OPTION_AMOUNT_MISMATCH';
const REDIRECT_PAYER_FOR_ALTERNATE_FUNDING='REDIRECT_PAYER_FOR_ALTERNATE_FUNDING';
const REFERENCE_ID_NOT_FOUND='REFERENCE_ID_NOT_FOUND';
const REFERENCE_ID_REQUIRED='REFERENCE_ID_REQUIRED';
const DUPLICATE_REFERENCE_ID='DUPLICATE_REFERENCE_ID';
const SHIPPING_ADDRESS_INVALID='SHIPPING_ADDRESS_INVALID';
const SHIPPING_OPTION_NOT_SELECTED='SHIPPING_OPTION_NOT_SELECTED';
const SHIPPING_OPTIONS_NOT_SUPPORTED='SHIPPING_OPTIONS_NOT_SUPPORTED';
const TAX_TOTAL_MISMATCH='TAX_TOTAL_MISMATCH';
const TAX_TOTAL_REQUIRED='TAX_TOTAL_REQUIRED';
const TRANSACTION_AMOUNT_EXCEEDS_MONTHLY_MAX_LIMIT='TRANSACTION_AMOUNT_EXCEEDS_MONTHLY_MAX_LIMIT';
const TRANSACTION_BLOCKED_BY_PAYEE='TRANSACTION_BLOCKED_BY_PAYEE';
const TRANSACTION_LIMIT_EXCEEDED='TRANSACTION_LIMIT_EXCEEDED';
const TRANSACTION_RECEIVING_LIMIT_EXCEEDED='TRANSACTION_RECEIVING_LIMIT_EXCEEDED';
const TRANSACTION_REFUSED='TRANSACTION_REFUSED';
const UNSUPPORTED_INTENT='UNSUPPORTED_INTENT';
const UNSUPPORTED_PATCH_PARAMETER_VALUE='UNSUPPORTED_PATCH_PARAMETER_VALUE';
const UNSUPPORTED_PAYMENT_INSTRUCTION='UNSUPPORTED_PAYMENT_INSTRUCTION';
const PAYEE_ACCOUNT_NOT_SUPPORTED='PAYEE_ACCOUNT_NOT_SUPPORTED';
const PAYEE_ACCOUNT_NOT_VERIFIED='PAYEE_ACCOUNT_NOT_VERIFIED';
const PAYEE_NOT_CONSENTED='PAYEE_NOT_CONSENTED';
private $code;
private $message;
private $httpCode;
private $url;
private $args;
public function __construct(string $code, string $message, int $httpCode, string $url, array $args)
{
$this->code = $code;
$this->message = $message;
$this->httpCode = $httpCode;
$this->url = $url;
$this->args = $args;
}
public function code() : string
{
return $this->code;
}
public function is(string $compare) : bool
{
return $this->code() === $compare;
}
public function message() : string
{
return $this->message;
}
public function httpCode() : int
{
return $this->httpCode;
}
public function url() : string
{
return $this->url;
}
public function args() : array
{
return $this->args;
}
}

View file

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Entity;
class ErrorResponseCollection
{
private $errors;
public function __construct(ErrorResponse ...$errors)
{
$this->errors = $errors;
}
/**
* @return ErrorResponse[]
*/
public function errors() : array
{
return $this->errors;
}
public function hasErrorCode(string $code) : bool
{
foreach ($this->errors() as $error) {
if ($error->is($code)) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace Inpsyde\PayPalCommerce\ApiClient\Factory;
use Inpsyde\PayPalCommerce\ApiClient\Entity\ErrorResponse;
use Inpsyde\PayPalCommerce\ApiClient\Entity\ErrorResponseCollection;
class ErrorResponseCollectionFactory
{
public function fromPayPalResponse(
\stdClass $response,
int $statusCode,
string $url,
array $args
) : ErrorResponseCollection {
if (isset($response->error)) {
return new ErrorResponseCollection(
new ErrorResponse(
(string) $response->error,
(isset($response->error->description)) ? (string) $response->error->description : '',
$statusCode,
$url,
$args
)
);
}
if (! isset($response->details) || ! is_array($response->details)) {
return new ErrorResponseCollection();
}
$errors = [];
foreach ($response->details as $detail) {
$errors[] = new ErrorResponse(
(string) $detail->issue,
(string) $detail->description,
$statusCode,
$url,
$args
);
}
return new ErrorResponseCollection(... $errors);
}
public function unknownError(string $url, array $args) : ErrorResponseCollection
{
return new ErrorResponseCollection(
new ErrorResponse(
'UNKNOWN',
'unknown',
0,
$url,
$args
)
);
}
}