From f065977a348c6eee161de1fd5918078d12e5d7d8 Mon Sep 17 00:00:00 2001 From: Mateusz Zalewski Date: Thu, 24 Sep 2020 10:34:01 +0200 Subject: [PATCH 1/3] Use always PAYPAL_ATTRIBUTION_ID from payment method configuration --- README.md | 2 - spec/Client/PayPalClientSpec.php | 64 ++++++++++++++++--- src/Client/PayPalClient.php | 13 ++-- src/Resources/config/services/api.xml | 2 +- tests/Application/.env | 1 - .../Context/Setup/PaymentPayPalContext.php | 9 +-- tests/Behat/Resources/services.xml | 1 - 7 files changed, 64 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 412ec953..83bed35d 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,6 @@ Sylius Core Team’s plugin for [PayPal Commerce Platform](https://www.paypal.co PAYPAL_API_BASE_URL='https://api.sandbox.paypal.com/' # just for now, it will be eventually hardcoded (as we always want to use Sylius PayPal facilitator) PAYPAL_FACILITATOR_URL='https://paypal.sylius.com' - PAYPAL_TRACKING_ID='sylius-ppcp4p-bn-code' ``` ### Live @@ -100,7 +99,6 @@ Sylius Core Team’s plugin for [PayPal Commerce Platform](https://www.paypal.co PAYPAL_API_BASE_URL='https://api.paypal.com/' # just for now, it will be eventually hardcoded (as we always want to use Sylius PayPal facilitator) PAYPAL_FACILITATOR_URL='https://prod.paypal.sylius.com' - PAYPAL_TRACKING_ID='sylius-ppcp4p-bn-code' ``` 5. Copy and apply migrations diff --git a/spec/Client/PayPalClientSpec.php b/spec/Client/PayPalClientSpec.php index 6454ad57..94b012c4 100644 --- a/spec/Client/PayPalClientSpec.php +++ b/spec/Client/PayPalClientSpec.php @@ -23,13 +23,25 @@ use Sylius\PayPalPlugin\Client\PayPalClientInterface; use Sylius\PayPalPlugin\Exception\PayPalApiTimeoutException; use Sylius\PayPalPlugin\Exception\PayPalAuthorizationException; +use Sylius\PayPalPlugin\Provider\PayPalConfigurationProviderInterface; use Sylius\PayPalPlugin\Provider\UuidProviderInterface; final class PayPalClientSpec extends ObjectBehavior { - function let(ClientInterface $client, LoggerInterface $logger, UuidProviderInterface $uuidProvider): void - { - $this->beConstructedWith($client, $logger, $uuidProvider, 'https://test-api.paypal.com/', 'TRACKING-ID', 5); + function let( + ClientInterface $client, + LoggerInterface $logger, + UuidProviderInterface $uuidProvider, + PayPalConfigurationProviderInterface $payPalConfigurationProvider + ): void { + $this->beConstructedWith( + $client, + $logger, + $uuidProvider, + $payPalConfigurationProvider, + 'https://test-api.paypal.com/', + 5 + ); } function it_implements_pay_pal_client_interface(): void @@ -79,9 +91,12 @@ function it_throws_an_exception_if_client_could_not_be_authorized( function it_calls_get_request_on_paypal_api( ClientInterface $client, + PayPalConfigurationProviderInterface $payPalConfigurationProvider, ResponseInterface $response, StreamInterface $body ): void { + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $client->request( 'GET', 'https://test-api.paypal.com/v2/get-request/', @@ -105,10 +120,21 @@ function it_logs_all_requests_if_logging_level_is_increased( ClientInterface $client, LoggerInterface $logger, UuidProviderInterface $uuidProvider, + PayPalConfigurationProviderInterface $payPalConfigurationProvider, ResponseInterface $response, StreamInterface $body ): void { - $this->beConstructedWith($client, $logger, $uuidProvider, 'https://test-api.paypal.com/', 'TRACKING-ID', 5, true); + $this->beConstructedWith( + $client, + $logger, + $uuidProvider, + $payPalConfigurationProvider, + 'https://test-api.paypal.com/', + 5, + true + ); + + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); $client->request( 'GET', @@ -137,10 +163,13 @@ function it_logs_all_requests_if_logging_level_is_increased( function it_logs_debug_id_from_failed_get_request( ClientInterface $client, LoggerInterface $logger, + PayPalConfigurationProviderInterface $payPalConfigurationProvider, RequestException $exception, ResponseInterface $response, StreamInterface $body ): void { + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $client->request( 'GET', 'https://test-api.paypal.com/v2/get-request/', @@ -171,9 +200,11 @@ function it_calls_post_request_on_paypal_api( ClientInterface $client, ResponseInterface $response, StreamInterface $body, - UuidProviderInterface $uuidProvider + UuidProviderInterface $uuidProvider, + PayPalConfigurationProviderInterface $payPalConfigurationProvider ): void { $uuidProvider->provide()->willReturn('REQUEST-ID'); + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); $client->request( 'POST', @@ -203,9 +234,11 @@ function it_calls_post_request_on_paypal_api_with_extra_headers( ClientInterface $client, ResponseInterface $response, StreamInterface $body, - UuidProviderInterface $uuidProvider + UuidProviderInterface $uuidProvider, + PayPalConfigurationProviderInterface $payPalConfigurationProvider ): void { $uuidProvider->provide()->willReturn('REQUEST-ID'); + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); $client->request( 'POST', @@ -238,9 +271,11 @@ function it_logs_debug_id_from_failed_post_request( RequestException $exception, ResponseInterface $response, StreamInterface $body, - UuidProviderInterface $uuidProvider + UuidProviderInterface $uuidProvider, + PayPalConfigurationProviderInterface $payPalConfigurationProvider ): void { $uuidProvider->provide()->willReturn('REQUEST-ID'); + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); $client->request( 'POST', @@ -276,8 +311,11 @@ function it_logs_debug_id_from_failed_post_request( function it_calls_patch_request_on_paypal_api( ClientInterface $client, ResponseInterface $response, - StreamInterface $body + StreamInterface $body, + PayPalConfigurationProviderInterface $payPalConfigurationProvider ): void { + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $client->request( 'PATCH', 'https://test-api.paypal.com/v2/patch-request/123123', @@ -306,8 +344,11 @@ function it_logs_debug_id_from_failed_patch_request( LoggerInterface $logger, RequestException $exception, ResponseInterface $response, - StreamInterface $body + StreamInterface $body, + PayPalConfigurationProviderInterface $payPalConfigurationProvider ): void { + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $client->request( 'PATCH', 'https://test-api.paypal.com/v2/patch-request/123123', @@ -339,8 +380,11 @@ 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 + ClientInterface $client, + PayPalConfigurationProviderInterface $payPalConfigurationProvider ): void { + $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $client->request( 'GET', 'https://test-api.paypal.com/v2/get-request/', diff --git a/src/Client/PayPalClient.php b/src/Client/PayPalClient.php index 1e020f44..6058e490 100644 --- a/src/Client/PayPalClient.php +++ b/src/Client/PayPalClient.php @@ -20,6 +20,7 @@ use Psr\Log\LoggerInterface; use Sylius\PayPalPlugin\Exception\PayPalApiTimeoutException; use Sylius\PayPalPlugin\Exception\PayPalAuthorizationException; +use Sylius\PayPalPlugin\Provider\PayPalConfigurationProviderInterface; use Sylius\PayPalPlugin\Provider\UuidProviderInterface; final class PayPalClient implements PayPalClientInterface @@ -33,11 +34,11 @@ final class PayPalClient implements PayPalClientInterface /** @var UuidProviderInterface */ private $uuidProvider; - /** @var string */ - private $baseUrl; + /** @var PayPalConfigurationProviderInterface */ + private $payPalConfigurationProvider; /** @var string */ - private $trackingId; + private $baseUrl; /** @var int */ private $requestTrialsLimit; @@ -49,16 +50,16 @@ public function __construct( ClientInterface $client, LoggerInterface $logger, UuidProviderInterface $uuidProvider, + PayPalConfigurationProviderInterface $payPalConfigurationProvider, string $baseUrl, - string $trackingId, int $requestTrialsLimit, bool $loggingLevelIncreased = false ) { $this->client = $client; $this->logger = $logger; $this->uuidProvider = $uuidProvider; + $this->payPalConfigurationProvider = $payPalConfigurationProvider; $this->baseUrl = $baseUrl; - $this->trackingId = $trackingId; $this->requestTrialsLimit = $requestTrialsLimit; $this->loggingLevelIncreased = $loggingLevelIncreased; } @@ -105,7 +106,7 @@ private function request(string $method, string $url, string $token, array $data 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', 'Accept' => 'application/json', - 'PayPal-Partner-Attribution-Id' => $this->trackingId, + 'PayPal-Partner-Attribution-Id' => $this->payPalConfigurationProvider->getPartnerAttributionId(), ], $extraHeaders), ]; diff --git a/src/Resources/config/services/api.xml b/src/Resources/config/services/api.xml index 6e85f0d6..5b5c253b 100644 --- a/src/Resources/config/services/api.xml +++ b/src/Resources/config/services/api.xml @@ -13,8 +13,8 @@ + %env(resolve:PAYPAL_API_BASE_URL)% - %env(resolve:PAYPAL_TRACKING_ID)% %sylius.pay_pal.request_trials_limit% %sylius.paypal.logging.increased% diff --git a/tests/Application/.env b/tests/Application/.env index 478cfe2e..ce688a51 100644 --- a/tests/Application/.env +++ b/tests/Application/.env @@ -22,7 +22,6 @@ DATABASE_URL=mysql://root@127.0.0.1/sylius_pay_pal_plugin_%kernel.environment%?s MAILER_URL=smtp://localhost ###< symfony/swiftmailer-bundle ### -PAYPAL_TRACKING_ID='sylius-ppcp4p-bn-code' PAYPAL_API_BASE_URL='https://api.sandbox.paypal.com/' PAYPAL_REPORTS_SFTP_HOST='' PAYPAL_FACILITATOR_URL='https://paypal.sylius.com' diff --git a/tests/Behat/Context/Setup/PaymentPayPalContext.php b/tests/Behat/Context/Setup/PaymentPayPalContext.php index a0d15726..52ce364b 100644 --- a/tests/Behat/Context/Setup/PaymentPayPalContext.php +++ b/tests/Behat/Context/Setup/PaymentPayPalContext.php @@ -45,9 +45,6 @@ final class PaymentPayPalContext implements Context /** @var string */ private $clientId; - /** @var string */ - private $partnerAttributionId; - public function __construct( SharedStorageInterface $sharedStorage, PaymentMethodRepositoryInterface $paymentMethodRepository, @@ -55,8 +52,7 @@ public function __construct( array $gatewayFactories, TranslatorInterface $translator, PayPalSelectPaymentPageInterface $selectPaymentPage, - string $clientId, - string $partnerAttributionId + string $clientId ) { $this->sharedStorage = $sharedStorage; $this->paymentMethodRepository = $paymentMethodRepository; @@ -65,7 +61,6 @@ public function __construct( $this->translator = $translator; $this->selectPaymentPage = $selectPaymentPage; $this->clientId = $clientId; - $this->partnerAttributionId = $partnerAttributionId; } /** @@ -109,7 +104,7 @@ private function createPaymentMethod( $paymentMethod->getGatewayConfig()->setConfig([ 'client_id' => $this->clientId, 'client_secret' => 'SECRET', - 'partner_attribution_id' => $this->partnerAttributionId, + 'partner_attribution_id' => 'sylius-ppcp4p-bn-code', 'merchant_id' => 'MERCHANT-ID', 'reports_sftp_username' => 'USERNAME', 'reports_sftp_password' => 'PASSWORD', diff --git a/tests/Behat/Resources/services.xml b/tests/Behat/Resources/services.xml index e8ba9df8..3585143d 100644 --- a/tests/Behat/Resources/services.xml +++ b/tests/Behat/Resources/services.xml @@ -29,7 +29,6 @@ %env(resolve:TEST_CLIENT_ID)% - %env(resolve:PAYPAL_TRACKING_ID)% From 9ec03ba0f1a6315bb944a095f0c94e5dfd13ec70 Mon Sep 17 00:00:00 2001 From: Mateusz Zalewski Date: Fri, 25 Sep 2020 00:35:50 +0200 Subject: [PATCH 2/3] Use configuration to detemine which URLs to use --- README.md | 32 +------ spec/Api/WebhookApiSpec.php | 87 ++++++++++++------- spec/Client/PayPalClientSpec.php | 51 +++++++---- src/Api/WebhookApi.php | 29 +++++-- src/Client/PayPalClient.php | 11 ++- src/DependencyInjection/Configuration.php | 1 + .../SyliusPayPalExtension.php | 10 +++ src/Resources/config/services.xml | 5 +- src/Resources/config/services/api.xml | 6 +- src/Resources/config/services/onboarding.xml | 4 +- tests/Application/.env | 4 - 11 files changed, 143 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 83bed35d..44419c3b 100644 --- a/README.md +++ b/README.md @@ -79,29 +79,7 @@ Sylius Core Team’s plugin for [PayPal Commerce Platform](https://www.paypal.co cp -R vendor/sylius/paypal-plugin/src/Resources/views/bundles/* templates/bundles/ ``` -4. Add env variables - - ### Sandbox - - ``` - #.env - - PAYPAL_API_BASE_URL='https://api.sandbox.paypal.com/' - # just for now, it will be eventually hardcoded (as we always want to use Sylius PayPal facilitator) - PAYPAL_FACILITATOR_URL='https://paypal.sylius.com' - ``` - - ### Live - - ``` - #.env - - PAYPAL_API_BASE_URL='https://api.paypal.com/' - # just for now, it will be eventually hardcoded (as we always want to use Sylius PayPal facilitator) - PAYPAL_FACILITATOR_URL='https://prod.paypal.sylius.com' - ``` - -5. Copy and apply migrations +4. Copy and apply migrations ``` cp -R vendor/sylius/paypal-plugin/migrations/ src/Migrations/ @@ -131,13 +109,7 @@ it's required to configure SFTP account and set its data in `.env` file. ![accounts](docs/reports-accounts.png) -5. Configure following env variables - - ``` - PAYPAL_REPORTS_SFTP_HOST='reports.paypal.com' - PAYPAL_REPORTS_SFTP_USERNAME='USERNAME' - PAYPAL_REPORTS_SFTP_PASSWORD='PASSWORD' - ``` +5. Configure username and password in payment method's configuration ## Processing payments diff --git a/spec/Api/WebhookApiSpec.php b/spec/Api/WebhookApiSpec.php index 07ac5da8..d43422ab 100644 --- a/spec/Api/WebhookApiSpec.php +++ b/spec/Api/WebhookApiSpec.php @@ -4,44 +4,71 @@ namespace spec\Sylius\PayPalPlugin\Api; +use GuzzleHttp\ClientInterface; use PhpSpec\ObjectBehavior; -use Prophecy\Argument; -use Sylius\PayPalPlugin\Client\PayPalClientInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\StreamInterface; final class WebhookApiSpec extends ObjectBehavior { - function let(PayPalClientInterface $client): void + function let(ClientInterface $client): void { - $this->beConstructedWith($client); + $this->beConstructedWith($client, 'http://base-url.com/'); } - function it_registers_webhook(PayPalClientInterface $client): void - { - $client->post( - 'v1/notifications/webhooks', - 'TOKEN', - Argument::that(function ($data): bool { - return - $data['url'] === 'https://webhook.com' && - $data['event_types'][0]['name'] === 'PAYMENT.CAPTURE.REFUNDED'; - }) - )->shouldBeCalled(); - - $this->register('TOKEN', 'https://webhook.com'); + function it_registers_webhook( + ClientInterface $client, + 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); + $response->getBody()->willReturn($body); + $body->getContents()->willReturn('{ "status": "CREATED" }'); + + $this->register('TOKEN', 'https://webhook.com')->shouldReturn(['status' => 'CREATED']);; } - function it_registers_webhook_without_https(PayPalClientInterface $client): void - { - $client->post( - 'v1/notifications/webhooks', - 'TOKEN', - Argument::that(function ($data): bool { - return - $data['url'] === 'https://webhook.com' && - $data['event_types'][0]['name'] === 'PAYMENT.CAPTURE.REFUNDED'; - }) - )->shouldBeCalled(); - - $this->register('TOKEN', 'http://webhook.com'); + function it_registers_webhook_without_https( + ClientInterface $client, + 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); + $response->getBody()->willReturn($body); + $body->getContents()->willReturn('{ "status": "CREATED" }'); + + $this->register('TOKEN', 'http://webhook.com')->shouldReturn(['status' => 'CREATED']);; } } diff --git a/spec/Client/PayPalClientSpec.php b/spec/Client/PayPalClientSpec.php index 94b012c4..64f3e1df 100644 --- a/spec/Client/PayPalClientSpec.php +++ b/spec/Client/PayPalClientSpec.php @@ -20,6 +20,8 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; use Psr\Log\LoggerInterface; +use Sylius\Component\Channel\Context\ChannelContextInterface; +use Sylius\Component\Core\Model\ChannelInterface; use Sylius\PayPalPlugin\Client\PayPalClientInterface; use Sylius\PayPalPlugin\Exception\PayPalApiTimeoutException; use Sylius\PayPalPlugin\Exception\PayPalAuthorizationException; @@ -32,13 +34,18 @@ function let( ClientInterface $client, LoggerInterface $logger, UuidProviderInterface $uuidProvider, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelContextInterface $channelContext, + ChannelInterface $channel ): void { + $channelContext->getChannel()->willReturn($channel); + $this->beConstructedWith( $client, $logger, $uuidProvider, $payPalConfigurationProvider, + $channelContext, 'https://test-api.paypal.com/', 5 ); @@ -92,10 +99,11 @@ function it_throws_an_exception_if_client_could_not_be_authorized( function it_calls_get_request_on_paypal_api( ClientInterface $client, PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel, ResponseInterface $response, StreamInterface $body ): void { - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'GET', @@ -121,6 +129,8 @@ function it_logs_all_requests_if_logging_level_is_increased( LoggerInterface $logger, UuidProviderInterface $uuidProvider, PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelContextInterface $channelContext, + ChannelInterface $channel, ResponseInterface $response, StreamInterface $body ): void { @@ -129,12 +139,14 @@ function it_logs_all_requests_if_logging_level_is_increased( $logger, $uuidProvider, $payPalConfigurationProvider, + $channelContext, 'https://test-api.paypal.com/', 5, true ); - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $channelContext->getChannel()->willReturn($channel); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'GET', @@ -164,11 +176,12 @@ function it_logs_debug_id_from_failed_get_request( ClientInterface $client, LoggerInterface $logger, PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel, RequestException $exception, ResponseInterface $response, StreamInterface $body ): void { - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'GET', @@ -201,10 +214,11 @@ function it_calls_post_request_on_paypal_api( ResponseInterface $response, StreamInterface $body, UuidProviderInterface $uuidProvider, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel ): void { $uuidProvider->provide()->willReturn('REQUEST-ID'); - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'POST', @@ -235,10 +249,11 @@ function it_calls_post_request_on_paypal_api_with_extra_headers( ResponseInterface $response, StreamInterface $body, UuidProviderInterface $uuidProvider, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel ): void { $uuidProvider->provide()->willReturn('REQUEST-ID'); - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'POST', @@ -272,10 +287,11 @@ function it_logs_debug_id_from_failed_post_request( ResponseInterface $response, StreamInterface $body, UuidProviderInterface $uuidProvider, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel ): void { $uuidProvider->provide()->willReturn('REQUEST-ID'); - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'POST', @@ -312,9 +328,10 @@ function it_calls_patch_request_on_paypal_api( ClientInterface $client, ResponseInterface $response, StreamInterface $body, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel ): void { - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'PATCH', @@ -345,9 +362,10 @@ function it_logs_debug_id_from_failed_patch_request( RequestException $exception, ResponseInterface $response, StreamInterface $body, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel ): void { - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'PATCH', @@ -381,9 +399,10 @@ 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, - PayPalConfigurationProviderInterface $payPalConfigurationProvider + PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelInterface $channel ): void { - $payPalConfigurationProvider->getPartnerAttributionId()->willReturn('TRACKING-ID'); + $payPalConfigurationProvider->getPartnerAttributionId($channel)->willReturn('TRACKING-ID'); $client->request( 'GET', diff --git a/src/Api/WebhookApi.php b/src/Api/WebhookApi.php index fcf22c96..0fcd0038 100644 --- a/src/Api/WebhookApi.php +++ b/src/Api/WebhookApi.php @@ -4,27 +4,38 @@ namespace Sylius\PayPalPlugin\Api; -use Sylius\PayPalPlugin\Client\PayPalClientInterface; +use GuzzleHttp\ClientInterface; final class WebhookApi implements WebhookApiInterface { - /** @var PayPalClientInterface */ + /** @var ClientInterface */ private $client; - public function __construct(PayPalClientInterface $client) + /** @var string */ + private $baseUrl; + + public function __construct(ClientInterface $client, string $baseUrl) { $this->client = $client; + $this->baseUrl = $baseUrl; } public function register(string $token, string $webhookUrl): array { - $data = [ - 'url' => preg_replace('/^http:/i', 'https:', $webhookUrl), - 'event_types' => [ - ['name' => 'PAYMENT.CAPTURE.REFUNDED'], + $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'], + ], + ] + ]); - return $this->client->post('v1/notifications/webhooks', $token, $data); + return (array) json_decode($response->getBody()->getContents(), true); } } diff --git a/src/Client/PayPalClient.php b/src/Client/PayPalClient.php index 6058e490..ecdb4d78 100644 --- a/src/Client/PayPalClient.php +++ b/src/Client/PayPalClient.php @@ -18,6 +18,8 @@ use GuzzleHttp\Exception\RequestException; use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; +use Sylius\Component\Channel\Context\ChannelContextInterface; +use Sylius\Component\Core\Model\ChannelInterface; use Sylius\PayPalPlugin\Exception\PayPalApiTimeoutException; use Sylius\PayPalPlugin\Exception\PayPalAuthorizationException; use Sylius\PayPalPlugin\Provider\PayPalConfigurationProviderInterface; @@ -37,6 +39,9 @@ final class PayPalClient implements PayPalClientInterface /** @var PayPalConfigurationProviderInterface */ private $payPalConfigurationProvider; + /** @var ChannelContextInterface */ + private $channelContext; + /** @var string */ private $baseUrl; @@ -51,6 +56,7 @@ public function __construct( LoggerInterface $logger, UuidProviderInterface $uuidProvider, PayPalConfigurationProviderInterface $payPalConfigurationProvider, + ChannelContextInterface $channelContext, string $baseUrl, int $requestTrialsLimit, bool $loggingLevelIncreased = false @@ -59,6 +65,7 @@ public function __construct( $this->logger = $logger; $this->uuidProvider = $uuidProvider; $this->payPalConfigurationProvider = $payPalConfigurationProvider; + $this->channelContext = $channelContext; $this->baseUrl = $baseUrl; $this->requestTrialsLimit = $requestTrialsLimit; $this->loggingLevelIncreased = $loggingLevelIncreased; @@ -101,12 +108,14 @@ public function patch(string $url, string $token, array $data = null): array private function request(string $method, string $url, string $token, array $data = null, array $extraHeaders = []): array { + /** @var ChannelInterface $channel */ + $channel = $this->channelContext->getChannel(); $options = [ 'headers' => array_merge([ 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', 'Accept' => 'application/json', - 'PayPal-Partner-Attribution-Id' => $this->payPalConfigurationProvider->getPartnerAttributionId(), + 'PayPal-Partner-Attribution-Id' => $this->payPalConfigurationProvider->getPartnerAttributionId($channel), ], $extraHeaders), ]; diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 0e874733..84d66d9f 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -16,6 +16,7 @@ public function getConfigTreeBuilder(): TreeBuilder $rootNode ->children() + ->booleanNode('sandbox')->defaultTrue()->end() ->arrayNode('logging') ->addDefaultsIfNotSet() ->children() diff --git a/src/DependencyInjection/SyliusPayPalExtension.php b/src/DependencyInjection/SyliusPayPalExtension.php index 8c84441c..8e18ada4 100644 --- a/src/DependencyInjection/SyliusPayPalExtension.php +++ b/src/DependencyInjection/SyliusPayPalExtension.php @@ -19,6 +19,16 @@ public function load(array $config, ContainerBuilder $container): void $container->setParameter('sylius.paypal.logging.increased', $config['logging']['increased']); + if ($config['sandbox']) { + $container->setParameter('sylius.pay_pal.facilitator_url', 'https://paypal.sylius.com'); + $container->setParameter('sylius.pay_pal.api_base_url', 'https://api.sandbox.paypal.com/'); + $container->setParameter('sylius.pay_pal.reports_sftp_host', 'reports.sandbox.paypal.com'); + } else { + $container->setParameter('sylius.pay_pal.facilitator_url', 'https://prod.paypal.sylius.com'); + $container->setParameter('sylius.pay_pal.api_base_url', 'https://api.paypal.com/'); + $container->setParameter('sylius.pay_pal.reports_sftp_host', 'reports.paypal.com'); + } + $loader->load('services.xml'); } diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 9e5a770a..3940f615 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -9,7 +9,6 @@ - %env(resolve:PAYPAL_FACILITATOR_URL)% sylius.pay_pal @@ -182,7 +181,7 @@ /> - %env(resolve:PAYPAL_REPORTS_SFTP_HOST)% + %sylius.pay_pal.reports_sftp_host% - %sylius.paypal.facilitator_url% + %sylius.pay_pal.facilitator_url% diff --git a/src/Resources/config/services/api.xml b/src/Resources/config/services/api.xml index 5b5c253b..7f63f067 100644 --- a/src/Resources/config/services/api.xml +++ b/src/Resources/config/services/api.xml @@ -14,7 +14,8 @@ - %env(resolve:PAYPAL_API_BASE_URL)% + + %sylius.pay_pal.api_base_url% %sylius.pay_pal.request_trials_limit% %sylius.paypal.logging.increased% @@ -84,7 +85,8 @@ id="Sylius\PayPalPlugin\Api\WebhookApiInterface" class="Sylius\PayPalPlugin\Api\WebhookApi" > - + + %sylius.pay_pal.api_base_url% - %sylius.paypal.facilitator_url% + %sylius.pay_pal.facilitator_url% - %sylius.paypal.facilitator_url% + %sylius.pay_pal.facilitator_url% diff --git a/tests/Application/.env b/tests/Application/.env index ce688a51..628cf1ed 100644 --- a/tests/Application/.env +++ b/tests/Application/.env @@ -21,7 +21,3 @@ DATABASE_URL=mysql://root@127.0.0.1/sylius_pay_pal_plugin_%kernel.environment%?s # Delivery is disabled by default via "null://localhost" MAILER_URL=smtp://localhost ###< symfony/swiftmailer-bundle ### - -PAYPAL_API_BASE_URL='https://api.sandbox.paypal.com/' -PAYPAL_REPORTS_SFTP_HOST='' -PAYPAL_FACILITATOR_URL='https://paypal.sylius.com' From 8aee02368d5097d141a1a9f2d4382a5d2b4bda51 Mon Sep 17 00:00:00 2001 From: Mateusz Zalewski Date: Fri, 25 Sep 2020 00:44:59 +0200 Subject: [PATCH 3/3] Inform about sandbox mode in README --- README.md | 12 ++++++++++++ spec/Api/WebhookApiSpec.php | 8 ++++---- src/Api/WebhookApi.php | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 44419c3b..9f6c5b9c 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,18 @@ Sylius Core Team’s plugin for [PayPal Commerce Platform](https://www.paypal.co To make PayPal integration working, your local Sylius URL should be accessible for the PayPal servers. Therefore you can add the proper directive to your `/etc/hosts` (something like `127.0.0.1 sylius.local`) or use a service as [ngrok](https://ngrok.com/). +#### Sandbox vs Live + +By default, plugin operates in the sandbox mode. I means all the transactions would be used with the sandbox URLs and code. +To change it, you need to configure the plugin properly: + +```yaml +sylius_pay_pal: + sandbox: false +``` + +You can, for example, configure it only for the production environment (e.g. in `config/packages/prod/sylius_pay_pal_plugin.yaml`). + ## PayPal reports To be able to download reports about your payouts, you need to have reports feature enabled on your PayPal account. Also, diff --git a/spec/Api/WebhookApiSpec.php b/spec/Api/WebhookApiSpec.php index d43422ab..bb6165e5 100644 --- a/spec/Api/WebhookApiSpec.php +++ b/spec/Api/WebhookApiSpec.php @@ -35,13 +35,13 @@ function it_registers_webhook( 'event_types' => [ ['name' => 'PAYMENT.CAPTURE.REFUNDED'], ], - ] + ], ] )->willReturn($response); $response->getBody()->willReturn($body); $body->getContents()->willReturn('{ "status": "CREATED" }'); - $this->register('TOKEN', 'https://webhook.com')->shouldReturn(['status' => 'CREATED']);; + $this->register('TOKEN', 'https://webhook.com')->shouldReturn(['status' => 'CREATED']); } function it_registers_webhook_without_https( @@ -63,12 +63,12 @@ function it_registers_webhook_without_https( 'event_types' => [ ['name' => 'PAYMENT.CAPTURE.REFUNDED'], ], - ] + ], ] )->willReturn($response); $response->getBody()->willReturn($body); $body->getContents()->willReturn('{ "status": "CREATED" }'); - $this->register('TOKEN', 'http://webhook.com')->shouldReturn(['status' => 'CREATED']);; + $this->register('TOKEN', 'http://webhook.com')->shouldReturn(['status' => 'CREATED']); } } diff --git a/src/Api/WebhookApi.php b/src/Api/WebhookApi.php index 0fcd0038..e73887ce 100644 --- a/src/Api/WebhookApi.php +++ b/src/Api/WebhookApi.php @@ -33,7 +33,7 @@ public function register(string $token, string $webhookUrl): array 'event_types' => [ ['name' => 'PAYMENT.CAPTURE.REFUNDED'], ], - ] + ], ]); return (array) json_decode($response->getBody()->getContents(), true);