From 5aa040a255b655f12d50d10ebbc0aad150d05ceb Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 17 Oct 2019 12:26:29 +0200 Subject: [PATCH 01/27] Use the PrestaShop Service Locator --- adyen.php | 9 +-- .../AdminAdyenPrestashopCronController.php | 9 +-- controllers/front/Notifications.php | 6 +- controllers/front/Payment.php | 6 +- controllers/front/ThreeDSProcess.php | 6 +- controllers/front/Validate3d.php | 6 +- helper/Data.php | 38 ++++++------ service/{CheckoutFactory.php => Checkout.php} | 25 ++------ service/CheckoutUtility.php | 31 ++++++++++ ...{CheckoutUtilityFactory.php => Client.php} | 29 +++++---- service/ClientFactory.php | 60 ------------------- .../classes/Configuration.php} | 59 ++++++++++-------- .../adapter/classes/order/OrderAdapter.php | 8 +-- tests/helper/DataTest.php | 31 +++++++--- 14 files changed, 134 insertions(+), 189 deletions(-) rename service/{CheckoutFactory.php => Checkout.php} (57%) create mode 100644 service/CheckoutUtility.php rename service/{CheckoutUtilityFactory.php => Client.php} (59%) delete mode 100644 service/ClientFactory.php rename service/{helper/DataFactory.php => adapter/classes/Configuration.php} (68%) diff --git a/adyen.php b/adyen.php index 6b485c16..590dd0b1 100644 --- a/adyen.php +++ b/adyen.php @@ -24,7 +24,6 @@ use Adyen\AdyenException; use Adyen\PrestaShop\helper\Data as AdyenHelperData; use Adyen\PrestaShop\model\Hashing; -use Adyen\PrestaShop\service\helper\DataFactory as AdyenHelperDataFactory; require __DIR__ . '/vendor/autoload.php'; @@ -75,13 +74,9 @@ public function __construct() $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_); $this->currencies = true; - $adyenHelperFactory = new AdyenHelperDataFactory(); - $this->helper_data = $adyenHelperFactory->createAdyenHelperData( - Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helper_data = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); - $this->hashing = new Hashing(); + $this->hashing = Adapter_ServiceLocator::get('Adyen\PrestaShop\model\Hashing'); // start for 1.6 $this->is_eu_compatible = 1; diff --git a/controllers/admin/AdminAdyenPrestashopCronController.php b/controllers/admin/AdminAdyenPrestashopCronController.php index 5c87a5b2..2363e98e 100644 --- a/controllers/admin/AdminAdyenPrestashopCronController.php +++ b/controllers/admin/AdminAdyenPrestashopCronController.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen PrestaShop module + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. @@ -34,12 +34,7 @@ class AdminAdyenPrestashopCronController extends \ModuleAdminController */ public function __construct() { - - $adyenHelperFactory = new \Adyen\PrestaShop\service\helper\DataFactory(); - $this->helperData = $adyenHelperFactory->createAdyenHelperData( - \Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); if (\Tools::getValue('token') != $this->helperData->decrypt(\Configuration::get('ADYEN_CRONJOB_TOKEN'))) { die('Invalid token'); diff --git a/controllers/front/Notifications.php b/controllers/front/Notifications.php index 03aef29d..537df51a 100644 --- a/controllers/front/Notifications.php +++ b/controllers/front/Notifications.php @@ -33,11 +33,7 @@ class AdyenNotificationsModuleFrontController extends FrontController public function __construct() { parent::__construct(); - $adyenHelperFactory = new \Adyen\PrestaShop\service\helper\DataFactory(); - $this->helperData = $adyenHelperFactory->createAdyenHelperData( - Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); } /** diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index c73d4d49..062a3cd3 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -28,11 +28,7 @@ public function __construct() { parent::__construct(); $this->context = \Context::getContext(); - $adyenHelperFactory = new \Adyen\PrestaShop\service\helper\DataFactory(); - $this->helperData = $adyenHelperFactory->createAdyenHelperData( - \Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); $this->helperData->startSession(); } diff --git a/controllers/front/ThreeDSProcess.php b/controllers/front/ThreeDSProcess.php index ba093183..43a1c98d 100644 --- a/controllers/front/ThreeDSProcess.php +++ b/controllers/front/ThreeDSProcess.php @@ -34,11 +34,7 @@ public function __construct() { parent::__construct(); $this->context = \Context::getContext(); - $adyenHelperFactory = new \Adyen\PrestaShop\service\helper\DataFactory(); - $this->helperData = $adyenHelperFactory->createAdyenHelperData( - \Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); $this->helperData->startSession(); } diff --git a/controllers/front/Validate3d.php b/controllers/front/Validate3d.php index 7e540a60..faff195d 100644 --- a/controllers/front/Validate3d.php +++ b/controllers/front/Validate3d.php @@ -26,11 +26,7 @@ public function __construct() { parent::__construct(); $this->context = \Context::getContext(); - $adyenHelperFactory = new \Adyen\PrestaShop\service\helper\DataFactory(); - $this->helperData = $adyenHelperFactory->createAdyenHelperData( - \Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); } public function postProcess() diff --git a/helper/Data.php b/helper/Data.php index 5a137b59..53baa6af 100644 --- a/helper/Data.php +++ b/helper/Data.php @@ -22,13 +22,14 @@ namespace Adyen\PrestaShop\helper; +use Address; use Adyen; use Adyen\AdyenException; -use Adyen\Service\CheckoutUtility; -use Adyen\Service\Checkout; -use \Currency; -use \Address; -use \Country; +use Adyen\PrestaShop\service\adapter\classes\Configuration; +use Adyen\PrestaShop\service\Checkout; +use Adyen\PrestaShop\service\CheckoutUtility; +use Country; +use Currency; class Data { @@ -37,11 +38,6 @@ class Data */ private $httpHost; - /** - * @var array - */ - private $configuration; - /** * @var string */ @@ -57,18 +53,21 @@ class Data */ private $adyenCheckoutService; + /** + * @var Configuration + */ + private $configuration; + public function __construct( - $httpHost, - $configuration, - $sslEncryptionKey, + Configuration $configuration, CheckoutUtility $adyenCheckoutUtilityService, Checkout $adyenCheckoutService ) { - $this->httpHost = $httpHost; - $this->configuration = $configuration; - $this->sslEncryptionKey = $sslEncryptionKey; + $this->httpHost = $configuration->httpHost; + $this->sslEncryptionKey = $configuration->sslEncryptionKey; $this->adyenCheckoutUtilityService = $adyenCheckoutUtilityService; $this->adyenCheckoutService = $adyenCheckoutService; + $this->configuration = $configuration; } /** @@ -88,7 +87,6 @@ public function getOrigin() */ public function getOriginKeyForOrigin() { - $origin = $this->getOrigin(); $params = array("originDomains" => array($origin)); @@ -159,10 +157,9 @@ public function fetchPaymentMethods($cart, $language) return $responseData; } - public function isDemoMode() { - if (strpos($this->configuration['mode'], \Adyen\Environment::TEST) !== false) { + if (strpos($this->configuration->adyenMode, \Adyen\Environment::TEST) !== false) { return true; } else { return false; @@ -229,7 +226,7 @@ private function createAdyenClient() */ public function getAPIKey() { - return $this->configuration['apiKey']; + return $this->configuration->apiKey; } public function encrypt($data) @@ -315,7 +312,6 @@ public function buildControllerResponseJson($action, $details = array()) !empty($details['issuerUrl']) && !empty($details['paymentData']) && !empty($details['redirectMethod'])) { - $response = array( 'action' => 'threeDS1', 'paRequest' => $details['paRequest'], diff --git a/service/CheckoutFactory.php b/service/Checkout.php similarity index 57% rename from service/CheckoutFactory.php rename to service/Checkout.php index 424fc25d..10832c2e 100644 --- a/service/CheckoutFactory.php +++ b/service/Checkout.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen PrestaShop Module + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. @@ -22,25 +22,10 @@ namespace Adyen\PrestaShop\service; - -class CheckoutFactory +class Checkout extends \Adyen\Service\Checkout { - /** - * Creates a Checkout Utility Service with as little arguments as possible. - * - * @param string $apiKey - * @param string $environment - * @return \Adyen\Service\Checkout - * @throws \Adyen\AdyenException - */ - public function createDefaultCheckout($apiKey, $environment) + public function __construct(Client $client) { - $clientFactory = new \Adyen\PrestaShop\service\ClientFactory(); - $adyenCheckoutService = new \Adyen\Service\Checkout( - $clientFactory->createDefaultClient( - $apiKey, \Configuration::get('ADYEN_LIVE_ENDPOINT_URL_PREFIX'), $environment - ) - ); - return $adyenCheckoutService; + parent::__construct($client); } -} +} \ No newline at end of file diff --git a/service/CheckoutUtility.php b/service/CheckoutUtility.php new file mode 100644 index 00000000..8b7ce910 --- /dev/null +++ b/service/CheckoutUtility.php @@ -0,0 +1,31 @@ +createDefaultClient( - $apiKey, \Configuration::get('ADYEN_LIVE_ENDPOINT_URL_PREFIX'), $environment - ) + parent::__construct(); + $this->setXApiKey($configuration->apiKey); + $this->setAdyenPaymentSource( + \Adyen\PrestaShop\service\Configuration::MODULE_NAME, + \Adyen\PrestaShop\service\Configuration::VERSION ); - return $adyenCheckoutUtilityService; + $this->setExternalPlatform("PrestaShop", _PS_VERSION_); + $this->setEnvironment($configuration->adyenMode, $configuration->liveEndpointPrefix); + + $this->configuration = $configuration; } } \ No newline at end of file diff --git a/service/ClientFactory.php b/service/ClientFactory.php deleted file mode 100644 index 39f9c444..00000000 --- a/service/ClientFactory.php +++ /dev/null @@ -1,60 +0,0 @@ -setXApiKey($encryptedApiKey); - $client->setAdyenPaymentSource(\Adyen\PrestaShop\service\Configuration::MODULE_NAME, \Adyen\PrestaShop\service\Configuration::VERSION); - $client->setExternalPlatform("PrestaShop", _PS_VERSION_); - $client->setEnvironment($environment, $liveEndpointUrlPrefix); - return $client; - } - - /** - * Determines if PrestaShop is running in demo mode - * - * @param string $mode - * @return bool - */ - public function isDemoMode($mode) - { - if (strpos($mode, 'test') !== false) { - return true; - } else { - return false; - } - } -} diff --git a/service/helper/DataFactory.php b/service/adapter/classes/Configuration.php similarity index 68% rename from service/helper/DataFactory.php rename to service/adapter/classes/Configuration.php index aff620b8..4c724df5 100644 --- a/service/helper/DataFactory.php +++ b/service/adapter/classes/Configuration.php @@ -20,33 +20,42 @@ * See the LICENSE file for more info. */ -namespace Adyen\PrestaShop\service\helper; +namespace Adyen\PrestaShop\service\adapter\classes; -use Adyen\PrestaShop\service\CheckoutUtilityFactory; -use Adyen\PrestaShop\service\CheckoutFactory; - -class DataFactory +class Configuration { /** - * Creates an Adyen helper object with as little arguments as possible. - * - * @param $adyenRunningMode - * @param $sslEncryptionKey - * @return \Adyen\PrestaShop\helper\Data - * @throws \Adyen\AdyenException + * @var string + */ + public $httpHost; + + /** + * @var string + */ + public $adyenMode; + + /** + * @var string + */ + public $sslEncryptionKey; + + /** + * @var string + */ + public $apiKey; + + /** + * @var string */ - public function createAdyenHelperData($adyenRunningMode, $sslEncryptionKey) + public $liveEndpointPrefix; + + public function __construct() { - $checkoutUtilityFactory = new CheckoutUtilityFactory(); - $checkoutFactory = new CheckoutFactory(); - $apiKey = $this->getAPIKey($adyenRunningMode, $sslEncryptionKey); - return new \Adyen\PrestaShop\helper\Data( - \Tools::getHttpHost(true, true), - array('mode' => $adyenRunningMode, 'apiKey' => $apiKey), - $sslEncryptionKey, - $checkoutUtilityFactory->createDefaultCheckoutUtility($apiKey, $adyenRunningMode), - $checkoutFactory->createDefaultCheckout($apiKey, $adyenRunningMode) - ); + $this->httpHost = \Tools::getHttpHost(true, true); + $this->adyenMode = \Configuration::get('ADYEN_MODE'); + $this->sslEncryptionKey = _COOKIE_KEY_; + $this->apiKey = $this->getAPIKey($this->adyenMode, $this->sslEncryptionKey); + $this->liveEndpointPrefix = \Configuration::get('ADYEN_LIVE_ENDPOINT_URL_PREFIX'); } /** @@ -54,6 +63,7 @@ public function createAdyenHelperData($adyenRunningMode, $sslEncryptionKey) * * @param string $adyenRunningMode * @param $password + * * @return string */ private function getAPIKey($adyenRunningMode, $password) @@ -70,6 +80,7 @@ private function getAPIKey($adyenRunningMode, $password) * Checks if plug-in is running in test mode or not * * @param $adyenRunningMode + * * @return bool */ private function isTestMode($adyenRunningMode) @@ -86,6 +97,7 @@ private function isTestMode($adyenRunningMode) * * @param $data * @param $password + * * @return string */ private function decrypt($data, $password) @@ -97,5 +109,4 @@ private function decrypt($data, $password) list($data, $iv) = explode('::', base64_decode($data), 2); return openssl_decrypt($data, 'aes-256-ctr', $password, 0, $iv); } - -} +} \ No newline at end of file diff --git a/service/adapter/classes/order/OrderAdapter.php b/service/adapter/classes/order/OrderAdapter.php index 8b8f7fde..84c6dcb7 100644 --- a/service/adapter/classes/order/OrderAdapter.php +++ b/service/adapter/classes/order/OrderAdapter.php @@ -14,7 +14,7 @@ * ############# * ############ * - * Adyen PrestaShop module + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. @@ -32,11 +32,7 @@ class OrderAdapter */ public function __construct() { - $adyenHelperFactory = new \Adyen\PrestaShop\service\helper\DataFactory(); - $this->helperData = $adyenHelperFactory->createAdyenHelperData( - \Configuration::get('ADYEN_MODE'), - _COOKIE_KEY_ - ); + $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); } /** diff --git a/tests/helper/DataTest.php b/tests/helper/DataTest.php index cae67faa..0d8743d4 100644 --- a/tests/helper/DataTest.php +++ b/tests/helper/DataTest.php @@ -22,7 +22,9 @@ namespace Adyen\PrestaShop\helper; -use Adyen\Service\CheckoutUtility; +use Adyen\PrestaShop\service\adapter\classes\Configuration; +use Adyen\PrestaShop\service\Checkout; +use Adyen\PrestaShop\service\CheckoutUtility; class DataTest extends \PHPUnit_Framework_TestCase { @@ -31,23 +33,34 @@ class DataTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $sslEncryptionKey = 'adyen-prestashop-fake-key'; $originDomain = 'https://example.com'; + /** @var Configuration|\PHPUnit_Framework_MockObject_MockObject $configuration */ + $configuration = $this->getMockBuilder('Adyen\PrestaShop\service\adapter\classes\Configuration') + ->disableOriginalConstructor() + ->getMock(); + + $configuration->sslEncryptionKey = 'adyen-prestashop-fake-key'; + $configuration->httpHost = $originDomain; + /** @var CheckoutUtility|\PHPUnit_Framework_MockObject_MockObject $adyenCheckoutUtilityService */ - $adyenCheckoutUtilityService = $this->getMockBuilder(CheckoutUtility::class) - ->disableOriginalConstructor() - ->getMock(); + $adyenCheckoutUtilityService = $this->getMockBuilder('Adyen\PrestaShop\service\CheckoutUtility') + ->disableOriginalConstructor() + ->getMock(); $adyenCheckoutUtilityService->method('originKeys') ->with(["originDomains" => [$originDomain]]) ->willReturn(['originKeys' => [$originDomain => 'asdf']]); + /** @var Checkout|\PHPUnit_Framework_MockObject_MockObject $adyenCheckoutService */ + $adyenCheckoutService = $this->getMockBuilder('Adyen\PrestaShop\service\Checkout') + ->disableOriginalConstructor() + ->getMock(); + $this->adyenHelper = new Data( - $originDomain, - ['mode' => \Adyen\Environment::TEST, 'apiKey' => 'ADYEN_APIKEY_TEST'], - $sslEncryptionKey, - $adyenCheckoutUtilityService + $configuration, + $adyenCheckoutUtilityService, + $adyenCheckoutService ); } From 49da1ec46406345d86a7864c094ef4c6ce6bb9ed Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 17 Oct 2019 15:15:33 +0200 Subject: [PATCH 02/27] Clean up code --- helper/Data.php | 72 ++++++++----------------------------------------- 1 file changed, 11 insertions(+), 61 deletions(-) diff --git a/helper/Data.php b/helper/Data.php index 53baa6af..c2d65e82 100644 --- a/helper/Data.php +++ b/helper/Data.php @@ -70,26 +70,14 @@ public function __construct( $this->configuration = $configuration; } - /** - * @return mixed - */ - public function getOrigin() - { - return $this->httpHost; - } - /** * Get origin key for a specific origin using the adyen api library client * - * @param $origin - * @param int|null $storeId * @return string */ public function getOriginKeyForOrigin() { - $origin = $this->getOrigin(); - - $params = array("originDomains" => array($origin)); + $params = array("originDomains" => array($this->httpHost)); try { $response = $this->adyenCheckoutUtilityService->originKeys($params); @@ -100,8 +88,8 @@ public function getOriginKeyForOrigin() $originKey = ""; // TODO: improve error treatment - if (!empty($response['originKeys'][$origin])) { - $originKey = $response['originKeys'][$origin]; + if (!empty($response['originKeys'][$this->httpHost])) { + $originKey = $response['originKeys'][$this->httpHost]; } else { $this->adyenLogger()->logError("OriginKey is empty, please verify that your API key is correct"); } @@ -110,8 +98,9 @@ public function getOriginKeyForOrigin() } /** - * @param $store - * @param $country + * @param $cart + * @param $language + * * @return array */ public function fetchPaymentMethods($cart, $language) @@ -186,49 +175,6 @@ public function adyenLogger() return $logger; } - /** - * Initializes and returns Adyen Client and sets the required parameters of it - * - * @return \Adyen\Client - * @throws AdyenException - */ - public function initializeAdyenClient() - { - $apiKey = $this->getAPIKey(); - $client = $this->createAdyenClient(); - $client->setApplicationName("Prestashop plugin"); - $client->setXApiKey($apiKey); - $client->setAdyenPaymentSource(\Adyen\PrestaShop\service\Configuration::MODULE_NAME, \Adyen\PrestaShop\service\Configuration::VERSION); - $client->setExternalPlatform("Prestashop", _PS_VERSION_); - - if ($this->isDemoMode()) { - $client->setEnvironment(\Adyen\Environment::TEST); - } else { - $client->setEnvironment(\Adyen\Environment::LIVE, \Configuration::get('ADYEN_LIVE_ENDPOINT_URL_PREFIX')); - } - return $client; - } - - /** - * @return \Adyen\Client - * @throws \Adyen\AdyenException - */ - private function createAdyenClient() - { - return new \Adyen\Client(); - } - - /** - * Retrieve the API key - * - * @param int|null $storeId - * @return string - */ - public function getAPIKey() - { - return $this->configuration->apiKey; - } - public function encrypt($data) { // Generate an initialization vector @@ -382,7 +328,11 @@ public function formatAmount($amount, $currency) /** * @param $context - * @return int + * @param $cart + * + * @return void + * @throws \PrestaShopDatabaseException + * @throws \PrestaShopException */ public function cloneCurrentCart($context, $cart) { From 6ef46178f4c4e7fac0d941b47b335b5f3daa9f23 Mon Sep 17 00:00:00 2001 From: marcoss Date: Fri, 25 Oct 2019 13:11:56 +0200 Subject: [PATCH 03/27] Add a wrapper for ServiceLocator --- service/adapter/classes/ServiceLocator.php | 43 ++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 service/adapter/classes/ServiceLocator.php diff --git a/service/adapter/classes/ServiceLocator.php b/service/adapter/classes/ServiceLocator.php new file mode 100644 index 00000000..9e779375 --- /dev/null +++ b/service/adapter/classes/ServiceLocator.php @@ -0,0 +1,43 @@ + Date: Fri, 25 Oct 2019 13:15:41 +0200 Subject: [PATCH 04/27] Use the wrapped ServiceLocator --- adyen.php | 9 ++++----- .../admin/AdminAdyenPrestashopCronController.php | 4 +++- controllers/front/Notifications.php | 3 ++- controllers/front/Payment.php | 11 ++++++----- controllers/front/ThreeDSProcess.php | 4 +++- controllers/front/Validate3d.php | 6 ++++-- helper/Data.php | 8 ++++++++ service/adapter/classes/order/OrderAdapter.php | 4 +++- 8 files changed, 33 insertions(+), 16 deletions(-) diff --git a/adyen.php b/adyen.php index 590dd0b1..7296b77f 100644 --- a/adyen.php +++ b/adyen.php @@ -21,9 +21,9 @@ */ // init composer autoload -use Adyen\AdyenException; use Adyen\PrestaShop\helper\Data as AdyenHelperData; use Adyen\PrestaShop\model\Hashing; +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; require __DIR__ . '/vendor/autoload.php'; @@ -61,7 +61,7 @@ class Adyen extends PaymentModule /** * Adyen constructor. * - * @throws AdyenException + * @throws \PrestaShop\PrestaShop\Adapter\CoreException */ public function __construct() { @@ -74,9 +74,8 @@ public function __construct() $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_); $this->currencies = true; - $this->helper_data = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); - - $this->hashing = Adapter_ServiceLocator::get('Adyen\PrestaShop\model\Hashing'); + $this->helper_data = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->hashing = ServiceLocator::get('Adyen\PrestaShop\model\Hashing'); // start for 1.6 $this->is_eu_compatible = 1; diff --git a/controllers/admin/AdminAdyenPrestashopCronController.php b/controllers/admin/AdminAdyenPrestashopCronController.php index 2363e98e..2f606df3 100644 --- a/controllers/admin/AdminAdyenPrestashopCronController.php +++ b/controllers/admin/AdminAdyenPrestashopCronController.php @@ -20,6 +20,8 @@ * See the LICENSE file for more info. */ +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; + class AdminAdyenPrestashopCronController extends \ModuleAdminController { /** @@ -34,7 +36,7 @@ class AdminAdyenPrestashopCronController extends \ModuleAdminController */ public function __construct() { - $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); if (\Tools::getValue('token') != $this->helperData->decrypt(\Configuration::get('ADYEN_CRONJOB_TOKEN'))) { die('Invalid token'); diff --git a/controllers/front/Notifications.php b/controllers/front/Notifications.php index 537df51a..c18b1ed3 100644 --- a/controllers/front/Notifications.php +++ b/controllers/front/Notifications.php @@ -21,6 +21,7 @@ */ use Adyen\PrestaShop\controllers\FrontController; +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; use Adyen\PrestaShop\service\notification\NotificationReceiver; class AdyenNotificationsModuleFrontController extends FrontController @@ -33,7 +34,7 @@ class AdyenNotificationsModuleFrontController extends FrontController public function __construct() { parent::__construct(); - $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); } /** diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index 062a3cd3..8cd161d5 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -20,6 +20,8 @@ * See the LICENSE file for more info. */ +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; + class AdyenPaymentModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController { public $ssl = true; @@ -28,7 +30,7 @@ public function __construct() { parent::__construct(); $this->context = \Context::getContext(); - $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); $this->helperData->startSession(); } @@ -40,8 +42,6 @@ public function __construct() public function postProcess() { $cart = $this->context->cart; - $client = $this->helperData->initializeAdyenClient(); - // Handle 3DS1 flow, when the payments call is already done and the details are submitted from the frontend, by the place order button if (!empty($_REQUEST['paRequest']) && !empty($_REQUEST['md']) && !empty($_REQUEST['issuerUrl']) && !empty($_REQUEST['paymentData']) && !empty($_REQUEST['redirectMethod'])) { @@ -78,7 +78,8 @@ public function postProcess() $request = $this->buildRecurringData($request, $_REQUEST); // call adyen library - $service = new \Adyen\Service\Checkout($client); + /** @var Adyen\PrestaShop\service\Checkout $service */ + $service = ServiceLocator::get('Adyen\PrestaShop\service\Checkout'); try { $response = $service->payments($request); @@ -295,7 +296,7 @@ public function buildCCData($request, $payload) // 3DS2 request data $request['additionalData']['allow3DS2'] = true; - $request['origin'] = $this->helperData->getOrigin(); + $request['origin'] = $this->helperData->getHttpHost(); $request['channel'] = 'web'; if (!empty($payload['browserInfo'])) { diff --git a/controllers/front/ThreeDSProcess.php b/controllers/front/ThreeDSProcess.php index 43a1c98d..635399e9 100644 --- a/controllers/front/ThreeDSProcess.php +++ b/controllers/front/ThreeDSProcess.php @@ -20,6 +20,8 @@ * See the LICENSE file for more info. */ +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; + class AdyenThreeDSProcessModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController { /** @@ -34,7 +36,7 @@ public function __construct() { parent::__construct(); $this->context = \Context::getContext(); - $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); $this->helperData->startSession(); } diff --git a/controllers/front/Validate3d.php b/controllers/front/Validate3d.php index faff195d..2cefa947 100644 --- a/controllers/front/Validate3d.php +++ b/controllers/front/Validate3d.php @@ -1,5 +1,4 @@ context = \Context::getContext(); - $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); } public function postProcess() diff --git a/helper/Data.php b/helper/Data.php index c2d65e82..5a404027 100644 --- a/helper/Data.php +++ b/helper/Data.php @@ -409,4 +409,12 @@ public function getTemplateFromModulePath($templatePath) return 'module:adyen/' . ltrim($templatePath, '/'); } + + /** + * @return string + */ + public function getHttpHost() + { + return $this->httpHost; + } } \ No newline at end of file diff --git a/service/adapter/classes/order/OrderAdapter.php b/service/adapter/classes/order/OrderAdapter.php index 84c6dcb7..543fb21b 100644 --- a/service/adapter/classes/order/OrderAdapter.php +++ b/service/adapter/classes/order/OrderAdapter.php @@ -23,6 +23,8 @@ namespace Adyen\PrestaShop\service\adapter\classes\order; +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; + class OrderAdapter { /** @@ -32,7 +34,7 @@ class OrderAdapter */ public function __construct() { - $this->helperData = Adapter_ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); } /** From 5801d68f8b6fb838f27906b58c05c1468eedb132 Mon Sep 17 00:00:00 2001 From: marcoss Date: Fri, 25 Oct 2019 13:17:22 +0200 Subject: [PATCH 05/27] Show up Local Payment Methods --- adyen.php | 81 +++++++++++++++++++ .../templates/front/local-payment-method.tpl | 38 +++++++++ 2 files changed, 119 insertions(+) create mode 100644 views/templates/front/local-payment-method.tpl diff --git a/adyen.php b/adyen.php index 7296b77f..86543cae 100644 --- a/adyen.php +++ b/adyen.php @@ -602,6 +602,51 @@ public function hookPaymentOptions() } } + if (!empty($paymentMethods['paymentMethods'])) { + foreach ($paymentMethods['paymentMethods'] as $paymentMethod) { + $issuerList = []; + if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme') { + continue; + } + if (isset($paymentMethod['details'])) { + foreach ($paymentMethod['details'] as $paymentMethodDetails) { + if (key_exists('key', $paymentMethodDetails) && $paymentMethodDetails['key'] == 'issuer') { + $issuerList = $paymentMethodDetails['items']; + break; + } + } + } + $this->context->smarty->assign( + array( + 'locale' => $this->helper_data->getLocale($this->context->language), + 'originKey' => $this->helper_data->getOriginKeyForOrigin(), + 'environment' => Configuration::get('ADYEN_MODE'), + 'issuerList' => json_encode($issuerList), + 'paymentMethodType' => $paymentMethod['type'], + 'paymentMethodName' => $paymentMethod['name'], + 'paymentProcessUrl' => $this->context->link->getModuleLink( + $this->name, + 'Payment', + array(), + true + ), + 'renderPayButton' => false, + ) + ); + $localPaymentMethod = new PrestaShop\PrestaShop\Core\Payment\PaymentOption(); + $localPaymentMethod->setCallToActionText($this->l('Pay by ' . $paymentMethod['name'])) + ->setForm( + $this->context->smarty->fetch( + _PS_MODULE_DIR_ . $this->name . '/views/templates/front/local-payment-method.tpl' + ) + ) + ->setAction( + $this->context->link->getModuleLink($this->name, 'Payment', array(), true) + ); + + $payment_options[] = $localPaymentMethod; + } + } $embeddedOption = new PrestaShop\PrestaShop\Core\Payment\PaymentOption(); @@ -667,6 +712,42 @@ public function hookPayment() } } + if (!empty($paymentMethods['paymentMethods'])) { + foreach ($paymentMethods['paymentMethods'] as $paymentMethod) { + $issuerList = []; + if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme') { + continue; + } + if (isset($paymentMethod['details'])) { + foreach ($paymentMethod['details'] as $paymentMethodDetails) { + if (key_exists('key', $paymentMethodDetails) && $paymentMethodDetails['key'] == 'issuer') { + $issuerList = $paymentMethodDetails['items']; + break; + } + } + } + $this->context->smarty->assign( + array( + 'locale' => $this->helper_data->getLocale($this->context->language), + 'originKey' => $this->helper_data->getOriginKeyForOrigin(), + 'environment' => Configuration::get('ADYEN_MODE'), + 'prestashop16' => true, + 'issuerList' => json_encode($issuerList), + 'paymentMethodType' => $paymentMethod['type'], + 'paymentMethodName' => $paymentMethod['name'], + 'paymentProcessUrl' => $this->context->link->getModuleLink( + $this->name, + 'Payment', + array(), + true + ), + 'renderPayButton' => true, + ) + ); + $payments .= $this->display(__FILE__, '/views/templates/front/local-payment-method.tpl'); + } + } + $this->context->smarty->assign( array( 'locale' => $this->helper_data->getLocale($this->context->language), // no locale in Prestashop1.6 only languageCode that is en-en but we need en_EN diff --git a/views/templates/front/local-payment-method.tpl b/views/templates/front/local-payment-method.tpl new file mode 100644 index 00000000..97c91423 --- /dev/null +++ b/views/templates/front/local-payment-method.tpl @@ -0,0 +1,38 @@ +{if !$originKey} +
+
There is an error with retrieving the originKey, + please check your API key in the Adyen Module configuration
+
+{else} +
+ +
{l s='Pay with ' mod='adyen'}{$paymentMethodName}
+
+
+ + + + {if $renderPayButton} + + {/if} + +
+
+{/if} From 8a51f0b9e65f1858c7167f284fb5bb26d6c5f3e4 Mon Sep 17 00:00:00 2001 From: Marcos Garcia Date: Mon, 21 Oct 2019 10:20:19 +0200 Subject: [PATCH 06/27] PW-1637 (#27) * Add an exception that is usually logged somewhere * Create a refund model * Simplify unnecessary abstraction * Replace qualifier with an import * Listen to actionOrderSlipAdd hook * Fix notification message * Add a method to get an order by order slips This will be used as the merchant reference in the refund request. When a refund notification arrives, we need to be sure to fetch an order based on this order slip id. * Change reference to ID * Adjust fetching of order object based on order slips * Fix order object fetching * Fix module * Update service/modification/Refund.php Co-Authored-By: Alessio Zampatti * Remove logging * Extract method for SQL query * Make intentions more explicit * Fix Refund tests * Fix Refund tests * Refactor the Adyen main class * Help @aleffio Co-Authored-By: Alessio Zampatti --- adyen.php | 182 +++++++++++++++++- exception/GenericLoggedException.php | 30 +++ service/Configuration.php | 4 +- .../adapter/classes/order/OrderAdapter.php | 17 ++ service/modification/Refund.php | 138 +++++++++++++ .../NotificationNotFoundException.php | 29 +++ .../notification/NotificationProcessor.php | 13 +- service/notification/NotificationReceiver.php | 15 +- tests/modification/RefundTest.php | 99 ++++++++++ .../Adyen/Service/CronControllerTest.php | 122 ++++++++++++ .../Service/NotificationReceiverTest.php | 34 ++-- upgrade/upgrade-1.1.0.php | 40 ++++ 12 files changed, 684 insertions(+), 39 deletions(-) create mode 100644 exception/GenericLoggedException.php create mode 100644 service/modification/Refund.php create mode 100644 service/modification/exception/NotificationNotFoundException.php create mode 100644 tests/modification/RefundTest.php create mode 100644 tests/service/Adyen/Service/CronControllerTest.php create mode 100644 upgrade/upgrade-1.1.0.php diff --git a/adyen.php b/adyen.php index 86543cae..6929c3ed 100644 --- a/adyen.php +++ b/adyen.php @@ -21,16 +21,21 @@ */ // init composer autoload -use Adyen\PrestaShop\helper\Data as AdyenHelperData; -use Adyen\PrestaShop\model\Hashing; -use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; - require __DIR__ . '/vendor/autoload.php'; if (!defined('_PS_VERSION_')) { exit; } +use Adyen\AdyenException; +use Adyen\PrestaShop\exception\GenericLoggedException; +use Adyen\PrestaShop\helper\Data as AdyenHelperData; +use Adyen\PrestaShop\model\Hashing; +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; +use Adyen\PrestaShop\service\helper\DataFactory as AdyenHelperDataFactory; +use Adyen\PrestaShop\service\modification\Refund; +use Adyen\Service\Modification; + class Adyen extends PaymentModule { /** @@ -117,6 +122,7 @@ public function install() && $this->registerHook('displayHeader') && $this->registerHook('displayAdminOrder') && $this->registerHook('moduleRoutes') + && $this->registerHook('actionOrderSlipAdd') // the table for notifications from Adyen needs to be both in install and upgrade && $this->createAdyenNotificationTable() && $this->installTab() @@ -138,6 +144,7 @@ public function install() && $this->registerHook('paymentReturn') && $this->registerHook('adminOrder') && $this->registerHook('moduleRoutes') + && $this->registerHook('actionOrderSlipAdd') // the table for notifications from Adyen needs to be both in install and upgrade && $this->createAdyenNotificationTable(); } @@ -560,6 +567,7 @@ public function hookOrderConfirmation() * Hook payment options PrestaShop > 1.7 * @return array * @throws SmartyException + * @throws AdyenException */ public function hookPaymentOptions() { @@ -815,4 +823,170 @@ public function hookDisplayPaymentTop() } + + public function hookActionOrderSlipAdd(array $params) + { + try { + $client = $this->helper_data->initializeAdyenClient(); + } catch (AdyenException $e) { + $this->addMessageToOrderForOrderSlipAndLogErrorMessage( + 'Error initializing Adyen Client in actionOrderSlipAdd hook:' . PHP_EOL . $e->getMessage() + ); + return; + } + try { + $modificationService = new Modification($client); + } catch (AdyenException $e) { + $this->addMessageToOrderForOrderSlipAndLogErrorMessage( + 'Error initializing Adyen Modification Service in actionOrderSlipAdd hook:' + . PHP_EOL . $e->getMessage() + ); + return; + } + $refundService = new Refund( + $modificationService, + Db::getInstance(), + \Configuration::get('ADYEN_MERCHANT_ACCOUNT'), + $this->helper_data->adyenLogger() + ); + + /** @var Order $order */ + $order = $params['order']; + + try { + /** @var OrderSlip $orderSlip */ + $orderSlip = $order->getOrderSlipsCollection()->orderBy('date_upd', 'desc')->getFirst(); + } catch (PrestaShopException $e) { + $this->addMessageToOrderForOrderSlipAndLogErrorMessage( + 'Error fetching order slips in actionOrderSlipAdd hook:' . PHP_EOL . $e->getMessage() + ); + return; + } + + $currency = Currency::getCurrency($order->id_currency); + + try { + $refundService->request($orderSlip, $currency['iso_code']); + } catch (AdyenException $e) { + $this->addMessageToOrderForOrderSlip( + "Problem connecting to Adyen endpoint: " . $e->getMessage(), + $order, + $orderSlip + ); + } catch (PrestaShopDatabaseException $e) { + $this->addMessageToOrderForOrderSlip( + "Problem with database connection: " . $e->getMessage(), + $order, + $orderSlip + ); + } + } + + private function addMessageToOrderForOrderSlipAndLogErrorMessage( + $message, + Order $order = null, + OrderSlip $orderSlip = null + ) { + if (isset($order) && isset($orderSlip)) { + $this->addMessageToOrderForOrderSlip($message, $order, $orderSlip); + } + $this->helper_data->adyenLogger()->logError($message); + } + + /** + * @param string $message + * @param Order $order + * @param OrderSlip $orderSlip + * @return bool + */ + private function addMessageToOrderForOrderSlip($message, Order $order, OrderSlip $orderSlip) + { + try { + $customer = $order->getCustomer(); + if (empty($customer)) { + throw new GenericLoggedException( + "Customer with id: \"{$order->id_customer}\" cannot be found for" . + " order with id: \"{$order->id}\" while processing" . + " order slip with id: \"{$orderSlip->id}\"." + ); + } + $customerThread = $this->createCustomerThread($order, $orderSlip, $customer); + $this->createCustomerMessage($message, $customerThread); + } catch (GenericLoggedException $e) { + $this->helper_data->adyenLogger()->logError($e->getMessage()); + return false; + } + return true; + } + + /** + * @param Order $order + * @param OrderSlip $orderSlip + * @param Customer $customer + * @return CustomerThread + * @throws GenericLoggedException + */ + private function createCustomerThread(Order $order, OrderSlip $orderSlip, Customer $customer) + { + try { + $customerThread = new CustomerThread( + CustomerThread::getIdCustomerThreadByEmailAndIdOrder($customer->email, $order->id) + ); + if (empty($customerThread->id)) { + $customerThread = new CustomerThread(); + $customerThread->id_contact = 0; + $customerThread->id_customer = (int)$customer->id; + $customerThread->id_shop = (int)$this->context->shop->id; + $customerThread->id_order = (int)$order->id; + $customerThread->id_lang = (int)$this->context->language->id; + $customerThread->email = $customer->email; + $customerThread->status = 'open'; + $customerThread->token = Tools::passwdGen(12); + if (!$customerThread->add()) { + throw new GenericLoggedException( + "Could not start a Customer Thread for Order Slip with id \"{$orderSlip->id}\"." + ); + } + } + } catch (PrestaShopDatabaseException $e) { + throw new GenericLoggedException( + 'Could not start a Customer Thread for Order Slip with id "' . $orderSlip->id . + '". Reason:' . PHP_EOL . $e->getMessage() + ); + } catch (PrestaShopException $e) { + throw new GenericLoggedException( + "Could not start a Customer Thread for Order Slip with id \"" . $orderSlip->id . + '". Reason:' . PHP_EOL . $e->getMessage() + ); + } + return $customerThread; + } + + /** + * @param $message + * @param CustomerThread $customerThread + * @throws GenericLoggedException + */ + private function createCustomerMessage($message, CustomerThread $customerThread) + { + try { + $customerMessage = new CustomerMessage(); + $customerMessage->id_customer_thread = $customerThread->id; + $customerMessage->id_employee = $this->context->employee->id; + $customerMessage->message = $message; + $customerMessage->private = 1; + + if (!$customerMessage->add()) { + throw new GenericLoggedException('An error occurred while saving the message.'); + } + } catch (PrestaShopDatabaseException $e) { + throw new GenericLoggedException( + 'An error occurred while saving the message. Reason:' . PHP_EOL . $e->getMessage() + ); + } catch (PrestaShopException $e) { + throw new GenericLoggedException( + 'An error occurred while saving the message. Reason:' . PHP_EOL . $e->getMessage() + ); + } + } } diff --git a/exception/GenericLoggedException.php b/exception/GenericLoggedException.php new file mode 100644 index 00000000..32766499 --- /dev/null +++ b/exception/GenericLoggedException.php @@ -0,0 +1,30 @@ +id_order); + } } \ No newline at end of file diff --git a/service/modification/Refund.php b/service/modification/Refund.php new file mode 100644 index 00000000..36a882ee --- /dev/null +++ b/service/modification/Refund.php @@ -0,0 +1,138 @@ +modificationClient = $modificationClient; + $this->db = $db; + $this->merchantAccount = $merchantAccount; + $this->logger = $logger; + } + + /** + * @param OrderSlip $orderSlip + * @param string $currency + * + * @return bool + */ + public function request(OrderSlip $orderSlip, $currency) + { + $amount = (new Currency())->sanitize($orderSlip->amount, $currency); + + try { + $pspReference = $this->getPSPReferenceByOrderId($orderSlip->id_order); + } catch (NotificationNotFoundException $e) { + $this->logger->logError($e->getMessage()); + return false; + } catch (PrestaShopDatabaseException $e) { + $this->logger->logError($e->getMessage()); + return false; + } + try { + $this->modificationClient->refund( + [ + 'originalReference' => $pspReference, + 'modificationAmount' => [ + 'value' => $amount, + 'currency' => $currency + ], + 'reference' => $orderSlip->id, + 'merchantAccount' => $this->merchantAccount + ] + ); + } catch (AdyenException $e) { + $this->logger->logError($e->getMessage()); + return false; + } + return true; + } + + /** + * @param string $orderId + * + * @return string + * @throws PrestaShopDatabaseException + * @throws NotificationNotFoundException + */ + private function getPSPReferenceByOrderId($orderId) + { + $results = $this->db->executeS( + sprintf( + <<reason:" . $notification['reason'] . PHP_EOL : $successResult . PHP_EOL; + $success = (!empty($notification['reason'])) ? "$successResult" . PHP_EOL . "reason:" . $notification['reason'] . PHP_EOL : $successResult . PHP_EOL; $type = 'Adyen HTTP Notification(s):'; $comment = sprintf( @@ -150,7 +155,11 @@ public function addMessage($notification) $success ); - $order = $this->orderAdapter->getOrderByCartId($notification['merchant_reference']); + if ($notification['event_code'] == 'REFUND') { + $order = $this->orderAdapter->getOrderByOrderSlipId($notification['merchant_reference']); + } else { + $order = $this->orderAdapter->getOrderByCartId($notification['merchant_reference']); + } if (empty($order)) { $this->helperData->adyenLogger()->logError('Order with id: "' . $notification['merchant_reference'] . '" cannot be found while notification with id: "' . $notification['entity_id'] . '" was processed.'); diff --git a/service/notification/NotificationReceiver.php b/service/notification/NotificationReceiver.php index 5f948965..7b263eb7 100644 --- a/service/notification/NotificationReceiver.php +++ b/service/notification/NotificationReceiver.php @@ -25,6 +25,7 @@ use Adyen\PrestaShop\helper\Data as AdyenHelper; use Adyen\Util\HmacSignature; +use DateTime; use Db; class NotificationReceiver @@ -174,7 +175,7 @@ protected function authorised($response) // validate hmac - if (!$this->verifyHmac($response)) { + if (!$this->hmacSignature->isValidNotificationHMAC($this->notificationHMAC, $response)) { $message = 'HMAC key validation failed'; $this->helperData->adyenLogger()->logError($message); throw new HMACKeyValidationException($message); @@ -337,7 +338,7 @@ private function insertNotification($notification) } // do this to set both fields in the correct timezone - $date = new \DateTime(); + $date = new DateTime(); $data['created_at'] = $date->format('Y-m-d H:i:s'); $data['updated_at'] = $date->format('Y-m-d H:i:s'); @@ -387,14 +388,4 @@ protected function getUnprocessedNotifications() return $this->dbInstance->getValue($sql); } - - /** - * @param $notification - * @return bool - * @throws \Adyen\AdyenException - */ - private function verifyHmac($notification) - { - return $this->hmacSignature->isValidNotificationHMAC($this->notificationHMAC, $notification); - } } diff --git a/tests/modification/RefundTest.php b/tests/modification/RefundTest.php new file mode 100644 index 00000000..a088314c --- /dev/null +++ b/tests/modification/RefundTest.php @@ -0,0 +1,99 @@ +getMockBuilder('Adyen\Service\Modification') + ->disableOriginalConstructor() + ->getMock(); + $modificationClient->expects($this->once()) + ->method('refund') + ->with($this->equalTo([ + 'originalReference' => $pspReference, + 'modificationAmount' => [ + 'value' => $amount * 100, + 'currency' => $currency + ], + 'reference' => (string)$merchantReference, + 'merchantAccount' => $merchantAccount + ])) + ->willReturn(true); + + /** @var PHPUnit_Framework_MockObject_MockObject|OrderSlip $orderSlip */ + $orderSlip = $this->getMockBuilder('OrderSlip') + ->disableOriginalConstructor() + ->getMock(); + $orderSlip->id_order = $orderId; + $orderSlip->amount = $amount; + $orderSlip->id = 1; + + $pattern = 'select * from ps_adyen_notification a inner join ps_orders o on a.merchant_reference = o.id_cart'; + $pattern = str_replace('*', '.+', $pattern); + $pattern = str_replace(' ', '\\s+', $pattern); + /** @var PHPUnit_Framework_MockObject_MockObject|\Db $databaseConnection */ + $databaseConnection = $this->getMockBuilder('Db') + ->disableOriginalConstructor() + ->getMock(); + $databaseConnection->expects($this->once()) + ->method('executeS') + ->with($this->matchesRegularExpression("/$pattern/si")) + ->willReturn([['pspReference' => $pspReference]]); + + $refund = new Refund($modificationClient, $databaseConnection, $merchantAccount); + $this->assertEquals(true, $refund->request($orderSlip, $currency)); + } +} diff --git a/tests/service/Adyen/Service/CronControllerTest.php b/tests/service/Adyen/Service/CronControllerTest.php new file mode 100644 index 00000000..2945bee7 --- /dev/null +++ b/tests/service/Adyen/Service/CronControllerTest.php @@ -0,0 +1,122 @@ +pSQL($string); +} + +class CronControllerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var m\MockInterface + */ + public static $functions; + + /** + * @var \FileLogger|\PHPUnit_Framework_MockObject_MockObject $logger + */ + private $logger; + + /** + * @var AdyenHelper|\PHPUnit_Framework_MockObject_MockObject $adyenHelper + */ + private $adyenHelper; + + /** + * @var Db|\PHPUnit_Framework_MockObject_MockObject $dbInstance + */ + private $dbInstance; + + /** + * + */ + protected function setUp() + { + self::$functions = m::mock(); + + $this->logger = $this->getMockBuilder(\FileLogger::class) + ->disableOriginalConstructor() + ->getMock(); + $this->logger->method('logError'); + + $this->adyenHelper = $this->getMockBuilder(AdyenHelper::class) + ->disableOriginalConstructor() + ->getMock(); + $this->adyenHelper->method('adyenLogger')->willReturn($this->logger); + + $this->dbInstance = $this->getMockBuilder(Db::class)->disableOriginalConstructor()->getMock(); + } + + public function tearDown() + { + // see Mockery's documentation for why we do this + m::close(); + } + + public function testNotificationIsProcessedAndMessageAdded() + { + $notification = json_decode(file_get_contents(__DIR__ . '/unprocessed-notification.json'), true); + + $this->dbInstance->method('insert')->with( + _DB_PREFIX_ . 'adyen_notification', + $this->callback(function ($subject) use ($notification) { + $arr = [ + 'pspreference' => $notification['pspReference'], + 'merchant_reference' => $notification['merchantReference'], + 'event_code' => $notification['eventCode'], + 'success' => $notification['success'], + 'payment_method' => $notification['paymentMethod'], + 'amount_value' => $notification['amount']['value'], + 'amount_currency' => $notification['amount']['currency'], + 'reason' => $notification['reason'], + 'additional_data' => pSQL(serialize($notification['additionalData'])), + 'done' => $notification['done'], + 'processing' => $notification['processing'], + 'created_at' => $notification['created_at'], + 'updated_at' => $notification['updated_at'] + ]; + return $arr == $subject; + }), + false, + false, + Db::INSERT, + false + ); + + /** @noinspection PhpUnhandledExceptionInspection */ + //$this->assertEquals(true, $notificationReceiver->doPostProcess($notificationItems)); + + //todo finish test + } +} diff --git a/tests/service/Adyen/Service/NotificationReceiverTest.php b/tests/service/Adyen/Service/NotificationReceiverTest.php index cab03956..a0a2b03d 100644 --- a/tests/service/Adyen/Service/NotificationReceiverTest.php +++ b/tests/service/Adyen/Service/NotificationReceiverTest.php @@ -20,17 +20,13 @@ * See the LICENSE file for more info. */ -namespace Adyen\PrestaShop\service; +namespace Adyen\PrestaShop\service\notification; use Adyen\PrestaShop\helper\Data as AdyenHelper; -use Adyen\PrestaShop\service\notification\AuthenticationException; -use Adyen\PrestaShop\service\notification\AuthorizationException; -use Adyen\PrestaShop\service\notification\HMACKeyValidationException; -use Adyen\PrestaShop\service\notification\MerchantAccountCodeException; -use Adyen\PrestaShop\service\notification\NotificationReceiver; use Adyen\Util\HmacSignature; use Db; use Mockery as m; +use PHPUnit\Framework\TestCase; function pSQL($string) { @@ -38,7 +34,7 @@ function pSQL($string) return NotificationReceiverTest::$functions->pSQL($string); } -class NotificationReceiverTest extends \PHPUnit_Framework_TestCase +class NotificationReceiverTest extends TestCase { /** * @var m\MockInterface @@ -69,19 +65,19 @@ protected function setUp() { self::$functions = m::mock(); - $this->logger = $this->getMockBuilder(\FileLogger::class) - ->disableOriginalConstructor() - ->getMock(); + $this->logger = $this->getMockBuilder('FileLogger') + ->disableOriginalConstructor() + ->getMock(); $this->logger->method('logError'); - $this->adyenHelper = $this->getMockBuilder(AdyenHelper::class) - ->disableOriginalConstructor() - ->getMock(); + $this->adyenHelper = $this->getMockBuilder('Adyen\PrestaShop\helper\Data') + ->disableOriginalConstructor() + ->getMock(); $this->adyenHelper->method('adyenLogger')->willReturn($this->logger); - $this->hmacSignature = $this->getMock(HmacSignature::class); + $this->hmacSignature = $this->getMock('Adyen\Util\HmacSignature'); - $this->dbInstance = $this->getMockBuilder(Db::class)->disableOriginalConstructor()->getMock(); + $this->dbInstance = $this->getMockBuilder('Db')->disableOriginalConstructor()->getMock(); } public function tearDown() @@ -108,7 +104,7 @@ public function testInvalidHMACThrowsException() $this->dbInstance ); - $this->setExpectedException(HMACKeyValidationException::class); + $this->setExpectedException('Adyen\PrestaShop\service\notification\HMACKeyValidationException'); /** @noinspection PhpUnhandledExceptionInspection */ $notificationReceiver->doPostProcess( @@ -130,7 +126,7 @@ public function testInvalidCredentialsThrowsException() $this->dbInstance ); - $this->setExpectedException(AuthenticationException::class); + $this->setExpectedException('Adyen\PrestaShop\service\notification\AuthenticationException'); /** @noinspection PhpUnhandledExceptionInspection */ $notificationReceiver->doPostProcess( @@ -155,7 +151,7 @@ public function testInvalidMerchantConfigurationThrowsException() $_SERVER['PHP_AUTH_USER'] = 'username'; $_SERVER['PHP_AUTH_PW'] = 'password'; - $this->setExpectedException(MerchantAccountCodeException::class); + $this->setExpectedException('Adyen\PrestaShop\service\notification\MerchantAccountCodeException'); /** @noinspection PhpUnhandledExceptionInspection */ $notificationReceiver->doPostProcess( @@ -180,7 +176,7 @@ public function testInvalidMerchantConfigurationThrowsAuthorizationExceptionForN $_SERVER['PHP_AUTH_USER'] = 'username'; $_SERVER['PHP_AUTH_PW'] = 'password'; - $this->setExpectedException(AuthorizationException::class); + $this->setExpectedException('Adyen\PrestaShop\service\notification\AuthorizationException'); /** @noinspection PhpUnhandledExceptionInspection */ $notificationReceiver->doPostProcess( diff --git a/upgrade/upgrade-1.1.0.php b/upgrade/upgrade-1.1.0.php new file mode 100644 index 00000000..2b10fb28 --- /dev/null +++ b/upgrade/upgrade-1.1.0.php @@ -0,0 +1,40 @@ +registerHook('actionOrderSlipAdd'); + $module->registerHook('displayPaymentTop'); + return true; +} From c901a18dc815c0d6ab1558c8002c4e681a797910 Mon Sep 17 00:00:00 2001 From: Marcos Garcia Date: Thu, 24 Oct 2019 14:31:35 +0200 Subject: [PATCH 07/27] Add PHP Code Sniffer (#29) * Add PHP Code Sniffer * Move configuration around * Clarify PHPCS instruction --- .travis.yml | 51 +++++++++++++++++++ adyen.php | 5 ++ composer.json | 3 +- .../AdminAdyenPrestashopCronController.php | 4 ++ controllers/front/Notifications.php | 4 ++ controllers/front/Payment.php | 4 ++ controllers/front/ThreeDSProcess.php | 4 ++ controllers/front/Validate3d.php | 7 ++- phpcs.xml | 36 +++++++++++++ tests/bootstrap.php | 11 ++-- tests/test_constants.php | 25 +++++++++ upgrade/upgrade-1.0.1.php | 4 ++ 12 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 .travis.yml create mode 100644 phpcs.xml create mode 100644 tests/test_constants.php diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..9e5cd17c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,51 @@ +# Travis CI (MIT License) configuration file +# @link https://travis-ci.org/ + +# Use new container based environment +sudo: false + +# Declare project language. +# @link http://about.travis-ci.org/docs/user/languages/php/ +language: php + +# Declare versions of PHP to use. Use one decimal max. +# @link http://docs.travis-ci.com/user/build-configuration/ +matrix: + fast_finish: true + + include: + # aliased to a recent 5.3 version + - php: '5.3' + # aliased to a recent 5.4 version + - php: '5.4' + # aliased to a recent 5.5 version + - php: '5.5' + # aliased to a recent 5.6 version + - php: '5.6' + # aliased to a recent 7.0 version + - php: '7.0' + # aliased to a recent 7.1 version + - php: '7.1' + env: SNIFF=1 + +before_install: + - if [[ "$SNIFF" == "1" ]]; then export PHPCS_DIR=/tmp/phpcs; fi + - if [[ "$SNIFF" == "1" ]]; then export PHPCOMPAT_DIR=/tmp/PHPCompatibility; fi + # Install PHP CodeSniffer. + - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/squizlabs/PHP_CodeSniffer.git $PHPCS_DIR; fi + # Install PHP Compatibility Standard. + - if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/wimg/PHPCompatibility.git $PHPCOMPAT_DIR; fi + # Set install path for PHP Compatibility Standard. + # @link https://github.com/squizlabs/PHP_CodeSniffer/wiki/Configuration-Options#setting-the-installed-standard-paths + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs --config-set installed_paths $PHPCOMPAT_DIR; fi + # After CodeSniffer install you should refresh your path. + - if [[ "$SNIFF" == "1" ]]; then phpenv rehash; fi + + +# Run test script commands. +# All commands must exit with code 0 on success. Anything else is considered failure. +script: + # Search for PHP syntax errors. + - find -L . -path ./vendor -prune -o -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l + # Run PHPCS. + - if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs; fi \ No newline at end of file diff --git a/adyen.php b/adyen.php index 6929c3ed..2914c44a 100644 --- a/adyen.php +++ b/adyen.php @@ -20,6 +20,11 @@ * See the LICENSE file for more info. */ +// PrestaShop good practices ask developers to check if PrestaShop is loaded +// before running any other PHP code, which breaks a PSR1 element. +// Also, the main class is not in a namespace, which breaks another element. +// phpcs:disable PSR1.Files.SideEffects,PSR1.Classes.ClassDeclaration + // init composer autoload require __DIR__ . '/vendor/autoload.php'; diff --git a/composer.json b/composer.json index a408ed92..8f990960 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ }, "require-dev": { "phpunit/phpunit": "~4", - "mockery/mockery": "dev-master" + "mockery/mockery": "dev-master", + "squizlabs/php_codesniffer": "3.*" } } diff --git a/controllers/admin/AdminAdyenPrestashopCronController.php b/controllers/admin/AdminAdyenPrestashopCronController.php index 2f606df3..d64682c0 100644 --- a/controllers/admin/AdminAdyenPrestashopCronController.php +++ b/controllers/admin/AdminAdyenPrestashopCronController.php @@ -20,6 +20,10 @@ * See the LICENSE file for more info. */ +// This class is not in a namespace because of the way PrestaShop loads +// Controllers, which breaks a PSR1 element. +// phpcs:disable PSR1.Classes.ClassDeclaration + use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; class AdminAdyenPrestashopCronController extends \ModuleAdminController diff --git a/controllers/front/Notifications.php b/controllers/front/Notifications.php index c18b1ed3..2db97988 100644 --- a/controllers/front/Notifications.php +++ b/controllers/front/Notifications.php @@ -20,6 +20,10 @@ * See the LICENSE file for more info. */ +// This class is not in a namespace because of the way PrestaShop loads +// Controllers, which breaks a PSR1 element. +// phpcs:disable PSR1.Classes.ClassDeclaration + use Adyen\PrestaShop\controllers\FrontController; use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; use Adyen\PrestaShop\service\notification\NotificationReceiver; diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index 8cd161d5..5ddfbd22 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -20,6 +20,10 @@ * See the LICENSE file for more info. */ +// This class is not in a namespace because of the way PrestaShop loads +// Controllers, which breaks a PSR1 element. +// phpcs:disable PSR1.Classes.ClassDeclaration + use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; class AdyenPaymentModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController diff --git a/controllers/front/ThreeDSProcess.php b/controllers/front/ThreeDSProcess.php index 635399e9..110d2589 100644 --- a/controllers/front/ThreeDSProcess.php +++ b/controllers/front/ThreeDSProcess.php @@ -20,6 +20,10 @@ * See the LICENSE file for more info. */ +// This class is not in a namespace because of the way PrestaShop loads +// Controllers, which breaks a PSR1 element. +// phpcs:disable PSR1.Classes.ClassDeclaration + use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; class AdyenThreeDSProcessModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController diff --git a/controllers/front/Validate3d.php b/controllers/front/Validate3d.php index 2cefa947..5949831b 100644 --- a/controllers/front/Validate3d.php +++ b/controllers/front/Validate3d.php @@ -20,6 +20,11 @@ * See the LICENSE file for more info. */ +// This class is not in a namespace because of the way PrestaShop loads +// Controllers, which breaks a PSR1 element. +// phpcs:disable PSR1.Classes.ClassDeclaration + + use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; class AdyenValidate3dModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController @@ -109,4 +114,4 @@ public function postProcess() break; } } -} \ No newline at end of file +} diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 00000000..f0504201 --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,36 @@ + + + + + vendor/* + views/js/threeds2-js-utils.js + + . + + + + + + + + \ No newline at end of file diff --git a/tests/bootstrap.php b/tests/bootstrap.php index af651151..96354cde 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -20,14 +20,11 @@ * See the LICENSE file for more info. */ -define('_PS_IN_TEST_', true); -define('_PS_ROOT_DIR_', __DIR__ . '/../../..'); -define('_PS_MODULE_DIR_', _PS_ROOT_DIR_ . '/tests/resources/modules/'); +require_once 'test_constants.php'; -define('DS', DIRECTORY_SEPARATOR); -$mainDir = dirname(__DIR__) . DS . '..' . DS . '..' . DS; +$mainDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR; /** @noinspection PhpIncludeInspection */ -require_once($mainDir . 'config' . DS . 'defines.inc.php'); +require_once($mainDir . 'config' . DIRECTORY_SEPARATOR . 'defines.inc.php'); require_once(_PS_CONFIG_DIR_ . 'autoload.php'); require_once(_PS_CONFIG_DIR_ . 'bootstrap.php'); -require_once(__DIR__ . DS . '..' . DS . 'vendor' . DS . 'autoload.php'); +require_once(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'); diff --git a/tests/test_constants.php b/tests/test_constants.php new file mode 100644 index 00000000..c0659d35 --- /dev/null +++ b/tests/test_constants.php @@ -0,0 +1,25 @@ + Date: Thu, 24 Oct 2019 14:32:11 +0200 Subject: [PATCH 08/27] Create CODEOWNERS (#28) --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..788b242b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Aleffio @cyattilakiss @msilvagarcia From 0c18d9f9b941287d1eead0d1cb4c620d804f9c89 Mon Sep 17 00:00:00 2001 From: Alessio Zampatti Date: Thu, 24 Oct 2019 16:09:02 +0200 Subject: [PATCH 09/27] Updated copyright (#30) --- README.md | 24 +++++++++---------- adyen.php | 4 ++-- controllers/admin/index.php | 2 +- controllers/front/index.php | 2 +- css/index.php | 2 +- helper/Data.php | 2 +- helper/index.php | 2 +- model/Hashing.php | 2 +- model/index.php | 2 +- .../adapter/classes/CustomerThreadAdapter.php | 2 +- views/templates/front/index.php | 2 +- views/templates/index.php | 2 +- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 1779a31f..fe47981d 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,24 @@ -# Adyen Payment plugin for Prestashop -Use Adyen's plugin for Prestashop to offer frictionless payments online, in-app, and in-store. +# Adyen Payment plugin for PrestaShop +Use Adyen's plugin for PrestaShop to offer frictionless payments online, in-app, and in-store. ## Integration The plugin integrates card component(Secured Fields) using Adyen Checkout for all card payments. ## Requirements -This plugin supports Prestashop version 1.6 or 1.7. +This plugin supports PrestaShop version 1.6 or 1.7. ## Collaboration We commit all our new features directly into our GitHub repository. But you can also request or suggest new features or code changes yourself! ## Installation -Copy the folders into the **/modules/adyen** folder of your main Prestashop environment. +Copy the folders into the **/modules/adyen** folder of your main PrestaShop environment. -Search for Adyen in the **Modules and Services**(1.6) / **Module Manager**(1.7) menu in the Prestashop admin panel and select Enable +Search for Adyen in the **Modules and Services**(1.6) / **Module Manager**(1.7) menu in the PrestaShop admin panel and select Enable ## Set up Adyen Customer Area -For authenticating API requests from your Prestashop platform, you need to provide an API key.  +For authenticating API requests from your PrestaShop platform, you need to provide an API key.  To generate an API Key: @@ -26,18 +26,18 @@ To generate an API Key: 2. Go to **Account** > **Users**, and click the user **ws@Company.[YourCompanyAccount]**. 3. Under **Authentication**, click **Generate New API Key**.  - (\*) Don't forget to copy and securely store the API Key in your system – you will need it later when [Configuring the plugin in Prestashop](). + (\*) Don't forget to copy and securely store the API Key in your system – you will need it later when [Configuring the plugin in PrestaShop](). 4. Click **Save** at the bottom of the page. -## Configuring the plugin in Prestashop -The configuration window is the same for both Prestashop 1.6 and 1.7 +## Configuring the plugin in PrestaShop +The configuration window is the same for both PrestaShop 1.6 and 1.7 Before you begin, make sure that you have set up your Adyen Customer Area. -Configure the Adyen plugin in your Prestashop admin panel:  +Configure the Adyen plugin in your PrestaShop admin panel:  -1. Log in to your Prestashop admin panel.  +1. Log in to your PrestaShop admin panel.  2. In the left navigation bar, go to **Modules and Services**(1.6) / **Modules** > **Module Manager**(1.7).  3. Search for Adyen in the search bar 4. Click on **Install** / **Enable Module** @@ -56,7 +56,7 @@ Configure the Adyen plugin in your Prestashop admin panel:  (\*) You noted this down when you Set up Adyen Customer Area. ## Support -You can create issues on our Prestashop Repository. In case of specific problems with your account, please contact support@adyen.com. +You can create issues on our PrestaShop Repository. In case of specific problems with your account, please contact support@adyen.com. ## API Library This module is using the Adyen APIs Library for PHP for all (API) connections to Adyen. diff --git a/adyen.php b/adyen.php index 2914c44a..51a500ef 100644 --- a/adyen.php +++ b/adyen.php @@ -498,7 +498,7 @@ public function displayForm() } /** - * Hook for header Prestashop 1.6 & > 1.7 + * Hook for header PrestaShop 1.6 & > 1.7 */ public function hookHeader() { @@ -763,7 +763,7 @@ public function hookPayment() $this->context->smarty->assign( array( - 'locale' => $this->helper_data->getLocale($this->context->language), // no locale in Prestashop1.6 only languageCode that is en-en but we need en_EN + 'locale' => $this->helper_data->getLocale($this->context->language), // no locale in PrestaShop1.6 only languageCode that is en-en but we need en_EN 'originKey' => $this->helper_data->getOriginKeyForOrigin(), 'environment' => Configuration::get('ADYEN_MODE'), 'paymentProcessUrl' => $this->context->link->getModuleLink($this->name, 'Payment', array(), true), diff --git a/controllers/admin/index.php b/controllers/admin/index.php index 5b3d8c71..f7ab767f 100644 --- a/controllers/admin/index.php +++ b/controllers/admin/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen PrestaShop module + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/controllers/front/index.php b/controllers/front/index.php index ae43cf8f..66c14b79 100755 --- a/controllers/front/index.php +++ b/controllers/front/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/css/index.php b/css/index.php index ae43cf8f..66c14b79 100755 --- a/css/index.php +++ b/css/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/helper/Data.php b/helper/Data.php index 5a404027..e2366773 100644 --- a/helper/Data.php +++ b/helper/Data.php @@ -386,7 +386,7 @@ public function startSession() */ public function getLocale($language) { - // no locale in Prestashop1.6 only languageCode that is en-en but we need en_EN + // no locale in PrestaShop1.6 only languageCode that is en-en but we need en_EN if ($this->isPrestashop16()) { return $language->iso_code; } else { diff --git a/helper/index.php b/helper/index.php index 0d637bd4..5b6a2a44 100644 --- a/helper/index.php +++ b/helper/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/model/Hashing.php b/model/Hashing.php index 7a008822..4a69cb50 100644 --- a/model/Hashing.php +++ b/model/Hashing.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/model/index.php b/model/index.php index 0d637bd4..5b6a2a44 100644 --- a/model/index.php +++ b/model/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/service/adapter/classes/CustomerThreadAdapter.php b/service/adapter/classes/CustomerThreadAdapter.php index 19826c67..4ed646a7 100644 --- a/service/adapter/classes/CustomerThreadAdapter.php +++ b/service/adapter/classes/CustomerThreadAdapter.php @@ -14,7 +14,7 @@ * ############# * ############ * - * Adyen PrestaShop module + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/views/templates/front/index.php b/views/templates/front/index.php index 0d637bd4..5b6a2a44 100644 --- a/views/templates/front/index.php +++ b/views/templates/front/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. diff --git a/views/templates/index.php b/views/templates/index.php index 0d637bd4..5b6a2a44 100644 --- a/views/templates/index.php +++ b/views/templates/index.php @@ -13,7 +13,7 @@ * ############# * ############ * - * Adyen Prestashop Extension + * Adyen PrestaShop plugin * * Copyright (c) 2019 Adyen B.V. * This file is open source and available under the MIT license. From ff8c2531adf26a1bfb7f799674205196181f81a2 Mon Sep 17 00:00:00 2001 From: marcoss Date: Wed, 30 Oct 2019 17:57:45 +0100 Subject: [PATCH 10/27] Rename variable --- views/templates/front/local-payment-method.tpl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/views/templates/front/local-payment-method.tpl b/views/templates/front/local-payment-method.tpl index 97c91423..48fe31f2 100644 --- a/views/templates/front/local-payment-method.tpl +++ b/views/templates/front/local-payment-method.tpl @@ -20,10 +20,12 @@ {/if} +
{l s='Pay with ' mod='adyen'}{$paymentMethodName}
+
+
+ + + + {if $renderPayButton} + + {/if} + +
+ +{/if} From 713e722794ae9e03b23320c8a4f7006b7c89e539 Mon Sep 17 00:00:00 2001 From: marcoss Date: Fri, 1 Nov 2019 15:56:59 +0100 Subject: [PATCH 13/27] Fix condition with `empty` --- controllers/front/Payment.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index 5ddfbd22..dab95f47 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -137,8 +137,8 @@ public function postProcess() if (\Validate::isLoadedObject($new_order)) { $paymentCollection = $new_order->getOrderPaymentCollection(); foreach ($paymentCollection as $payment) { - if (!empty($response['additionalData']['cardBin'] && - !empty($response['additionalData']['cardSummary']))) { + if (!empty($response['additionalData']['cardBin']) && + !empty($response['additionalData']['cardSummary'])) { $payment->card_number = pSQL($response['additionalData']['cardBin'] . " *** " . $response['additionalData']['cardSummary']); } if (!empty($response['additionalData']['paymentMethod'])) { From 6f4161106abdde199a2ffe7201edfe194f81ea13 Mon Sep 17 00:00:00 2001 From: marcoss Date: Fri, 1 Nov 2019 16:01:17 +0100 Subject: [PATCH 14/27] Redirect shopper to external authorisation --- controllers/front/Payment.php | 103 +++++++++++++++++++++++++++++++++- controllers/front/Result.php | 40 +++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 controllers/front/Result.php diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index dab95f47..eec167ee 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -30,6 +30,11 @@ class AdyenPaymentModuleFrontController extends \Adyen\PrestaShop\controllers\Fr { public $ssl = true; + /** + * @var \Adyen\PrestaShop\helper\Data + */ + protected $helperData; + public function __construct() { parent::__construct(); @@ -46,6 +51,13 @@ public function __construct() public function postProcess() { $cart = $this->context->cart; + + $adyenPaymentType = Tools::getValue('adyen-payment-type'); + if (!empty($adyenPaymentType)) { + $this->processLocalPaymentMethod($cart, $adyenPaymentType, Tools::getValue('adyen-payment-issuer')); + return; + } + // Handle 3DS1 flow, when the payments call is already done and the details are submitted from the frontend, by the place order button if (!empty($_REQUEST['paRequest']) && !empty($_REQUEST['md']) && !empty($_REQUEST['issuerUrl']) && !empty($_REQUEST['paymentData']) && !empty($_REQUEST['redirectMethod'])) { @@ -363,7 +375,6 @@ public function buildPaymentData($request = array()) ); $request["reference"] = $cart->id; - $request["fraudOffset"] = "0"; return $request; } @@ -412,4 +423,94 @@ public function buildRecurringData($request = array(), $payload) return $request; } + private function buildLocalPaymentMethodData($paymentType, $paymentIssuer, $request = array()) + { + $request['paymentMethod']['type'] = $paymentType; + if (!empty($paymentIssuer)) { + $request['paymentMethod']['issuer'] = $paymentIssuer; + } + + return $request; + } + + private function buildReturnURL($request) + { + $request['returnUrl'] = $this->context->link->getModuleLink( + $this->module->name, + 'Result', + array(), + $this->ssl + ); + + return $request; + } + + private function processLocalPaymentMethod(\Cart $cart, $paymentType, $paymentIssuer) + { + $request = array(); + $request = $this->buildBrowserData($request); + $request = $this->buildLocalPaymentMethodData($paymentType, $paymentIssuer, $request); + $request = $this->buildPaymentData($request); + $request = $this->buildMerchantAccountData($request); + $request = $this->buildRecurringData($request, $_REQUEST); + $request = $this->buildReturnURL($request); + + // call adyen library + /** @var Adyen\PrestaShop\service\Checkout $service */ + $service = ServiceLocator::get('Adyen\PrestaShop\service\Checkout'); + + try { + $response = $service->payments($request); + } catch (\Adyen\AdyenException $e) { + $this->helperData->adyenLogger()->logError( + "There was an error with the payment method. id: " . $cart->id . " Response: " . $e->getMessage() + ); + + $this->ajaxRender( + $this->helperData->buildControllerResponseJson( + 'error', + [ + 'message' => "There was an error with the payment method, please choose another one." + ] + ) + ); + return; + } + + switch ($response['resultCode']) { + case 'RedirectShopper': + $redirectUrl = null; + $redirectMethod = null; + $paymentData = null; + + if (!empty($response['redirect']['url'])) { + $redirectUrl = $response['redirect']['url']; + } + + if (!empty($response['redirect']['method'])) { + $redirectMethod = $response['redirect']['method']; + } + + if (!empty($response['paymentData'])) { + $paymentData = $response['paymentData']; + } + + if ($redirectUrl && $redirectMethod && $paymentData) { + $_SESSION['redirectUrl'] = $redirectUrl; + $_SESSION['redirectMethod'] = $redirectMethod; + $_SESSION['paymentData'] = $paymentData; + + $cartId = $this->context->cart->id; + $this->context->cookie->id_cart = ""; + $this->context->cookie->id_cart_temp = $cartId; + + Tools::redirect($redirectUrl); + return; + } else { + // invalid parameters + $isValid = false; + } + break; + } + } } diff --git a/controllers/front/Result.php b/controllers/front/Result.php new file mode 100644 index 00000000..a350cc48 --- /dev/null +++ b/controllers/front/Result.php @@ -0,0 +1,40 @@ +context->cookie->id_cart_temp); + var_dump($_REQUEST); + die; + } +} From bf8778fbc30d4c4dd30928720a3876dbbbb27794 Mon Sep 17 00:00:00 2001 From: marcoss Date: Tue, 5 Nov 2019 12:50:32 +0100 Subject: [PATCH 15/27] Display and log error on uncaught response codes --- controllers/front/Payment.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index eec167ee..b114ee37 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -511,6 +511,18 @@ private function processLocalPaymentMethod(\Cart $cart, $paymentType, $paymentIs $isValid = false; } break; + default: + $this->helperData->adyenLogger()->logError( + 'Unsupported result code in response: ' . print_r($response, true) + ); + + $this->ajaxRender( + $this->helperData->buildControllerResponseJson( + 'error', + ['message' => "Unsupported result code: {$response['resultCode']}"] + ) + ); + return; } } } From 8f50d4a5fae368bcc173e2d14c5a2a309e55775c Mon Sep 17 00:00:00 2001 From: Marcos Garcia Date: Wed, 6 Nov 2019 09:53:44 +0100 Subject: [PATCH 16/27] Remove recurring data --- controllers/front/Payment.php | 1 - 1 file changed, 1 deletion(-) diff --git a/controllers/front/Payment.php b/controllers/front/Payment.php index a672273d..2ba0121c 100644 --- a/controllers/front/Payment.php +++ b/controllers/front/Payment.php @@ -450,7 +450,6 @@ private function processLocalPaymentMethod(\Cart $cart, $paymentType, $paymentIs $request = $this->buildLocalPaymentMethodData($paymentType, $paymentIssuer, $request); $request = $this->buildPaymentData($request); $request = $this->buildMerchantAccountData($request); - $request = $this->buildRecurringData($request, $_REQUEST); $request = $this->buildReturnURL($request); // call adyen library From 1db8c8b039cc0a4a34b7cfee3e0ae2123362eec3 Mon Sep 17 00:00:00 2001 From: marcoss Date: Wed, 6 Nov 2019 16:18:47 +0100 Subject: [PATCH 17/27] Fix ServiceLocator calls --- adyen.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/adyen.php b/adyen.php index 68e4c3b2..e86166c2 100644 --- a/adyen.php +++ b/adyen.php @@ -77,8 +77,12 @@ public function __construct() $this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_); $this->currencies = true; - $this->helper_data = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); - $this->hashing = ServiceLocator::get('Adyen\PrestaShop\model\Hashing'); + $this->helper_data = \Adyen\PrestaShop\service\adapter\classes\ServiceLocator::get( + 'Adyen\PrestaShop\helper\Data' + ); + $this->hashing = \Adyen\PrestaShop\service\adapter\classes\ServiceLocator::get( + 'Adyen\PrestaShop\model\Hashing' + ); // start for 1.6 $this->is_eu_compatible = 1; From f78649fa359d354848865c582c9c5f73c5d16dfe Mon Sep 17 00:00:00 2001 From: marcoss Date: Wed, 6 Nov 2019 16:19:12 +0100 Subject: [PATCH 18/27] Setup a default value for `ADYEN_MODE` --- service/adapter/classes/Configuration.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/service/adapter/classes/Configuration.php b/service/adapter/classes/Configuration.php index 4c724df5..bf81d395 100644 --- a/service/adapter/classes/Configuration.php +++ b/service/adapter/classes/Configuration.php @@ -52,7 +52,9 @@ class Configuration public function __construct() { $this->httpHost = \Tools::getHttpHost(true, true); - $this->adyenMode = \Configuration::get('ADYEN_MODE'); + $adyenMode = \Configuration::get('ADYEN_MODE'); + $adyenMode = !empty($adyenMode) ? $adyenMode : \Adyen\Environment::TEST; + $this->adyenMode = $adyenMode; $this->sslEncryptionKey = _COOKIE_KEY_; $this->apiKey = $this->getAPIKey($this->adyenMode, $this->sslEncryptionKey); $this->liveEndpointPrefix = \Configuration::get('ADYEN_LIVE_ENDPOINT_URL_PREFIX'); From c0473d2712f98c2e98c0700872f806859ef2c7cd Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 7 Nov 2019 16:58:37 +0100 Subject: [PATCH 19/27] Fix escaping on JSON string --- views/templates/front/local-payment-method.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/templates/front/local-payment-method.tpl b/views/templates/front/local-payment-method.tpl index 48fe31f2..2a1f8913 100644 --- a/views/templates/front/local-payment-method.tpl +++ b/views/templates/front/local-payment-method.tpl @@ -28,7 +28,7 @@ } } }; - var issuerList = {$issuerList}; + var issuerList = {$issuerList nofilter}; if (issuerList.length) { configuration.items = issuerList; } From 1cf700edb0d32389083df958f6ebf7daed3be26a Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 7 Nov 2019 17:00:13 +0100 Subject: [PATCH 20/27] Restrict Local Payment Methods to iDeal --- adyen.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/adyen.php b/adyen.php index 509f4fed..4a8b740b 100644 --- a/adyen.php +++ b/adyen.php @@ -624,7 +624,8 @@ public function hookPaymentOptions() if (!empty($paymentMethods['paymentMethods'])) { foreach ($paymentMethods['paymentMethods'] as $paymentMethod) { $issuerList = []; - if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme') { + // restrict to iDeal only for now + if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme' || $paymentMethod['type'] != 'ideal') { continue; } if (!empty($paymentMethod['details'])) { @@ -981,6 +982,10 @@ private function getLocalPaymentMethods(array $paymentMethods) { $payments = ''; foreach ($paymentMethods['paymentMethods'] as $paymentMethod) { + // restrict to iDeal only for now + if ($paymentMethod['type'] != 'ideal') { + continue; + } $issuerList = []; if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme') { continue; From c5579358914adf9b61ac2a86a4cf0cedebe66654 Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 7 Nov 2019 17:01:27 +0100 Subject: [PATCH 21/27] Use ServiceLocator --- adyen.php | 12 ++++++------ service/Modification.php | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 service/Modification.php diff --git a/adyen.php b/adyen.php index 4a8b740b..a5aa46fb 100644 --- a/adyen.php +++ b/adyen.php @@ -784,16 +784,16 @@ public function hookActionOrderSlipAdd(array $params) } try { - $client = $this->helper_data->initializeAdyenClient(); + $modificationService = \Adyen\PrestaShop\service\adapter\classes\ServiceLocator::get( + 'Adyen\Service\ResourceModel\Modification' + ); } catch (Adyen\AdyenException $e) { $this->addMessageToOrderForOrderSlipAndLogErrorMessage( - 'Error initializing Adyen Client in actionOrderSlipAdd hook:' . PHP_EOL . $e->getMessage() + 'Error initializing Adyen Modification Service in actionOrderSlipAdd hook:' + . PHP_EOL . $e->getMessage() ); return; - } - try { - $modificationService = new Adyen\Service\Modification($client); - } catch (Adyen\AdyenException $e) { + } catch (\PrestaShop\PrestaShop\Adapter\CoreException $e) { $this->addMessageToOrderForOrderSlipAndLogErrorMessage( 'Error initializing Adyen Modification Service in actionOrderSlipAdd hook:' . PHP_EOL . $e->getMessage() diff --git a/service/Modification.php b/service/Modification.php new file mode 100644 index 00000000..21609522 --- /dev/null +++ b/service/Modification.php @@ -0,0 +1,31 @@ + Date: Thu, 7 Nov 2019 17:01:55 +0100 Subject: [PATCH 22/27] Start session by default --- controllers/FrontController.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/controllers/FrontController.php b/controllers/FrontController.php index faf26f10..746baade 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -22,6 +22,7 @@ namespace Adyen\PrestaShop\controllers; +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; use PrestaShopException; abstract class FrontController extends \ModuleFrontController @@ -31,6 +32,12 @@ abstract class FrontController extends \ModuleFrontController */ protected $helperData; + public function __construct() + { + parent::__construct(); + ServiceLocator::get('Adyen\PrestaShop\helper\Data')->startSession(); + } + /** * @param null $value * @param null $controller From 25b87b3127d0de8942fcca9be2b221a9ff5fac6e Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 7 Nov 2019 17:03:03 +0100 Subject: [PATCH 23/27] Refactor to ServiceLocator --- controllers/front/ThreeDSProcess.php | 18 +++++++++++++----- controllers/front/Validate3d.php | 9 ++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/controllers/front/ThreeDSProcess.php b/controllers/front/ThreeDSProcess.php index 110d2589..3e686786 100644 --- a/controllers/front/ThreeDSProcess.php +++ b/controllers/front/ThreeDSProcess.php @@ -82,10 +82,8 @@ public function postProcess() // Send the payments details request try { - $client = $this->helperData->initializeAdyenClient(); - - // call lib - $service = new \Adyen\Service\Checkout($client); + /** @var \Adyen\PrestaShop\service\Client $service */ + $service = ServiceLocator::get('Adyen\PrestaShop\service\Client'); $result = $service->paymentsDetails($request); } catch (\Adyen\AdyenException $e) { @@ -94,7 +92,17 @@ public function postProcess() array( 'message' => '3D secure 2.0 failed' ) - )); + ) + ); + } catch (\PrestaShop\PrestaShop\Adapter\CoreException $e) { + $this->ajaxRender( + $this->helperData->buildControllerResponseJson( + 'error', + array( + 'message' => '3D secure 2.0 failed' + ) + ) + ); } // Check if result is challenge shopper, if yes return the token diff --git a/controllers/front/Validate3d.php b/controllers/front/Validate3d.php index 5949831b..f4261025 100644 --- a/controllers/front/Validate3d.php +++ b/controllers/front/Validate3d.php @@ -24,7 +24,6 @@ // Controllers, which breaks a PSR1 element. // phpcs:disable PSR1.Classes.ClassDeclaration - use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; class AdyenValidate3dModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController @@ -40,7 +39,6 @@ public function postProcess() { // retrieve cart from temp value and restore the cart to approve payment $cart = new Cart((int)$this->context->cookie->__get("id_cart_temp")); - $client = $this->helperData->initializeAdyenClient(); $requestMD = $_REQUEST['MD']; $requestPaRes = $_REQUEST['PaRes']; @@ -56,12 +54,9 @@ public function postProcess() ) ); - $client->setAdyenPaymentSource(\Adyen\PrestaShop\service\Configuration::MODULE_NAME, \Adyen\PrestaShop\service\Configuration::VERSION); - try { - $client = $this->helperData->initializeAdyenClient(); - // call lib - $service = new \Adyen\Service\Checkout($client); + /** @var \Adyen\PrestaShop\service\Checkout $service */ + $service = ServiceLocator::get('Adyen\PrestaShop\service\Checkout'); $response = $service->paymentsDetails($request); } catch (\Adyen\AdyenException $e) { $this->helperData->adyenLogger()->logError("Error during validate3d paymentsDetails call: exception: " . $e->getMessage()); From 5174b5ad92d5a7d9ba9871745c20e6dac8019a77 Mon Sep 17 00:00:00 2001 From: marcoss Date: Thu, 7 Nov 2019 17:03:33 +0100 Subject: [PATCH 24/27] Implement iDeal processing --- controllers/front/Result.php | 46 +++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/controllers/front/Result.php b/controllers/front/Result.php index a350cc48..fef1cbef 100644 --- a/controllers/front/Result.php +++ b/controllers/front/Result.php @@ -24,6 +24,8 @@ // Controllers, which breaks a PSR1 element. // phpcs:disable PSR1.Classes.ClassDeclaration +use Adyen\PrestaShop\service\adapter\classes\ServiceLocator; + class AdyenResultModuleFrontController extends \Adyen\PrestaShop\controllers\FrontController { /** @@ -33,8 +35,46 @@ class AdyenResultModuleFrontController extends \Adyen\PrestaShop\controllers\Fro public function postProcess() { - var_dump($this->context->cookie->id_cart_temp); - var_dump($_REQUEST); - die; + if (!isset($_SESSION['paymentData'])) { + \Tools::redirect($this->context->link->getPageLink('order', $this->ssl)); + return; + } + /** @var \Adyen\PrestaShop\service\Checkout $checkout */ + $checkout = ServiceLocator::get('Adyen\PrestaShop\service\Checkout'); + $response = $checkout->paymentsDetails( + array( + 'paymentData' => $_SESSION['paymentData'], + 'details' => Tools::getAllValues() + ) + ); + unset($_SESSION['paymentData']); + $cart = new Cart($this->context->cookie->id_cart_temp); + if ($response['resultCode'] == 'Authorised') { + $total = (float)$cart->getOrderTotal(true, \Cart::BOTH); + $extra_vars = array(); + if (!empty($response['pspReference'])) { + $extra_vars['transaction_id'] = $response['pspReference']; + } + $currencyId = $cart->id_currency; + $customer = new \Customer($cart->id_customer); + $this->module->validateOrder( + $cart->id, 2, $total, $this->module->displayName, null, $extra_vars, + (int)$currencyId, false, $customer->secure_key + ); + \Tools::redirect( + $this->context->link->getPageLink( + 'order-confirmation', $this->ssl, null, + 'id_cart=' . $cart->id . '&id_module=' . $this->module->id . '&id_order=' . $this->module->currentOrder . '&key=' . $customer->secure_key + ) + ); + } else { + /** @var \Adyen\PrestaShop\helper\Data $helperData */ + $helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + // create new cart from the current cart + $helperData->cloneCurrentCart($this->context, $cart); + + $helperData->adyenLogger()->logError("The payment was refused, id: " . $cart->id); + $this->setTemplate($helperData->getTemplateFromModulePath('views/templates/front/error.tpl')); + } } } From 8df65a036f05a3f82ea799021bb5efd900026bcc Mon Sep 17 00:00:00 2001 From: Marcos Garcia Date: Fri, 8 Nov 2019 11:48:39 +0100 Subject: [PATCH 25/27] Instantiate `helperData` Co-Authored-By: cyattilakiss <42297201+cyattilakiss@users.noreply.github.com> --- controllers/FrontController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controllers/FrontController.php b/controllers/FrontController.php index 746baade..ad193f3c 100644 --- a/controllers/FrontController.php +++ b/controllers/FrontController.php @@ -35,7 +35,8 @@ abstract class FrontController extends \ModuleFrontController public function __construct() { parent::__construct(); - ServiceLocator::get('Adyen\PrestaShop\helper\Data')->startSession(); + $this->helperData = ServiceLocator::get('Adyen\PrestaShop\helper\Data'); + $this->helperData->startSession(); } /** From a8bb9e4ed6f7574d0cf87461f91cd8472d7be514 Mon Sep 17 00:00:00 2001 From: marcoss Date: Fri, 8 Nov 2019 13:04:16 +0100 Subject: [PATCH 26/27] Fix problem with 3DS --- controllers/front/ThreeDSProcess.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/controllers/front/ThreeDSProcess.php b/controllers/front/ThreeDSProcess.php index 3e686786..73c1c1a4 100644 --- a/controllers/front/ThreeDSProcess.php +++ b/controllers/front/ThreeDSProcess.php @@ -64,6 +64,7 @@ public function postProcess() 'message' => "3D secure 2.0 failed, payment data not found" ) )); + return; } // Depends on the component's response we send a fingerprint or the challenge result @@ -82,8 +83,8 @@ public function postProcess() // Send the payments details request try { - /** @var \Adyen\PrestaShop\service\Client $service */ - $service = ServiceLocator::get('Adyen\PrestaShop\service\Client'); + /** @var \Adyen\PrestaShop\service\Checkout $service */ + $service = ServiceLocator::get('Adyen\PrestaShop\service\Checkout'); $result = $service->paymentsDetails($request); } catch (\Adyen\AdyenException $e) { From e5f447501d24d7cd023c8bc28df3f0ef772a40c8 Mon Sep 17 00:00:00 2001 From: marcoss Date: Mon, 11 Nov 2019 11:51:03 +0100 Subject: [PATCH 27/27] Remove restriction with iDeal --- adyen.php | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/adyen.php b/adyen.php index a5aa46fb..8751925b 100644 --- a/adyen.php +++ b/adyen.php @@ -624,8 +624,7 @@ public function hookPaymentOptions() if (!empty($paymentMethods['paymentMethods'])) { foreach ($paymentMethods['paymentMethods'] as $paymentMethod) { $issuerList = []; - // restrict to iDeal only for now - if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme' || $paymentMethod['type'] != 'ideal') { + if (!$this->isSimplePaymentMethod($paymentMethod)) { continue; } if (!empty($paymentMethod['details'])) { @@ -982,12 +981,8 @@ private function getLocalPaymentMethods(array $paymentMethods) { $payments = ''; foreach ($paymentMethods['paymentMethods'] as $paymentMethod) { - // restrict to iDeal only for now - if ($paymentMethod['type'] != 'ideal') { - continue; - } $issuerList = []; - if (empty($paymentMethod['type']) || $paymentMethod['type'] == 'scheme') { + if (!$this->isSimplePaymentMethod($paymentMethod)) { continue; } if (isset($paymentMethod['details'])) { @@ -1044,4 +1039,20 @@ private function getStandardPaymentMethod() $payments .= $this->display(__FILE__, '/views/templates/front/payment.tpl'); return $payments; } + + /** + * @param $paymentMethod + * + * @return bool + */ + private function isSimplePaymentMethod($paymentMethod) + { + return !empty($paymentMethod['type']) + && $paymentMethod['type'] != 'scheme' + && ( + empty($paymentMethod['details']) || ( + $paymentMethod['details'][0]['key'] == 'issuer' && $paymentMethod['details'][0]['type'] == 'select' + ) + ); + } }