Skip to content

Commit

Permalink
Merge pull request from GHSA-25fx-mxc2-76g7
Browse files Browse the repository at this point in the history
Secure pay with PayPal form URL with order token + require 3D Secure
  • Loading branch information
Zales0123 authored Oct 5, 2021
2 parents a375013 + 2adc46b commit 814923c
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 20 deletions.
12 changes: 12 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
### UPGRADE FROM 1.3.0 to 1.3.1

1. `sylius_paypal_plugin_pay_with_paypal_form` route now operates on both payment ID and order token. URl then changed from
`/pay-with-paypal/{id}` to `/pay-with-paypal/{orderToken}/{paymentId}`. If you use this route anywhere in your application, you
need to change the URL attributes

### UPGRADE FROM 1.2.3 to 1.2.4

1. `sylius_paypal_plugin_pay_with_paypal_form` route now operates on both payment ID and order token. URl then changed from
`/pay-with-paypal/{id}` to `/pay-with-paypal/{orderToken}/{paymentId}`. If you use this route anywhere in your application, you
need to change the URL attributes

### UPGRADE FROM 1.0.X TO 1.1.0

1. Upgrade your application to [Sylius 1.8](https://github.com/Sylius/Sylius/blob/master/UPGRADE-1.8.md).
Expand Down
3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ parameters:
# Test dependencies
- 'tests/Application/app/**.php'
- 'tests/Application/src/**.php'

ignoreErrors:
- '/Call to an undefined method Sylius\\Component\\Core\\Repository\\PaymentRepositoryInterface\:\:createQueryBuilder\(\)\./'
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<directory name="vendor" />
<file name="src/DependencyInjection/Configuration.php" />
<file name="src/UrlUtils.php" />
<file name="src/Controller/PayWithPayPalFormAction.php" />
</ignoreFiles>
</projectFiles>

Expand Down
8 changes: 7 additions & 1 deletion spec/Payum/Action/ResolveNextRouteActionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ final class ResolveNextRouteActionSpec extends ObjectBehavior
function it_executes_resolve_next_route_request_with_processing_payment(
ResolveNextRoute $request,
PaymentInterface $payment,
OrderInterface $order,
PaymentMethodInterface $paymentMethod,
GatewayConfigInterface $gatewayConfig
): void {
Expand All @@ -28,19 +29,24 @@ function it_executes_resolve_next_route_request_with_processing_payment(
$paymentMethod->getGatewayConfig()->willReturn($gatewayConfig);
$gatewayConfig->getFactoryName()->willReturn('sylius.pay_pal');

$payment->getOrder()->willReturn($order);
$order->getTokenValue()->willReturn('123!@#asd');

$request->setRouteName('sylius_paypal_plugin_pay_with_paypal_form')->shouldBeCalled();
$request->setRouteParameters(['id' => 12])->shouldBeCalled();
$request->setRouteParameters(['orderToken' => '123!@#asd', 'paymentId' => 12])->shouldBeCalled();

$this->execute($request);
}

function it_executes_resolve_next_route_request_with_completed_payment(
ResolveNextRoute $request,
PaymentInterface $payment,
OrderInterface $order,
PaymentMethodInterface $paymentMethod,
GatewayConfigInterface $gatewayConfig
): void {
$request->getFirstModel()->willReturn($payment);
$payment->getOrder()->willReturn($order);

$payment->getState()->willReturn(PaymentInterface::STATE_COMPLETED);
$payment->getMethod()->willReturn($paymentMethod);
Expand Down
23 changes: 22 additions & 1 deletion src/Controller/PayWithPayPalFormAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ public function __construct(

public function __invoke(Request $request): Response
{
$paymentId = (string) $request->attributes->get('paymentId');
$orderToken = (string) $request->attributes->get('orderToken');

/** @var PaymentInterface $payment */
$payment = $this->paymentRepository->find($request->attributes->get('id'));
$payment = $this->findOneByPaymentIdOrderToken($paymentId, $orderToken);
/** @var PaymentMethodInterface $paymentMethod */
$paymentMethod = $payment->getMethod();

Expand Down Expand Up @@ -79,4 +82,22 @@ public function __invoke(Request $request): Response
'partner_attribution_id' => $partnerAttributionId,
]));
}

/**
* Need to be used due to support for Sylius 1.8.
* After dropping it, we can switch to Sylius\Component\Core\Repository\PaymentRepositoryInterface::findOneByOrderToken
*/
private function findOneByPaymentIdOrderToken(string $paymentId, string $orderToken): ?PaymentInterface
{
return $this->paymentRepository
->createQueryBuilder('p')
->innerJoin('p.order', 'o')
->andWhere('p.id = :paymentId')
->andWhere('o.tokenValue = :orderToken')
->setParameter('paymentId', $paymentId)
->setParameter('orderToken', $orderToken)
->getQuery()
->getOneOrNullResult()
;
}
}
10 changes: 6 additions & 4 deletions src/Payum/Action/ResolveNextRouteAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ public function execute($request): void
/** @var PaymentInterface $payment */
$payment = $request->getFirstModel();

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

if ($payment->getState() === PaymentInterface::STATE_NEW) {
$request->setRouteName('sylius_paypal_plugin_pay_with_paypal_form');
$request->setRouteParameters(['id' => $payment->getId()]);
$request->setRouteParameters(
['orderToken' => $order->getTokenValue(), 'paymentId' => $payment->getId()]
);

return;
}
Expand All @@ -32,9 +37,6 @@ public function execute($request): void
return;
}

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

$request->setRouteName('sylius_shop_order_show');
$request->setRouteParameters(['tokenValue' => $order->getTokenValue()]);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/config/shop_routing.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
sylius_paypal_plugin_pay_with_paypal_form:
path: /pay-with-paypal/{id}
path: /pay-with-paypal/{orderToken}/{paymentId}
methods: [GET]
defaults:
_controller: Sylius\PayPalPlugin\Controller\PayWithPayPalFormAction
Expand Down
46 changes: 33 additions & 13 deletions src/Resources/views/payWithPaypal.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@
});
if (paypal.HostedFields.isEligible() === true) {
let processingOrderId;
paypal.HostedFields.render({
createOrder: function(data, actions) {
document.querySelector('#paypal-payment-container').classList.add('loading');
Expand All @@ -339,6 +341,8 @@
}).then(function(res) {
return res.json();
}).then(function(data) {
processingOrderId = data.orderID;
return data.orderID;
});
},
Expand Down Expand Up @@ -419,6 +423,7 @@
if (formValid) {
hostedFields.submit({
contingencies: ['SCA_ALWAYS'],
cardholderName: document.getElementById('card-holder-name').value,
billingAddress: {
streetAddress: document.getElementById('card-billing-address-street').value,
Expand All @@ -428,20 +433,35 @@
countryCodeAlpha2: document.getElementById('card-billing-address-country').value
}
}).then(payload => {
return fetch(completePayPalOrderUrl, {
method: 'post'
}).then(function(res) {
return res.json();
if (payload.authenticationReason == 'SUCCESSFUL' && payload.authenticationStatus == 'YES') {
return fetch(completePayPalOrderUrl, {
method: 'post'
}).then(function(res) {
return res.json();
}).then(function(data) {
if (data.status == 'processing') {
return fetch(cancelPayPalPaymentUrl, {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ payPalOrderId: data.orderID })
}).then(window.location.reload());
}
window.location.href = data.return_url;
});
}
return fetch(errorPayPalPaymentUrl, {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify('Invalid 3D Secure authentication.')
}).then(function(data) {
if (data.status == 'processing') {
return fetch(cancelPayPalPaymentUrl, {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ payPalOrderId: data.orderID })
}).then(window.location.reload());
}
window.location.href = data.return_url;
return fetch(cancelPayPalPaymentUrl, {
method: 'post',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ payPalOrderId: processingOrderId })
}).then(window.location.reload());
});
});
} else {
Expand Down

0 comments on commit 814923c

Please sign in to comment.