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 a1f07421 authored by Giorgos Adam's avatar Giorgos Adam Committed by GitHub

Merge pull request #161 from Adyen/develop

Release 2.1.0
parents 1201e022 3ff4c38b
......@@ -26,4 +26,8 @@ namespace Adyen\Payment\Block\Info;
class Oneclick extends Cc
{
/**
* @var string
*/
protected $_template = 'Adyen_Payment::info/adyen_oneclick.phtml';
}
This diff is collapsed.
......@@ -97,7 +97,7 @@ class Result extends \Magento\Framework\App\Action\Action
if ($result) {
$session = $this->_session;
$session->getQuote()->setIsActive(false)->save();
$this->_redirect('checkout/onepage/success', ['utm_nooverride' => '1']);
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
} else {
$this->_cancel($response);
$this->_redirect('checkout/cart');
......
......@@ -95,7 +95,7 @@ class ResultPos extends \Magento\Framework\App\Action\Action
if ($result) {
$session = $this->_session;
$session->getQuote()->setIsActive(false)->save();
$this->_redirect('checkout/onepage/success', ['utm_nooverride' => '1']);
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
} else {
$this->_cancel($response);
$this->_redirect('checkout/cart');
......
......@@ -133,7 +133,7 @@ class Validate3d extends \Magento\Framework\App\Action\Action
$order->getPayment()->setAdditionalInformation('3dActive', '');
$this->_orderRepository->save($order);
$this->_redirect('checkout/onepage/success', ['utm_nooverride' => '1']);
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
} else {
$order->addStatusHistoryComment(__('3D-secure validation was unsuccessful.'))->save();
......@@ -162,7 +162,7 @@ class Validate3d extends \Magento\Framework\App\Action\Action
$this->_view->renderLayout();
}
} else {
$this->_redirect('checkout/onepage/success/', ['utm_nooverride' => '1']);
$this->_redirect('checkout/onepage/success', ['_query' => ['utm_nooverride' => '1']]);
}
}
......
......@@ -88,7 +88,7 @@ class TransactionCancel implements ClientInterface
$service = new \Adyen\Service\Modification($this->_client);
try {
$response = $service->cancelOrRefund($request);
$response = $service->cancel($request);
} catch(\Adyen\AdyenException $e) {
$response = null;
}
......
......@@ -86,11 +86,26 @@ class SepaValidator extends AbstractValidator
$newString .= $movedCharArray[$key];
}
if (bcmod($newString, '97') == 1) {
return true;
} else {
return false;
if (function_exists("bcmod")) {
return bcmod($newString, '97') == 1;
}
/**
* if server does not support bcmoc then do this manually:
* http://au2.php.net/manual/en/function.bcmod.php#38474
*/
$x = $newString;
$y = "97";
$take = 5;
$mod = "";
do {
$a = (int)$mod . substr($x, 0, $take);
$x = substr($x, $take);
$mod = $a % $y;
} while (strlen($x));
return (int)$mod == 1;
} else {
return false;
}
......
......@@ -770,6 +770,22 @@ class Data extends AbstractHelper
}
}
/**
* For Klarna And AfterPay use VatCategory High others use none
*
* @param $paymentMethod
* @return bool
*/
public function isVatCategoryHigh($paymentMethod)
{
if ($paymentMethod == "klarna" ||
strlen($paymentMethod) >= 9 && substr($paymentMethod, 0, 9) == 'afterpay_'
) {
return true;
}
return false;
}
/**
* @return bool
*/
......
......@@ -80,6 +80,16 @@ class PaymentMethods extends AbstractHelper
*/
protected $_assetSource;
/**
* @var \Magento\Framework\View\DesignInterface
*/
protected $_design;
/**
* @var \Magento\Framework\View\Design\Theme\ThemeProviderInterface
*/
protected $_themeProvider;
/**
* PaymentMethods constructor.
*
......@@ -93,6 +103,8 @@ class PaymentMethods extends AbstractHelper
* @param \Magento\Framework\View\Asset\Repository $assetRepo
* @param \Magento\Framework\App\RequestInterface $request
* @param \Magento\Framework\View\Asset\Source $assetSource
* @param \Magento\Framework\View\DesignInterface $design
* @param \Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider
*/
public function __construct(
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
......@@ -104,7 +116,9 @@ class PaymentMethods extends AbstractHelper
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Magento\Framework\View\Asset\Repository $assetRepo,
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\View\Asset\Source $assetSource
\Magento\Framework\View\Asset\Source $assetSource,
\Magento\Framework\View\DesignInterface $design,
\Magento\Framework\View\Design\Theme\ThemeProviderInterface $themeProvider
) {
$this->_quoteRepository = $quoteRepository;
$this->_quoteIdMaskFactory = $quoteIdMaskFactory;
......@@ -116,7 +130,8 @@ class PaymentMethods extends AbstractHelper
$this->_assetRepo = $assetRepo;
$this->_request = $request;
$this->_assetSource = $assetSource;
$this->_design = $design;
$this->_themeProvider = $themeProvider;
}
/**
......@@ -208,11 +223,24 @@ class PaymentMethods extends AbstractHelper
// add icon location in result
if ($this->_adyenHelper->showLogos()) {
// Fix for MAGETWO-70402 https://github.com/magento/magento2/pull/7686
// Explicitly setting theme
$themeCode = "Magento/blank";
$themeId = $this->_design->getConfigurationDesignTheme(\Magento\Framework\App\Area::AREA_FRONTEND);
if(!empty($themeId)) {
$theme = $this->_themeProvider->getThemeById($themeId);
if($theme && !empty($theme->getCode())) {
$themeCode = $theme->getCode();
}
}
$params = [];
// use frontend area
$params = array_merge(['area' => 'frontend', '_secure' => $this->_request->isSecure()], $params);
$params = array_merge([
'area' => \Magento\Framework\App\Area::AREA_FRONTEND,
'_secure' => $this->_request->isSecure(),
'theme' => $themeCode
], $params);
$asset = $this->_assetRepo->createAsset('Adyen_Payment::images/logos/' .
$paymentMethodCode . '.png', $params);
......
......@@ -56,7 +56,7 @@ class CcType extends \Magento\Payment\Model\Source\Cctype
*/
public function getAllowedTypes()
{
return ['VI', 'MC', 'AE', 'DI', 'JCB', 'UN', 'OT', 'MI'];
return ['VI', 'MC', 'AE', 'DI', 'JCB', 'UN', 'MI', 'DN'];
}
/**
......
......@@ -25,6 +25,10 @@ namespace Adyen\Payment\Model;
use Magento\Framework\Webapi\Exception;
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
use Magento\Framework\App\Area;
use Magento\Framework\App\AreaList;
use Magento\Framework\Phrase\Renderer\Placeholder;
use Magento\Framework\Phrase;
class Cron
{
......@@ -162,6 +166,11 @@ class Cron
*/
protected $_adyenOrderPaymentCollectionFactory;
/**
* @var AreaList
*/
protected $_areaList;
/**
* Cron constructor.
*
......@@ -177,6 +186,7 @@ class Cron
* @param Api\PaymentRequest $paymentRequest
* @param Order\PaymentFactory $adyenOrderPaymentFactory
* @param Resource\Order\Payment\CollectionFactory $adyenOrderPaymentCollectionFactory
* @param AreaList $areaList
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
......@@ -190,7 +200,8 @@ class Cron
\Adyen\Payment\Model\Resource\Billing\Agreement\CollectionFactory $billingAgreementCollectionFactory,
\Adyen\Payment\Model\Api\PaymentRequest $paymentRequest,
\Adyen\Payment\Model\Order\PaymentFactory $adyenOrderPaymentFactory,
\Adyen\Payment\Model\Resource\Order\Payment\CollectionFactory $adyenOrderPaymentCollectionFactory
\Adyen\Payment\Model\Resource\Order\Payment\CollectionFactory $adyenOrderPaymentCollectionFactory,
AreaList $areaList
) {
$this->_scopeConfig = $scopeConfig;
$this->_adyenLogger = $adyenLogger;
......@@ -204,6 +215,7 @@ class Cron
$this->_adyenPaymentRequest = $paymentRequest;
$this->_adyenOrderPaymentFactory = $adyenOrderPaymentFactory;
$this->_adyenOrderPaymentCollectionFactory = $adyenOrderPaymentCollectionFactory;
$this->_areaList = $areaList;
}
/**
......@@ -212,6 +224,12 @@ class Cron
*/
public function processNotification()
{
// needed for Magento < 2.2.0 https://github.com/magento/magento2/pull/8413
$renderer = Phrase::getRenderer();
if($renderer instanceof Placeholder) {
$this->_areaList->getArea(Area::AREA_CRONTAB)->load(Area::PART_TRANSLATE);
}
$this->_order = null;
// execute notifications from 2 minute or earlier because order could not yet been created by magento
......@@ -224,8 +242,16 @@ class Cron
// create collection
$notifications = $this->_notificationFactory->create();
$notifications->addFieldToFilter('done', 0);
$notifications->addFieldToFilter('processing', 0);
$notifications->addFieldToFilter('created_at', $dateRange);
foreach ($notifications as $notification) {
// set Cron processing to true
$notification->setProcessing(true);
$notification->setUpdatedAt(new \DateTime());
$notification->save();
}
// loop over the notifications
$count = 0;
foreach ($notifications as $notification) {
......@@ -244,6 +270,11 @@ class Cron
"This is a recurring_contract notification wait an extra 5 minutes
before processing this to make sure the contract exists"
);
// set processing back to false
$notification->setProcessing(false);
$notification->setUpdatedAt($dateEnd);
$notification->save();
continue;
}
......@@ -320,9 +351,9 @@ class Cron
$this->_order->save();
// set done to true
$dateEnd = new \DateTime();
$notification->setDone(true);
$notification->setUpdatedAt($dateEnd);
$notification->setProcessing(false);
$notification->setUpdatedAt(new \DateTime());
$notification->save();
$this->_adyenLogger->addAdyenNotificationCronjob(
sprintf("Notification %s is processed", $notification->getEntityId())
......
......@@ -36,6 +36,7 @@ class AdyenHppDataAssignObserver extends AbstractDataAssignObserver
const GENDER = 'gender';
const DOB = 'dob';
const TELEPHONE = 'telephone';
const DF_VALUE = 'df_value';
/**
......@@ -46,7 +47,8 @@ class AdyenHppDataAssignObserver extends AbstractDataAssignObserver
self::ISSUER_ID,
self::GENDER,
self::DOB,
self::TELEPHONE
self::TELEPHONE,
self::DF_VALUE
];
/**
......
......@@ -59,6 +59,10 @@ class UpgradeSchema implements UpgradeSchemaInterface
$this->updateSchemaVersion204($setup);
}
if (version_compare($context->getVersion(), '2.0.7', '<')) {
$this->updateSchemaVersion207($setup);
}
$setup->endSetup();
}
......@@ -262,4 +266,32 @@ class UpgradeSchema implements UpgradeSchemaInterface
]
);
}
/**
* Upgrade to 2.0.7
*
* @param SchemaSetupInterface $setup
* @return void
*/
public function updateSchemaVersion207(SchemaSetupInterface $setup)
{
$connection = $setup->getConnection();
$tableName = $setup->getTable('adyen_notification');
$adyenNotificationProcessingColumn = [
'type' => Table::TYPE_BOOLEAN,
'length' => 1,
'nullable' => true,
'default' => 0,
'comment' => 'Adyen Notification Cron Processing',
'after' => \Adyen\Payment\Model\Notification::DONE
];
$connection->addColumn(
$tableName,
'processing',
$adyenNotificationProcessingColumn
);
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
"name": "adyen/module-payment",
"description": "Official Magento2 Plugin to connect to Payment Service Provider Adyen.",
"type": "magento2-module",
"version": "2.0.6",
"version": "2.1.0",
"license": [
"OSL-3.0",
"AFL-3.0"
......
......@@ -45,13 +45,13 @@
</field>
<field id="hmac_test" translate="label" type="obscure" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
<label>HMAC Key for Test</label>
<tooltip>Copy and paste the HMAC key of the skin you want to use from Test Customer Area => Skins. => click on [skin code] => Edit => HMAC for Test platform. Currently, only the older SHA-1 HMAC calculation method is supported in this plugin.</tooltip>
<tooltip>Copy and paste the HMAC key of the skin you want to use from Test Customer Area => Skins. => click on [skin code] => Edit => HMAC for Test platform.</tooltip>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<config_path>payment/adyen_hpp/hmac_test</config_path>
</field>
<field id="hmac_live" translate="label" type="obscure" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="1">
<label>HMAC Key for Live</label>
<tooltip>Copy and paste the HMAC key of the skin you want to use from Test Customer Area => Skins. => click on [skin code] => Edit => HMAC for Live platform. Currently, only the older SHA-1 HMAC calculation method is supported in this plugin.</tooltip>
<tooltip>Copy and paste the HMAC key of the skin you want to use from Test Customer Area => Skins. => click on [skin code] => Edit => HMAC for Live platform.</tooltip>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<config_path>payment/adyen_hpp/hmac_live</config_path>
</field>
......
......@@ -24,10 +24,10 @@
-->
<include xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_include.xsd">
<group id="adyen_oneclick" translate="label" type="text" sortOrder="150" showInDefault="1" showInWebsite="1" showInStore="1">
<label><![CDATA[OneClick - Requires Adyen Credit Card]]></label>
<label><![CDATA[Stored Payment Methods - Requires Adyen Credit Card]]></label>
<frontend_model>Magento\Paypal\Block\Adminhtml\System\Config\Fieldset\Payment</frontend_model>
<fieldset_css>adyen-method-adyen-cc</fieldset_css>
<comment><![CDATA[During checkout shoppers can choose to have their payment details remembered and stored for trusted websites in Adyen’s highly secure platform. Adyen takes care of this process for its customers. Shoppers can then select in the Magento checkout the saved card and checkout with ‘OneClick’.]]></comment>
<comment><![CDATA[During checkout shoppers can choose to have their payment details remembered and stored for trusted websites in Adyen’s highly secure platform. Adyen takes care of this process for its customers. Shoppers can then select the stored payment method in the checkout.]]></comment>
<field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Enabled</label>
......
......@@ -64,7 +64,7 @@
<adyen_oneclick>
<active>1</active>
<model>AdyenPaymentOneclickFacade</model>
<title>Adyen OneClick</title>
<title>Adyen Stored Payment Methods</title>
<allowspecific>0</allowspecific>
<sort_order>1</sort_order>
<cctypes>AE,VI,MC,DI</cctypes> <!-- important to show the payment method isAvailabe()-->
......
......@@ -24,7 +24,7 @@
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Adyen_Payment" setup_version="2.0.6">
<module name="Adyen_Payment" setup_version="2.1.0">
<sequence>
<module name="Magento_Sales"/>
<module name="Magento_Quote"/>
......
......@@ -40,7 +40,7 @@ $currentCountry = $block->getInfoData('country');
<?php foreach($block->getOneClickCards() as $card): ?>
<?php if($card['agreement_label'] != ""):?>
<dt class="admin__field-option">
<input id="p_method_adyen_oneclick_<?php echo $card['reference_id']?>" value="<?php echo $card['reference_id']; ?>" type="radio" name="payment[recurring_detail_reference]" title="Adyen OneClick" onclick="document.getElementById('adyen_oneclick_variant').value = '<?php echo $card['agreement_data']['variant']; ?>';" class="admin__control-radio">
<input id="p_method_adyen_oneclick_<?php echo $card['reference_id']?>" value="<?php echo $card['reference_id']; ?>" type="radio" name="payment[recurring_detail_reference]" title="Adyen Stored Payment Methods" onclick="document.getElementById('adyen_oneclick_variant').value = '<?php echo $card['agreement_data']['variant']; ?>';" class="admin__control-radio">
<label class="admin__field-label" for="p_method_adyen_oneclick_<?php echo $card['reference_id']?>"><?php echo $card['agreement_label']; ?></label>
</dt>
<?php endif; ?>
......
......@@ -6,7 +6,8 @@
/*global alert*/
var config = {
paths: {
'adyen/encrypt' : 'Adyen_Payment/js/view/payment/adyen.encrypt.min'
'adyen/encrypt' : 'Adyen_Payment/js/view/payment/adyen.encrypt.min',
'adyen/df' : 'https://live.adyen.com/hpp/js/df'
},
config: {
mixins: {
......
......@@ -36,9 +36,11 @@ $_info = $this->getInfo();
<dt class="title"><?php echo $block->escapeHtml($block->getMethod()->getTitle()) ?></dt>
<?php else: ?>
<?php if ($_brandCode = $_info->getAdditionalInformation('brand_code')):?>
<dt class="title"><?php echo $_brandCode; ?></dt>
<?php endif;?>
<?php if ($_methodTitle = $_info->getAdditionalInformation('method_title')):?>
<dt class="title"><?php echo $_methodTitle; ?></dt>
<?php elseif ($_brandCode = $_info->getAdditionalInformation('brand_code')):?>
<dt class="title"><?php echo $_brandCode; ?></dt>
<?php endif;?>
<?php endif; ?>
......
......@@ -35,12 +35,14 @@ define(
'Magento_Checkout/js/model/url-builder',
'Adyen_Payment/js/model/adyen-payment-service',
'Magento_Customer/js/model/customer',
'Magento_Checkout/js/model/full-screen-loader'
'Magento_Checkout/js/model/full-screen-loader',
'adyen/df'
],
function (ko, $, Component, setPaymentMethodAction, selectPaymentMethodAction, quote, checkoutData, additionalValidators, storage, urlBuilder, adyenPaymentService, customer, fullScreenLoader) {
function (ko, $, Component, setPaymentMethodAction, selectPaymentMethodAction, quote, checkoutData, additionalValidators, storage, urlBuilder, adyenPaymentService, customer, fullScreenLoader, deviceFingerprint) {
'use strict';
var brandCode = ko.observable(null);
var paymentMethod = ko.observable(null);
var dfValue = ko.observable(null);
return Component.extend({
self: this,
......@@ -55,7 +57,8 @@ define(
'issuerId',
'gender',
'dob',
'telephone'
'telephone',
'dfValue'
]);
return this;
},
......@@ -89,6 +92,12 @@ define(
).done(
function (response) {
adyenPaymentService.setPaymentMethods(response);
// set device fingerprint value
dfSet('dfValue', 0);
// propagate this manually to knockoutjs otherwise it would not work
dfValue($('#dfValue').val());
fullScreenLoader.stopLoader();
}
).fail(function(error) {
......@@ -114,7 +123,6 @@ define(
return self.validate();
}
if(value.brandCode == "ideal") {
result.issuerIds = value.issuers;
result.issuerId = ko.observable(null);
......@@ -155,17 +163,16 @@ define(
if (this.validate() && additionalValidators.validate()) {
var data = {};
data.method = self.method;
data.po_number = null;
var additionalData = {};
additionalData.brand_code = self.value;
additionalData.df_value = dfValue();
if(brandCode() == "ideal") {
additionalData.issuer_id = this.issuerId();
} else if(brandCode() == "klarna") {
} else if(self.isPaymentMethodOpenInvoiceMethod()) {
additionalData.gender = this.gender();
additionalData.dob = this.dob();
additionalData.telephone = this.telephone();
......@@ -187,7 +194,7 @@ define(
"method": self.method,
"po_number": null,
"additional_data": {
brand_code: self.value,
brand_code: self.value
}
};
......@@ -205,7 +212,7 @@ define(
isBrandCodeChecked: ko.computed(function () {
if(!quote.paymentMethod()) {
return null;
return null;
}
if(quote.paymentMethod().method == paymentMethod()) {
......
......@@ -80,32 +80,35 @@ define(
event.preventDefault();
}
var cse_key = this.getCSEKey();
var options = { enableValidations: false};
var cseInstance = adyen.encrypt.createEncryption(cse_key, options);
var generationtime = self.getGenerationTime();
var cardData = {
cvc : self.creditCardVerificationNumber,
expiryMonth : self.creditCardExpMonth(),
expiryYear : self.creditCardExpYear(),
generationtime : generationtime
};
var encryptedData = cseInstance.encrypt(cardData);
// set payment method to adyen_hpp
var data = {
"method": self.method,
"po_number": null,
"additional_data": {
encrypted_data: encryptedData,
recurring_detail_reference: self.value,
variant: self.agreement_data.variant,
number_of_installments: self.installment
recurring_detail_reference: self.value
}
};
}
// only use CSE and installments for cards
if (self.agreement_data.card) {
var cse_key = this.getCSEKey();
var options = { enableValidations: false};
var cseInstance = adyen.encrypt.createEncryption(cse_key, options);
var generationtime = self.getGenerationTime();
var cardData = {
cvc : self.creditCardVerificationNumber,
expiryMonth : self.creditCardExpMonth(),
expiryYear : self.creditCardExpYear(),
generationtime : generationtime
};
var encryptedData = cseInstance.encrypt(cardData);
// set payment method to adyen_hpp
data.additional_data.encrypted_data = encryptedData;
data.additional_data.number_of_installments = self.installment;
}
if (this.validate() && additionalValidators.validate()) {
//this.isPlaceOrderActionAllowed(false);
......
......@@ -99,7 +99,7 @@
<input type="text" class="input-text"
name="payment[dob]"
data-bind="
datepicker: { storage: datepickerValue, options: { showOn: 'both' } },
datepicker: { storage: datepickerValue, options: { showOn: 'both', changeYear: true, yearRange: '-99:-1', defaultDate: '-20y' } },
attr: {
title: $t('Date of Birth'),
'data-container': getCode() + '-dob',
......@@ -153,6 +153,11 @@
<!--/ko-->
<!--/ko-->
<input type="hidden" name="payment[dfValue]" data-bind="attr: { id: 'dfValue', value: dfValue }" />
<!-- ko if: (isPaymentMethodSelectionOnAdyen()) -->
<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
......
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