diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 53fe8f2a..0a7f06b6 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,11 +19,11 @@ jobs:
strategy:
fail-fast: false
matrix:
- php: ["8.0", "8.1"]
+ php: ["8.1", "8.2"]
node: ["16.x"]
mysql: ["5.7", "8.0"]
symfony: ["^5.4", "^6.0"]
- sylius: ["~1.12.0"]
+ sylius: ["~1.12.0", "1.13.x-dev"]
env:
APP_ENV: test
DATABASE_URL: "mysql://root:root@127.0.0.1/sylius?serverVersion=${{ matrix.mysql }}"
@@ -149,10 +149,12 @@ jobs:
-
name: Validate composer.json
+ if: ${{ matrix.sylius != '1.13.x-dev' }}
run: composer validate --ansi --strict
-
name: Run analysis
+ if: ${{ matrix.sylius != '1.13.x-dev' }}
run: composer analyse
-
diff --git a/composer.json b/composer.json
index 2bd8f17f..21567e79 100644
--- a/composer.json
+++ b/composer.json
@@ -7,10 +7,13 @@
"require": {
"php": "^8.0",
"doctrine/doctrine-migrations-bundle": "^3.0",
+ "php-http/discovery": "^1.17",
"phpseclib/phpseclib": "^2.0",
- "polishsymfonycommunity/symfony-mocker-container": "^1.0",
+ "psr/http-client": "^1.0",
+ "psr/http-client-implementation": "~1.0",
+ "psr/http-factory-implementation": "~1.0",
"sylius-labs/doctrine-migrations-extra-bundle": "^0.1.4 || ^0.2",
- "sylius/sylius": "~1.12.0",
+ "sylius/sylius": "~1.12.0 || 1.13.x-dev",
"symfony/mailer": "^5.4 || ^6.0"
},
"require-dev": {
@@ -27,16 +30,19 @@
"friends-of-behat/symfony-extension": "^2.1",
"friends-of-behat/variadic-extension": "^1.3",
"lchrusciel/api-test-case": "^5.1",
+ "nyholm/psr7": "^1.8",
"phpspec/phpspec": "^7.0",
"phpstan/phpstan": "^1.6",
"phpstan/phpstan-doctrine": "1.3.37",
"phpstan/phpstan-webmozart-assert": "^1.1",
"phpunit/phpunit": "^8.5",
+ "polishsymfonycommunity/symfony-mocker-container": "^1.0",
"sylius-labs/coding-standard": "^4.0",
"sylius/sylius-rector": "^1.0",
"symfony/browser-kit": "^5.4 || ^6.0",
"symfony/debug-bundle": "^5.4 || ^6.0",
"symfony/dotenv": "^5.4 || ^6.0",
+ "symfony/http-client": "^5.4 || ^6.0",
"symfony/intl": "^5.4 || ^6.0",
"symfony/web-profiler-bundle": "^5.4 || ^6.0",
"symfony/webpack-encore-bundle": "^1.15"
@@ -59,7 +65,8 @@
"dealerdirect/phpcodesniffer-composer-installer": false,
"ocramius/package-versions": false,
"symfony/flex": true,
- "symfony/thanks": false
+ "symfony/thanks": false,
+ "php-http/discovery": true
}
},
"extra": {
@@ -77,5 +84,8 @@
]
},
"prefer-stable": true,
- "minimum-stability": "dev"
+ "minimum-stability": "dev",
+ "suggest": {
+ "php-http/guzzle6-adapter ":"Required to use this package on 32bit PHP"
+ }
}
diff --git a/spec/Api/WebhookApiSpec.php b/spec/Api/WebhookApiSpec.php
index bb6165e5..25a25b76 100644
--- a/spec/Api/WebhookApiSpec.php
+++ b/spec/Api/WebhookApiSpec.php
@@ -4,40 +4,42 @@
namespace spec\Sylius\PayPalPlugin\Api;
-use GuzzleHttp\ClientInterface;
use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;
final class WebhookApiSpec extends ObjectBehavior
{
- function let(ClientInterface $client): void
- {
- $this->beConstructedWith($client, 'http://base-url.com/');
+ function let(
+ ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ StreamFactoryInterface $streamFactory,
+ StreamInterface $stream,
+ RequestInterface $request
+ ): void {
+ $this->beConstructedWith($client, $requestFactory, $streamFactory, 'http://base-url.com/');
+ $request->withHeader(Argument::any(), Argument::any())->willReturn($request);
+ $request->withBody(Argument::any())->willReturn($request);
+ $streamFactory->createStream(Argument::any())->willReturn($stream);
}
function it_registers_webhook(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response,
StreamInterface $body
): void {
- $client->request(
- 'POST',
- 'http://base-url.com/v1/notifications/webhooks',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- 'json' => [
- 'url' => 'https://webhook.com',
- 'event_types' => [
- ['name' => 'PAYMENT.CAPTURE.REFUNDED'],
- ],
- ],
- ]
- )->willReturn($response);
+
+ $requestFactory->createRequest('POST','http://base-url.com/v1/notifications/webhooks')
+ ->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{ "status": "CREATED" }');
@@ -46,26 +48,15 @@ function it_registers_webhook(
function it_registers_webhook_without_https(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response,
StreamInterface $body
): void {
- $client->request(
- 'POST',
- 'http://base-url.com/v1/notifications/webhooks',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- 'json' => [
- 'url' => 'https://webhook.com',
- 'event_types' => [
- ['name' => 'PAYMENT.CAPTURE.REFUNDED'],
- ],
- ],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('POST','http://base-url.com/v1/notifications/webhooks')
+ ->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{ "status": "CREATED" }');
diff --git a/spec/Client/PayPalClientSpec.php b/spec/Client/PayPalClientSpec.php
index 64f3e1df..0a9f1dfb 100644
--- a/spec/Client/PayPalClientSpec.php
+++ b/spec/Client/PayPalClientSpec.php
@@ -13,11 +13,15 @@
namespace spec\Sylius\PayPalPlugin\Client;
-use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Log\LoggerInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
@@ -32,6 +36,10 @@ final class PayPalClientSpec extends ObjectBehavior
{
function let(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ StreamFactoryInterface $streamFactory,
+ RequestInterface $request,
+ StreamInterface $stream,
LoggerInterface $logger,
UuidProviderInterface $uuidProvider,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
@@ -39,9 +47,14 @@ function let(
ChannelInterface $channel
): void {
$channelContext->getChannel()->willReturn($channel);
+ $streamFactory->createStream(Argument::any())->willReturn($stream);
+ $request->withHeader(Argument::any(), Argument::any())->willReturn($request);
+ $request->withBody(Argument::any())->willReturn($request);
$this->beConstructedWith(
$client,
+ $requestFactory,
+ $streamFactory,
$logger,
$uuidProvider,
$payPalConfigurationProvider,
@@ -58,17 +71,15 @@ function it_implements_pay_pal_client_interface(): void
function it_returns_auth_token_for_given_client_data(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response,
StreamInterface $body
): void {
- $client->request(
- 'POST',
- 'https://test-api.paypal.com/v1/oauth2/token',
- [
- 'auth' => ['CLIENT_ID', 'CLIENT_SECRET'],
- 'form_params' => ['grant_type' => 'client_credentials'],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('POST', 'https://test-api.paypal.com/v1/oauth2/token')->willReturn($request);
+ $request->withHeader(Argument::any(), Argument::any())->willReturn($request);
+ $request->withBody(Argument::any())->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"access_token": "TOKEN"}');
@@ -78,16 +89,13 @@ function it_returns_auth_token_for_given_client_data(
function it_throws_an_exception_if_client_could_not_be_authorized(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response
): void {
- $client->request(
- 'POST',
- 'https://test-api.paypal.com/v1/oauth2/token',
- [
- 'auth' => ['CLIENT_ID', 'CLIENT_SECRET'],
- 'form_params' => ['grant_type' => 'client_credentials'],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('POST', 'https://test-api.paypal.com/v1/oauth2/token')->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getStatusCode()->willReturn(401);
$this
@@ -98,6 +106,8 @@ function it_throws_an_exception_if_client_could_not_be_authorized(
function it_calls_get_request_on_paypal_api(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
ChannelInterface $channel,
ResponseInterface $response,
@@ -105,18 +115,9 @@ function it_calls_get_request_on_paypal_api(
): void {
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'GET',
- 'https://test-api.paypal.com/v2/get-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- ],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('GET', 'https://test-api.paypal.com/v2/get-request/')->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"status": "OK", "id": "123123"}');
@@ -126,6 +127,9 @@ function it_calls_get_request_on_paypal_api(
function it_logs_all_requests_if_logging_level_is_increased(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ StreamFactoryInterface $streamFactory,
+ RequestInterface $request,
LoggerInterface $logger,
UuidProviderInterface $uuidProvider,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
@@ -136,6 +140,8 @@ function it_logs_all_requests_if_logging_level_is_increased(
): void {
$this->beConstructedWith(
$client,
+ $requestFactory,
+ $streamFactory,
$logger,
$uuidProvider,
$payPalConfigurationProvider,
@@ -148,18 +154,9 @@ function it_logs_all_requests_if_logging_level_is_increased(
$channelContext->getChannel()->willReturn($channel);
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'GET',
- 'https://test-api.paypal.com/v2/get-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- ],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('GET', 'https://test-api.paypal.com/v2/get-request/')->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"status": "OK", "id": "123123"}');
@@ -174,6 +171,8 @@ function it_logs_all_requests_if_logging_level_is_increased(
function it_logs_debug_id_from_failed_get_request(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
LoggerInterface $logger,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
ChannelInterface $channel,
@@ -183,18 +182,8 @@ function it_logs_debug_id_from_failed_get_request(
): void {
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'GET',
- 'https://test-api.paypal.com/v2/get-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- ],
- ]
- )->willThrow($exception->getWrappedObject());
+ $requestFactory->createRequest('GET', 'https://test-api.paypal.com/v2/get-request/')->willReturn($request);
+ $client->sendRequest($request)->willThrow($exception->getWrappedObject());
$exception->getResponse()->willReturn($response);
$response->getBody()->willReturn($body);
@@ -211,6 +200,8 @@ function it_logs_debug_id_from_failed_get_request(
function it_calls_post_request_on_paypal_api(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response,
StreamInterface $body,
UuidProviderInterface $uuidProvider,
@@ -220,20 +211,9 @@ function it_calls_post_request_on_paypal_api(
$uuidProvider->provide()->willReturn('REQUEST-ID');
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'POST',
- 'https://test-api.paypal.com/v2/post-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- 'PayPal-Request-Id' => 'REQUEST-ID',
- ],
- 'json' => ['parameter' => 'value', 'another_parameter' => 'another_value'],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('POST', 'https://test-api.paypal.com/v2/post-request/')->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"status": "OK", "id": "123123"}');
@@ -246,7 +226,10 @@ function it_calls_post_request_on_paypal_api(
function it_calls_post_request_on_paypal_api_with_extra_headers(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response,
+ StreamFactoryInterface $streamFactory,
StreamInterface $body,
UuidProviderInterface $uuidProvider,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
@@ -255,21 +238,9 @@ function it_calls_post_request_on_paypal_api_with_extra_headers(
$uuidProvider->provide()->willReturn('REQUEST-ID');
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'POST',
- 'https://test-api.paypal.com/v2/post-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- 'PayPal-Request-Id' => 'REQUEST-ID',
- 'CUSTOM_HEADER' => 'header',
- ],
- 'json' => ['parameter' => 'value', 'another_parameter' => 'another_value'],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('POST', 'https://test-api.paypal.com/v2/post-request/')->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
+
$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"status": "OK", "id": "123123"}');
@@ -278,10 +249,15 @@ function it_calls_post_request_on_paypal_api_with_extra_headers(
->post('v2/post-request/', 'TOKEN', ['parameter' => 'value', 'another_parameter' => 'another_value'], ['CUSTOM_HEADER' => 'header'])
->shouldReturn(['status' => 'OK', 'id' => '123123'])
;
+
+ $request->withHeader('CUSTOM_HEADER', 'header')->shouldBeCalled();
+ $streamFactory->createStream(json_encode(['parameter' => 'value', 'another_parameter' => 'another_value']))->shouldBeCalled();
}
function it_logs_debug_id_from_failed_post_request(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
LoggerInterface $logger,
RequestException $exception,
ResponseInterface $response,
@@ -293,20 +269,8 @@ function it_logs_debug_id_from_failed_post_request(
$uuidProvider->provide()->willReturn('REQUEST-ID');
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'POST',
- 'https://test-api.paypal.com/v2/post-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- 'PayPal-Request-Id' => 'REQUEST-ID',
- ],
- 'json' => ['parameter' => 'value', 'another_parameter' => 'another_value'],
- ]
- )->willThrow($exception->getWrappedObject());
+ $requestFactory->createRequest('POST', 'https://test-api.paypal.com/v2/post-request/')->willReturn($request);
+ $client->sendRequest($request)->willThrow($exception->getWrappedObject());
$exception->getResponse()->willReturn($response);
$response->getBody()->willReturn($body);
@@ -326,26 +290,16 @@ function it_logs_debug_id_from_failed_post_request(
function it_calls_patch_request_on_paypal_api(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
ResponseInterface $response,
StreamInterface $body,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
ChannelInterface $channel
): void {
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
-
- $client->request(
- 'PATCH',
- 'https://test-api.paypal.com/v2/patch-request/123123',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- ],
- 'json' => ['parameter' => 'value', 'another_parameter' => 'another_value'],
- ]
- )->willReturn($response);
+ $requestFactory->createRequest('PATCH', 'https://test-api.paypal.com/v2/patch-request/123123')->willReturn($request);
+ $client->sendRequest($request)->willReturn($response);
$response->getStatusCode()->willReturn(200);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"status": "OK", "id": "123123"}');
@@ -358,6 +312,8 @@ function it_calls_patch_request_on_paypal_api(
function it_logs_debug_id_from_failed_patch_request(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
LoggerInterface $logger,
RequestException $exception,
ResponseInterface $response,
@@ -367,19 +323,8 @@ function it_logs_debug_id_from_failed_patch_request(
): void {
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'PATCH',
- 'https://test-api.paypal.com/v2/patch-request/123123',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- ],
- 'json' => ['parameter' => 'value', 'another_parameter' => 'another_value'],
- ]
- )->willThrow($exception->getWrappedObject());
+ $requestFactory->createRequest('PATCH', 'https://test-api.paypal.com/v2/patch-request/123123')->willReturn($request);
+ $client->sendRequest($request)->willThrow($exception->getWrappedObject());
$exception->getResponse()->willReturn($response);
$response->getBody()->willReturn($body);
@@ -399,23 +344,15 @@ function it_logs_debug_id_from_failed_patch_request(
function it_throws_exception_if_the_timeout_has_been_reached_the_specified_amount_of_time(
ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $request,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
ChannelInterface $channel
): void {
$payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID');
- $client->request(
- 'GET',
- 'https://test-api.paypal.com/v2/get-request/',
- [
- 'headers' => [
- 'Authorization' => 'Bearer TOKEN',
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- 'PayPal-Partner-Attribution-Id' => 'TRACKING-ID',
- ],
- ]
- )->willThrow(ConnectException::class);
+ $requestFactory->createRequest('GET', 'https://test-api.paypal.com/v2/get-request/')->willReturn($request);
+ $client->sendRequest($request)->willThrow(ConnectException::class);
$this
->shouldThrow(PayPalApiTimeoutException::class)
diff --git a/spec/Onboarding/Processor/BasicOnboardingProcessorSpec.php b/spec/Onboarding/Processor/BasicOnboardingProcessorSpec.php
index 51da39d2..5b491b29 100644
--- a/spec/Onboarding/Processor/BasicOnboardingProcessorSpec.php
+++ b/spec/Onboarding/Processor/BasicOnboardingProcessorSpec.php
@@ -4,9 +4,12 @@
namespace spec\Sylius\PayPalPlugin\Onboarding\Processor;
-use GuzzleHttp\ClientInterface;
use Payum\Core\Model\GatewayConfigInterface;
use PhpSpec\ObjectBehavior;
+use Prophecy\Argument;
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use Sylius\Component\Core\Model\PaymentMethod;
@@ -21,13 +24,24 @@ final class BasicOnboardingProcessorSpec extends ObjectBehavior
{
function let(
ClientInterface $httpClient,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $apiRequest,
SellerWebhookRegistrarInterface $sellerWebhookRegistrar
): void {
- $this->beConstructedWith($httpClient, $sellerWebhookRegistrar, 'https://paypal.facilitator.com');
+ $this->beConstructedWith(
+ $httpClient,
+ $requestFactory,
+ $sellerWebhookRegistrar,
+ 'https://paypal.facilitator.com'
+ );
+
+ $apiRequest->withHeader(Argument::any(), Argument::any())->willReturn($apiRequest);
}
function it_processes_onboarding_for_supported_payment_method_and_request(
ClientInterface $httpClient,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $apiRequest,
SellerWebhookRegistrarInterface $sellerWebhookRegistrar,
ResponseInterface $response,
StreamInterface $body,
@@ -60,19 +74,11 @@ function it_processes_onboarding_for_supported_payment_method_and_request(
$request->query = new ParameterBag(['onboarding_id' => 'ONBOARDING-ID']);
- $httpClient
- ->request(
- 'GET',
- 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID',
- [
- 'headers' => [
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- ]
- )
- ->willReturn($response)
- ;
+ $requestFactory->createRequest(
+ 'GET',
+ 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID'
+ )->willReturn($apiRequest);
+ $httpClient->sendRequest($apiRequest)->willReturn($response);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn(
@@ -90,6 +96,8 @@ function it_processes_onboarding_for_supported_payment_method_and_request(
function it_processes_onboarding_for_supported_payment_method_with_not_granted_permissions_and_request(
ClientInterface $httpClient,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $apiRequest,
SellerWebhookRegistrarInterface $sellerWebhookRegistrar,
ResponseInterface $response,
StreamInterface $body,
@@ -111,19 +119,11 @@ function it_processes_onboarding_for_supported_payment_method_with_not_granted_p
$request->query = new ParameterBag(['onboarding_id' => 'ONBOARDING-ID', 'permissionsGranted' => false]);
- $httpClient
- ->request(
- 'GET',
- 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID',
- [
- 'headers' => [
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- ]
- )
- ->willReturn($response)
- ;
+ $requestFactory->createRequest(
+ 'GET',
+ 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID'
+ )->willReturn($apiRequest);
+ $httpClient->sendRequest($apiRequest)->willReturn($response);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn(
@@ -153,6 +153,8 @@ function it_processes_onboarding_for_supported_payment_method_with_not_granted_p
function it_processes_onboarding_for_supported_payment_method_with_not_granted_permissions_and_without_registered_webhook(
ClientInterface $httpClient,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $apiRequest,
SellerWebhookRegistrarInterface $sellerWebhookRegistrar,
ResponseInterface $response,
StreamInterface $body,
@@ -174,19 +176,12 @@ function it_processes_onboarding_for_supported_payment_method_with_not_granted_p
$request->query = new ParameterBag(['onboarding_id' => 'ONBOARDING-ID', 'permissionsGranted' => false]);
- $httpClient
- ->request(
- 'GET',
- 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID',
- [
- 'headers' => [
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- ]
- )
- ->willReturn($response)
- ;
+ $requestFactory->createRequest(
+ 'GET',
+ 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID'
+ )->willReturn($apiRequest);
+ $httpClient->sendRequest($apiRequest)->willReturn($response);
+
$response->getBody()->willReturn($body);
$body->getContents()->willReturn(
@@ -270,6 +265,8 @@ function it_does_not_support_payment_method_that_has_client_id_is_not_set_on_req
function it_throws_error_if_facilitator_data_is_not_loaded(
ClientInterface $httpClient,
+ RequestFactoryInterface $requestFactory,
+ RequestInterface $apiRequest,
ResponseInterface $response,
StreamInterface $body,
GatewayConfigInterface $gatewayConfig,
@@ -282,19 +279,11 @@ function it_throws_error_if_facilitator_data_is_not_loaded(
$request->query = new ParameterBag(['onboarding_id' => 'ONBOARDING-ID']);
- $httpClient
- ->request(
- 'GET',
- 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID',
- [
- 'headers' => [
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- ]
- )
- ->willReturn($response)
- ;
+ $requestFactory->createRequest(
+ 'GET',
+ 'https://paypal.facilitator.com/partner-referrals/check/ONBOARDING-ID'
+ )->willReturn($apiRequest);
+ $httpClient->sendRequest($apiRequest)->willReturn($response);
$response->getBody()->willReturn($body);
$body->getContents()->willReturn('{"client_id":null,"client_secret":null}');
diff --git a/src/Api/WebhookApi.php b/src/Api/WebhookApi.php
index 89c0be6f..e836bb40 100644
--- a/src/Api/WebhookApi.php
+++ b/src/Api/WebhookApi.php
@@ -4,35 +4,54 @@
namespace Sylius\PayPalPlugin\Api;
-use GuzzleHttp\ClientInterface;
+
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use Psr\Http\Message\StreamFactoryInterface;
final class WebhookApi implements WebhookApiInterface
{
private ClientInterface $client;
+ private RequestFactoryInterface $requestFactory;
+
+ private StreamFactoryInterface $streamFactory;
+
private string $baseUrl;
- public function __construct(ClientInterface $client, string $baseUrl)
- {
+ public function __construct(
+ ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ StreamFactoryInterface $streamFactory,
+ string $baseUrl
+ ) {
$this->client = $client;
+ $this->requestFactory = $requestFactory;
+ $this->streamFactory = $streamFactory;
$this->baseUrl = $baseUrl;
}
public function register(string $token, string $webhookUrl): array
{
- $response = $this->client->request('POST', $this->baseUrl . 'v1/notifications/webhooks', [
- 'headers' => [
- 'Authorization' => 'Bearer ' . $token,
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- 'json' => [
- 'url' => preg_replace('/^http:/i', 'https:', $webhookUrl),
- 'event_types' => [
- ['name' => 'PAYMENT.CAPTURE.REFUNDED'],
- ],
- ],
- ]);
+ $request = $this->requestFactory->createRequest('POST', $this->baseUrl . 'v1/notifications/webhooks')
+ ->withHeader('Authorization', 'Bearer ' . $token)
+ ->withHeader('Content-Type', 'application/json')
+ ->withHeader('Accept', 'application/json');
+
+ $request = $request->withBody(
+ $this->streamFactory->createStream(
+ json_encode(
+ [
+ 'url' => preg_replace('/^http:/i', 'https:', $webhookUrl),
+ 'event_types' => [
+ ['name' => 'PAYMENT.CAPTURE.REFUNDED'],
+ ]
+ ]
+ )
+ )
+ );
+
+ $response = $this->client->sendRequest($request);
return (array) json_decode($response->getBody()->getContents(), true);
}
diff --git a/src/Client/PayPalClient.php b/src/Client/PayPalClient.php
index a4935bc3..61a06fe7 100644
--- a/src/Client/PayPalClient.php
+++ b/src/Client/PayPalClient.php
@@ -13,11 +13,14 @@
namespace Sylius\PayPalPlugin\Client;
-use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
+use Psr\Http\Client\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamFactoryInterface;
use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpClient\Psr18Client;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\PayPalPlugin\Exception\PayPalApiTimeoutException;
@@ -27,7 +30,11 @@
final class PayPalClient implements PayPalClientInterface
{
- private ClientInterface $client;
+ private ClientInterface $client;
+
+ private RequestFactoryInterface $requestFactory;
+
+ private StreamFactoryInterface $streamFactory;
private LoggerInterface $logger;
@@ -44,7 +51,9 @@ final class PayPalClient implements PayPalClientInterface
private bool $loggingLevelIncreased;
public function __construct(
- ClientInterface $client,
+ ClientInterface $client,
+ RequestFactoryInterface $requestFactory,
+ StreamFactoryInterface $streamFactory,
LoggerInterface $logger,
UuidProviderInterface $uuidProvider,
PayPalConfigurationProviderInterface $payPalConfigurationProvider,
@@ -54,6 +63,8 @@ public function __construct(
bool $loggingLevelIncreased = false
) {
$this->client = $client;
+ $this->requestFactory = $requestFactory;
+ $this->streamFactory = $streamFactory;
$this->logger = $logger;
$this->uuidProvider = $uuidProvider;
$this->payPalConfigurationProvider = $payPalConfigurationProvider;
@@ -145,7 +156,44 @@ private function request(string $method, string $url, string $token, array $data
private function doRequest(string $method, string $fullUrl, array $options): ResponseInterface
{
try {
- $response = $this->client->request($method, $fullUrl, $options);
+ $request = $this->requestFactory->createRequest($method, $fullUrl);
+
+ if (isset($options['auth'])) {
+ $request = $request->withHeader(
+ 'Authorization',
+ sprintf(
+ "Basic %s",
+ base64_encode(sprintf("%s:%s", $options['auth'][0], $options['auth'][1]))
+ )
+ );
+ }
+
+ if (isset($options['form_params'])) {
+ $request = $request->withHeader('Content-Type', 'application/x-www-form-urlencoded');
+ $request = $request->withBody(
+ $this->streamFactory->createStream(http_build_query(
+ $options['form_params'],
+ '',
+ '&',
+ PHP_QUERY_RFC1738
+ ))
+ );
+
+ }
+
+ if (isset($options['json'])) {
+ $request = $request->withBody(
+ $this->streamFactory->createStream(json_encode($options['json']))
+ );
+ }
+
+ if (isset($options['headers'])) {
+ foreach ($options['headers'] as $header => $headerValue) {
+ $request = $request->withHeader($header, $headerValue);
+ }
+ }
+
+ $response = $this->client->sendRequest($request);
} catch (ConnectException $exception) {
--$this->requestTrialsLimit;
if ($this->requestTrialsLimit === 0) {
diff --git a/src/Listener/PayPalOrderCompletedListener.php b/src/Listener/PayPalOrderCompletedListener.php
new file mode 100644
index 00000000..61f25520
--- /dev/null
+++ b/src/Listener/PayPalOrderCompletedListener.php
@@ -0,0 +1,37 @@
+getSubject();
+ Assert::isInstanceOf($order, OrderInterface::class);
+
+ $this->completeProcessor->completePayPalOrder($order);
+ }
+}
diff --git a/src/Listener/PayPalPaymentRefundedListener.php b/src/Listener/PayPalPaymentRefundedListener.php
new file mode 100644
index 00000000..0382140d
--- /dev/null
+++ b/src/Listener/PayPalPaymentRefundedListener.php
@@ -0,0 +1,36 @@
+getSubject();
+ Assert::isInstanceOf($payment, PaymentInterface::class);
+
+ $this->paymentRefundProcessor->refund($payment);
+ }
+}
\ No newline at end of file
diff --git a/src/Onboarding/Processor/BasicOnboardingProcessor.php b/src/Onboarding/Processor/BasicOnboardingProcessor.php
index 89e69335..8a1a583c 100644
--- a/src/Onboarding/Processor/BasicOnboardingProcessor.php
+++ b/src/Onboarding/Processor/BasicOnboardingProcessor.php
@@ -4,7 +4,8 @@
namespace Sylius\PayPalPlugin\Onboarding\Processor;
-use GuzzleHttp\ClientInterface;
+use Psr\Http\Message\RequestFactoryInterface;
+use Psr\Http\Client\ClientInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\PayPalPlugin\Exception\PayPalPluginException;
use Sylius\PayPalPlugin\Exception\PayPalWebhookAlreadyRegisteredException;
@@ -17,16 +18,20 @@ final class BasicOnboardingProcessor implements OnboardingProcessorInterface
{
private ClientInterface $httpClient;
+ private RequestFactoryInterface $requestFactory;
+
private SellerWebhookRegistrarInterface $sellerWebhookRegistrar;
private string $url;
public function __construct(
ClientInterface $httpClient,
+ RequestFactoryInterface $requestFactory,
SellerWebhookRegistrarInterface $sellerWebhookRegistrar,
string $url
) {
$this->httpClient = $httpClient;
+ $this->requestFactory = $requestFactory;
$this->sellerWebhookRegistrar = $sellerWebhookRegistrar;
$this->url = $url;
}
@@ -43,16 +48,15 @@ public function process(
Assert::notNull($gatewayConfig);
$onboardingId = (string) $request->query->get('onboarding_id');
- $checkPartnerReferralsResponse = $this->httpClient->request(
+ $checkPartnerReferralsRequest = $this->requestFactory->createRequest(
'GET',
- sprintf('%s/partner-referrals/check/%s', $this->url, $onboardingId),
- [
- 'headers' => [
- 'Content-Type' => 'application/json',
- 'Accept' => 'application/json',
- ],
- ]
- );
+ sprintf('%s/partner-referrals/check/%s', $this->url, $onboardingId)
+ )
+ ->withHeader('Content-Type', 'application/json')
+ ->withHeader('Accept', 'application/json')
+ ;
+
+ $checkPartnerReferralsResponse = $this->httpClient->sendRequest($checkPartnerReferralsRequest);
$response = (array) json_decode($checkPartnerReferralsResponse->getBody()->getContents(), true);
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
index 94ac7197..bc8c1d60 100644
--- a/src/Resources/config/services.xml
+++ b/src/Resources/config/services.xml
@@ -6,6 +6,7 @@
+
diff --git a/src/Resources/config/services/api.xml b/src/Resources/config/services/api.xml
index 88b94775..5a262ec6 100644
--- a/src/Resources/config/services/api.xml
+++ b/src/Resources/config/services/api.xml
@@ -6,11 +6,14 @@
true
+
-
+
+
+
@@ -86,7 +89,9 @@
id="Sylius\PayPalPlugin\Api\WebhookApiInterface"
class="Sylius\PayPalPlugin\Api\WebhookApi"
>
-
+
+
+
%sylius.pay_pal.api_base_url%
diff --git a/src/Resources/config/services/onboarding.xml b/src/Resources/config/services/onboarding.xml
index 917f0971..71b22cfc 100644
--- a/src/Resources/config/services/onboarding.xml
+++ b/src/Resources/config/services/onboarding.xml
@@ -15,7 +15,8 @@
id="Sylius\PayPalPlugin\Onboarding\Processor\OnboardingProcessorInterface"
class="Sylius\PayPalPlugin\Onboarding\Processor\BasicOnboardingProcessor"
>
-
+
+
%sylius.pay_pal.facilitator_url%
diff --git a/src/Resources/config/services/workflow.xml b/src/Resources/config/services/workflow.xml
new file mode 100644
index 00000000..e0982f98
--- /dev/null
+++ b/src/Resources/config/services/workflow.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Resources/views/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig b/src/Resources/views/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig
index ece6954b..2c841237 100644
--- a/src/Resources/views/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig
+++ b/src/Resources/views/bundles/SyliusShopBundle/Checkout/SelectPayment/_choice.html.twig
@@ -12,7 +12,7 @@
{% endif %}
{% if method.gatewayConfig.factoryName == 'sylius.pay_pal' %}
- {{ render(controller('Sylius\\PayPalPlugin\\Controller\\PayPalButtonsController:renderPaymentPageButtonsAction', {'orderId': order.id})) }}
+ {{ render(controller('Sylius\\PayPalPlugin\\Controller\\PayPalButtonsController::renderPaymentPageButtonsAction', {'orderId': order.id})) }}
{% endif %}
diff --git a/tests/Application/composer.json b/tests/Application/composer.json
index af8a51b2..c5ee6856 100644
--- a/tests/Application/composer.json
+++ b/tests/Application/composer.json
@@ -1,5 +1,8 @@
{
"name": "sylius/paypal-plugin",
"description": "PayPal plugin for Sylius",
- "license": "MIT"
+ "license": "MIT",
+ "require": {
+ "nyholm/psr7": "^1.8"
+ }
}
diff --git a/tests/Application/config/bundles.php b/tests/Application/config/bundles.php
index d260b314..4f4da692 100644
--- a/tests/Application/config/bundles.php
+++ b/tests/Application/config/bundles.php
@@ -1,6 +1,7 @@
['all' => true],
@@ -62,10 +63,15 @@
Sylius\Calendar\SyliusCalendarBundle::class => ['all' => true],
];
-if (Kernel::MINOR_VERSION < 12) {
- $bundles[Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class] = ['all' => true];
-} else {
+if (defined(SyliusCoreBundle::class.'::VERSION_ID') && SyliusCoreBundle::VERSION_ID >= '11200') {
$bundles[League\FlysystemBundle\FlysystemBundle::class] = ['all' => true];
+} else {
+ $bundles[Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class] = ['all' => true];
+}
+
+
+if ( defined(SyliusCoreBundle::class.'::VERSION_ID') && SyliusCoreBundle::VERSION_ID >= '11300') {
+ $bundles[Sylius\Abstraction\StateMachine\SyliusStateMachineAbstractionBundle::class] = ['all' => true];
}
return $bundles;
diff --git a/tests/Application/config/packages/nyholm_psr7.yaml b/tests/Application/config/packages/nyholm_psr7.yaml
new file mode 100644
index 00000000..5011e61a
--- /dev/null
+++ b/tests/Application/config/packages/nyholm_psr7.yaml
@@ -0,0 +1,11 @@
+services:
+ # Register nyholm/psr7 services for autowiring with PSR-17 (HTTP factories)
+ Psr\Http\Message\RequestFactoryInterface: '@nyholm.psr7.psr17_factory'
+ Psr\Http\Message\ResponseFactoryInterface: '@nyholm.psr7.psr17_factory'
+ Psr\Http\Message\ServerRequestFactoryInterface: '@nyholm.psr7.psr17_factory'
+ Psr\Http\Message\StreamFactoryInterface: '@nyholm.psr7.psr17_factory'
+ Psr\Http\Message\UploadedFileFactoryInterface: '@nyholm.psr7.psr17_factory'
+ Psr\Http\Message\UriFactoryInterface: '@nyholm.psr7.psr17_factory'
+
+ nyholm.psr7.psr17_factory:
+ class: Nyholm\Psr7\Factory\Psr17Factory
\ No newline at end of file
diff --git a/tests/Application/config/packages/test/framework.yaml b/tests/Application/config/packages/test/framework.yaml
index fc1d3c13..1890c8d0 100644
--- a/tests/Application/config/packages/test/framework.yaml
+++ b/tests/Application/config/packages/test/framework.yaml
@@ -2,3 +2,10 @@ framework:
test: ~
session:
storage_factory_id: session.storage.factory.mock_file
+
+ mailer:
+ dsn: 'null://null'
+ cache:
+ pools:
+ test.mailer_pool:
+ adapter: cache.adapter.filesystem
\ No newline at end of file