We will work on Apr 26th (Saturday) and will be off from Apr 30th (Wednesday) until May 2nd (Friday) for public holiday in our country

Commit 6ecfbe45 authored by Alessio Zampatti's avatar Alessio Zampatti Committed by GitHub

PW-329: Include cron health checks (#222)

* PW-329: Include cron health checks

* An admin message will show up if there is a notification which has not been processed for more than 10 minutes
* Trigger the same check on a notification coming from the Adyen Backoffice

* PW-329: Moved the croncheck into the try/catch clause, minor issues fix.

* PW-329: Moved the cronchecktest so that it is initiated only after the Authentication is done.
parent dd4a3a43
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2017 Adyen B.V.
* This file is open source and available under the MIT license.
* See the LICENSE file for more info.
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\AdminMessage;
class CronMessage implements \Magento\Framework\Notification\MessageInterface
{
protected $_authSession;
protected $_cronCheck;
protected $_dateChecked;
protected $_adyenHelper;
protected $_timezoneInterface;
public function __construct(
\Magento\Backend\Model\Auth\Session $authSession,
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezoneInterface
) {
$this->_authSession = $authSession;
$this->_cronCheck = $this->getSessionData("cronCheck");
$this->_dateChecked = $this->getSessionData("dateChecked");
$this->_adyenHelper = $adyenHelper;
$this->_timezoneInterface = $timezoneInterface;
}
/**
* Message identity
*/
const MESSAGE_IDENTITY = 'Adyen Cronjob system message';
/**
* Retrieve unique system message identity
*
* @return string
*/
public function getIdentity()
{
return self::MESSAGE_IDENTITY;
}
/**
* Check whether the system message should be shown
*
* @return bool
*/
public function isDisplayed()
{
// Only execute the query the first time you access the Admin page
if ($this->_authSession->isFirstPageAfterLogin()) {
$this->_dateChecked = $this->_timezoneInterface->date();
$this->_cronCheck = $this->_adyenHelper->getUnprocessedNotifications();
$this->setSessionData("cronCheck", $this->_cronCheck);
$this->setSessionData("dateChecked", $this->_dateChecked);
}
// Do not show any message if there are no unprocessed notifications
if ($this->_cronCheck > 0) {
return true;
} else {
return false;
}
}
/**
* Retrieve system message text
*
* @return \Magento\Framework\Phrase
*/
public function getText()
{
$message = __('You have ' . $this->_cronCheck . ' unprocessed notification(s). Please check your Cron');
$urlMagento = "http://devdocs.magento.com/guides/v2.0/config-guide/cli/config-cli-subcommands-cron.html";
$urlAdyen = "https://docs.adyen.com/developers/plug-ins-and-partners/magento/magento-2/configuring-the-adyen-plug-in";
$message .= __(' and visit <a href="%1">Magento DevDocs</a> and <a href="%2">Adyen Docs</a> on how to configure Cron.',
$urlMagento, $urlAdyen);
$message .= __('<i> Last cron check was: %1</i> ', $this->_dateChecked->format('d/m/Y H:i:s'));
return __($message);
}
/**
* Retrieve system message severity
*
* @return int
*/
public function getSeverity()
{
return self::SEVERITY_CRITICAL;
}
/**
* Set the current value for the backend session
*/
public function setSessionData($key, $value)
{
return $this->_authSession->setData($key, $value);
}
/**
* Retrieve the session value
*/
public function getSessionData($key, $remove = false)
{
return $this->_authSession->getData($key, $remove);
}
}
......@@ -110,12 +110,23 @@ class Json extends \Magento\Framework\App\Action\Action
}
}
$acceptedMessage = "[accepted]";
$cronCheckTest = $notificationItems['notificationItems'][0]['NotificationRequestItem']['pspReference'];
// Run the query for checking unprocessed notifications, do this only for test notifications coming from the Adyen Customer Area
if ($this->_isTestNotification($cronCheckTest)) {
$unprocessedNotifications = $this->_adyenHelper->getUnprocessedNotifications();
if ($unprocessedNotifications > 0) {
$acceptedMessage .= "\nYou have " . $unprocessedNotifications . " unprocessed notifications.";
}
}
$this->_adyenLogger->addAdyenNotification("The result is accepted");
$this->getResponse()
->clearHeader('Content-Type')
->setHeader('Content-Type', 'text/html')
->setBody("[accepted]");
->setBody($acceptedMessage);
return;
} else {
if ($notificationMode == "") {
......@@ -139,11 +150,12 @@ class Json extends \Magento\Framework\App\Action\Action
{
$mode = $this->_adyenHelper->getAdyenAbstractConfigData('demo_mode');
if (($mode=='1' && $notificationMode == "false") || ($mode=='0' && $notificationMode == 'true')) {
if (($mode == '1' && $notificationMode == "false") || ($mode == '0' && $notificationMode == 'true')) {
return true;
}
return false;
}
/**
* save notification into the database for cronjob to execute notification
*
......@@ -157,7 +169,7 @@ class Json extends \Magento\Framework\App\Action\Action
// validate the notification
if ($this->authorised($response)) {
// check if notificaiton already exists
// check if notification already exists
if (!$this->_isDuplicate($response)) {
try {
$notification = $this->_objectManager->create('Adyen\Payment\Model\Notification');
......@@ -215,7 +227,7 @@ class Json extends \Magento\Framework\App\Action\Action
}
return false;
}
/**
* HTTP Authentication of the notification
*
......@@ -234,8 +246,7 @@ class Json extends \Magento\Framework\App\Action\Action
$submitedMerchantAccount = $response['merchantAccountCode'];
if (empty($submitedMerchantAccount) && empty($internalMerchantAccount)) {
if (strtolower(substr($response['pspReference'], 0, 17)) == "testnotification_" ||
strtolower(substr($response['pspReference'], 0, 5)) == "test_") {
if ($this->_isTestNotification($response['pspReference'])) {
echo 'merchantAccountCode is empty in magento settings';
exit();
}
......@@ -244,8 +255,7 @@ class Json extends \Magento\Framework\App\Action\Action
// validate username and password
if ((!isset($_SERVER['PHP_AUTH_USER']) && !isset($_SERVER['PHP_AUTH_PW']))) {
if (strtolower(substr($response['pspReference'], 0, 17)) == "testnotification_" ||
strtolower(substr($response['pspReference'], 0, 5)) == "test_") {
if ($this->_isTestNotification($response['pspReference'])) {
echo 'Authentication failed: PHP_AUTH_USER and PHP_AUTH_PW are empty. See Adyen Magento manual CGI mode';
exit();
}
......@@ -263,8 +273,7 @@ class Json extends \Magento\Framework\App\Action\Action
}
// If notification is test check if fields are correct if not return error
if (strtolower(substr($response['pspReference'], 0, 17)) == "testnotification_" ||
strtolower(substr($response['pspReference'], 0, 5)) == "test_") {
if ($this->_isTestNotification($response['pspReference'])) {
if ($accountCmp != 0) {
echo 'MerchantAccount in notification is not the same as in Magento settings';
exit();
......@@ -288,7 +297,7 @@ class Json extends \Magento\Framework\App\Action\Action
$eventCode = trim($response['eventCode']);
$success = trim($response['success']);
$originalReference = null;
if(isset($response['originalReference'])) {
if (isset($response['originalReference'])) {
$originalReference = trim($response['originalReference']);
}
$notification = $this->_objectManager->create('Adyen\Payment\Model\Notification');
......@@ -301,24 +310,25 @@ class Json extends \Magento\Framework\App\Action\Action
protected function _fixCgiHttpAuthentication()
{
// do nothing if values are already there
if(!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
return;
} elseif (isset($_SERVER['REDIRECT_REMOTE_AUTHORIZATION']) &&
$_SERVER['REDIRECT_REMOTE_AUTHORIZATION'] != '') {
$_SERVER['REDIRECT_REMOTE_AUTHORIZATION'] != ''
) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
explode(':', base64_decode($_SERVER['REDIRECT_REMOTE_AUTHORIZATION']),2);
explode(':', base64_decode($_SERVER['REDIRECT_REMOTE_AUTHORIZATION']), 2);
} elseif (!empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
explode(':', base64_decode(substr($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 6)),2);
explode(':', base64_decode(substr($_SERVER['REDIRECT_HTTP_AUTHORIZATION'], 6)), 2);
} elseif (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)),2);
explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)), 2);
} elseif (!empty($_SERVER['REMOTE_USER'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
explode(':', base64_decode(substr($_SERVER['REMOTE_USER'], 6)),2);
explode(':', base64_decode(substr($_SERVER['REMOTE_USER'], 6)), 2);
} elseif (!empty($_SERVER['REDIRECT_REMOTE_USER'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
explode(':', base64_decode(substr($_SERVER['REDIRECT_REMOTE_USER'], 6)),2);
explode(':', base64_decode(substr($_SERVER['REDIRECT_REMOTE_USER'], 6)), 2);
}
}
......@@ -329,4 +339,21 @@ class Json extends \Magento\Framework\App\Action\Action
{
$this->getResponse()->setHttpResponseCode(401);
}
/**
* If notification is a test notification from Adyen Customer Area
*
* @param $pspReference
* @return bool
*/
protected function _isTestNotification($pspReference)
{
if (strpos(strtolower($pspReference), "test_") !== false
|| strpos(strtolower($pspReference), "testnotification_") !== false
) {
return true;
} else {
return false;
}
}
}
\ No newline at end of file
......@@ -68,7 +68,7 @@ class Data extends AbstractHelper
/**
* Data constructor.
*
*
* @param \Magento\Framework\App\Helper\Context $context
* @param \Magento\Framework\Encryption\EncryptorInterface $encryptor
* @param \Magento\Framework\Config\DataInterface $dataStorage
......@@ -86,7 +86,8 @@ class Data extends AbstractHelper
\Magento\Framework\Module\ModuleListInterface $moduleList,
\Adyen\Payment\Model\Resource\Billing\Agreement\CollectionFactory $billingAgreementCollectionFactory,
\Magento\Framework\View\Asset\Repository $assetRepo,
\Magento\Framework\View\Asset\Source $assetSource
\Magento\Framework\View\Asset\Source $assetSource,
\Adyen\Payment\Model\Resource\Notification\CollectionFactory $notificationFactory
) {
parent::__construct($context);
$this->_encryptor = $encryptor;
......@@ -96,6 +97,7 @@ class Data extends AbstractHelper
$this->_billingAgreementCollectionFactory = $billingAgreementCollectionFactory;
$this->_assetRepo = $assetRepo;
$this->_assetSource = $assetSource;
$this->_notificationFactory = $notificationFactory;
}
/**
......@@ -127,7 +129,8 @@ class Data extends AbstractHelper
* @desc return recurring types for configuration setting
* @return array
*/
public function getCaptureModes() {
public function getCaptureModes()
{
return [
'auto' => 'immediate',
'manual' => 'manual'
......@@ -138,7 +141,8 @@ class Data extends AbstractHelper
* @desc return recurring types for configuration setting
* @return array
*/
public function getPaymentRoutines() {
public function getPaymentRoutines()
{
return [
'single' => 'Single Page Payment Routine',
'multi' => 'Multi-page Payment Routine'
......@@ -154,7 +158,7 @@ class Data extends AbstractHelper
*/
public function formatAmount($amount, $currency)
{
switch($currency) {
switch ($currency) {
case "JPY":
case "IDR":
case "KRW":
......@@ -213,7 +217,7 @@ class Data extends AbstractHelper
public function originalAmount($amount, $currency)
{
// check the format
switch($currency) {
switch ($currency) {
case "JPY":
case "IDR":
case "KRW":
......@@ -454,7 +458,7 @@ class Data extends AbstractHelper
{
switch ($this->isDemoMode()) {
case true:
$secretWord = $this->_encryptor->decrypt(trim($this->getAdyenHppConfigData('hmac_test')));
$secretWord = $this->_encryptor->decrypt(trim($this->getAdyenHppConfigData('hmac_test')));
break;
default:
$secretWord = $this->_encryptor->decrypt(trim($this->getAdyenHppConfigData('hmac_live')));
......@@ -467,7 +471,7 @@ class Data extends AbstractHelper
{
switch ($this->isDemoMode()) {
case true:
$secretWord = $this->_encryptor->decrypt(trim($this->getAdyenPayByMailConfigData('hmac_test')));
$secretWord = $this->_encryptor->decrypt(trim($this->getAdyenPayByMailConfigData('hmac_test')));
break;
default:
$secretWord = $this->_encryptor->decrypt(trim($this->getAdyenPayByMailConfigData('hmac_live')));
......@@ -501,7 +505,7 @@ class Data extends AbstractHelper
public function getWsUsername($storeId = null)
{
if ($this->isDemoMode($storeId)) {
$wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_test', $storeId));
$wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_test', $storeId));
} else {
$wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_live', $storeId));
}
......@@ -515,9 +519,11 @@ class Data extends AbstractHelper
public function getWsPassword($storeId = null)
{
if ($this->isDemoMode($storeId)) {
$wsPassword = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('ws_password_test', $storeId)));
$wsPassword = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('ws_password_test',
$storeId)));
} else {
$wsPassword = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('ws_password_live', $storeId)));
$wsPassword = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('ws_password_live',
$storeId)));
}
return $wsPassword;
}
......@@ -567,7 +573,7 @@ class Data extends AbstractHelper
*/
public function getCcTypesAltData()
{
$adyenCcTypes = $this->getAdyenCcTypes();
$adyenCcTypes = $this->getAdyenCcTypes();
$types = [];
foreach ($adyenCcTypes as $key => $data) {
$types[$data['code_alt']] = $data;
......@@ -596,7 +602,7 @@ class Data extends AbstractHelper
{
$path = 'payment/' . $paymentMethodCode . '/' . $field;
if(!$flag) {
if (!$flag) {
return $this->scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId);
} else {
return $this->scopeConfig->isSetFlag($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId);
......@@ -610,9 +616,44 @@ class Data extends AbstractHelper
public function getSepaCountries()
{
$sepaCountriesAllowed = [
"AT", "BE", "BG", "CH", "CY", "CZ", "DE", "DK", "EE", "ES", "FI", "FR", "GB", "GF", "GI", "GP", "GR", "HR",
"HU", "IE", "IS", "IT", "LI", "LT", "LU", "LV", "MC", "MQ", "MT", "NL", "NO", "PL", "PT", "RE", "RO", "SE",
"SI", "SK"
"AT",
"BE",
"BG",
"CH",
"CY",
"CZ",
"DE",
"DK",
"EE",
"ES",
"FI",
"FR",
"GB",
"GF",
"GI",
"GP",
"GR",
"HR",
"HU",
"IE",
"IS",
"IT",
"LI",
"LT",
"LU",
"LV",
"MC",
"MQ",
"MT",
"NL",
"NO",
"PL",
"PT",
"RE",
"RO",
"SE",
"SI",
"SK"
];
$countryList = $this->_country->toOptionArray();
......@@ -629,7 +670,7 @@ class Data extends AbstractHelper
public function getModuleVersion()
{
return (string) $this->_moduleList->getOne("Adyen_Payment")['setup_version'];
return (string)$this->_moduleList->getOne("Adyen_Payment")['setup_version'];
}
public function getBoletoTypes()
......@@ -695,7 +736,8 @@ class Data extends AbstractHelper
$agreementData['variant'] = 'sepadirectdebit';
}
$data = ['reference_id' => $billingAgreement->getReferenceId(),
$data = [
'reference_id' => $billingAgreement->getReferenceId(),
'agreement_label' => $billingAgreement->getAgreementLabel(),
'agreement_data' => $agreementData
];
......@@ -706,7 +748,7 @@ class Data extends AbstractHelper
$asset = $this->createAsset(
'Adyen_Payment::images/logos/' . $logoName . '.png'
);
$icon = null;
$placeholder = $this->_assetSource->findSource($asset);
if ($placeholder) {
......@@ -763,10 +805,12 @@ class Data extends AbstractHelper
{
if (strlen($paymentMethod) >= 9 && substr($paymentMethod, 0, 9) == 'afterpay_') {
return true;
} else if($paymentMethod == 'klarna' || $paymentMethod == 'ratepay') {
return true;
} else {
return false;
if ($paymentMethod == 'klarna' || $paymentMethod == 'ratepay') {
return true;
} else {
return false;
}
}
}
......@@ -790,7 +834,7 @@ class Data extends AbstractHelper
}
return false;
}
/**
* @return bool
*/
......@@ -816,9 +860,17 @@ class Data extends AbstractHelper
return $this->_assetRepo->createAsset($fileId, $params);
}
public function getStoreLocale($storeId) {
public function getStoreLocale($storeId)
{
$path = \Magento\Directory\Helper\Data::XML_PATH_DEFAULT_LOCALE;
return $this->scopeConfig->getValue($path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId);
}
public function getUnprocessedNotifications()
{
$notifications = $this->_notificationFactory->create();
$notifications->unprocessedNotificationsFilter();
return count($notifications);
}
}
\ No newline at end of file
......@@ -32,4 +32,18 @@ class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\Ab
{
$this->_init('Adyen\Payment\Model\Notification', 'Adyen\Payment\Model\Resource\Notification');
}
/**
* Filter the notifications table to see if there are any unprocessed ones that have been created more than 10 minutes ago
*/
public function unprocessedNotificationsFilter()
{
$dateEnd = new \DateTime();
$dateEnd->modify('-10 minute');
$dateRange = ['to' => $dateEnd, 'datetime' => true];
$this->addFieldToFilter('done', 0);
$this->addFieldToFilter('processing', 0);
$this->addFieldToFilter('created_at', $dateRange);
return $this;
}
}
\ No newline at end of file
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Notification\MessageList">
<arguments>
<argument name="messages" xsi:type="array">
<item name="cronMessage" xsi:type="string">Adyen\Payment\AdminMessage\CronMessage</item>
</argument>
</arguments>
</type>
</config>
......@@ -30,6 +30,7 @@
<module name="Magento_Quote"/>
<module name="Magento_Checkout"/>
<module name="Magento_Paypal"/>
<module name="Magento_AdminNotification"/>
</sequence>
</module>
</config>
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