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 48b45ef5 authored by Rik ter Beek's avatar Rik ter Beek Committed by GitHub

Merge pull request #367 from Adyen/PW-790(incomplete)

Pw 790 Save and update billing agreements based on the response from the payments call
parents fa758982 37705217
......@@ -29,12 +29,12 @@ class APIKeyMessage implements \Magento\Framework\Notification\MessageInterface
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $_adyenHelper;
protected $adyenHelper;
/**
* @var \Magento\AdminNotification\Model\InboxFactory
*/
protected $_inboxFactory;
protected $inboxFactory;
/**
* @var \Magento\Store\Model\StoreManagerInterface
......@@ -53,6 +53,8 @@ class APIKeyMessage implements \Magento\Framework\Notification\MessageInterface
*
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\AdminNotification\Model\InboxFactory $inboxFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManagerInterface
* @param \Magento\Backend\Model\Auth\Session $authSession
*/
public function __construct(
\Adyen\Payment\Helper\Data $adyenHelper,
......@@ -60,8 +62,8 @@ class APIKeyMessage implements \Magento\Framework\Notification\MessageInterface
\Magento\Store\Model\StoreManagerInterface $storeManagerInterface,
\Magento\Backend\Model\Auth\Session $authSession
) {
$this->_adyenHelper = $adyenHelper;
$this->_inboxFactory = $inboxFactory;
$this->adyenHelper = $adyenHelper;
$this->inboxFactory = $inboxFactory;
$this->storeManagerInterface = $storeManagerInterface;
$this->authSession = $authSession;
}
......@@ -83,24 +85,29 @@ class APIKeyMessage implements \Magento\Framework\Notification\MessageInterface
*/
public function isDisplayed()
{
// Only execute the query the first time you access the Admin page
if ($this->authSession->isFirstPageAfterLogin() && empty($this->_adyenHelper->getAPIKey())) {
if ($this->authSession->isFirstPageAfterLogin() &&
!empty($this->adyenHelper->getWsUsername()) &&
empty($this->adyenHelper->getAPIKey())
) {
try {
$title = "Adyen extension requires the API KEY!";
$title = 'Adyen extension requires the API KEY!';
$messageData[] = array(
$messageData[] = [
'severity' => $this->getSeverity(),
'date_added' => date("Y-m-d"),
'date_added' => date('Y-m-d'),
'title' => $title,
'description' => $this->getText(),
'url' => "https://docs.adyen.com/developers/plug-ins-and-partners/magento-2/set-up-the-plugin-in-magento#step3configuretheplugininmagento",
);
'url' => 'https://docs.adyen.com/developers/plug-ins-and-partners/magento-2/' .
'set-up-the-plugin-in-magento#step3configuretheplugininmagento',
];
/*
* The parse function checks if the $versionData message exists in the inbox,
* otherwise it will create it and add it to the inbox.
*/
$this->_inboxFactory->create()->parse(array_reverse($messageData));
$this->inboxFactory->create()->parse($messageData);
return true;
} catch (\Exception $e) {
......@@ -114,14 +121,16 @@ class APIKeyMessage implements \Magento\Framework\Notification\MessageInterface
/**
* Retrieve system message text
*
* @return \Magento\Framework\Phrase
* @return string
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function getText()
{
if (!empty($this->_adyenHelper->getWsUsername())) {
$message = "Please provide API-KEY for the webservice user " . $this->_adyenHelper->getWsUsername() . " for default/store " . $this->storeManagerInterface->getStore()->getName();
}else{
$message = "Please provide API-KEY for default/store " . $this->storeManagerInterface->getStore()->getName();
$message = '';
if (!empty($this->adyenHelper->getWsUsername())) {
$message = 'Please provide API-KEY for the webservice user ' .
$this->adyenHelper->getWsUsername() . ' for default/store ' .
$this->storeManagerInterface->getStore()->getName();
}
return $message;
......
......@@ -235,9 +235,7 @@ class Redirect extends \Magento\Payment\Block\Form
);
$formFields['shopperEmail'] = $shopperEmail;
// recurring
$recurringType = trim($this->_adyenHelper->getAdyenAbstractConfigData(
'recurring_type'
));
$recurringType = $this->_adyenHelper->getRecurringTypeFromOneclickRecurringSetting();
$brandCode = $this->_order->getPayment()->getAdditionalInformation(
\Adyen\Payment\Observer\AdyenHppDataAssignObserver::BRAND_CODE
);
......
......@@ -183,7 +183,7 @@ class PayByMailCommand implements CommandInterface
$formFields['shopperEmail'] = $shopperEmail;
// recurring
$recurringType = trim($this->_adyenHelper->getAdyenAbstractConfigData('recurring_type', $storeId));
$recurringType = $this->_adyenHelper->getRecurringTypeFromOneclickRecurringSetting($storeId);
$sessionValidity = $this->_adyenHelper->getAdyenPayByMailConfigData('session_validity', $storeId);
......
......@@ -65,7 +65,11 @@ class CcAuthorizationDataBuilder implements BuilderInterface
$storeId = $order->getStoreId();
$request = [];
// If ccType is set use this. For bcmc you need bcmc otherwise it will fail
$request['paymentMethod']['type'] = "scheme";
if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::VARIANT)) {
$request['paymentMethod']['type'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::VARIANT);
}
if ($cardNumber = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::CREDIT_CARD_NUMBER)) {
$request['paymentMethod']['encryptedCardNumber'] = $cardNumber;
......
......@@ -20,6 +20,7 @@
*
* Author: Adyen <magento@adyen.com>
*/
namespace Adyen\Payment\Gateway\Request;
use Magento\Payment\Gateway\Request\BuilderInterface;
......@@ -50,9 +51,11 @@ class RecurringDataBuilder implements BuilderInterface
$this->appState = $context->getAppState();
}
/**
* @param array $buildSubject
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function build(array $buildSubject)
{
......@@ -61,45 +64,25 @@ class RecurringDataBuilder implements BuilderInterface
/** @var \Magento\Payment\Gateway\Data\PaymentDataObject $paymentDataObject */
$paymentDataObject = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($buildSubject);
$payment = $paymentDataObject->getPayment();
// Needs to change when oneclick,cc using facade impl.
$paymentMethodCode = $payment->getMethodInstance()->getCode();
$customerId = $payment->getOrder()->getCustomerId();
$storeId = null;
if ($this->appState->getAreaCode() === \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) {
$storeId = $payment->getOrder()->getStoreId();
}
$recurringType = $this->adyenHelper->getAdyenAbstractConfigData('recurring_type', $storeId);
// set the recurring type
$recurringContractType = null;
if ($recurringType) {
if ($paymentMethodCode == \Adyen\Payment\Model\Ui\AdyenOneclickConfigProvider::CODE) {
/*
* For ONECLICK look at the recurringPaymentType that the merchant
* has selected in Adyen ONECLICK settings
*/
if ($payment->getAdditionalInformation('customer_interaction')) {
$recurringContractType = \Adyen\Payment\Model\RecurringType::ONECLICK;
} else {
$recurringContractType = \Adyen\Payment\Model\RecurringType::RECURRING;
}
} elseif ($paymentMethodCode == \Adyen\Payment\Model\Ui\AdyenCcConfigProvider::CODE) {
if ($payment->getAdditionalInformation("store_cc") == "" &&
($recurringType == "ONECLICK,RECURRING" || $recurringType == "RECURRING")) {
$recurringContractType = \Adyen\Payment\Model\RecurringType::RECURRING;
} elseif ($payment->getAdditionalInformation("store_cc") == "1") {
$recurringContractType = $recurringType;
}
} else {
$recurringContractType = $recurringType;
$enableOneclick = $this->adyenHelper->getAdyenAbstractConfigData('enable_oneclick', $storeId);
$enableRecurring = $this->adyenHelper->getAdyenAbstractConfigData('enable_recurring', $storeId);
if ($enableOneclick) {
$result['enableOneclick'] = true;
}
if ($enableRecurring) {
$result['enableRecurring'] = true;
}
// only when recurringContractType is set and when a customer is loggedIn
if ($recurringContractType && $customerId > 0) {
$recurring = ['contract' => $recurringContractType];
$result['recurring'] = $recurring;
if ($payment->getAdditionalInformation('store_cc') === '1') {
$result['paymentMethod']['storeDetails'] = true;
}
return $result;
......
......@@ -27,6 +27,18 @@ use Magento\Payment\Gateway\Response\HandlerInterface;
class CheckoutPaymentsDetailsHandler implements HandlerInterface
{
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $adyenHelper;
public function __construct(
\Adyen\Payment\Helper\Data $adyenHelper
) {
$this->adyenHelper = $adyenHelper;
}
/**
* @param array $handlingSubject
* @param array $response
......@@ -53,9 +65,16 @@ class CheckoutPaymentsDetailsHandler implements HandlerInterface
$payment->setTransactionId($response['pspReference']);
}
if (!empty($response['additionalData']) &&
!empty($response['additionalData']['recurring.recurringDetailReference'])
) {
$order = $payment->getOrder();
$this->adyenHelper->createAdyenBillingAgreement($order, $response['additionalData']);
}
// do not close transaction so you can do a cancel() and void
$payment->setIsTransactionClosed(false);
$payment->setShouldCloseParentTransaction(false);
}
}
......@@ -35,8 +35,8 @@ class Data extends AbstractHelper
const LIVE = 'live';
const CHECKOUT_CONTEXT_URL_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/';
const CHECKOUT_CONTEXT_URL_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/';
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/2.0.0-beta.4/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/2.0.0-beta.4/adyen.js';
const CHECKOUT_COMPONENT_JS_LIVE = 'https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/2.0.0/adyen.js';
const CHECKOUT_COMPONENT_JS_TEST = 'https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/2.0.0/adyen.js';
/**
* @var \Magento\Framework\Encryption\EncryptorInterface
......@@ -108,9 +108,13 @@ class Data extends AbstractHelper
*/
protected $cache;
/**
* @var \Adyen\Payment\Model\Billing\AgreementFactory
*/
protected $billingAgreementFactory;
/**
* Data constructor.
*
* @param \Magento\Framework\App\Helper\Context $context
* @param \Magento\Framework\Encryption\EncryptorInterface $encryptor
* @param \Magento\Framework\Config\DataInterface $dataStorage
......@@ -126,6 +130,7 @@ class Data extends AbstractHelper
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\App\CacheInterface $cache
* @param \Adyen\Payment\Model\Billing\AgreementFactory $billingAgreementFactory
*/
public function __construct(
\Magento\Framework\App\Helper\Context $context,
......@@ -142,7 +147,8 @@ class Data extends AbstractHelper
\Magento\Framework\App\ProductMetadataInterface $productMetadata,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\App\CacheInterface $cache
\Magento\Framework\App\CacheInterface $cache,
\Adyen\Payment\Model\Billing\AgreementFactory $billingAgreementFactory
) {
parent::__construct($context);
$this->_encryptor = $encryptor;
......@@ -159,6 +165,7 @@ class Data extends AbstractHelper
$this->adyenLogger = $adyenLogger;
$this->storeManager = $storeManager;
$this->cache = $cache;
$this->billingAgreementFactory = $billingAgreementFactory;
}
/**
......@@ -1345,14 +1352,13 @@ class Data extends AbstractHelper
{
return new \Adyen\Service\PosPayment($client);
}
return $client;
}
/**
* @return \Adyen\Client
* @throws \Adyen\AdyenException
*/
private function createAdyenClient() {
private function createAdyenClient()
{
return new \Adyen\Client();
}
......@@ -1412,7 +1418,8 @@ class Data extends AbstractHelper
* @param int|null $storeId
* @return string
*/
public function getCheckoutContextUrl($storeId = null) {
public function getCheckoutContextUrl($storeId = null)
{
if ($this->isDemoMode($storeId)) {
return self::CHECKOUT_CONTEXT_URL_TEST;
}
......@@ -1434,11 +1441,84 @@ class Data extends AbstractHelper
* @param int|null $storeId
* @return string
*/
public function getCheckoutCardComponentJs($storeId = null) {
public function getCheckoutCardComponentJs($storeId = null)
{
if ($this->isDemoMode($storeId)) {
return self::CHECKOUT_COMPONENT_JS_TEST;
}
return self::CHECKOUT_COMPONENT_JS_LIVE;
}
public function createAdyenBillingAgreement($order, $additionalData)
{
if (!empty($additionalData['recurring.recurringDetailReference'])) {
$listRecurringContracts = null;
try {
// Get or create billing agreement
$billingAgreement = $this->billingAgreementFactory->create();
$billingAgreement->load($additionalData['recurring.recurringDetailReference'], 'reference_id');
// check if BA exists
if (!($billingAgreement && $billingAgreement->getAgreementId() > 0 && $billingAgreement->isValid())) {
// create new BA
$this->adyenLogger->addAdyenDebug("Creating new Billing Agreement");
$billingAgreement = $this->billingAgreementFactory->create();
$billingAgreement->setStoreId($order->getStoreId());
$billingAgreement->importOrderPayment($order->getPayment());
$message = __('Created billing agreement #%1.',
$additionalData['recurring.recurringDetailReference']);
} else {
$billingAgreement->setIsObjectChanged(true);
$message = __('Updated billing agreement #%1.',
$additionalData['recurring.recurringDetailReference']);
}
// Populate billing agreement data
$billingAgreement->setCcBillingAgreement($additionalData);
if ($billingAgreement->isValid()) {
// save into sales_billing_agreement_order
$billingAgreement->addOrderRelation($order);
// add to order to save agreement
$order->addRelatedObject($billingAgreement);
} else {
$message = __('Failed to create billing agreement for this order.');
throw new \Exception($message);
}
} catch (\Exception $exception) {
$message = $exception->getMessage();
$this->adyenLogger->error("exception: " . $message);
}
$comment = $order->addStatusHistoryComment($message);
$order->addRelatedObject($comment);
}
}
/**
* For backwards compatibility get the recurringType used for HPP + current billing agreements
*
* @param null $storeId
* @return null|string
*/
public function getRecurringTypeFromOneclickRecurringSetting($storeId = null)
{
$enableOneclick = $this->getAdyenAbstractConfigData('enable_oneclick', $storeId);
$enableRecurring = $this->getAdyenAbstractConfigData('enable_recurring', $storeId);
if ($enableOneclick && $enableRecurring) {
return \Adyen\Payment\Model\RecurringType::ONECLICK_RECURRING;
} elseif ($enableOneclick && !$enableRecurring) {
return \Adyen\Payment\Model\RecurringType::ONECLICK;
} elseif (!$enableOneclick && $enableRecurring) {
return \Adyen\Payment\Model\RecurringType::RECURRING;
} else {
return \Adyen\Payment\Model\RecurringType::NONE;
}
return null;
}
}
......@@ -119,6 +119,8 @@ class PaymentRequest extends DataObject
throw new \Magento\Framework\Exception\LocalizedException(__('3D secure failed'));
}
$this->_adyenHelper->createAdyenBillingAgreement($order, $result['additionalData']);
return $result;
}
......
......@@ -29,7 +29,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
/**
* @var \Adyen\Payment\Helper\Data
*/
private $_adyenHelper;
private $adyenHelper;
/**
* Agreement constructor.
......@@ -66,7 +66,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
$data
);
$this->_adyenHelper = $adyenHelper;
$this->adyenHelper = $adyenHelper;
}
/**
......@@ -105,7 +105,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
// Billing agreement is CC
if (isset($data['card']['number'])) {
$ccType = $data['variant'];
$ccTypes = $this->_adyenHelper->getCcTypesAltData();
$ccTypes = $this->adyenHelper->getCcTypesAltData();
if (isset($ccTypes[$ccType])) {
$ccType = $ccTypes[$ccType]['name'];
......@@ -123,7 +123,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
}
if ($data['variant'] == 'paypal') {
$email = "";
$email = '';
if (isset($data['tokenDetails']['tokenData']['EmailId'])) {
$email = $data['tokenDetails']['tokenData']['EmailId'];
......@@ -150,9 +150,7 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
public function setAgreementData($data)
{
if (is_array($data)) {
unset($data['creationDate']);
unset($data['recurringDetailReference']);
unset($data['payment_method']);
unset($data['creationDate'], $data['recurringDetailReference'], $data['payment_method']);
}
$this->setData('agreement_data', json_encode($data));
......@@ -166,4 +164,51 @@ class Agreement extends \Magento\Paypal\Model\Billing\Agreement
{
return json_decode($this->getData('agreement_data'), true);
}
public function setCcBillingAgreement($contractDetail)
{
$this
->setMethodCode('adyen_oneclick')
->setReferenceId($contractDetail['recurring.recurringDetailReference']);
// Billing agreement is CC
if (isset($contractDetail['cardBin']) &&
isset($contractDetail['cardHolderName']) &&
isset($contractDetail['cardSummary']) &&
isset($contractDetail['expiryDate']) &&
isset($contractDetail['paymentMethod'])) {
$ccType = $contractDetail['paymentMethod'];
$ccTypes = $this->adyenHelper->getCcTypesAltData();
if (isset($ccTypes[$ccType])) {
$ccType = $ccTypes[$ccType]['name'];
}
$label = __(
'%1, %2, **** %3',
$ccType,
$contractDetail['cardHolderName'],
$contractDetail['cardSummary']
);
$this->setAgreementLabel($label);
}
$expiryDate = explode('/', $contractDetail['expiryDate']);
$recurringType = $this->adyenHelper->getRecurringTypeFromOneclickRecurringSetting();
$agreementData = [
'card' => [
'holderName' => $contractDetail['cardHolderName'],
'number' => $contractDetail['cardSummary'],
'expiryMonth' => $expiryDate[0],
'expiryYear' => $expiryDate[1]
],
'variant' => $contractDetail['paymentMethod'],
'contractTypes' => explode(',', $recurringType)
];
$this->setAgreementData($agreementData);
return $this;
}
}
......@@ -130,10 +130,10 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
]
]);
$recurringType = $this->_adyenHelper->getAdyenAbstractConfigData('recurring_type');
$enableOneclick = $this->_adyenHelper->getAdyenAbstractConfigData('enable_oneclick');
$canCreateBillingAgreement = false;
if ($recurringType == "ONECLICK" || $recurringType == "ONECLICK,RECURRING") {
if ($enableOneclick) {
$canCreateBillingAgreement = true;
}
......
......@@ -138,9 +138,9 @@ class AdyenOneclickConfigProvider implements ConfigProviderInterface
$config['payment']['adyenOneclick']['checkoutUrl'] = $this->_adyenHelper->getCheckoutContextUrl($this->_storeManager->getStore()->getId());
$config['payment']['adyenOneclick']['locale'] = $this->_adyenHelper->getStoreLocale($this->_storeManager->getStore()->getId());
$recurringType = $this->_adyenHelper->getAdyenAbstractConfigData('recurring_type');
$enableOneclick = $this->_adyenHelper->getAdyenAbstractConfigData('enable_oneclick');
$canCreateBillingAgreement = false;
if ($recurringType == "ONECLICK" || $recurringType == "ONECLICK,RECURRING") {
if ($enableOneclick) {
$canCreateBillingAgreement = true;
}
......
......@@ -39,6 +39,7 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
const EXPIRY_MONTH = 'expiryMonth';
const EXPIRY_YEAR = 'expiryYear';
const HOLDER_NAME = 'holderName';
const VARIANT = 'variant';
/**
* @var array
......@@ -51,7 +52,8 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
self::SECURITY_CODE,
self::EXPIRY_MONTH,
self::EXPIRY_YEAR,
self::HOLDER_NAME
self::HOLDER_NAME,
self::VARIANT
];
/**
......
......@@ -34,6 +34,7 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
const RECURRING_DETAIL_REFERENCE = 'recurring_detail_reference';
const SECURITY_CODE = 'cvc';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const VARIANT = 'variant';
/**
* @var array
......@@ -41,7 +42,8 @@ class AdyenOneclickDataAssignObserver extends AbstractDataAssignObserver
protected $additionalInformationList = [
self::RECURRING_DETAIL_REFERENCE,
self::SECURITY_CODE,
self::NUMBER_OF_INSTALLMENTS
self::NUMBER_OF_INSTALLMENTS,
self::VARIANT
];
/**
......
<?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\Setup;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\App\Config\Storage\WriterInterface;
/**
* Class UpgradeData
* @package Adyen\Payment\Setup
*/
class UpgradeData implements UpgradeDataInterface
{
/**
* @var WriterInterface
*/
private $configWriter;
/**
* @var ReinitableConfigInterface
*/
private $reinitableConfig;
public function __construct(
WriterInterface $configWriter,
ReinitableConfigInterface $reinitableConfig
) {
$this->configWriter = $configWriter;
$this->reinitableConfig = $reinitableConfig;
}
/**
* @param ModuleDataSetupInterface $setup
* @param ModuleContextInterface $context
*/
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
if (version_compare($context->getVersion(), '2.4.4', '<')) {
$this->updateSchemaVersion244($setup);
}
$setup->endSetup();
}
/**
* Upgrade to 2.4.4
* We use new configuration options to define if you want to store the payment for oneclick or
* recurring or a combination of those in a more friendly way and make it easier to integrate with our checkout API
*
* @param ModuleDataSetupInterface $setup
*/
public function updateSchemaVersion244(ModuleDataSetupInterface $setup)
{
// convert billing agreement select box to oneclick recurring settings
$pathEnableOneclick = "payment/adyen_abstract/enable_oneclick";
$pathEnableRecurring = "payment/adyen_abstract/enable_recurring";
$configDataTable = $setup->getTable('core_config_data');
$connection = $setup->getConnection();
$select = $connection->select()
->from($configDataTable)
->where(
'path = ?',
'payment/adyen_abstract/recurring_type'
);
$configRecurringTypeValues = $connection->fetchAll($select);
foreach ($configRecurringTypeValues as $configRecurringTypeValue) {
$scope = $configRecurringTypeValue['scope'];
$scopeId = $configRecurringTypeValue['scope_id'];
switch ($configRecurringTypeValue['value']) {
case \Adyen\Payment\Model\RecurringType::ONECLICK:
$this->configWriter->save(
$pathEnableOneclick,
'1',
$scope,
$scopeId
);
$this->configWriter->save(
$pathEnableRecurring,
'0',
$scope,
$scopeId
);
break;
case \Adyen\Payment\Model\RecurringType::ONECLICK_RECURRING:
$this->configWriter->save(
$pathEnableOneclick,
'1',
$scope,
$scopeId
);
$this->configWriter->save(
$pathEnableRecurring,
'1',
$scope,
$scopeId
);
break;
case \Adyen\Payment\Model\RecurringType::RECURRING:
$this->configWriter->save(
$pathEnableOneclick,
'0',
$scope,
$scopeId
);
$this->configWriter->save(
$pathEnableRecurring,
'1',
$scope,
$scopeId
);
break;
case \Adyen\Payment\Model\RecurringType::NONE:
$this->configWriter->save(
$pathEnableOneclick,
'0',
$scope,
$scopeId
);
$this->configWriter->save(
$pathEnableRecurring,
'0',
$scope,
$scopeId
);
break;
}
}
// re-initialize otherwise it will cause errors
$this->reinitableConfig->reinit();
}
}
\ 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.4.3",
"version": "2.4.4",
"license": [
"OSL-3.0",
"AFL-3.0"
......
......@@ -22,33 +22,30 @@
* 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_billing_agreements" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
<include xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_include.xsd">
<group id="adyen_billing_agreements" translate="label" type="text" sortOrder="50" showInDefault="1"
showInWebsite="1" showInStore="1">
<label><![CDATA[Advanced: Billing Agreements]]></label>
<frontend_model>Magento\Config\Block\System\Config\Form\Fieldset</frontend_model>
<comment>
<![CDATA[
<p>
<strong>ONECLICK</strong>: The shopper opts in to storing their card details for future use.
The shopper is present for the subsequent transaction, for cards the security code (CVC/CVV) is required.
</p>
<p>
<strong>RECURRING*</strong>: Payment details are stored for future use. For cards, the security
code (CVC/CVV) is not required for subsequent payments.
</p>
<p>
<strong>ONECLICK, RECURRING*</strong>: Payment details are stored for future use. This allows the use of
the stored payment details regardless of whether the shopper is on your site or not.
</p>
<p>* keep in mind you need the recurring permission enabled. You can contact magento@adyen.com to enable this for your account.
]]>
</comment>
<field id="enable_oneclick" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1"
showInStore="1">
<label>Enable OneClick</label>
<tooltip>The shopper opts in to storing their card details for future use. The shopper is present for the
subsequent transaction, for cards the security code (CVC/CVV) is required.
</tooltip>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_abstract/enable_oneclick</config_path>
</field>
<field id="recurring_type" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Agreement Type</label>
<tooltip>When enabled, users can save their Credit Cards and their SEPA authorizations. ONECLICK will require the input of the CVC for subsequent payments, while RECURRING does not.</tooltip>
<source_model>Adyen\Payment\Model\Config\Source\RecurringType</source_model>
<config_path>payment/adyen_abstract/recurring_type</config_path>
<field id="enable_recurring" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1"
showInStore="1">
<label>Enable Recurring</label>
<tooltip>Payment details are stored for future use. For cards, the security
code (CVC/CVV) is not required for subsequent payments.
</tooltip>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<config_path>payment/adyen_abstract/enable_recurring</config_path>
</field>
</group>
</include>
\ No newline at end of file
......@@ -28,20 +28,21 @@
<adyen_abstract>
<active>0</active>
<model>AdyenPaymentGenericFacade</model>
<recurring_type>ONECLICK</recurring_type>
<order_status>pending</order_status>
<demo_mode>0</demo_mode>
<demo_mode>1</demo_mode>
<debug>1</debug>
<title_renderer>title_image</title_renderer>
<sepa_flow>sale</sepa_flow>
<split_payments_refund_strategy>1</split_payments_refund_strategy>
<return_path>checkout/cart</return_path>
<enable_oneclick>1</enable_oneclick>
<enable_recurring>0</enable_recurring>
<group>adyen</group>
</adyen_abstract>
<adyen_cc>
<active>1</active>
<model>AdyenPaymentCcFacade</model>
<title>Adyen CreditCard</title>
<title>Credit Card</title>
<allowspecific>0</allowspecific>
<sort_order>2</sort_order>
<cctypes>AE,VI,MC,DI</cctypes>
......
......@@ -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.4.3">
<module name="Adyen_Payment" setup_version="2.4.4">
<sequence>
<module name="Magento_Sales"/>
<module name="Magento_Quote"/>
......
This diff is collapsed.
......@@ -54,7 +54,9 @@ define(
'expiryYear',
'setStoreCc',
'installment',
'creditCardDetailsValid'
'creditCardDetailsValid',
'variant',
'placeOrderAllowed'
]);
return this;
......@@ -68,10 +70,8 @@ define(
*/
renderSecureFields: function() {
var self = this;
self.placeOrderAllowed(false);
self.creditCardOwner.subscribe(function () {
self.updateButton();
});
installments.setInstallments(0);
......@@ -85,8 +85,9 @@ define(
var card = checkout.create('card', {
originKey: self.getOriginKey(),
loadingContext: self.getLoadingContext(),
type: 'card',
hasHolderName: true,
holderNameRequired: true,
groupTypes: self.getAvailableCardTypeAltCodes(),
onChange: function(state) {
......@@ -134,26 +135,24 @@ define(
}else{
self.creditCardType("")
}
if (state.isValid) {
// Here we enable the button if the component is now valid
},
onValid: function(state) {
self.variant(state.brand);
self.creditCardNumber(state.data.encryptedCardNumber);
self.expiryMonth(state.data.encryptedExpiryMonth);
self.expiryYear(state.data.encryptedExpiryYear);
self.securityCode(state.data.encryptedSecurityCode);
self.creditCardOwner(state.data.holderName);
self.creditCardDetailsValid(true);
}else{
self.placeOrderAllowed(true);
},
onError: function(state) {
self.creditCardDetailsValid(false);
self.placeOrderAllowed(false);
}
self.updateButton();
},
onError: function() {}
});
card.mount(cardNode);
self.isPlaceOrderActionAllowed(false);
},
/**
* Builds the payment details part of the payment information reqeust
......@@ -164,6 +163,7 @@ define(
return {
'method': this.item.method,
additional_data: {
'card_brand': this.variant(),
'cc_type': this.creditCardType(),
'number': this.creditCardNumber(),
'cvc': this.securityCode(),
......@@ -180,19 +180,7 @@ define(
* @returns {boolean}
*/
isButtonActive: function() {
return this.isActive() && this.getCode() == this.isChecked() && this.isPlaceOrderActionAllowed();
},
/**
* Checks if the pay button can be enabled and enables if can
*/
updateButton: function() {
var self = this;
if (self.isCardOwnerValid() && self.isCreditCardDetailsValid()) {
self.isPlaceOrderActionAllowed(true);
} else {
self.isPlaceOrderActionAllowed(false);
}
return this.isActive() && this.getCode() == this.isChecked() && this.isPlaceOrderActionAllowed() && this.placeOrderAllowed();
},
/**
* Custom place order function
......@@ -246,9 +234,7 @@ define(
var validate = $(form).validation() && $(form).validation('isValid');
var owner = Boolean($(form + ' #creditCardHolderName').valid());
if (!validate || !owner) {
if (!validate) {
return false;
}
......
......@@ -45,6 +45,7 @@ define(
var variant = ko.observable(null);
var paymentMethod = ko.observable(null);
var numberOfInstallments = ko.observable(null);
var isValid = ko.observable(false);
return Component.extend({
defaults: {
......@@ -141,8 +142,12 @@ define(
'creditCardExpMonth': ko.observable(creditCardExpMonth),
'creditCardExpYear': ko.observable(creditCardExpYear),
'getInstallments': ko.observableArray(installments),
'placeOrderAllowed': ko.observable(false),
isButtonActive: function() {
return self.isActive() && this.getCode() == self.isChecked() && self.isBillingAgreementChecked() && this.placeOrderAllowed();
},
/**
* @override
*/
......@@ -189,7 +194,7 @@ define(
* creates the card component,
* sets up the callbacks for card components
*/
renderSecureCVC: function() {
renderSecureCVC: function () {
var self = this;
var oneClickCardNode = document.getElementById('cvcContainer-' + self.value);
......@@ -198,12 +203,22 @@ define(
locale: self.getLocale()
});
// this should be fixed in new version of checkout card component
var hideCVC = false;
if (self.agreement_data.variant == "bcmc") {
hideCVC = true;
self.placeOrderAllowed(true);
} else if(self.agreement_data.variant == "maestro") {
// for maestro cvc is optional
self.placeOrderAllowed(true);
}
var oneClickCard = checkout
.create('card', {
originKey: self.getOriginKey(),
loadingContext: self.getLoadingContext(),
type: self.agreement_data.variant,
oneClick: true,
hideCVC: hideCVC,
// Specific for oneClick cards
details: [
......@@ -221,15 +236,32 @@ define(
}
},
onChange: function(state) {
onChange: function (state) {
if (state.isValid) {
self.encryptedCreditCardVerificationNumber = state.data.encryptedSecurityCode;
} else {
self.encryptedCreditCardVerificationNumber = '';
}
},
onValid: function (state) {
if (state.isValid) {
self.placeOrderAllowed(true);
isValid(true);
} else {
isValid(false);
}
return;
},
onError: function(data) {
self.placeOrderAllowed(false);
isValid(false);
return;
}
})
.mount(oneClickCardNode);
window.adyencheckout = oneClickCard;
},
/**
* Builds the payment details part of the payment information reqeust
......@@ -261,16 +293,8 @@ define(
var validate = $(form).validation() && $(form).validation('isValid');
// if oneclick or recurring is a card check CVC validity
var cid = true;
if (this.agreement_data.card) {
// if encrypted cvc is empty the request is not valid
if (this.hasVerification() && this.encryptedCreditCardVerificationNumber.length === 0) {
cid = false;
}
}
if (!validate || !cid) {
// bcmc does not have any cvc
if (!validate || (isValid() == false && variant() != "bcmc" && variant() != "maestro")) {
return false;
}
......
......@@ -87,7 +87,9 @@
</li>
<!--/ko-->
</ul>
<p class="helper-text" data-bind="css: {hidden: creditCardType() !== ''} "><!-- ko text: $t('(Please provide a card with the type from the list above)')--><!-- /ko --></p>
<p class="helper-text" data-bind="css: {hidden: creditCardType() !== ''} ">
<!-- ko text: $t('(Please provide a card with the type from the list above)')-->
<!-- /ko --></p>
<input type="hidden"
name="payment[cc_type]"
class="input-text"
......@@ -98,36 +100,11 @@
</div>
</div>
<div class="field holdername type">
<label data-bind="attr: {for: 'creditCardHolderName'}" class="label">
<span><!-- ko text: $t('Credit Card Owner')--><!-- /ko --></span>
</label>
<div class="control">
<input type="text"
class="input-text required-entry"
data-encrypted-name="holderName"
value=""
data-bind="attr: {
id: 'creditCardHolderName',
title: $t('Credit Card Owner'),
placeholder: $t('Credit Card Owner'),
'data-container': getCode() + '-cc-owner'
},
enable: isActive($parents),
value: creditCardOwner,
valueUpdate: 'keyup' "
data-validate="{required:true}"
/>
</div>
</div>
<div class="field number cardContainerField">
<div afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}" ></div>
<div afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}"></div>
</div>
<!-- ko if: (hasInstallments())-->
<div class="field required"
......
......@@ -23,7 +23,6 @@
-->
<!-- ko foreach: getAdyenBillingAgreements() -->
<div class="payment-method" data-bind="css: {'_active': (value == $parent.isBillingAgreementChecked())}">
......@@ -63,7 +62,6 @@
</div>
<form class="form" action="#" method="post" data-bind="
attr: {'id': 'adyen_oneclick_' + value, 'data-role': 'adyen_oneclick_' + value },
mageInit: {
......@@ -73,7 +71,8 @@
'orderSaveUrl':$parent.getPlaceOrderUrl(),
}, 'validation':[]}">
<fieldset data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}">
<fieldset
data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + $parent.getCode() + '_' + value}">
<!-- ko if: agreement_data.card -->
......@@ -87,7 +86,7 @@
</div>
<!-- ko if: hasVerification()-->
<div afterRender="renderSecureCVC()" data-bind="attr: { id: 'cvcContainer-' + value}" ></div>
<div afterRender="renderSecureCVC()" data-bind="attr: { id: 'cvcContainer-' + value}"></div>
<!-- /ko -->
<!--/ko-->
......@@ -124,7 +123,8 @@
<!-- ko if: number_of_installments.length > 0 -->
<div class="field required" data-bind="attr: {id: getCode() + '_installments_div'}, visible: getInstallments().length > 0">
<div class="field required"
data-bind="attr: {id: getCode() + '_installments_div'}, visible: getInstallments().length > 0">
<label data-bind="attr: {for: getCode() + '_installments'}" class="label">
<span><!-- ko text: $t('Installments')--><!-- /ko --></span>
</label>
......@@ -160,8 +160,7 @@
data-bind="
click: placeOrder,
attr: {title: $t('Place Order')},
enable: (value == $parent.isBillingAgreementChecked())
"
enable: isButtonActive()"
disabled>
<span data-bind="text: $t('Place Order')"></span>
</button>
......
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