Skip to content

Commit 06ccaac

Browse files
committed
ACP2E-1338: Google reCaptcha in Incorrect position
1 parent 3a85576 commit 06ccaac

File tree

7 files changed

+142
-15
lines changed

7 files changed

+142
-15
lines changed

ReCaptchaCheckout/view/frontend/web/js/reCaptchaCheckout.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ define(
1414
return Component.extend({
1515
defaults: {
1616
template: 'Magento_ReCaptchaCheckout/reCaptcha',
17-
skipPayments: []
17+
skipPayments: [] // List of payment methods that do not require this reCaptcha
1818
},
1919

2020
/**

ReCaptchaPaypal/Block/LayoutProcessor/Checkout/Onepage.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,17 @@ public function __construct(
5050
public function process($jsLayout)
5151
{
5252
$key = 'paypal_payflowpro';
53+
$skipCheckoutRecaptchaForPayments = [
54+
Config::METHOD_EXPRESS => true,
55+
Config::METHOD_WPP_PE_EXPRESS => true,
56+
Config::METHOD_WPP_PE_BML => true,
57+
];
5358
if ($this->isCaptchaEnabled->isCaptchaEnabledFor($key)) {
5459
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
5560
['payment']['children']['payments-list']['children']['paypal-captcha']['children']
5661
['recaptcha']['settings'] = $this->captchaUiConfigResolver->get($key);
5762
if ($this->isCaptchaEnabled->isCaptchaEnabledFor('place_order')) {
58-
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
59-
['payment']['children']['payments-list']['children']['before-place-order']['children']
60-
['place-order-recaptcha']['skipPayments'] += [
61-
Config::METHOD_EXPRESS => true,
62-
Config::METHOD_PAYFLOWPRO => true,
63-
Config::METHOD_WPP_PE_EXPRESS => true,
64-
Config::METHOD_WPP_PE_BML => true,
65-
];
63+
$skipCheckoutRecaptchaForPayments[Config::METHOD_PAYFLOWPRO] = true;
6664
}
6765
} else {
6866
if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
@@ -71,6 +69,11 @@ public function process($jsLayout)
7169
['payment']['children']['payments-list']['children']['paypal-captcha']['children']['recaptcha']);
7270
}
7371
}
72+
if ($this->isCaptchaEnabled->isCaptchaEnabledFor('place_order')) {
73+
$jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']
74+
['payment']['children']['payments-list']['children']['before-place-order']['children']
75+
['place-order-recaptcha']['skipPayments'] += $skipCheckoutRecaptchaForPayments;
76+
}
7477

7578
return $jsLayout;
7679
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ReCaptchaPaypal\Model;
9+
10+
use Magento\Framework\Session\SessionManager;
11+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
12+
13+
/**
14+
* Saves the date and time the reCaptcha was verified
15+
*
16+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
17+
*/
18+
class ReCaptchaSession
19+
{
20+
private const PAYPAL_PAYFLOWPRO_RECAPTCHA = 'paypal_payflowpro_recaptcha';
21+
private const REPLAY_TIMEOUT = 120;
22+
23+
/**
24+
* @var TimezoneInterface
25+
*/
26+
private TimezoneInterface $timezone;
27+
28+
/**
29+
* @var SessionManager
30+
*/
31+
private SessionManager $transparentSession;
32+
33+
/**
34+
* @var SessionManager
35+
*/
36+
private SessionManager $checkoutSession;
37+
38+
/**
39+
* @param TimezoneInterface $timezone
40+
* @param SessionManager $transparentSession
41+
* @param SessionManager $checkoutSession
42+
*/
43+
public function __construct(
44+
TimezoneInterface $timezone,
45+
SessionManager $transparentSession,
46+
SessionManager $checkoutSession,
47+
) {
48+
$this->timezone = $timezone;
49+
$this->transparentSession = $transparentSession;
50+
$this->checkoutSession = $checkoutSession;
51+
}
52+
53+
/**
54+
* Saves quote_id and datetime the reCaptcha was verified
55+
*
56+
* @return bool
57+
*/
58+
public function save(): bool
59+
{
60+
$result = false;
61+
if ($this->checkoutSession->getQuote()) {
62+
$this->transparentSession->setData(
63+
self::PAYPAL_PAYFLOWPRO_RECAPTCHA,
64+
[
65+
'quote_id' => $this->checkoutSession->getQuote()->getId(),
66+
'verified_at' => $this->timezone->date()->getTimestamp(),
67+
]
68+
);
69+
$result = true;
70+
}
71+
return $result;
72+
}
73+
74+
/**
75+
* Checks whether the reCaptcha extended time has not expired
76+
*
77+
* @param int $quoteId
78+
* @return bool
79+
*/
80+
public function isValid(int $quoteId): bool
81+
{
82+
$result = false;
83+
$data = $this->transparentSession->getData(self::PAYPAL_PAYFLOWPRO_RECAPTCHA) ?? [];
84+
if (isset($data['quote_id'])
85+
&& (int) $data['quote_id'] === $quoteId
86+
&& ($data['verified_at'] + self::REPLAY_TIMEOUT) >= $this->timezone->date()->getTimestamp()
87+
) {
88+
$this->transparentSession->unsetData(self::PAYPAL_PAYFLOWPRO_RECAPTCHA);
89+
$result = true;
90+
}
91+
return $result;
92+
}
93+
}

ReCaptchaPaypal/Observer/PayPalObserver.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Magento\Framework\Exception\InputException;
1717
use Magento\Framework\Exception\LocalizedException;
1818
use Magento\Framework\Serialize\SerializerInterface;
19+
use Magento\ReCaptchaPaypal\Model\ReCaptchaSession;
1920
use Magento\ReCaptchaUi\Model\CaptchaResponseResolverInterface;
2021
use Magento\ReCaptchaUi\Model\ErrorMessageConfigInterface;
2122
use Magento\ReCaptchaUi\Model\IsCaptchaEnabledInterface;
@@ -76,6 +77,11 @@ class PayPalObserver implements ObserverInterface
7677
*/
7778
private $validationErrorMessagesProvider;
7879

80+
/**
81+
* @var ReCaptchaSession
82+
*/
83+
private $reCaptchaSession;
84+
7985
/**
8086
* @param CaptchaResponseResolverInterface $captchaResponseResolver
8187
* @param ValidationConfigResolverInterface $validationConfigResolver
@@ -86,6 +92,7 @@ class PayPalObserver implements ObserverInterface
8692
* @param LoggerInterface $logger
8793
* @param ErrorMessageConfigInterface|null $errorMessageConfig
8894
* @param ValidationErrorMessagesProvider|null $validationErrorMessagesProvider
95+
* @param ReCaptchaSession|null $reCaptchaSession
8996
*/
9097
public function __construct(
9198
CaptchaResponseResolverInterface $captchaResponseResolver,
@@ -96,7 +103,8 @@ public function __construct(
96103
IsCaptchaEnabledInterface $isCaptchaEnabled,
97104
LoggerInterface $logger,
98105
?ErrorMessageConfigInterface $errorMessageConfig = null,
99-
?ValidationErrorMessagesProvider $validationErrorMessagesProvider = null
106+
?ValidationErrorMessagesProvider $validationErrorMessagesProvider = null,
107+
?ReCaptchaSession $reCaptchaSession = null
100108
) {
101109
$this->captchaResponseResolver = $captchaResponseResolver;
102110
$this->validationConfigResolver = $validationConfigResolver;
@@ -109,6 +117,8 @@ public function __construct(
109117
?? ObjectManager::getInstance()->get(ErrorMessageConfigInterface::class);
110118
$this->validationErrorMessagesProvider = $validationErrorMessagesProvider
111119
?? ObjectManager::getInstance()->get(ValidationErrorMessagesProvider::class);
120+
$this->reCaptchaSession = $reCaptchaSession
121+
?? ObjectManager::getInstance()->get(ReCaptchaSession::class);
112122
}
113123

114124
/**
@@ -148,6 +158,9 @@ public function execute(Observer $observer): void
148158
$validationResult->getErrors(),
149159
$key
150160
);
161+
} elseif ($this->isCaptchaEnabled->isCaptchaEnabledFor('place_order')) {
162+
// Extend reCaptcha verification to place order
163+
$this->reCaptchaSession->save();
151164
}
152165
}
153166
}

ReCaptchaPaypal/Plugin/SkipPlaceOrderRecaptchaValidation.php renamed to ReCaptchaPaypal/Plugin/ReplayPayflowReCaptchaForPlaceOrder.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
use Magento\Framework\Webapi\Rest\Request;
1111
use Magento\Paypal\Model\Config;
1212
use Magento\ReCaptchaCheckout\Model\WebapiConfigProvider;
13+
use Magento\ReCaptchaPaypal\Model\ReCaptchaSession;
1314
use Magento\ReCaptchaUi\Model\IsCaptchaEnabledInterface;
1415
use Magento\ReCaptchaValidationApi\Api\Data\ValidationConfigInterface;
1516
use Magento\ReCaptchaWebapiApi\Api\Data\EndpointInterface;
1617

17-
class SkipPlaceOrderRecaptchaValidation
18+
class ReplayPayflowReCaptchaForPlaceOrder
1819
{
1920
private const PAYPAL_PAYFLOWPRO_CAPTCHA_ID = 'paypal_payflowpro';
2021

@@ -28,20 +29,28 @@ class SkipPlaceOrderRecaptchaValidation
2829
*/
2930
private Request $request;
3031

32+
/**
33+
* @var ReCaptchaSession
34+
*/
35+
private ReCaptchaSession $reCaptchaSession;
36+
3137
/**
3238
* @param IsCaptchaEnabledInterface $isCaptchaEnabled
3339
* @param Request $request
40+
* @param ReCaptchaSession $reCaptchaSession
3441
*/
3542
public function __construct(
3643
IsCaptchaEnabledInterface $isCaptchaEnabled,
37-
Request $request
44+
Request $request,
45+
ReCaptchaSession $reCaptchaSession
3846
) {
3947
$this->isCaptchaEnabled = $isCaptchaEnabled;
4048
$this->request = $request;
49+
$this->reCaptchaSession = $reCaptchaSession;
4150
}
4251

4352
/**
44-
* Skip captcha validation for "place order" button if captcha is enabled for payflowpro
53+
* Skip reCaptcha validation for "place order" button if captcha is enabled for payflowpro
4554
*
4655
* @param WebapiConfigProvider $subject
4756
* @param ValidationConfigInterface $result
@@ -58,8 +67,11 @@ public function afterGetConfigFor(
5867
if ($result && $this->isCaptchaEnabled->isCaptchaEnabledFor(self::PAYPAL_PAYFLOWPRO_CAPTCHA_ID)) {
5968
$bodyParams = $this->request->getBodyParams();
6069
$paymentMethod = $bodyParams['paymentMethod'] ?? $bodyParams['payment_method'] ?? [];
70+
$cartId = $bodyParams['cartId'] ?? $bodyParams['cart_id'] ?? null;
6171
if (isset($paymentMethod['method']) && $paymentMethod['method'] === Config::METHOD_PAYFLOWPRO) {
62-
return null;
72+
if ($cartId && $this->reCaptchaSession->isValid((int) $cartId)) {
73+
return null;
74+
}
6375
}
6476
}
6577

ReCaptchaPaypal/etc/frontend/di.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@
2121
</argument>
2222
</arguments>
2323
</type>
24+
<type name="Magento\ReCaptchaPaypal\Model\ReCaptchaSession">
25+
<arguments>
26+
<argument name="transparentSession" xsi:type="object">Magento\Framework\Session\Generic\Proxy</argument>
27+
<argument name="checkoutSession" xsi:type="object">Magento\Checkout\Model\Session\Proxy</argument>
28+
</arguments>
29+
</type>
2430
</config>

ReCaptchaPaypal/etc/webapi_rest/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
99
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
1010
<type name="Magento\ReCaptchaCheckout\Model\WebapiConfigProvider">
11-
<plugin name="skip_place_order_recaptcha_validation" type="Magento\ReCaptchaPaypal\Plugin\SkipPlaceOrderRecaptchaValidation"/>
11+
<plugin name="skip_place_order_recaptcha_validation" type="Magento\ReCaptchaPaypal\Plugin\ReplayPayflowReCaptchaForPlaceOrder"/>
1212
</type>
1313
</config>

0 commit comments

Comments
 (0)