Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
20cd23e
Fix cancelling PayPal payment only when possible
GSadee Jul 21, 2025
5c45806
Prevent unnecessary payment cancellation after PayPal (#377)
mpysiak Jul 29, 2025
d4ad9a5
PayPayConfigurationType hidden fields fix
tomkalon Aug 4, 2025
6ad94bc
Added "sylius/resource-bundle": "^1.11" dependency
tomkalon Aug 5, 2025
f5290d3
Truncate product name to max 127 characters for PayPal API compliance
tomkalon Aug 5, 2025
b9df127
Upgrade: phpseclib/phpseclib from 2.x to 3.x
tomkalon Aug 6, 2025
3c32617
Remove 'final' from PayPalOrderItemController
tomkalon Aug 13, 2025
900eadb
Allow PayPal order processing for orders in states other than "new"
tomkalon Aug 14, 2025
73ddb8a
Upgrade: phpseclib/phpseclib from 2.x to 3.x (#385)
TheMilek Aug 14, 2025
f0b6142
Merge branch '1.7' into draft/remove-final-from-deprecated-controller
TheMilek Aug 21, 2025
c399695
Merge branch '1.7' into fix/paypal-api-product-name-limit
TheMilek Aug 21, 2025
71d4e0d
Merge branch '1.7' into fix/composer-require
TheMilek Aug 21, 2025
dd4300d
Merge branch '1.7' into fix/configuration-and-payment-process
TheMilek Aug 21, 2025
7f702d4
Remove 'final' from PayPalOrderItemController (#386)
TheMilek Aug 21, 2025
11ad6c9
Merge branch '1.7' into fix/paypal-api-product-name-limit
TheMilek Aug 26, 2025
c7e1466
Truncate product name to fit PayPal API limits (max 127 characters) (…
TheMilek Aug 26, 2025
15a6dad
Merge branch '1.7' into fix/composer-require
TheMilek Aug 26, 2025
d752825
Fixes incorrect dependency on sylius/resource-bundle (#382)
TheMilek Sep 1, 2025
79c58cd
Fix/configuration and payment process (#381)
TheMilek Sep 1, 2025
8f3eae2
[Maintenance] Add missing attributes mapping to entities
NoResponseMate Oct 10, 2025
0e7f490
[Maintenance] Make known upstream vulnerabilities not fail the pipe
NoResponseMate Oct 10, 2025
18749c2
[Maintenance] Add missing attributes mapping to entities (#390)
Rafikooo Oct 10, 2025
2dc15ab
CancelPayPalOrderAction has been fixed
tomkalon Aug 5, 2025
96c6077
Prevent cart from being cleared when PayPal Express checkout is cance…
NoResponseMate Oct 13, 2025
8e85c0f
Cancel payment only if it's possible
LucaGallinari Apr 8, 2022
b8bd8a0
Cancel payment only if it's possible (#391)
GSadee Oct 13, 2025
ecf560f
Create a query service to get paypal payments
NoResponseMate Oct 13, 2025
53afaea
[Payment] Incorporate payment query into payment modification control…
NoResponseMate Oct 13, 2025
fee6748
Fix performance issue of getting all payments within the payment flow…
GSadee Oct 15, 2025
15acefd
[ExpressCheckout] Get paypal methods directly instead of defaulting
NoResponseMate Oct 14, 2025
107a06b
[Maintenance] Update CI builds
NoResponseMate Oct 15, 2025
5a4035f
[Maintenance] Update CI builds (#397)
GSadee Oct 15, 2025
9240a8e
[ExpressCheckout] Get paypal methods directly instead of defaulting (…
GSadee Oct 15, 2025
2d16f56
[Maintenance] Deprecate PaymentProvider in favour of PaypalPaymentQuery
NoResponseMate Oct 15, 2025
3153b3c
[Maintenance] Deprecate PaymentProvider in favour of PaypalPaymentQue…
GSadee Oct 15, 2025
8db71cc
Fix line items creation being tied with the number of taxes
NoResponseMate Oct 15, 2025
304ffee
[Refund] Fix partial refunds within same day
NoResponseMate Oct 16, 2025
87dc7bb
Allow skipping shipping/payment steps in express checkout
NoResponseMate Oct 16, 2025
ca2f9c8
[DI] Allow setting sandbox mode and increased logging via env variables
NoResponseMate Oct 17, 2025
e0d981f
[DI] Allow setting sandbox mode and increased logging via env variabl…
GSadee Oct 20, 2025
9062908
[ExpressCheckout] Allow skipping shipping/payment steps (#404)
GSadee Oct 20, 2025
2cfbf13
[Maintenance] Fix invalid PaymentMethod form labels
NoResponseMate Oct 16, 2025
a8a9cee
[Refund] Fix partial refunds within same day (#401)
GSadee Oct 20, 2025
94c3c12
Fix supported locales resolving
NoResponseMate Oct 16, 2025
fffec83
[Maintenance] Fix invalid PaymentMethod form labels (#403)
Rafikooo Oct 20, 2025
c01ef7d
Fix line items creation being tied with the number of taxes (#399)
GSadee Oct 20, 2025
53d7518
[Checkout] Fix supported locales resolving (#402)
GSadee Oct 20, 2025
6e832af
[PaymentMethod] Fix invalid response checking for enabling paypal
NoResponseMate Oct 20, 2025
f8a1710
[Maintenance] Add missing locale processor argument and cover pay for…
NoResponseMate Oct 21, 2025
ca4b0ce
[Admin][Fix] Allow creating sandbox paypal payment method
NoResponseMate Oct 21, 2025
8e33d7a
[Maintenance] Locale resolving fixes (#406)
GSadee Oct 22, 2025
866bef5
[PaymentMethod] Fix creating sandbox method (#407)
GSadee Oct 22, 2025
d71285c
Resolve conflicts between 1.7 and 2.0
NoResponseMate Oct 22, 2025
f530e47
[UPMERGE] 1.7 -> 2.0 (#379)
GSadee Oct 23, 2025
241723e
[Maintenance] Boost phpstan
NoResponseMate Oct 24, 2025
c176ada
[Maintenance] Boost phpstan (#410)
Rafikooo Oct 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ jobs:
database: ["mysql", "postgres"]
mysql: ["8.4"]
postgres: ["15.8"]
node: ["20.x"]
node: ["22.x"]
state_machine_adapter: ["symfony_workflow"]

include:
- php: "8.3"
symfony: "~7.2.0"
symfony: "~7.3.0"
sylius: "~2.1.0"
node: "24.x"
database: "mysql"
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"friends-of-behat/symfony-extension": "^2.1",
"friends-of-behat/variadic-extension": "^1.3",
"lchrusciel/api-test-case": "^5.1",
"matthiasnoback/symfony-dependency-injection-test": "^5.0",
"nyholm/psr7": "^1.8",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-doctrine": "^2.0",
Expand Down
53 changes: 52 additions & 1 deletion config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,33 @@
<import resource="services/**/*.xml" />
</imports>

<parameters>
<parameter key="sylius_paypal.prioritize_paypal_as_default_method">true</parameter>

<parameter type="collection" key="sylius_paypal.repository.query.pay_pal_payment.updatable_states">
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_CART</parameter>
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_NEW</parameter>
</parameter>
<parameter type="collection" key="sylius_paypal.repository.query.pay_pal_payment.cancellable_states">
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_CART</parameter>
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_NEW</parameter>
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_PROCESSING</parameter>
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_AUTHORIZED</parameter>
</parameter>
<parameter type="collection" key="sylius_paypal.repository.query.pay_pal_payment.refundable_states">
<parameter type="constant">Sylius\Component\Payment\Model\PaymentInterface::STATE_COMPLETED</parameter>
</parameter>
</parameters>

<services>
<service id="sylius_paypal.form.extension.payment_method" class="Sylius\PayPalPlugin\Form\Extension\PaymentMethodTypeExtension">
<tag name="form.type_extension" />
</service>

<service id="sylius_paypal.form.type.paypal_configuration" class="Sylius\PayPalPlugin\Form\Type\PayPalConfigurationType">
<argument>%sylius_paypal.sandbox%</argument>

<tag name="form.type" />
<tag name="sylius.gateway_configuration_type" type="sylius_paypal" label="sylius_paypal.label" />
</service>

Expand All @@ -46,6 +67,7 @@
<argument type="service" id="router" />
<argument type="service" id="request_stack" />
<argument type="service" id="sylius_paypal.provider.paypal_payment_method" />
<argument>%sylius_paypal.sandbox%</argument>
<tag name="kernel.event_listener" event="sylius.payment_method.initialize_create" method="initializeCreate" />
</service>

Expand Down Expand Up @@ -75,6 +97,7 @@
>
<argument type="service" id="sylius.repository.payment" />
<argument type="service" id="sylius.repository.order" />
<deprecated package="sylius/paypal-plugin" version="1.7">The "%service_id%" service is deprecated since 1.7 and will be removed in 3.0.</deprecated>
</service>
<service id="Sylius\PayPalPlugin\Provider\PaymentProviderInterface" alias="sylius_paypal.provider.payment" />

Expand Down Expand Up @@ -157,7 +180,9 @@
<service
id="sylius_paypal.processor.locale"
class="Sylius\PayPalPlugin\Processor\LocaleProcessor"
/>
>
<argument type="service" id="sylius_paypal.resolver.supported_locale" />
</service>
<service id="Sylius\PayPalPlugin\Processor\LocaleProcessorInterface" alias="sylius_paypal.processor.locale" />

<service
Expand Down Expand Up @@ -188,6 +213,7 @@
>
<argument type="service" id=".inner" />
<argument type="service" id="sylius.repository.payment_method" />
<argument>%sylius_paypal.prioritize_paypal_as_default_method%</argument>
</service>

<service
Expand Down Expand Up @@ -291,5 +317,30 @@

<service id="sylius_paypal.verifier.payment_amount" class="Sylius\PayPalPlugin\Verifier\PaymentAmountVerifier" />
<service id="Sylius\PayPalPlugin\Verifier\PaymentAmountVerifierInterface" alias="sylius_paypal.verifier.payment_amount" />

<service
id="sylius_paypal.repository.query.paypal_payment"
class="Sylius\PayPalPlugin\Repository\Query\PaypalPaymentQuery"
>
<argument type="service" id="sylius.manager.payment" />
<argument type="service" id="sylius.repository.payment"/>
<argument>%sylius_paypal.repository.query.pay_pal_payment.updatable_states%</argument>
<argument>%sylius_paypal.repository.query.pay_pal_payment.cancellable_states%</argument>
<argument>%sylius_paypal.repository.query.pay_pal_payment.refundable_states%</argument>
</service>
<service id="Sylius\PayPalPlugin\Repository\Query\PaypalPaymentQueryInterface" alias="sylius_paypal.repository.query.paypal_payment" />

<service id="sylius_paypal.resolver.paypal_payment_methods" class="Sylius\PayPalPlugin\Resolver\PayPalPaymentMethodsResolver">
<argument type="service" id="sylius.repository.payment_method" />
</service>
<service id="Sylius\PayPalPlugin\Resolver\PayPalPaymentMethodsResolverInterface" alias="sylius_paypal.resolver.paypal_payment_methods" />

<service
id="sylius_paypal.resolver.supported_locale"
class="Sylius\PayPalPlugin\Resolver\SupportedLocaleResolver"
>
<argument>%sylius_paypal.supported_locales%</argument>
</service>
<service id="Sylius\PayPalPlugin\Resolver\SupportedLocaleResolverInterface" alias="sylius_paypal.resolver.supported_locale" />
</services>
</container>
10 changes: 8 additions & 2 deletions config/services/controller.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
<argument type="service" id="sylius_paypal.provider.payment" />
<argument type="service" id="sylius.manager.payment" />
<argument type="service" id="sylius_paypal.provider.paypal_refund_data" />
<argument type="service" id="sylius_paypal.repository.query.paypal_payment" />
</service>

<service id="sylius_paypal.controller.cancel_paypal_order" class="Sylius\PayPalPlugin\Controller\CancelPayPalOrderAction">
<argument type="service" id="sylius_paypal.provider.payment" />
<argument type="service" id="sylius.repository.order" />
<argument>null</argument>
<argument>null</argument>
<argument type="service" id="request_stack" />
</service>

Expand All @@ -38,6 +39,7 @@
<argument type="service" id="request_stack" />
<argument type="service" id="sylius_abstraction.state_machine" />
<argument type="service" id="sylius.order_processing.order_payment_processor.checkout" />
<argument type="service" id="sylius_paypal.repository.query.paypal_payment" />
</service>

<service id="sylius_paypal.controller.cancel_last_paypal_payment" class="Sylius\PayPalPlugin\Controller\CancelLastPayPalPaymentAction">
Expand All @@ -50,6 +52,7 @@
<service id="sylius_paypal.controller.cancel_paypal_checkout_payment" class="Sylius\PayPalPlugin\Controller\CancelPayPalCheckoutPaymentAction">
<argument type="service" id="sylius_paypal.provider.payment" />
<argument type="service" id="sylius_paypal.manager.payment_state" />
<argument type="service" id="sylius_paypal.repository.query.paypal_payment" />
</service>

<service id="sylius_paypal.controller.complete_paypal_order" class="Sylius\PayPalPlugin\Controller\CompletePayPalOrderAction">
Expand Down Expand Up @@ -89,6 +92,7 @@
<argument type="service" id="sylius_paypal.resolver.capture_payment" />
<argument type="service" id="sylius.remover.payment.order" />
<argument type="service" id="sylius.order_processing.order_processor" />
<argument type="service" id="sylius_paypal.resolver.paypal_payment_methods" />
</service>

<service id="sylius_paypal.controller.paypal_buttons" class="Sylius\PayPalPlugin\Controller\PayPalButtonsController">
Expand All @@ -108,6 +112,7 @@
<argument type="service" id="sylius_paypal.provider.available_countries" />
<argument type="service" id="sylius_paypal.api.cache_authorize_client" />
<argument type="service" id="sylius_paypal.api.identity" />
<argument type="service" id="sylius_paypal.processor.locale" />
</service>

<service id="sylius_paypal.controller.process_paypal_order" class="Sylius\PayPalPlugin\Controller\ProcessPayPalOrderAction">
Expand All @@ -129,6 +134,7 @@
<argument type="service" id="sylius_paypal.api.update_order" />
<argument type="service" id="sylius.factory.address" />
<argument type="service" id="sylius.order_processing.order_processor" />
<argument type="service" id="sylius_paypal.repository.query.paypal_payment" />
</service>

<service id="sylius_paypal.controller.complete_paypal_order_from_payment_page" class="Sylius\PayPalPlugin\Controller\CompletePayPalOrderFromPaymentPageAction">
Expand Down
2 changes: 0 additions & 2 deletions ecs.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
return static function (ECSConfig $config): void {
$config->paths([
'src',
'spec',
'tests/Behat',
'tests/Functional',
'tests/Service',
Expand All @@ -37,7 +36,6 @@
);

$config->skip([
VisibilityRequiredFixer::class => ['*Spec.php'],
InlineDocCommentDeclarationSniff::class . '.MissingVariable',
]);
};
14 changes: 6 additions & 8 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@ includes:
- vendor/phpstan/phpstan-webmozart-assert/extension.neon

parameters:
level: 3

reportUnmatchedIgnoredErrors: false
level: 6

paths:
- 'src/'
- src

excludePaths:
# Makes PHPStan crash
- 'src/DependencyInjection/Configuration.php'
- 'src/DependencyInjection/SyliusPayPalExtension.php'

# Test dependencies
- 'tests/Application/app/**.php'
- 'tests/Application/src/**.php'
ignoreErrors:
- identifier: missingType.iterableValue

- '/Dead catch - Sylius\\PayPalPlugin\\Exception\\PayPalWebhookUrlNotValidException is never thrown in the try block\./' # architectural smell
2 changes: 1 addition & 1 deletion src/Api/CacheAuthorizeClientApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

final readonly class CacheAuthorizeClientApi implements CacheAuthorizeClientApiInterface
{
/** @param ObjectRepository<PayPalCredentialsInterface> $payPalCredentialsRepository */
public function __construct(
private ObjectManager $payPalCredentialsManager,
private ObjectRepository $payPalCredentialsRepository,
Expand All @@ -32,7 +33,6 @@ public function __construct(

public function authorize(PaymentMethodInterface $paymentMethod): string
{
/** @var PayPalCredentialsInterface|null $payPalCredentials */
$payPalCredentials = $this->payPalCredentialsRepository->findOneBy(['paymentMethod' => $paymentMethod]);
if ($payPalCredentials !== null && !$payPalCredentials->isExpired()) {
return $payPalCredentials->accessToken();
Expand Down
1 change: 1 addition & 0 deletions src/Console/Command/CompletePaidPaymentsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
)]
final class CompletePaidPaymentsCommand extends Command
{
/** @param PaymentRepositoryInterface<PaymentInterface> $paymentRepository */
public function __construct(
private readonly PaymentRepositoryInterface $paymentRepository,
private readonly ObjectManager $paymentManager,
Expand Down
5 changes: 5 additions & 0 deletions src/Controller/CancelLastPayPalPaymentAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

final readonly class CancelLastPayPalPaymentAction
{
/** @param OrderRepositoryInterface<OrderInterface> $orderRepository */
public function __construct(
private ObjectManager $objectManager,
private StateMachineInterface $stateMachineFactory,
Expand All @@ -41,6 +42,10 @@ public function __invoke(Request $request): Response
/** @var PaymentInterface $payment */
$payment = $order->getLastPayment();

if (!$this->stateMachineFactory->can($payment, PaymentTransitions::GRAPH, PaymentTransitions::TRANSITION_CANCEL)) {
return new Response('', Response::HTTP_NO_CONTENT);
}

$this->stateMachineFactory->apply($payment, PaymentTransitions::GRAPH, PaymentTransitions::TRANSITION_CANCEL);

/** @var PaymentInterface $lastPayment */
Expand Down
35 changes: 29 additions & 6 deletions src/Controller/CancelPayPalCheckoutPaymentAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,51 @@

use Sylius\PayPalPlugin\Manager\PaymentStateManagerInterface;
use Sylius\PayPalPlugin\Provider\PaymentProviderInterface;
use Sylius\PayPalPlugin\Repository\Query\PaypalPaymentQueryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;

final readonly class CancelPayPalCheckoutPaymentAction
{
public function __construct(
private PaymentProviderInterface $paymentProvider,
private ?PaymentProviderInterface $paymentProvider,
private PaymentStateManagerInterface $paymentStateManager,
private ?PaypalPaymentQueryInterface $paypalPaymentQuery = null,
) {
if (null !== $this->paymentProvider) {
trigger_deprecation(
'sylius/paypal-plugin',
'1.7',
sprintf(
'Passing an instance of "%s" as the first argument is deprecated and will be prohibited in 3.0',
PaymentProviderInterface::class,
),
);
}
if (null === $this->paypalPaymentQuery) {
trigger_deprecation(
'sylius/paypal-plugin',
'1.7',
sprintf(
'Not passing an instance of "%s" is deprecated and will be prohibited in 3.0',
PaypalPaymentQueryInterface::class,
),
);
}
}

public function __invoke(Request $request): Response
{
/**
* @var string $content
*/
/** @var string $content */
$content = $request->getContent();

$content = (array) json_decode($content, true);

$payment = $this->paymentProvider->getByPayPalOrderId((string) $content['payPalOrderId']);
if (null !== $this->paypalPaymentQuery) {
$payment = $this->paypalPaymentQuery->getForCancellationByOrderId((string) $content['payPalOrderId']);
} else {
$payment = $this->paymentProvider->getByPayPalOrderId((string) $content['payPalOrderId']);
}

/** @var FlashBagInterface $flashBag */
$flashBag = $request->getSession()->getBag('flashes');
Expand Down
26 changes: 10 additions & 16 deletions src/Controller/CancelPayPalOrderAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,23 @@

final readonly class CancelPayPalOrderAction
{
/** @param OrderRepositoryInterface<OrderInterface>|null $orderRepository */
public function __construct(
private PaymentProviderInterface $paymentProvider,
private OrderRepositoryInterface $orderRepository,
private ?PaymentProviderInterface $paymentProvider,
private ?OrderRepositoryInterface $orderRepository,
private RequestStack $flashBagOrRequestStack,
) {
if (null !== $this->paymentProvider) {
trigger_deprecation('sylius/paypal-plugin', '1.7', sprintf('Passing an instance of %s as the first argument is deprecated and will be prohibited in 3.0', PaymentProviderInterface::class));
}
if (null !== $this->orderRepository) {
trigger_deprecation('sylius/paypal-plugin', '1.7', sprintf('Passing an instance of %s as the second argument is deprecated and will be prohibited in 3.0', OrderRepositoryInterface::class));
}
}

public function __invoke(Request $request): Response
{
/**
* @var string $content
*/
$content = $request->getContent();

$content = (array) json_decode($content, true);

$payment = $this->paymentProvider->getByPayPalOrderId((string) $content['payPalOrderId']);

/** @var OrderInterface $order */
$order = $payment->getOrder();
$this->orderRepository->remove($order);

FlashBagProvider::getFlashBag($this->flashBagOrRequestStack)->add('success', 'sylius_paypal.order_cancelled');
FlashBagProvider::getFlashBag($this->flashBagOrRequestStack)->add('success', 'sylius.pay_pal.order_cancelled');

return new Response('', Response::HTTP_NO_CONTENT);
}
Expand Down
Loading