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

Commit 7b2f7171 authored by Attila Kiss's avatar Attila Kiss Committed by GitHub

Merge pull request #748 from Adyen/develop

Release 6.2.0
parents 3e536742 7ee6f945
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
namespace Adyen\Payment\Controller\Process; namespace Adyen\Payment\Controller\Process;
use Adyen\Util\HmacSignature;
use Symfony\Component\Config\Definition\Exception\Exception; use Symfony\Component\Config\Definition\Exception\Exception;
use Magento\Framework\App\Request\Http as Http; use Magento\Framework\App\Request\Http as Http;
...@@ -56,6 +57,21 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -56,6 +57,21 @@ class Json extends \Magento\Framework\App\Action\Action
*/ */
private $serializer; private $serializer;
/**
* @var \Adyen\Payment\Helper\Config
*/
protected $configHelper;
/**
* @var \Adyen\Payment\Helper\IpAddress
*/
protected $ipAddressHelper;
/**
* @var HmacSignature
*/
private $hmacSignature;
/** /**
* Json constructor. * Json constructor.
* *
...@@ -63,12 +79,18 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -63,12 +79,18 @@ class Json extends \Magento\Framework\App\Action\Action
* @param \Adyen\Payment\Helper\Data $adyenHelper * @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger * @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Magento\Framework\Serialize\SerializerInterface $serializer * @param \Magento\Framework\Serialize\SerializerInterface $serializer
* @param \Adyen\Payment\Helper\Config $configHelper
* @param \Adyen\Payment\Helper\IpAddress $ipAddressHelper
* @param HmacSignature $hmacSignature
*/ */
public function __construct( public function __construct(
\Magento\Framework\App\Action\Context $context, \Magento\Framework\App\Action\Context $context,
\Adyen\Payment\Helper\Data $adyenHelper, \Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger, \Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Magento\Framework\Serialize\SerializerInterface $serializer \Magento\Framework\Serialize\SerializerInterface $serializer,
\Adyen\Payment\Helper\Config $configHelper,
\Adyen\Payment\Helper\IpAddress $ipAddressHelper,
HmacSignature $hmacSignature
) { ) {
parent::__construct($context); parent::__construct($context);
$this->_objectManager = $context->getObjectManager(); $this->_objectManager = $context->getObjectManager();
...@@ -76,6 +98,9 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -76,6 +98,9 @@ class Json extends \Magento\Framework\App\Action\Action
$this->_adyenHelper = $adyenHelper; $this->_adyenHelper = $adyenHelper;
$this->_adyenLogger = $adyenLogger; $this->_adyenLogger = $adyenLogger;
$this->serializer = $serializer; $this->serializer = $serializer;
$this->configHelper = $configHelper;
$this->ipAddressHelper = $ipAddressHelper;
$this->hmacSignature = $hmacSignature;
// Fix for Magento2.3 adding isAjax to the request params // Fix for Magento2.3 adding isAjax to the request params
if (interface_exists(\Magento\Framework\App\CsrfAwareActionInterface::class)) { if (interface_exists(\Magento\Framework\App\CsrfAwareActionInterface::class)) {
...@@ -180,6 +205,25 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -180,6 +205,25 @@ class Json extends \Magento\Framework\App\Action\Action
*/ */
protected function _processNotification($response, $notificationMode) protected function _processNotification($response, $notificationMode)
{ {
if ($this->configHelper->getNotificationsIpHmacCheck()) {
//Validate if the notification comes from a verified IP
if (!$this->isIpValid()) {
$this->_adyenLogger->addAdyenNotification(
"Notification has been rejected because the IP address could not be verified"
);
return false;
}
if ($this->hmacSignature->isHmacSupportedEventCode($response)) {
//Validate the Hmac calculation
if (!$this->hmacSignature->isValidNotificationHMAC($this->configHelper->getNotificationsHmacKey(),
$response)) {
$this->_adyenLogger->addAdyenNotification('HMAC key validation failed ' . print_r($response, 1));
return false;
}
}
}
// validate the notification // validate the notification
if ($this->authorised($response)) { if ($this->authorised($response)) {
// log the notification // log the notification
...@@ -271,18 +315,18 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -271,18 +315,18 @@ class Json extends \Magento\Framework\App\Action\Action
} }
// validate username and password // validate username and password
if ((!isset($_SERVER['PHP_AUTH_USER']) && !isset($_SERVER['PHP_AUTH_PW']))) { if ((!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']))) {
if ($this->_isTestNotification($response['pspReference'])) { if ($this->_isTestNotification($response['pspReference'])) {
$this->_returnResult( $this->_returnResult(
'Authentication failed: PHP_AUTH_USER and PHP_AUTH_PW are empty. See Adyen Magento manual CGI mode' 'Authentication failed: PHP_AUTH_USER or PHP_AUTH_PW are empty. See Adyen Magento manual CGI mode'
); );
} }
return false; return false;
} }
$usernameCmp = strcmp($_SERVER['PHP_AUTH_USER'], $username); $usernameIsValid = hash_equals($username, $_SERVER['PHP_AUTH_USER']);
$passwordCmp = strcmp($_SERVER['PHP_AUTH_PW'], $password); $passwordIsValid = hash_equals($password, $_SERVER['PHP_AUTH_PW']);
if ($usernameCmp === 0 && $passwordCmp === 0) { if ($usernameIsValid && $passwordIsValid) {
return true; return true;
} }
...@@ -295,6 +339,29 @@ class Json extends \Magento\Framework\App\Action\Action ...@@ -295,6 +339,29 @@ class Json extends \Magento\Framework\App\Action\Action
return false; return false;
} }
/**
* Checks if any of the possible remote IP address sending the notification is verified and returns the validation result
*
* @return bool
*/
protected function isIpValid()
{
$ipAddress = [];
//Getting remote and possibly forwarded IP addresses
if (!empty($_SERVER['REMOTE_ADDR'])) {
array_push($ipAddress, $_SERVER['REMOTE_ADDR']);
}
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
array_push($ipAddress, $_SERVER['HTTP_X_FORWARDED_FOR']);
}
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
array_push($ipAddress, $_SERVER['HTTP_CLIENT_IP']);
}
return $this->ipAddressHelper->isIpAddressValid($ipAddress);
}
/** /**
* If notification is already saved ignore it * If notification is already saved ignore it
* *
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2015 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Controller\Process;
class ResultPos extends \Magento\Framework\App\Action\Action
{
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $_adyenHelper;
/**
* @var \Magento\Sales\Model\OrderFactory
*/
protected $_orderFactory;
/**
* @var \Magento\Sales\Model\Order
*/
protected $_order;
/**
* @var \Magento\Sales\Model\Order\Status\HistoryFactory
*/
protected $_orderHistoryFactory;
/**
* @var \Magento\Checkout\Model\Session
*/
protected $_session;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
protected $_adyenLogger;
/**
* ResultPos constructor.
*
* @param \Magento\Framework\App\Action\Context $context
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\Sales\Model\OrderFactory $orderFactory
* @param \Magento\Sales\Model\Order\Status\HistoryFactory $orderHistoryFactory
* @param \Magento\Checkout\Model\Session $session
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Sales\Model\OrderFactory $orderFactory,
\Magento\Sales\Model\Order\Status\HistoryFactory $orderHistoryFactory,
\Magento\Checkout\Model\Session $session,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
) {
$this->_adyenHelper = $adyenHelper;
$this->_orderFactory = $orderFactory;
$this->_orderHistoryFactory = $orderHistoryFactory;
$this->_session = $session;
$this->_adyenLogger = $adyenLogger;
parent::__construct($context);
}
/**
* Return result
*/
public function execute()
{
$response = $this->getRequest()->getParams();
$this->_adyenLogger->addAdyenResult(print_r($response, true));
$result = $this->_validateResponse($response);
if ($result) {
$session = $this->_session;
$session->getQuote()->setIsActive(false)->save();
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
} else {
$this->_cancel($response);
$this->_redirect($this->_adyenHelper->getAdyenAbstractConfigData('return_path'));
}
}
/**
* @param $response
* @return bool
*/
private function _validateResponse($response)
{
$result = false;
if ($response != null && $response['result'] != "" && $this->_validateChecksum($response)) {
$incrementId = $response['merchantReference'];
$responseResult = $response['result'];
if ($incrementId) {
$order = $this->_getOrder($incrementId);
if ($order->getId()) {
$comment = __(
'%1 <br /> Result: %2 <br /> paymentMethod: %3',
'Adyen App Result URL Notification:',
$responseResult,
'POS'
);
if ($responseResult == 'APPROVED') {
$this->_adyenLogger->addAdyenResult('Result is approved');
$history = $this->_orderHistoryFactory->create()
//->setStatus($status)
->setComment($comment)
->setEntityName('order')
->setOrder($order);
$history->save();
// needed becuase then we need to save $order objects
$order->setAdyenResulturlEventCode("POS_APPROVED");
// save order
$order->save();
return true;
} else {
$this->_adyenLogger->addAdyenResult('Result is:' . $responseResult);
$history = $this->_orderHistoryFactory->create()
//->setStatus($status)
->setComment($comment)
->setEntityName('order')
->setOrder($order);
$history->save();
// cancel the order
if ($order->canCancel()) {
$order->cancel()->save();
$this->_adyenLogger->addAdyenResult('Order is cancelled');
} else {
$this->_adyenLogger->addAdyenResult('Order can not be cancelled');
}
}
} else {
$this->_adyenLogger->addAdyenResult('Order does not exists with increment_id: ' . $incrementId);
}
} else {
$this->_adyenLogger->addAdyenResult('Empty merchantReference');
}
} else {
$this->_adyenLogger->addAdyenResult('actionName or checksum failed or response is empty');
}
return $result;
}
/**
* Validate checksum from result parameters
*
* @param $response
* @return bool
*/
protected function _validateChecksum($response)
{
$checksum = $response['cs'];
$result = $response['result'];
$amount = $response['originalCustomAmount'];
$currency = $response['originalCustomCurrency'];
$sessionId = $response['sessionId'];
// for android sessionis is with low i
if ($sessionId == "") {
$sessionId = $response['sessionid'];
}
// calculate amount checksum
$amountChecksum = 0;
$amountLength = strlen($amount);
for ($i = 0; $i < $amountLength; $i++) {
// ASCII value use ord
$checksumCalc = ord($amount[$i]) - 48;
$amountChecksum += $checksumCalc;
}
$currencyChecksum = 0;
$currencyLength = strlen($currency);
for ($i = 0; $i < $currencyLength; $i++) {
$checksumCalc = ord($currency[$i]) - 64;
$currencyChecksum += $checksumCalc;
}
$resultChecksum = 0;
$resultLength = strlen($result);
for ($i = 0; $i < $resultLength; $i++) {
$checksumCalc = ord($result[$i]) - 64;
$resultChecksum += $checksumCalc;
}
$sessionIdChecksum = 0;
$sessionIdLength = strlen($sessionId);
for ($i = 0; $i < $sessionIdLength; $i++) {
$checksumCalc = $this->_getAscii2Int($sessionId[$i]);
$sessionIdChecksum += $checksumCalc;
}
$totalResultChecksum = (($amountChecksum + $currencyChecksum + $resultChecksum) * $sessionIdChecksum) % 100;
// check if request is valid
if ($totalResultChecksum == $checksum) {
$this->_adyenLogger->addAdyenResult('Checksum is valid');
return true;
}
$this->_adyenLogger->addAdyenResult('Checksum is invalid!');
return false;
}
/**
* @param $ascii
* @return int
*/
protected function _getAscii2Int($ascii)
{
if (is_numeric($ascii)) {
$int = ord($ascii) - 48;
} else {
$int = ord($ascii) - 64;
}
return $int;
}
/**
* @param $incrementId
* @return \Magento\Sales\Model\Order
*/
protected function _getOrder($incrementId)
{
if (!$this->_order) {
$this->_order = $this->_orderFactory->create()->loadByIncrementId($incrementId);
}
return $this->_order;
}
/**
* @param $response
*/
protected function _cancel($response)
{
$session = $this->_session;
// restore the quote
$session->restoreQuote();
$order = $this->_order;
if ($order) {
$this->_adyenHelper->cancelOrder($order);
if (isset($response['authResult']) &&
$response['authResult'] == \Adyen\Payment\Model\Notification::CANCELLED) {
$this->messageManager->addError(__('You have cancelled the order. Please try again'));
} else {
$this->messageManager->addError(__('Your payment failed, Please try again later'));
}
}
}
}
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Cron;
use Adyen\Payment\Helper\IpAddress;
use Adyen\Payment\Logger\AdyenLogger;
class ServerIpAddress
{
/**
* @var IpAddress $ipAddressHelper
*/
protected $ipAddressHelper;
/**
* @var AdyenLogger $adyenLogger
*/
protected $adyenLogger;
/**
* ServerIpAddress constructor.
* @param IpAddress $ipAddressHelper
* @param AdyenLogger $adyenLogger
*/
public function __construct(
IpAddress $ipAddressHelper,
AdyenLogger $adyenLogger
) {
$this->ipAddressHelper = $ipAddressHelper;
$this->adyenLogger = $adyenLogger;
}
public function execute()
{
//Check if there are already verified IP addresses in cache and refresh when empty
if (empty($this->ipAddressHelper->getIpAddressesFromCache())) {
$this->adyenLogger->addAdyenNotificationCronjob(
'There are no verified Adyen IP addresses in cache. Updating IP records.'
);
$this->ipAddressHelper->updateCachedIpAddresses();
}
}
}
...@@ -24,27 +24,47 @@ ...@@ -24,27 +24,47 @@
namespace Adyen\Payment\Helper; namespace Adyen\Payment\Helper;
use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Encryption\EncryptorInterface;
class Config class Config
{ {
const XML_PAYMENT_PREFIX = "payment"; const XML_PAYMENT_PREFIX = "payment";
const XML_ADYEN_ABSTRACT_PREFIX = "adyen_abstract"; const XML_ADYEN_ABSTRACT_PREFIX = "adyen_abstract";
const XML_NOTIFICATIONS_CAN_CANCEL_FIELD = "notifications_can_cancel"; const XML_NOTIFICATIONS_CAN_CANCEL_FIELD = "notifications_can_cancel";
const XML_NOTIFICATIONS_IP_HMAC_CHECK = "notifications_ip_hmac_check";
const XML_NOTIFICATIONS_HMAC_KEY_LIVE = "notification_hmac_key_live";
const XML_NOTIFICATIONS_HMAC_KEY_TEST = "notification_hmac_key_test";
/** /**
* @var Magento\Framework\App\Config\ScopeConfigInterface * @var Magento\Framework\App\Config\ScopeConfigInterface
*/ */
protected $scopeConfig; protected $scopeConfig;
/**
* @var EncryptorInterface
*/
private $encryptor;
/**
* @var \Adyen\Payment\Helper\Data
*/
private $adyenHelper;
/** /**
* Config constructor. * Config constructor.
* *
* @param Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param EncryptorInterface $encryptor
* @param \Adyen\Payment\Helper\Data $adyenHelper
*/ */
public function __construct( public function __construct(
ScopeConfigInterface $scopeConfig ScopeConfigInterface $scopeConfig,
EncryptorInterface $encryptor,
\Adyen\Payment\Helper\Data $adyenHelper
) { ) {
$this->scopeConfig = $scopeConfig; $this->scopeConfig = $scopeConfig;
$this->encryptor = $encryptor;
$this->adyenHelper = $adyenHelper;
} }
/** /**
...@@ -63,6 +83,48 @@ class Config ...@@ -63,6 +83,48 @@ class Config
); );
} }
/**
* Retrieve flag for notifications_ip_hmac_check
*
* @param int $storeId
* @return bool
*/
public function getNotificationsIpHmacCheck($storeId = null)
{
return (bool)$this->getConfigData(
self::XML_NOTIFICATIONS_IP_HMAC_CHECK,
self::XML_ADYEN_ABSTRACT_PREFIX,
$storeId,
true
);
}
/**
* Retrieve key for notifications_hmac_key
*
* @param int $storeId
* @return string
*/
public function getNotificationsHmacKey($storeId = null)
{
if ($this->adyenHelper->isDemoMode($storeId)) {
$key = $this->getConfigData(
self::XML_NOTIFICATIONS_HMAC_KEY_TEST,
self::XML_ADYEN_ABSTRACT_PREFIX,
$storeId,
false
);
} else {
$key = $this->getConfigData(
self::XML_NOTIFICATIONS_HMAC_KEY_LIVE,
self::XML_ADYEN_ABSTRACT_PREFIX,
$storeId,
false
);
}
return $this->encryptor->decrypt(trim($key));
}
/** /**
* Retrieve information from payment configuration * Retrieve information from payment configuration
* *
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Helper;
use Adyen\Util\IpAddress as IpAddressUtil;
use Adyen\Payment\Logger\AdyenLogger;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\Serialize\SerializerInterface;
/**
* Class IpAddress
* @package Adyen\Payment\Helper
*/
class IpAddress
{
const IP_ADDRESS_CACHE_ID = "Adyen_ip_address";
const IP_ADDRESS_CACHE_LIFETIME = 86400;
/**
* @var IpAddressUtil
*/
private $ipAddressUtil;
/**
* @var CacheInterface
*/
private $cache;
/**
* @var SerializerInterface
*/
private $serializer;
/**
* @var AdyenLogger $adyenLogger
*/
protected $adyenLogger;
/**
* IpAddress constructor.
*
* @param IpAddressUtil $ipAddressUtil
* @param CacheInterface $cache
* @param SerializerInterface $serializer
* @param AdyenLogger $adyenLogger
*/
public function __construct(
IpAddressUtil $ipAddressUtil,
CacheInterface $cache,
SerializerInterface $serializer,
AdyenLogger $adyenLogger
) {
$this->ipAddressUtil = $ipAddressUtil;
$this->cache = $cache;
$this->serializer = $serializer;
$this->adyenLogger = $adyenLogger;
}
/**
* Checks if the provided array of IPs addresses has been validated
*
* @param string[] $ipAddresses
* @return bool
*/
public function isIpAddressValid($ipAddresses)
{
if (empty($ipAddresses)) {
return false;
}
$cachedIpsArray = $this->getIpAddressesFromCache();
if (empty($cachedIpsArray)) {
$this->adyenLogger->addAdyenDebug(
'There are no verified Adyen IP addresses in cache. Updating IP records.'
);
$this->updateCachedIpAddresses();
}
foreach ($ipAddresses as $ipAddress) {
//If the IP is already cached return true
if (in_array($ipAddress, $cachedIpsArray)) {
return true;
}
}
return false;
}
/**
* Updates cache key containing Adyen webhook IP addresses with newly resolved records
*/
public function updateCachedIpAddresses()
{
$this->saveIpAddressesToCache($this->ipAddressUtil->getAdyenIpAddresses());
}
/**
* Saves array of IP addresses in cache key
*
* @param string[] $ipAddresses
*/
public function saveIpAddressesToCache($ipAddresses)
{
$this->cache->save(
$this->serializer->serialize($ipAddresses),
self::IP_ADDRESS_CACHE_ID,
[],
self::IP_ADDRESS_CACHE_LIFETIME
);
}
/**
* Loads value of IP addresses cache key and returns it as array
*
* @return array|bool|float|int|string|null
*/
public function getIpAddressesFromCache()
{
$serializedIpAddresses = $this->cache->load(self::IP_ADDRESS_CACHE_ID);
if (!empty($serializedIpAddresses)) {
return $this->serializer->unserialize($serializedIpAddresses);
}
return [];
}
}
...@@ -37,18 +37,23 @@ For more information see our [installation section](https://docs.adyen.com/devel ...@@ -37,18 +37,23 @@ For more information see our [installation section](https://docs.adyen.com/devel
## Setup Cron ## Setup Cron
Make sure that your Magento cron is running every minute. We are using a cronjob to process the notifications, our webhook service. The cronjob will be executed every minute. It only executes the notifications that have been received at least 2 minutes ago. This is to ensure that Magento has created the order, and all save after events are executed. A handy tool to get insight into your cronjobs is AOE scheduler. You can download this tool through Magento Connect or GitHub. Make sure that your Magento cron is running every minute. We are using a cronjob to process the notifications (our webhook service) and to update Adyen servers' IP addresses. The cronjobs will be executed every minute.
If you need to setup your cronjob in Magento <a href="http://devdocs.magento.com/guides/v2.0/config-guide/cli/config-cli-subcommands-cron.html" target="_blank">this is described here</a>
We have defined this:
``` ```
<group id="adyen_payment"> <group id="adyen_payment">
<job name="adyen_payment_process_notification" instance="Adyen\Payment\Model\Cron" method="processNotification"> <job name="adyen_payment_process_notification" instance="Adyen\Payment\Model\Cron" method="processNotification">
<schedule>*/1 * * * *</schedule> <schedule>*/1 * * * *</schedule>
</job> </job>
<job name="adyen_payment_server_address_caching" instance="Adyen\Payment\Cron\ServerIpAddress" method="execute">
<schedule>*/1 * * * *</schedule>
</job>
</group> </group>
``` ```
The notification processing service queries the records that have been received at least 2 minutes ago. This is to ensure that Magento has created the order, and all save after events are executed. A handy tool to get insight into your cronjobs is AOE scheduler. You can download this tool through Magento Connect or GitHub.
If you need to setup your cronjob in Magento <a href="http://devdocs.magento.com/guides/v2.0/config-guide/cli/config-cli-subcommands-cron.html" target="_blank">this is described here</a>
## Support ## Support
If you have a feature request, or spotted a bug or a technical problem, create a GitHub issue. For other questions, contact our [support team](https://support.adyen.com/hc/en-us/requests/new?ticket_form_id=360000705420). If you have a feature request, or spotted a bug or a technical problem, create a GitHub issue. For other questions, contact our [support team](https://support.adyen.com/hc/en-us/requests/new?ticket_form_id=360000705420).
......
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2020 Adyen BV (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Tests\Helper;
class IpAddressTest extends \PHPUnit\Framework\TestCase
{
/**
* @var \Adyen\Payment\Helper\IpAddress
*/
private $ipAddressHelper;
private function getSimpleMock($originalClassName)
{
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->getMock();
}
protected function setUp()
{
$cache = $this->getSimpleMock(\Magento\Framework\App\CacheInterface::class);
$cache->method('load')->willReturn(
array(
'1.2.3.4',
'20.20.20.20'
)
);
$serializer = $this->getSimpleMock(\Magento\Framework\Serialize\SerializerInterface::class);
$serializer->method('unserialize')->willReturnArgument(0);
$ipAddressUtil = $this->getSimpleMock(\Adyen\Util\IpAddress::class);
$adyenLogger = $this->getSimpleMock(\Adyen\Payment\Logger\AdyenLogger::class);
$this->ipAddressHelper = new \Adyen\Payment\Helper\IpAddress(
$ipAddressUtil,
$cache,
$serializer,
$adyenLogger
);
}
/**
* @dataProvider ipAddressesProvider
*/
public function testIsIpAddressValid($ipAddress, $expectedResult)
{
$this->assertEquals($expectedResult, $this->ipAddressHelper->isIpAddressValid([$ipAddress]));
}
public function testUpdateCachedIpAddresses()
{
$this->assertNull($this->ipAddressHelper->updateCachedIpAddresses());
}
public function testSaveIpAddressesToCache()
{
$this->assertNull($this->ipAddressHelper->saveIpAddressesToCache([]));
}
public function testGetIpAddressesFromCache()
{
$this->assertTrue(is_array($this->ipAddressHelper->getIpAddressesFromCache()));
}
public static function ipAddressesProvider()
{
return array(
array(
'1.2.3.4',
true
),
array(
'20.20.20.20',
true
),
array(
'8.8.8.8',
false
),
array(
'192.168.100.10',
false
),
array(
'500.168.100.10',
false
)
);
}
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"name": "adyen/module-payment", "name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.", "description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module", "type": "magento2-module",
"version": "6.1.2", "version": "6.2.0",
"license": [ "license": [
"OSL-3.0", "OSL-3.0",
"AFL-3.0" "AFL-3.0"
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
} }
], ],
"require": { "require": {
"adyen/php-api-library": "~6", "adyen/php-api-library": "^6.3",
"magento/framework": ">=101.0.8 <102 || >=102.0.1", "magento/framework": ">=101.0.8 <102 || >=102.0.1",
"magento/module-vault": "101.*", "magento/module-vault": "101.*",
"magento/module-paypal": ">=100.2.6" "magento/module-paypal": ">=100.2.6"
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
<include path="Adyen_Payment::system/adyen_checkout_experience.xml"/> <include path="Adyen_Payment::system/adyen_checkout_experience.xml"/>
<include path="Adyen_Payment::system/adyen_manual_review.xml"/> <include path="Adyen_Payment::system/adyen_manual_review.xml"/>
<include path="Adyen_Payment::system/adyen_split_payment.xml"/> <include path="Adyen_Payment::system/adyen_split_payment.xml"/>
<include path="Adyen_Payment::system/adyen_security.xml"/>
<include path="Adyen_Payment::system/adyen_cc.xml"/> <include path="Adyen_Payment::system/adyen_cc.xml"/>
<include path="Adyen_Payment::system/adyen_oneclick.xml"/> <include path="Adyen_Payment::system/adyen_oneclick.xml"/>
<include path="Adyen_Payment::system/adyen_hpp.xml"/> <include path="Adyen_Payment::system/adyen_hpp.xml"/>
......
<?xml version="1.0"?>
<!--
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment module (https://www.adyen.com/)
*
* Copyright (c) 2020 Adyen N.V. (https://www.adyen.com/)
* See LICENSE.txt for license details.
*
* Author: Adyen <magento@adyen.com>
*/
-->
<include xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_include.xsd">
<group id="adyen_security" translate="label" type="text" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="1">
<label><![CDATA[Advanced: Security]]></label>
<frontend_model>Magento\Config\Block\System\Config\Form\Fieldset</frontend_model>
<comment>
<![CDATA[
<p>
Enabling these features is strongly recommended to improve the security of your integration.
</p>
]]>
</comment>
<field id="notifications_ip_hmac_check" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Check notification's IP address and HMAC signature</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_abstract/notifications_ip_hmac_check</config_path>
<comment>
<![CDATA[
If enabled notifications will be accepted only when the IP address matches Adyen's servers and the HMAC
signature is verified. To learn more about these settings refer to
<a target="_blank" href="https://docs.adyen.com/plugins/magento-2/set-up-the-plugin-in-magento">Adyen documentation</a>.
]]>
</comment>
</field>
<field id="notification_hmac_key_test" translate="label" type="obscure" sortOrder="20" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>HMAC key test</label>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<config_path>payment/adyen_abstract/notification_hmac_key_test</config_path>
<tooltip>
<![CDATA[
Set HMAC key at first on Adyen so new notifications are sent with the key. To learn more about these settings refer to
<a target="_blank" href="https://docs.adyen.com/development-resources/webhooks/verify-hmac-signatures">Adyen documentation</a>.
]]>
</tooltip>
</field>
<field id="notification_hmac_key_live" translate="label" type="obscure" sortOrder="30" showInDefault="1"
showInWebsite="1" showInStore="1">
<label>HMAC key live</label>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<config_path>payment/adyen_abstract/notification_hmac_key_live</config_path>
<tooltip>
<![CDATA[
Set HMAC key at first on Adyen so new notifications are sent with the key. To learn more about these settings refer to
<a target="_blank" href="https://docs.adyen.com/development-resources/webhooks/verify-hmac-signatures">Adyen documentation</a>.
]]>
</tooltip>
</field>
</group>
</include>
...@@ -27,5 +27,8 @@ ...@@ -27,5 +27,8 @@
<job name="adyen_payment_process_notification" instance="Adyen\Payment\Model\Cron" method="processNotification"> <job name="adyen_payment_process_notification" instance="Adyen\Payment\Model\Cron" method="processNotification">
<schedule>*/1 * * * *</schedule> <schedule>*/1 * * * *</schedule>
</job> </job>
<job name="adyen_payment_server_address_caching" instance="Adyen\Payment\Cron\ServerIpAddress" method="execute">
<schedule>*/1 * * * *</schedule>
</job>
</group> </group>
</config> </config>
\ No newline at end of file
...@@ -1057,6 +1057,7 @@ ...@@ -1057,6 +1057,7 @@
<item name="payment/adyen_abstract/debug" xsi:type="string">1</item> <item name="payment/adyen_abstract/debug" xsi:type="string">1</item>
<item name="payment/adyen_apple_pay/full_path_location_pem_file_test" xsi:type="string">1</item> <item name="payment/adyen_apple_pay/full_path_location_pem_file_test" xsi:type="string">1</item>
<item name="payment/adyen_apple_pay/full_path_location_pem_file_live" xsi:type="string">1</item> <item name="payment/adyen_apple_pay/full_path_location_pem_file_live" xsi:type="string">1</item>
<item name="payment/adyen_abstract/notifications_ip_hmac_check" xsi:type="string">1</item>
</argument> </argument>
<argument name="sensitive" xsi:type="array"> <argument name="sensitive" xsi:type="array">
<item name="payment/adyen_abstract/merchant_account" xsi:type="string">1</item> <item name="payment/adyen_abstract/merchant_account" xsi:type="string">1</item>
...@@ -1075,6 +1076,8 @@ ...@@ -1075,6 +1076,8 @@
<item name="payment/adyen_apple_pay/merchant_identifier_test" xsi:type="string">1</item> <item name="payment/adyen_apple_pay/merchant_identifier_test" xsi:type="string">1</item>
<item name="payment/adyen_apple_pay/merchant_identifier_live" xsi:type="string">1</item> <item name="payment/adyen_apple_pay/merchant_identifier_live" xsi:type="string">1</item>
<item name="payment/adyen_google_pay/merchant_identifier" xsi:type="string">1</item> <item name="payment/adyen_google_pay/merchant_identifier" xsi:type="string">1</item>
<item name="payment/adyen_abstract/notification_hmac_key_test" xsi:type="string">1</item>
<item name="payment/adyen_abstract/notification_hmac_key_live" xsi:type="string">1</item>
</argument> </argument>
</arguments> </arguments>
</type> </type>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment