We will be off from 27/1 (Monday) to 31/1 (Friday) (GMT +7) for our Tet Holiday (Lunar New Year) in our country

Commit c8e009f6 authored by Attila Kiss's avatar Attila Kiss Committed by GitHub

[PW-3111] Use getOrigin helper function for returnUrl parameter in redirect controller (#924)

* Add PWA origin for the getRedirectUrl() in the transparent redirect

Add support for PWA dedicated frontend urls per store

* Add query when redirecting to the result controller

* Delete Redirect.php - not used anymore

* Add merchant reference in the return url as get param to support PWA

* Store details in the payment additional information object

* [WIP] use result as a generic handler for redirects

Validate all the redirects via payments/details
Validate the parameters for payments/details with the details list from
the first payments response

* [WIP] use result as a generic handler for redirects

* Update Controller/Process/Result.php
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>
Co-authored-by: default avatarÁngel Campos <angel.campos@adyen.com>
parent 1d5d1ed8
......@@ -23,6 +23,7 @@
namespace Adyen\Payment\Block\Transparent;
use Adyen\Payment\Helper\Data;
use Adyen\Service\Validator\DataArrayValidator;
use Magento\Framework\View\Element\Template;
......@@ -32,12 +33,20 @@ class Redirect extends Template
* @var \Magento\Framework\UrlInterface
*/
private $url;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
protected $adyenLogger;
/**
* @var Data
*/
protected $adyenHelper;
/**
* Redirect constructor.
*
* @param Template\Context $context
* @param \Magento\Framework\UrlInterface $url
* @param array $data
......@@ -46,24 +55,41 @@ class Redirect extends Template
Template\Context $context,
\Magento\Framework\UrlInterface $url,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
Data $adyenHelper,
array $data = []
) {
$this->url = $url;
$this->adyenLogger = $adyenLogger;
$this->adyenHelper = $adyenHelper;
parent::__construct($context, $data);
}
/**
* Returns url for redirect.
*
* @return string|null
*/
public function getRedirectUrl()
{
return $this->url->getUrl("adyen/process/redirect"); //TODO this will be replaced by getOrigin() for PWA integrations
$pwaOrigin = $this->adyenHelper->getAdyenAbstractConfigData("payment_origin_url", $this->_storeManager->getStore()->getId());
if ($pwaOrigin) {
$returnUrl = $pwaOrigin . "/adyen/process/result";
} else {
$returnUrl = $this->url->getUrl("adyen/process/result");
}
if (!empty($this->getRequest()->getQueryValue())) {
$query = http_build_query($this->getRequest()->getQueryValue(), '', '&');
$returnUrl .= '?' . $query;
}
return $returnUrl;
}
/**
* Returns params to be redirected.
*
* @return array
*/
public function getPostParams()
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Controller\Process;
use Magento\Framework\App\Request\Http as Http;
use Magento\Vault\Api\Data\PaymentTokenInterface;
use Magento\Vault\Api\Data\PaymentTokenFactoryInterface;
use Magento\Sales\Api\Data\OrderPaymentExtensionInterface;
use Magento\Sales\Api\Data\OrderPaymentExtensionInterfaceFactory;
use Magento\Sales\Model\ResourceModel\Order\Payment as OrderPaymentResource;
use Magento\Payment\Model\InfoInterface;
class Redirect extends \Magento\Framework\App\Action\Action
{
/**
* @var \Magento\Quote\Model\Quote
*/
protected $_quote = false;
/**
* @var \Magento\Checkout\Model\Session
*/
protected $_checkoutSession;
/**
* @var \Magento\Sales\Model\Order
*/
protected $_order;
/**
* @var \Magento\Sales\Model\OrderFactory
*/
protected $_orderFactory;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
protected $_adyenLogger;
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $_adyenHelper;
/**
* @var \Adyen\Payment\Model\Api\PaymentRequest
*/
protected $_paymentRequest;
/**
* @var \Magento\Sales\Api\OrderRepositoryInterface
*/
protected $_orderRepository;
/**
* @var PaymentTokenFactoryInterface
*/
private $paymentTokenFactory;
/**
* @var OrderPaymentExtensionInterfaceFactory
*/
private $paymentExtensionFactory;
/**
* @var OrderPaymentResource
*/
private $orderPaymentResource;
/**
* @var \Magento\Framework\Serialize\SerializerInterface
*/
private $serializer;
/**
* Redirect constructor.
*
* @param \Magento\Framework\App\Action\Context $context
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Adyen\Payment\Model\Api\PaymentRequest $paymentRequest
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
* @param PaymentTokenFactoryInterface $paymentTokenFactory
* @param OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory
* @param OrderPaymentResource $orderPaymentResource
* @param \Magento\Framework\Serialize\SerializerInterface $serializer
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Model\Api\PaymentRequest $paymentRequest,
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
PaymentTokenFactoryInterface $paymentTokenFactory,
OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory,
OrderPaymentResource $orderPaymentResource,
\Magento\Framework\Serialize\SerializerInterface $serializer
) {
parent::__construct($context);
$this->_adyenLogger = $adyenLogger;
$this->_adyenHelper = $adyenHelper;
$this->_paymentRequest = $paymentRequest;
$this->_orderRepository = $orderRepository;
$this->paymentTokenFactory = $paymentTokenFactory;
$this->paymentExtensionFactory = $paymentExtensionFactory;
$this->orderPaymentResource = $orderPaymentResource;
$this->serializer = $serializer;
if (interface_exists(\Magento\Framework\App\CsrfAwareActionInterface::class)) {
$request = $this->getRequest();
if ($request instanceof Http && $request->isPost()) {
$request->setParam('isAjax', true);
$request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest');
}
}
}
/**
* Validate 3D secure payment
*/
public function execute()
{
$active = null;
// check if 3d is active
$order = $this->_getOrder();
if ($order->getPayment()) {
$active = $order->getPayment()->getAdditionalInformation('3dActive');
$success = $order->getPayment()->getAdditionalInformation('3dSuccess');
}
// check if 3D secure is active. If not just go to success page
if ($active && $success != true) {
$this->_adyenLogger->addAdyenResult("3D secure is active");
// check if it is already processed
if ($this->getRequest()->isPost()) {
$this->_adyenLogger->addAdyenResult("Process 3D secure payment");
$requestPaRes = $this->getRequest()->getPost('PaRes');
$order->getPayment()->setAdditionalInformation('paResponse', $requestPaRes);
try {
$result = $this->_authorise3d($order->getPayment());
$responseCode = $result['resultCode'];
} catch (\Exception $e) {
$this->_adyenLogger->addAdyenResult("Process 3D secure payment was refused");
$responseCode = 'Refused';
}
$this->_adyenLogger->addAdyenResult("Process 3D secure payment result is: " . $responseCode);
// check if authorise3d was successful
if ($responseCode == 'Authorised') {
$order->addStatusHistoryComment(__('3D-secure validation was successful'))->save();
// set back to false so when pressed back button on the success page
// it will reactivate 3D secure
$order->getPayment()->setAdditionalInformation('3dActive', '');
$order->getPayment()->setAdditionalInformation('3dSuccess', true);
if (!$this->_adyenHelper->isCreditCardVaultEnabled() &&
!empty($result['additionalData']['recurring.recurringDetailReference'])) {
$this->_adyenHelper->createAdyenBillingAgreement($order, $result['additionalData']);
} elseif (!empty($result['additionalData']['recurring.recurringDetailReference'])
) {
try {
$additionalData = $result['additionalData'];
$token = $additionalData['recurring.recurringDetailReference'];
$expirationDate = $additionalData['expiryDate'];
$cardType = $additionalData['paymentMethod'];
$cardSummary = $additionalData['cardSummary'];
/** @var PaymentTokenInterface $paymentToken */
$paymentToken = $this->paymentTokenFactory->create(
PaymentTokenFactoryInterface::TOKEN_TYPE_CREDIT_CARD
);
$paymentToken->setGatewayToken($token);
$paymentToken->setExpiresAt($this->getExpirationDate($expirationDate));
$details = [
'type' => $cardType,
'maskedCC' => $cardSummary,
'expirationDate' => $expirationDate
];
$paymentToken->setTokenDetails(json_encode($details));
$extensionAttributes = $this->getExtensionAttributes($order->getPayment());
$extensionAttributes->setVaultPaymentToken($paymentToken);
$orderPayment = $order->getPayment()->setExtensionAttributes($extensionAttributes);
$add = $this->serializer->unserialize($orderPayment->getAdditionalData());
$add['force_save'] = true;
$orderPayment->setAdditionalData($this->serializer->serialize($add));
$this->orderPaymentResource->save($orderPayment);
} catch (\Exception $e) {
$this->_adyenLogger->error((string)$e->getMessage());
}
}
$this->_orderRepository->save($order);
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
} else {
/*
* Since responseCode!='Authorised' the order could be cancelled immediately,
* but redirect payments can have multiple conflicting responses.
* The order will be cancelled if an Authorization
* Success=False notification is processed instead
*/
$order->addStatusHistoryComment(
__(
'3D-secure validation was unsuccessful. This order will be cancelled when the related
notification has been processed.'
)
)->save();
$this->messageManager->addErrorMessage("3D-secure validation was unsuccessful");
// reactivate the quote
$session = $this->_getCheckout();
// restore the quote
$session->restoreQuote();
$this->_redirect($this->_adyenHelper->getAdyenAbstractConfigData('return_path'));
}
} else {
$this->_adyenLogger->addAdyenResult("Customer was redirected to bank for 3D-secure validation.");
$order->addStatusHistoryComment(
__(
'Customer was redirected to bank for 3D-secure validation. Once the shopper authenticated,
the order status will be updated accordingly.
<br />Make sure that your notifications are being processed!
<br />If the order is stuck on this status, the shopper abandoned the session.
The payment can be seen as unsuccessful.
<br />The order can be automatically cancelled based on the OFFER_CLOSED notification.
Please contact Adyen Support to enable this.'
)
)->save();
$this->_view->loadLayout();
$this->_view->getLayout()->initMessages();
$this->_view->renderLayout();
}
} else {
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
}
}
/**
* Return checkout session object
*
* @return \Magento\Checkout\Model\Session
*/
protected function _getCheckoutSession()
{
return $this->_checkoutSession;
}
/**
* Get order object
*
* @return \Magento\Sales\Model\Order
*/
protected function _getOrder()
{
if (!$this->_order) {
$incrementId = $this->_getCheckout()->getLastRealOrderId();
$this->_orderFactory = $this->_objectManager->get(\Magento\Sales\Model\OrderFactory::class);
$this->_order = $this->_orderFactory->create()->loadByIncrementId($incrementId);
}
return $this->_order;
}
/**
* @return \Magento\Checkout\Model\Session
*/
protected function _getCheckout()
{
return $this->_objectManager->get(\Magento\Checkout\Model\Session::class);
}
/**
* @return mixed
*/
protected function _getQuote()
{
return $this->_objectManager->get(\Magento\Quote\Model\Quote::class);
}
/**
* @return mixed
*/
protected function _getQuoteManagement()
{
return $this->_objectManager->get(\Magento\Quote\Model\QuoteManagement::class);
}
/**
* Called by redirect controller when cc payment has 3D secure
*
* @param $payment
* @return mixed
* @throws \Exception
*/
protected function _authorise3d($payment)
{
try {
$response = $this->_paymentRequest->authorise3d($payment);
} catch (\Exception $e) {
throw $e;
}
return $response;
}
/**
* @param $expirationDate
* @return string
*/
private function getExpirationDate($expirationDate)
{
$expirationDate = explode('/', $expirationDate);
//add leading zero to month
$month = sprintf("%02d", $expirationDate[0]);
$expDate = new \DateTime(
$expirationDate[1]
. '-'
. $month
. '-'
. '01'
. ' '
. '00:00:00',
new \DateTimeZone('UTC')
);
// add one month
$expDate->add(new \DateInterval('P1M'));
return $expDate->format('Y-m-d 00:00:00');
}
/**
* Get payment extension attributes
*
* @param InfoInterface $payment
* @return OrderPaymentExtensionInterface
*/
private function getExtensionAttributes(InfoInterface $payment)
{
$extensionAttributes = $payment->getExtensionAttributes();
if (null === $extensionAttributes) {
$extensionAttributes = $this->paymentExtensionFactory->create();
$payment->setExtensionAttributes($extensionAttributes);
}
return $extensionAttributes;
}
}
......@@ -24,6 +24,8 @@
namespace Adyen\Payment\Controller\Process;
use \Adyen\Payment\Model\Notification;
use Adyen\Service\Validator\DataArrayValidator;
use Magento\Framework\App\Request\Http as Http;
class Result extends \Magento\Framework\App\Action\Action
{
......@@ -89,6 +91,13 @@ class Result extends \Magento\Framework\App\Action\Action
$this->_adyenLogger = $adyenLogger;
$this->storeManager = $storeManager;
parent::__construct($context);
if (interface_exists(\Magento\Framework\App\CsrfAwareActionInterface::class)) {
$request = $this->getRequest();
if ($request instanceof Http && $request->isPost()) {
$request->setParam('isAjax', true);
$request->getHeaders()->addHeaderLine('X_REQUESTED_WITH', 'XMLHttpRequest');
}
}
}
/**
......@@ -96,6 +105,7 @@ class Result extends \Magento\Framework\App\Action\Action
*/
public function execute()
{
// GET and POST params together
$response = $this->getRequest()->getParams();
$this->_adyenLogger->addAdyenResult(print_r($response, true));
......@@ -153,6 +163,7 @@ class Result extends \Magento\Framework\App\Action\Action
$this->_adyenLogger->addAdyenResult('Processing ResultUrl');
// TODO check if needed since response is validated when calling this function
if (empty($response)) {
$this->_adyenLogger->addAdyenResult(
'Response is empty, please check your webserver that the result url accepts parameters'
......@@ -164,26 +175,20 @@ class Result extends \Magento\Framework\App\Action\Action
}
// If the merchant signature is present, authenticate the result url
// TODO validate if merchant signature is still used or can be removed
if (!empty($response['merchantSig'])) {
// authenticate result url
$authStatus = $this->_authenticate($response);
if (!$authStatus) {
throw new \Magento\Framework\Exception\LocalizedException(__('ResultUrl authentification failure'));
}
// Otherwise validate the pazload and get back the response that can be used to finish the order
} else {
// send the payload verification payment\details request to validate the response
$response = $this->validatePayloadAndReturnResponse($response);
}
$incrementId = null;
// send the payload verification payment\details request to validate the response
$response = $this->validatePayloadAndReturnResponse($response);
if (!empty($response['merchantReference'])) {
$incrementId = $response['merchantReference'];
}
$order = $this->_order;
$order = $this->_getOrder($incrementId);
if ($order->getId()) {
$this->_eventManager->dispatch(
'adyen_payment_process_resulturl_before',
[
......@@ -191,6 +196,8 @@ class Result extends \Magento\Framework\App\Action\Action
'adyen_response' => $response
]
);
// TODO is handled in the response?
if (isset($response['handled'])) {
return $response['handled_response'];
}
......@@ -205,11 +212,6 @@ class Result extends \Magento\Framework\App\Action\Action
'adyen_response' => $response
]
);
} else {
throw new \Magento\Framework\Exception\LocalizedException(
__('Order does not exists with increment_id: %1', $incrementId)
);
}
return $result;
}
......@@ -382,42 +384,58 @@ class Result extends \Magento\Framework\App\Action\Action
* @return mixed
* @throws \Adyen\AdyenException
*/
protected function validatePayloadAndReturnResponse($response)
protected function validatePayloadAndReturnResponse($result)
{
$client = $this->_adyenHelper->initializeAdyenClient($this->storeManager->getStore()->getId());
$service = $this->_adyenHelper->createAdyenCheckoutService($client);
$request = [];
if (!empty($result['merchantReference'])) {
//TODO Replace with order repository search for best practice
$order = $this->_orderFactory->create()->loadByIncrementId($result['merchantReference']);
} else {
$order = $this->_session->getLastRealOrder();
}
if (!empty($this->_session->getLastRealOrder()) &&
!empty($this->_session->getLastRealOrder()->getPayment())
) {
if (!empty($this->_session->getLastRealOrder()->getPayment()->getAdditionalInformation('paymentData'))) {
$request['paymentData'] = $this->_session->getLastRealOrder()->getPayment()->
getAdditionalInformation('paymentData');
if (!$order->getId()) {
throw new \Magento\Framework\Exception\LocalizedException(
__('Order cannot be loaded')
);
}
// remove paymentData from db
$this->_session->getLastRealOrder()->getPayment()->unsAdditionalInformation('paymentData');
$this->_session->getLastRealOrder()->getPayment()->save();
$payment = $order->getPayment();
$request = [];
// filter details to match the keys
$allowedParams = $payment->getAdditionalInformation('details');
$details = $result;
if (!empty($allowedParams)) {
$allowedParamsArray = [];
// TODO build a validator class which also validates the type of the param
foreach ($allowedParams as $allowedParam) {
$allowedParamsArray[] = $allowedParam['key'];
}
$details = DataArrayValidator::getArrayOnlyWithApprovedKeys($details, $allowedParamsArray);
}
$request["details"] = $details;
if (!empty($payment)) {
// for pending payment that redirect we store this under adyenPaymentData
// TODO: refactor the code in the plugin that all paymentData is stored in paymentData and not in adyenPaymentData
if (!empty($this->_session->getLastRealOrder()->getPayment()->getAdditionalInformation('adyenPaymentData'))) {
$request['paymentData'] = $this->_session->getLastRealOrder()->getPayment()->
getAdditionalInformation("adyenPaymentData");
if (!empty($payment->getAdditionalInformation('adyenPaymentData'))) {
$request['paymentData'] = $payment->getAdditionalInformation("adyenPaymentData");
// remove paymentData from db
$this->_session->getLastRealOrder()->getPayment()->unsAdditionalInformation('adyenPaymentData');
$this->_session->getLastRealOrder()->getPayment()->save();
$payment->unsAdditionalInformation('adyenPaymentData');
$payment->save();
}
} else {
$this->_adyenLogger->addError("Can't load the order id from the session");
$this->_adyenLogger->addError("Payment object cannot be loaded from order");
}
$request["details"] = $response;
if (!empty($this->_session->getLastRealOrder()) &&
// TODO check if this is ever reached
/*if (!empty($this->_session->getLastRealOrder()) &&
!empty($this->_session->getLastRealOrder()->getPayment()) &&
!empty($this->_session->getLastRealOrder()->getPayment()->getAdditionalInformation("details"))
) {
......@@ -427,10 +445,20 @@ class Result extends \Magento\Framework\App\Action\Action
if ($key !== false) {
$request["details"] = ["returnUrlQueryString" => http_build_query($response)];
}
}
}*/
try {
$response = $service->paymentsDetails($request);
if (!empty($response['merchantReference'])) {
if ($order->getIncrementId() === $response['merchantReference']) {
$this->_order = $order;
}
} else {
// TODO error handling
$this->_adyenLogger->addError("Wrong merchantReference was set in the query or in the session");
// TODO error page
}
} catch (\Adyen\AdyenException $e) {
$response['error'] = $e->getMessage();
}
......
......@@ -85,6 +85,7 @@ class CheckoutDataBuilder implements BuilderInterface
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
/** @var \Magento\Sales\Model\Order $order */
$order = $payment->getOrder();
$storeId = $order->getStoreId();
......@@ -96,7 +97,7 @@ class CheckoutDataBuilder implements BuilderInterface
$requestBody['returnUrl'] = $this->storeManager->getStore()->getBaseUrl(
\Magento\Framework\UrlInterface::URL_TYPE_LINK
) . 'adyen/process/result';
) . 'adyen/transparent/redirect?merchantReference=' . $order->getIncrementId();
// Additional data for ACH
if ($payment->getAdditionalInformation("bankAccountNumber")) {
......
......@@ -90,6 +90,10 @@ class CheckoutResponseValidator extends AbstractValidator
$payment->setAdditionalInformation('adyenPaymentData', $response['paymentData']);
}
if (!empty($response['details'])) {
$payment->setAdditionalInformation('details', $response['details']);
}
switch ($resultCode) {
case "Authorised":
case "Received":
......
......@@ -145,6 +145,10 @@ class PaymentResponseHandler
$payment->setAdditionalInformation('adyenPaymentData', $paymentsResponse['paymentData']);
}
if (!empty($paymentsResponse['details'])) {
$payment->setAdditionalInformation('details', $paymentsResponse['details']);
}
switch ($paymentsResponse['resultCode']) {
case self::PRESENT_TO_SHOPPER:
case self::PENDING:
......
......@@ -116,7 +116,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
'vaultCode' => self::CC_VAULT_CODE,
'isActive' => true,
'redirectUrl' => $this->_urlBuilder->getUrl(
'adyen/process/redirect/',
'checkout/onepage/success',
['_secure' => $this->_getRequest()->isSecure()]
)
]
......
......@@ -106,7 +106,7 @@ class AdyenGooglePayConfigProvider implements ConfigProviderInterface
self::CODE => [
'isActive' => true,
'redirectUrl' => $this->urlBuilder->getUrl(
'adyen/process/redirect/',
'checkout/onepage/success',
['_secure' => $this->_getRequest()->isSecure()]
),
'successUrl' => $this->urlBuilder->getUrl(
......
......@@ -117,7 +117,7 @@ class AdyenHppConfigProvider implements ConfigProviderInterface
self::CODE => [
'isActive' => true,
'redirectUrl' => $this->urlBuilder->getUrl(
'adyen/process/redirect',
'checkout/onepage/success',
['_secure' => $this->getRequest()->isSecure()]
)
]
......
......@@ -121,7 +121,7 @@ class AdyenOneclickConfigProvider implements ConfigProviderInterface
self::CODE => [
'isActive' => true,
'redirectUrl' => $this->_urlBuilder->getUrl(
'adyen/process/redirect/',
'checkout/onepage/success',
['_secure' => $this->_getRequest()->isSecure()]
)
]
......
......@@ -84,7 +84,7 @@ class AdyenPayByMailConfigProvider implements ConfigProviderInterface
self::CODE => [
'isActive' => true,
'redirectUrl' => $this->_urlBuilder->getUrl(
'adyen/process/redirect',
'checkout/onepage/success',
['_secure' => $this->_getRequest()->isSecure()]
)
]
......
......@@ -301,6 +301,7 @@ define(
modalClass: 'cc_actionModal',
});
// TODO only show modal when it's redirect shopper
popupModal.modal('openModal');
adyenPaymentService.paymentDetails(request).
......
......@@ -169,6 +169,7 @@ define(
validateThreeDSOrPlaceOrder: function (responseJSON) {
var response = JSON.parse(responseJSON);
if (response && response.type === 'RedirectShopper') {
// TODO do redirect with the component
window.location.replace(url.build(
window.checkoutConfig.payment[quote.paymentMethod().method].redirectUrl
));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment