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 1cda5566 authored by cyattilakiss's avatar cyattilakiss Committed by GitHub

Merge pull request #326 from Adyen/PW-306

PW-306 Secure Fields integration for card payments
parents c7bd96bd b756d531
<?php
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* Adyen Payment Module
*
* Copyright (c) 2018 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 APIKeyMessage implements \Magento\Framework\Notification\MessageInterface
{
/**
* @var \Adyen\Payment\Helper\Data
*/
protected $_adyenHelper;
/**
* @var \Magento\AdminNotification\Model\InboxFactory
*/
protected $_inboxFactory;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManagerInterface;
/**
* @var \Magento\Backend\Model\Auth\Session
*/
protected $authSession;
const MESSAGE_IDENTITY = 'Adyen API Key Control message';
/**
* APIKeyMessage constructor.
*
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\AdminNotification\Model\InboxFactory $inboxFactory
*/
public function __construct(
\Adyen\Payment\Helper\Data $adyenHelper,
\Magento\AdminNotification\Model\InboxFactory $inboxFactory,
\Magento\Store\Model\StoreManagerInterface $storeManagerInterface,
\Magento\Backend\Model\Auth\Session $authSession
) {
$this->_adyenHelper = $adyenHelper;
$this->_inboxFactory = $inboxFactory;
$this->storeManagerInterface = $storeManagerInterface;
$this->authSession = $authSession;
}
/**
* 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() && empty($this->_adyenHelper->getAPIKey())) {
try {
$title = "Adyen extension requires the API KEY!";
$messageData[] = array(
'severity' => $this->getSeverity(),
'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",
);
/*
* 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));
return true;
} catch (\Exception $e) {
return false;
}
}
return false;
}
/**
* Retrieve system message text
*
* @return \Magento\Framework\Phrase
*/
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();
}
return $message;
}
/**
* Retrieve system message severity
*
* @return int
*/
public function getSeverity()
{
return self::SEVERITY_CRITICAL;
}
}
<?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\Gateway\Http\Client;
use Magento\Payment\Gateway\Http\ClientInterface;
/**
* Class TransactionSale
*/
class TransactionPayment implements ClientInterface
{
/**
* PaymentRequest constructor.
*
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Encryption\EncryptorInterface $encryptor
* @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Adyen\Payment\Model\RecurringType $recurringType
* @param array $data
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Encryption\EncryptorInterface $encryptor,
\Adyen\Payment\Helper\Data $adyenHelper,
\Adyen\Payment\Model\RecurringType $recurringType,
array $data = []
) {
$this->_encryptor = $encryptor;
$this->_adyenHelper = $adyenHelper;
$this->_recurringType = $recurringType;
$this->_appState = $context->getAppState();
}
/**
* @param \Magento\Payment\Gateway\Http\TransferInterface $transferObject
* @return mixed
* @throws ClientException
*/
public function placeRequest(\Magento\Payment\Gateway\Http\TransferInterface $transferObject)
{
$request = $transferObject->getBody();
$client = $this->_adyenHelper->initializeAdyenClient();
$service = new \Adyen\Service\Checkout($client);
try {
$response = $service->payments($request);
} catch(\Adyen\AdyenException $e) {
$response['error'] = $e->getMessage();
}
return $response;
}
}
...@@ -38,6 +38,11 @@ class CcAuthorizationDataBuilder implements BuilderInterface ...@@ -38,6 +38,11 @@ class CcAuthorizationDataBuilder implements BuilderInterface
*/ */
private $appState; private $appState;
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
protected $_adyenLogger;
/** /**
* CcAuthorizationDataBuilder constructor. * CcAuthorizationDataBuilder constructor.
* *
...@@ -46,11 +51,13 @@ class CcAuthorizationDataBuilder implements BuilderInterface ...@@ -46,11 +51,13 @@ class CcAuthorizationDataBuilder implements BuilderInterface
*/ */
public function __construct( public function __construct(
\Adyen\Payment\Helper\Data $adyenHelper, \Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\Model\Context $context \Magento\Framework\Model\Context $context,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
) )
{ {
$this->adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->appState = $context->getAppState(); $this->appState = $context->getAppState();
$this->_adyenLogger = $adyenLogger;
} }
/** /**
...@@ -66,13 +73,21 @@ class CcAuthorizationDataBuilder implements BuilderInterface ...@@ -66,13 +73,21 @@ class CcAuthorizationDataBuilder implements BuilderInterface
$storeId = $order->getStoreId(); $storeId = $order->getStoreId();
$request = []; $request = [];
$request['paymentMethod']['type'] = "scheme";
$request['additionalData']['card.encrypted.json'] = $request['paymentMethod']['encryptedCardNumber'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::CREDIT_CARD_NUMBER);
$payment->getAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_DATA); $request['paymentMethod']['encryptedExpiryMonth'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::EXPIRY_MONTH);
$request['paymentMethod']['encryptedExpiryYear'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::EXPIRY_YEAR);
$request['paymentMethod']['encryptedSecurityCode'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::SECURITY_CODE);
$request['paymentMethod']['holderName'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME);
// Remove from additional data // Remove from additional data
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_DATA); $payment->unsAdditionalInformation(AdyenCcDataAssignObserver::CREDIT_CARD_NUMBER);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::EXPIRY_MONTH);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::EXPIRY_YEAR);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SECURITY_CODE);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::ENCRYPTED_DATA);
/** /**
* if MOTO for backend is enabled use MOTO as shopper interaction type * if MOTO for backend is enabled use MOTO as shopper interaction type
...@@ -84,10 +99,10 @@ class CcAuthorizationDataBuilder implements BuilderInterface ...@@ -84,10 +99,10 @@ class CcAuthorizationDataBuilder implements BuilderInterface
$request['shopperInteraction'] = "Moto"; $request['shopperInteraction'] = "Moto";
} }
// if installments is set add it into the request // if installments is set add it into the request
if ($payment->getAdditionalInformation('number_of_installments') && if ($payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) &&
$payment->getAdditionalInformation('number_of_installments') > 0 $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS) > 0
) { ) {
$request['installments']['value'] = $payment->getAdditionalInformation('number_of_installments'); $request['installments']['value'] = $payment->getAdditionalInformation(AdyenCcDataAssignObserver::NUMBER_OF_INSTALLMENTS);
} }
return $request; return $request;
......
<?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\Gateway\Response;
use Magento\Payment\Gateway\Response\HandlerInterface;
class CheckoutPaymentCommentHistoryHandler implements HandlerInterface
{
/**
* @param array $handlingSubject
* @param array $response
* @return $this
*/
public function handle(array $handlingSubject, array $response)
{
$payment = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($handlingSubject);
/** @var OrderPaymentInterface $payment */
$payment = $payment->getPayment();
$commentText = "Adyen Result response:";
if (isset($response['resultCode'])) {
$responseCode = $response['resultCode'];
} else {
// try to get response from response key (used for modifications
if (isset($response['response'])) {
$responseCode = $response['response'];
} else {
$responseCode = "";
}
}
if (isset($response['pspReference'])) {
$pspReference = $response['pspReference'];
} else {
$pspReference = "";
}
if ($responseCode) {
$commentText .= '<br /> authResult: ' . $responseCode;
$payment->getOrder()->setAdyenResulturlEventCode($responseCode);
}
if ($pspReference) {
$commentText .= '<br /> authResult: ' . $pspReference;
}
$comment = __($commentText);
$payment->getOrder()->addStatusHistoryComment($comment);
return $this;
}
}
<?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\Gateway\Response;
use Magento\Payment\Gateway\Response\HandlerInterface;
class CheckoutPaymentsDetailsHandler implements HandlerInterface
{
/**
* @param array $handlingSubject
* @param array $response
*/
public function handle(array $handlingSubject, array $response)
{
$payment = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($handlingSubject);
/** @var OrderPaymentInterface $payment */
$payment = $payment->getPayment();
// set transaction not to processing by default wait for notification
$payment->setIsTransactionPending(true);
// no not send order confirmation mail
$payment->getOrder()->setCanSendNewEmailFlag(false);
if (!empty($response['pspReference'])) {
// set pspReference as transactionId
$payment->setCcTransId($response['pspReference']);
$payment->setLastTransId($response['pspReference']);
// set transaction
$payment->setTransactionId($response['pspReference']);
}
// do not close transaction so you can do a cancel() and void
$payment->setIsTransactionClosed(false);
$payment->setShouldCloseParentTransaction(false);
}
}
<?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\Gateway\Validator;
use Magento\Payment\Gateway\Validator\AbstractValidator;
class CheckoutResponseValidator extends AbstractValidator
{
/**
* @var \Adyen\Payment\Logger\AdyenLogger
*/
private $adyenLogger;
/**
* GeneralResponseValidator constructor.
*
* @param \Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
*/
public function __construct(
\Magento\Payment\Gateway\Validator\ResultInterfaceFactory $resultFactory,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger
) {
$this->adyenLogger = $adyenLogger;
parent::__construct($resultFactory);
}
/**
* @param array $validationSubject
* @return \Magento\Payment\Gateway\Validator\ResultInterface
*/
public function validate(array $validationSubject)
{
$response = \Magento\Payment\Gateway\Helper\SubjectReader::readResponse($validationSubject);
$paymentDataObjectInterface = \Magento\Payment\Gateway\Helper\SubjectReader::readPayment($validationSubject);
$payment = $paymentDataObjectInterface->getPayment();
$payment->setAdditionalInformation('3dActive', false);
$isValid = true;
$errorMessages = [];
// validate result
if ($response && isset($response['resultCode'])) {
switch ($response['resultCode']) {
case "Authorised":
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
break;
case "Received":
$payment->setAdditionalInformation('pspReference', $response['pspReference']);
// set additionalData
if (isset($response['additionalData']) && is_array($response['additionalData'])) {
$additionalData = $response['additionalData'];
if (isset($additionalData['boletobancario.dueDate'])) {
$payment->setAdditionalInformation(
'dueDate',
$additionalData['boletobancario.dueDate']
);
}
if (isset($additionalData['boletobancario.expirationDate'])) {
$payment->setAdditionalInformation(
'expirationDate',
$additionalData['boletobancario.expirationDate']
);
}
if (isset($additionalData['boletobancario.url'])) {
$payment->setAdditionalInformation(
'url',
$additionalData['boletobancario.url']
);
}
}
break;
case "RedirectShopper":
$payment->setAdditionalInformation('3dActive', true);
$issuerUrl = $response['redirect']['url'];
$paReq = $response['redirect']['data']['PaReq'];
$md = $response['redirect']['data']['MD'];
if (!empty($paReq) && !empty($md) && !empty($issuerUrl)) {
$payment->setAdditionalInformation('issuerUrl', $issuerUrl);
$payment->setAdditionalInformation('paRequest', $paReq);
$payment->setAdditionalInformation('md', $md);
} else {
$isValid = false;
$errorMsg = __('3D secure is not valid.');
$this->adyenLogger->error($errorMsg);;
$errorMessages[] = $errorMsg;
}
break;
case "Refused":
$errorMsg = __('The payment is REFUSED.');
// this will result the specific error
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
break;
default:
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
break;
}
} else {
$errorMsg = __('Error with payment method please select different payment method.');
throw new \Magento\Framework\Exception\LocalizedException(__($errorMsg));
}
return $this->createResult($isValid, $errorMessages);
}
}
...@@ -33,6 +33,8 @@ class Data extends AbstractHelper ...@@ -33,6 +33,8 @@ class Data extends AbstractHelper
const MODULE_NAME = 'adyen-magento2'; const MODULE_NAME = 'adyen-magento2';
const TEST = 'test'; const TEST = 'test';
const LIVE = 'live'; 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/';
/** /**
* @var \Magento\Framework\Encryption\EncryptorInterface * @var \Magento\Framework\Encryption\EncryptorInterface
...@@ -94,6 +96,21 @@ class Data extends AbstractHelper ...@@ -94,6 +96,21 @@ class Data extends AbstractHelper
*/ */
protected $adyenLogger; protected $adyenLogger;
/**
* @var \Adyen\Service\ServiceFactory
*/
protected $adyenServiceFactory;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $storeManager;
/**
* @var \Magento\Framework\App\CacheInterface
*/
protected $cache;
/** /**
* Data constructor. * Data constructor.
* *
...@@ -105,8 +122,14 @@ class Data extends AbstractHelper ...@@ -105,8 +122,14 @@ class Data extends AbstractHelper
* @param \Adyen\Payment\Model\ResourceModel\Billing\Agreement\CollectionFactory $billingAgreementCollectionFactory * @param \Adyen\Payment\Model\ResourceModel\Billing\Agreement\CollectionFactory $billingAgreementCollectionFactory
* @param \Magento\Framework\View\Asset\Repository $assetRepo * @param \Magento\Framework\View\Asset\Repository $assetRepo
* @param \Magento\Framework\View\Asset\Source $assetSource * @param \Magento\Framework\View\Asset\Source $assetSource
* @param \Adyen\Payment\Model\ResourceModel\Notification\CollectionFactory $notificationFactory
* @param \Magento\Tax\Model\Config $taxConfig
* @param \Magento\Tax\Model\Calculation $taxCalculation
* @param \Magento\Framework\App\ProductMetadataInterface $productMetadata * @param \Magento\Framework\App\ProductMetadataInterface $productMetadata
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger * @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param \Adyen\Service\ServiceFactory $adyenServiceFactory
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Framework\App\CacheInterface $cache
*/ */
public function __construct( public function __construct(
\Magento\Framework\App\Helper\Context $context, \Magento\Framework\App\Helper\Context $context,
...@@ -121,7 +144,10 @@ class Data extends AbstractHelper ...@@ -121,7 +144,10 @@ class Data extends AbstractHelper
\Magento\Tax\Model\Config $taxConfig, \Magento\Tax\Model\Config $taxConfig,
\Magento\Tax\Model\Calculation $taxCalculation, \Magento\Tax\Model\Calculation $taxCalculation,
\Magento\Framework\App\ProductMetadataInterface $productMetadata, \Magento\Framework\App\ProductMetadataInterface $productMetadata,
\Adyen\Payment\Logger\AdyenLogger $adyenLogger \Adyen\Payment\Logger\AdyenLogger $adyenLogger,
\Adyen\Service\ServiceFactory $adyenServiceFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\App\CacheInterface $cache
) { ) {
parent::__construct($context); parent::__construct($context);
...@@ -137,6 +163,9 @@ class Data extends AbstractHelper ...@@ -137,6 +163,9 @@ class Data extends AbstractHelper
$this->_taxCalculation = $taxCalculation; $this->_taxCalculation = $taxCalculation;
$this->productMetadata = $productMetadata; $this->productMetadata = $productMetadata;
$this->adyenLogger = $adyenLogger; $this->adyenLogger = $adyenLogger;
$this->adyenServiceFactory = $adyenServiceFactory;
$this->storeManager = $storeManager;
$this->cache = $cache;
} }
/** /**
...@@ -577,33 +606,33 @@ class Data extends AbstractHelper ...@@ -577,33 +606,33 @@ class Data extends AbstractHelper
} }
/** /**
* @desc Retrieve the webserver username * @desc Retrieve the API key
* @return string * @return string
*/ */
public function getWsUsername($storeId = null) public function getAPIKey($storeId = null)
{ {
if ($this->isDemoMode($storeId)) { if ($this->isDemoMode($storeId)) {
$wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_test', $storeId)); $apiKey = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('api_key_test',
$storeId)));
} else { } else {
$wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_live', $storeId)); $apiKey = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('api_key_live',
$storeId)));
} }
return $wsUsername; return $apiKey;
} }
/** /**
* @desc Retrieve the webserver password * @desc Retrieve the webserver username
* @return string * @return string
*/ */
public function getWsPassword($storeId = null) public function getWsUsername($storeId = null)
{ {
if ($this->isDemoMode($storeId)) { if ($this->isDemoMode($storeId)) {
$wsPassword = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('ws_password_test', $wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_test', $storeId));
$storeId)));
} else { } else {
$wsPassword = $this->_encryptor->decrypt(trim($this->getAdyenAbstractConfigData('ws_password_live', $wsUsername = trim($this->getAdyenAbstractConfigData('ws_username_live', $storeId));
$storeId)));
} }
return $wsPassword; return $wsUsername;
} }
/** /**
...@@ -989,36 +1018,6 @@ class Data extends AbstractHelper ...@@ -989,36 +1018,6 @@ class Data extends AbstractHelper
return $notifications->getSize();; return $notifications->getSize();;
} }
/**
* @param $storeId
* @return mixed
*/
public function getLibraryToken($storeId = null)
{
if ($this->isDemoMode($storeId)) {
$libraryToken = $this->getAdyenCcConfigData('cse_library_token_test', $storeId);
} else {
$libraryToken = $this->getAdyenCcConfigData('cse_library_token_live', $storeId);
}
return $libraryToken;
}
/**
* Returns the hosted location of the client side encryption file
*
* @param null $storeId
* @return string
*/
public function getLibrarySource($storeId = null)
{
$environment = self::LIVE;
if ($this->isDemoMode($storeId)) {
$environment = self::TEST;
}
return "https://" . $environment . ".adyen.com/hpp/cse/js/" . $this->getLibraryToken($storeId) . ".shtml";
}
/** /**
* @param $formFields * @param $formFields
* @param $count * @param $count
...@@ -1174,13 +1173,11 @@ class Data extends AbstractHelper ...@@ -1174,13 +1173,11 @@ class Data extends AbstractHelper
public function initializeAdyenClient($storeId = null) public function initializeAdyenClient($storeId = null)
{ {
// initialize client // initialize client
$webserviceUsername = $this->getWsUsername($storeId); $apiKey = $this->getAPIKey($storeId);
$webservicePassword = $this->getWsPassword($storeId);
$client = new \Adyen\Client(); $client = $this->createAdyenClient();
$client->setApplicationName("Magento 2 plugin"); $client->setApplicationName("Magento 2 plugin");
$client->setUsername($webserviceUsername); $client->setXApiKey($apiKey);
$client->setPassword($webservicePassword);
$client->setAdyenPaymentSource($this->getModuleName(), $this->getModuleVersion()); $client->setAdyenPaymentSource($this->getModuleName(), $this->getModuleVersion());
...@@ -1196,4 +1193,74 @@ class Data extends AbstractHelper ...@@ -1196,4 +1193,74 @@ class Data extends AbstractHelper
return $client; return $client;
} }
/**
* @return \Adyen\Client
* @throws \Adyen\AdyenException
*/
private function createAdyenClient() {
return new \Adyen\Client();
}
/**
* Retrieve origin keys for platform's base url
*
* @return string
* @throws \Adyen\AdyenException
*/
public function getOriginKeyForBaseUrl()
{
$baseUrl = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB);
$parsed = parse_url($baseUrl);
$domain = $parsed['scheme'] . "://" . $parsed['host'];
if (!$originKey = $this->cache->load("Adyen_origin_key_for_" . $domain)) {
$originKey = "";
if ($originKey = $this->getOriginKeyForUrl($domain)) {
$this->cache->save($originKey, "Adyen_origin_key_for_" . $domain, array(), 60 * 60 * 24);
}
}
return $originKey;
}
/**
* Get origin key for a specific url using the adyen api library client
*
* @param $url
* @return mixed
* @throws \Adyen\AdyenException
*/
private function getOriginKeyForUrl($url)
{
$params = array(
"originDomains" => array(
$url
)
);
$client = $this->initializeAdyenClient();
$service = $this->adyenServiceFactory->createCheckoutUtility($client);
$respone = $service->originKeys($params);
if (empty($originKey = $respone['originKeys'][$url])) {
$originKey = "";
}
return $originKey;
}
/**
* @param int|null $storeId
* @return string
*/
public function getCheckoutContextUrl($storeId = null) {
if ($this->isDemoMode($storeId)) {
return self::CHECKOUT_CONTEXT_URL_TEST;
}
return self::CHECKOUT_CONTEXT_URL_LIVE;
}
} }
...@@ -24,9 +24,6 @@ ...@@ -24,9 +24,6 @@
namespace Adyen\Payment\Model\Ui; namespace Adyen\Payment\Model\Ui;
use Magento\Checkout\Model\ConfigProviderInterface; use Magento\Checkout\Model\ConfigProviderInterface;
use Magento\Payment\Helper\Data as PaymentHelper;
use Magento\Framework\View\Asset\Source as Source;
use \Magento\Payment\Gateway\Config\Config as Config;
class AdyenCcConfigProvider implements ConfigProviderInterface class AdyenCcConfigProvider implements ConfigProviderInterface
{ {
...@@ -65,24 +62,30 @@ class AdyenCcConfigProvider implements ConfigProviderInterface ...@@ -65,24 +62,30 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
*/ */
private $ccConfig; private $ccConfig;
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
private $storeManager;
/** /**
* AdyenCcConfigProvider constructor. * AdyenCcConfigProvider constructor.
* *
* @param PaymentHelper $paymentHelper * @param \Magento\Payment\Helper\Data $paymentHelper
* @param \Adyen\Payment\Helper\Data $adyenHelper * @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Framework\App\RequestInterface $request
* @param \Magento\Framework\UrlInterface $urlBuilder * @param \Magento\Framework\UrlInterface $urlBuilder
* @param Source $assetSource * @param \Magento\Framework\View\Asset\Source $assetSource
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Payment\Model\CcConfig $ccConfig * @param \Magento\Payment\Model\CcConfig $ccConfig
* @param Config $config
*/ */
public function __construct( public function __construct(
PaymentHelper $paymentHelper, \Magento\Payment\Helper\Data $paymentHelper,
\Adyen\Payment\Helper\Data $adyenHelper, \Adyen\Payment\Helper\Data $adyenHelper,
\Magento\Framework\App\RequestInterface $request, \Magento\Framework\App\RequestInterface $request,
\Magento\Framework\UrlInterface $urlBuilder, \Magento\Framework\UrlInterface $urlBuilder,
Source $assetSource, \Magento\Framework\View\Asset\Source $assetSource,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Payment\Model\CcConfig $ccConfig \Magento\Payment\Model\CcConfig $ccConfig
) )
{ {
...@@ -92,6 +95,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface ...@@ -92,6 +95,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
$this->_urlBuilder = $urlBuilder; $this->_urlBuilder = $urlBuilder;
$this->_assetSource = $assetSource; $this->_assetSource = $assetSource;
$this->ccConfig = $ccConfig; $this->ccConfig = $ccConfig;
$this->storeManager = $storeManager;
} }
/** /**
...@@ -116,6 +120,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface ...@@ -116,6 +120,7 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
'payment' => [ 'payment' => [
'ccform' => [ 'ccform' => [
'availableTypes' => [$methodCode => $this->getCcAvailableTypes($methodCode)], 'availableTypes' => [$methodCode => $this->getCcAvailableTypes($methodCode)],
'availableTypesByAlt' => [$methodCode => $this->getCcAvailableTypesByAlt($methodCode)],
'months' => [$methodCode => $this->getCcMonths()], 'months' => [$methodCode => $this->getCcMonths()],
'years' => [$methodCode => $this->getCcYears()], 'years' => [$methodCode => $this->getCcYears()],
'hasVerification' => [$methodCode => $this->hasVerification($methodCode)], 'hasVerification' => [$methodCode => $this->hasVerification($methodCode)],
...@@ -125,16 +130,23 @@ class AdyenCcConfigProvider implements ConfigProviderInterface ...@@ -125,16 +130,23 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
]); ]);
$recurringType = $this->_adyenHelper->getAdyenAbstractConfigData('recurring_type'); $recurringType = $this->_adyenHelper->getAdyenAbstractConfigData('recurring_type');
$canCreateBillingAgreement = false; $canCreateBillingAgreement = false;
if ($recurringType == "ONECLICK" || $recurringType == "ONECLICK,RECURRING") { if ($recurringType == "ONECLICK" || $recurringType == "ONECLICK,RECURRING") {
$canCreateBillingAgreement = true; $canCreateBillingAgreement = true;
} }
$config['payment'] ['adyenCc']['librarySource'] = $this->_adyenHelper->getLibrarySource(); $config['payment']['adyenCc']['methodCode'] = self::CODE;
$config['payment']['adyenCc']['locale'] = $this->_adyenHelper->getStoreLocale($this->storeManager->getStore()->getId());
$config['payment']['adyenCc']['generationTime'] = date("c"); $config['payment']['adyenCc']['generationTime'] = date("c");
$config['payment']['adyenCc']['canCreateBillingAgreement'] = $canCreateBillingAgreement; $config['payment']['adyenCc']['canCreateBillingAgreement'] = $canCreateBillingAgreement;
$config['payment']['adyenCc']['icons'] = $this->getIcons(); $config['payment']['adyenCc']['icons'] = $this->getIcons();
$config['payment']['adyenCc']['originKey'] = $this->_adyenHelper->getOriginKeyForBaseUrl();
$config['payment']['adyenCc']['checkoutUrl'] = $this->_adyenHelper->getCheckoutContextUrl($this->storeManager->getStore()->getId());
// has installments by default false // has installments by default false
$config['payment']['adyenCc']['hasInstallments'] = false; $config['payment']['adyenCc']['hasInstallments'] = false;
...@@ -175,6 +187,29 @@ class AdyenCcConfigProvider implements ConfigProviderInterface ...@@ -175,6 +187,29 @@ class AdyenCcConfigProvider implements ConfigProviderInterface
return $types; return $types;
} }
/**
* Retrieve availables credit card type codes by alt code
*
* @param string $methodCode
* @return array
*/
protected function getCcAvailableTypesByAlt($methodCode)
{
$types = [];
$ccTypes = $this->_adyenHelper->getAdyenCcTypes();
$availableTypes = $this->_adyenHelper->getAdyenCcConfigData('cctypes');
if ($availableTypes) {
$availableTypes = explode(',', $availableTypes);
foreach (array_keys($ccTypes) as $code) {
if (in_array($code, $availableTypes)) {
$types[$ccTypes[$code]['code_alt']] = $code;
}
}
}
return $types;
}
/** /**
* Get icons for available payment methods * Get icons for available payment methods
* *
......
...@@ -137,7 +137,8 @@ class AdyenOneclickConfigProvider implements ConfigProviderInterface ...@@ -137,7 +137,8 @@ class AdyenOneclickConfigProvider implements ConfigProviderInterface
$canCreateBillingAgreement = true; $canCreateBillingAgreement = true;
} }
$config['payment'] ['adyenOneclick']['librarySource'] = $this->_adyenHelper->getLibrarySource(); // Commented out otherwise would break the checkoutsince the getLibrarySource is removed
//$config['payment'] ['adyenOneclick']['librarySource'] = $this->_adyenHelper->getLibrarySource();
$config['payment']['adyenOneclick']['generationTime'] = date("c"); $config['payment']['adyenOneclick']['generationTime'] = date("c");
$config['payment']['adyenOneclick']['canCreateBillingAgreement'] = $canCreateBillingAgreement; $config['payment']['adyenOneclick']['canCreateBillingAgreement'] = $canCreateBillingAgreement;
......
...@@ -32,18 +32,28 @@ use Magento\Quote\Api\Data\PaymentInterface; ...@@ -32,18 +32,28 @@ use Magento\Quote\Api\Data\PaymentInterface;
class AdyenCcDataAssignObserver extends AbstractDataAssignObserver class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
{ {
const CC_TYPE = 'cc_type'; const CC_TYPE = 'cc_type';
const ENCRYPTED_DATA = 'encrypted_data';
const NUMBER_OF_INSTALLMENTS = 'number_of_installments'; const NUMBER_OF_INSTALLMENTS = 'number_of_installments';
const STORE_CC = 'store_cc'; const STORE_CC = 'store_cc';
const CREDIT_CARD_NUMBER = 'number';
const SECURITY_CODE = 'cvc';
const EXPIRY_MONTH = 'expiryMonth';
const EXPIRY_YEAR = 'expiryYear';
const HOLDER_NAME = 'holderName';
const ENCRYPTED_DATA = 'encrypted_data';
/** /**
* @var array * @var array
*/ */
protected $additionalInformationList = [ protected $additionalInformationList = [
self::CC_TYPE, self::CC_TYPE,
self::ENCRYPTED_DATA,
self::NUMBER_OF_INSTALLMENTS, self::NUMBER_OF_INSTALLMENTS,
self::STORE_CC self::STORE_CC,
self::CREDIT_CARD_NUMBER,
self::SECURITY_CODE,
self::EXPIRY_MONTH,
self::EXPIRY_YEAR,
self::HOLDER_NAME
]; ];
/** /**
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<argument name="messages" xsi:type="array"> <argument name="messages" xsi:type="array">
<item name="AdyenCronMessage" xsi:type="string">Adyen\Payment\AdminMessage\CronMessage</item> <item name="AdyenCronMessage" xsi:type="string">Adyen\Payment\AdminMessage\CronMessage</item>
<item name="AdyenVersionMessage" xsi:type="string">Adyen\Payment\AdminMessage\VersionMessage</item> <item name="AdyenVersionMessage" xsi:type="string">Adyen\Payment\AdminMessage\VersionMessage</item>
<item name="AdyenAPIKeyMessage" xsi:type="string">Adyen\Payment\AdminMessage\APIKeyMessage</item>
</argument> </argument>
</arguments> </arguments>
</type> </type>
......
...@@ -47,16 +47,6 @@ ...@@ -47,16 +47,6 @@
<source_model>Adyen\Payment\Model\Config\Source\CcType</source_model> <source_model>Adyen\Payment\Model\Config\Source\CcType</source_model>
<config_path>payment/adyen_cc/cctypes</config_path> <config_path>payment/adyen_cc/cctypes</config_path>
</field> </field>
<field id="cse_library_token_test" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Library token of Test Adyen Web Service User</label>
<tooltip>Copy this from the Test Adyen Customer Area => Settings => Users => System => [web service user]=> Library token.</tooltip>
<config_path>payment/adyen_cc/cse_library_token_test</config_path>
</field>
<field id="cse_library_token_live" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Library token of Live Adyen Web Service User</label>
<tooltip>Copy this from the Live Adyen Customer Area => Settings => Users => System => [web service user]=> Library token.</tooltip>
<config_path>payment/adyen_cc/cse_library_token_live</config_path>
</field>
<group id="adyen_cc_advanced_settings" translate="label" showInDefault="1" showInWebsite="1" sortOrder="150"> <group id="adyen_cc_advanced_settings" translate="label" showInDefault="1" showInWebsite="1" sortOrder="150">
<label>Advanced Settings</label> <label>Advanced Settings</label>
......
...@@ -49,27 +49,17 @@ ...@@ -49,27 +49,17 @@
<config_path>payment/adyen_abstract/notification_password</config_path> <config_path>payment/adyen_abstract/notification_password</config_path>
<tooltip>Set a password of your choice and copy it over to Adyen Customer Area => Settings => Server Communication => Standard Notification => Password.</tooltip> <tooltip>Set a password of your choice and copy it over to Adyen Customer Area => Settings => Server Communication => Standard Notification => Password.</tooltip>
</field> </field>
<field id="ws_username_test" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0"> <field id="api_key_test" translate="label" type="obscure" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Webservice username for Test</label> <label>API key for Test</label>
<tooltip>Find this in your Test Adyen Customer Area => Settings => Users => System. Normally this will be ws@Company.YourCompanyAccount. Copy and Paste the exact ws user name here.</tooltip> <tooltip>If you don't know your Api-Key, log in to your Test Customer Area. Navigate to Settings > Users > System, and click on your webservice user, normally this will be ws@Company.YourCompanyAccount. Under Checkout token is your API Key.</tooltip>
<config_path>payment/adyen_abstract/ws_username_test</config_path>
</field>
<field id="ws_password_test" translate="label" type="obscure" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Webservice Password for Test</label>
<tooltip>Find this in your Test Adyen Customer Area => Settings => Users => System. Click on your web service user and generate a new password. Copy and Paste the exact password here.</tooltip>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model> <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<config_path>payment/adyen_abstract/ws_password_test</config_path> <config_path>payment/adyen_abstract/api_key_test</config_path>
</field>
<field id="ws_username_live" translate="label" type="text" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Webservice username for Live</label>
<tooltip>This is only applicable if you have a Live account. Find this in your Live Adyen Customer Area => Settings => Users => System. Normally this will be ws@Company.YourCompanyAccount. Copy and Paste the exact ws user name here.</tooltip>
<config_path>payment/adyen_abstract/ws_username_live</config_path>
</field> </field>
<field id="ws_password_live" translate="label" type="obscure" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="0"> <field id="api_key_live" translate="label" type="obscure" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Webservice Password for Live</label> <label>API key for Live</label>
<tooltip>This is only applicable if you have a Live account. Find this in your Live Adyen Customer Area => Settings => Users => System. Click on your web service user and generate a new password. Copy and Paste the exact password here.</tooltip> <tooltip>If you don't know your Api-Key, log in to your Live Customer Area. Navigate to Settings > Users > System, and click on your webservice user, normally this will be ws@Company.YourCompanyAccount. Under Checkout token is your API Key.</tooltip>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model> <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<config_path>payment/adyen_abstract/ws_password_live</config_path> <config_path>payment/adyen_abstract/api_key_live</config_path>
</field> </field>
<field id="capture_mode" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="1"> <field id="capture_mode" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Capture Delay</label> <label>Capture Delay</label>
......
...@@ -387,8 +387,8 @@ ...@@ -387,8 +387,8 @@
<arguments> <arguments>
<argument name="requestBuilder" xsi:type="object">AdyenPaymentCcAuthorizeRequest</argument> <argument name="requestBuilder" xsi:type="object">AdyenPaymentCcAuthorizeRequest</argument>
<argument name="transferFactory" xsi:type="object">Adyen\Payment\Gateway\Http\TransferFactory</argument> <argument name="transferFactory" xsi:type="object">Adyen\Payment\Gateway\Http\TransferFactory</argument>
<argument name="client" xsi:type="object">Adyen\Payment\Gateway\Http\Client\TransactionAuthorization</argument> <argument name="client" xsi:type="object">Adyen\Payment\Gateway\Http\Client\TransactionPayment</argument>
<argument name="validator" xsi:type="object">GeneralResponseValidator</argument> <argument name="validator" xsi:type="object">CheckoutResponseValidator</argument>
<argument name="handler" xsi:type="object">AdyenPaymentCcResponseHandlerComposite</argument> <argument name="handler" xsi:type="object">AdyenPaymentCcResponseHandlerComposite</argument>
</arguments> </arguments>
</virtualType> </virtualType>
...@@ -593,8 +593,8 @@ ...@@ -593,8 +593,8 @@
<virtualType name="AdyenPaymentCcResponseHandlerComposite" type="Magento\Payment\Gateway\Response\HandlerChain"> <virtualType name="AdyenPaymentCcResponseHandlerComposite" type="Magento\Payment\Gateway\Response\HandlerChain">
<arguments> <arguments>
<argument name="handlers" xsi:type="array"> <argument name="handlers" xsi:type="array">
<item name="payment_details" xsi:type="string">Adyen\Payment\Gateway\Response\PaymentAuthorisationDetailsHandler</item> <item name="payment_details" xsi:type="string">Adyen\Payment\Gateway\Response\CheckoutPaymentsDetailsHandler</item>
<item name="payment_comments" xsi:type="string">Adyen\Payment\Gateway\Response\PaymentCommentHistoryHandler</item> <item name="payment_comments" xsi:type="string">Adyen\Payment\Gateway\Response\CheckoutPaymentCommentHistoryHandler</item>
</argument> </argument>
</arguments> </arguments>
</virtualType> </virtualType>
...@@ -764,6 +764,13 @@ ...@@ -764,6 +764,13 @@
</arguments> </arguments>
</virtualType> </virtualType>
<!--Checkout Response validator-->
<virtualType name="CheckoutResponseValidator" type="Adyen\Payment\Gateway\Validator\CheckoutResponseValidator">
<arguments>
<argument name="loggerInterface" xsi:type="object">Adyen\Payment\Logger\AdyenLogger</argument>
</arguments>
</virtualType>
<preference for="Magento\Paypal\Model\Billing\Agreement" type="Adyen\Payment\Model\Billing\Agreement" /> <preference for="Magento\Paypal\Model\Billing\Agreement" type="Adyen\Payment\Model\Billing\Agreement" />
<type name="Adyen\Payment\Logger\Handler\AdyenDebug"> <type name="Adyen\Payment\Logger\Handler\AdyenDebug">
......
...@@ -52,3 +52,4 @@ ...@@ -52,3 +52,4 @@
"You will be redirected to the Adyen App", "You will be redirected to the Adyen App" "You will be redirected to the Adyen App", "You will be redirected to the Adyen App"
"Continue to Adyen App", "Continue to Adyen App" "Continue to Adyen App", "Continue to Adyen App"
"Do not use Installments", "Do not use Installments" "Do not use Installments", "Do not use Installments"
"(Please provide a card with the type from the list above)", "(Please provide a card with the type from the list above)"
\ No newline at end of file
...@@ -52,3 +52,4 @@ ...@@ -52,3 +52,4 @@
"You will be redirected to the Adyen App", "U wordt doorgestuurd naar de Adyen-app" "You will be redirected to the Adyen App", "U wordt doorgestuurd naar de Adyen-app"
"Continue to Adyen App", "Doorgaan naar Adyen-app" "Continue to Adyen App", "Doorgaan naar Adyen-app"
"Do not use Installments", "Gebruik geen wederkerende betalingen" "Do not use Installments", "Gebruik geen wederkerende betalingen"
"(Please provide a card with the type from the list above)", "(Please provide a card with the type from the list above)"
...@@ -20,10 +20,35 @@ ...@@ -20,10 +20,35 @@
* Author: Adyen <magento@adyen.com> * Author: Adyen <magento@adyen.com>
*/ */
.hidden {
display: none;
}
.checkout-payment-method .ccard .changable-card-expiry { display:none; } .checkout-payment-method .ccard .changable-card-expiry { display:none; }
.checkout-payment-method .ccard .changable-card-expiry._active { display:block; } .checkout-payment-method .ccard .changable-card-expiry._active { display:block; }
.checkout-payment-method .ccard .expire-update._disable { display:none; } .checkout-payment-method .ccard .expire-update._disable { display:none; }
.checkout-payment-method .ccard .holdername .input-text { width: 225px; }
.checkout-payment-method .ccard .holdername .input-text {
width: 225px;
border: none;
padding: 0;
color: rgb(0, 27, 43);
font-size: 16px;
font-weight: 400;
}
.checkout-payment-method .ccard .holdername .input-text:focus {
border: none;
box-shadow: none;
}
.checkout-payment-method .ccard .holdername .input-text::placeholder,
.checkout-payment-method .ccard .holdername .input-text:placeholder-shown
{
color: rgb(144, 162, 189);
font-weight: 200;
}
.checkout-payment-method .payment-method-title, .checkout-payment-method .payment-method-title label { .checkout-payment-method .payment-method-title, .checkout-payment-method .payment-method-title label {
display: -webkit-flex; display: -webkit-flex;
...@@ -135,6 +160,26 @@ ...@@ -135,6 +160,26 @@
min-height: 42px; /* override magento min-height */ min-height: 42px; /* override magento min-height */
} }
/* Checkout card components style */
.adyen-checkout-card__form .adyen-checkout__input iframe{
max-height: 40px;
}
.adyen-checkout-card__form .adyen-checkout__input img{
display: none;
}
#adyen-cc-form .fieldset > .field > .label, .fieldset > .fields > .field > .label {
font-weight: 400;
}
#adyen-cc-form .fieldset > .holdername.field{
margin-bottom: 10px;
}
#adyen-cc-form .helper-text{
font-size: 11px;
color: rgb(144, 162, 189);
font-weight: 100;
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -29,73 +29,79 @@ define( ...@@ -29,73 +29,79 @@ define(
'Magento_Checkout/js/model/payment/additional-validators', 'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/quote',
'Adyen_Payment/js/model/installments', 'Adyen_Payment/js/model/installments',
'mage/url' 'mage/url',
'Adyen_Payment/js/adyen.2.0.0'
], ],
function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installments, url) { function ($, ko, Component, customer, creditCardData, additionalValidators, quote, installments, url) {
'use strict'; 'use strict';
var cvcLength = ko.observable(4);
return Component.extend({ return Component.extend({
defaults: { defaults: {
template: 'Adyen_Payment/payment/cc-form', template: 'Adyen_Payment/payment/cc-form',
creditCardOwner: '', creditCardOwner: '',
encryptedData: '',
setStoreCc: true, setStoreCc: true,
installment: '' installment: '',
creditCardDetailsValid: false
}, },
initObservable: function () { initObservable: function () {
this._super() this._super()
.observe([ .observe([
'creditCardType', 'creditCardType',
'creditCardExpYear',
'creditCardExpMonth',
'creditCardNumber',
'creditCardVerificationNumber',
'creditCardSsStartMonth',
'creditCardSsStartYear',
'selectedCardType',
'creditCardOwner', 'creditCardOwner',
'encryptedData', 'creditCardNumber',
'generationtime', 'securityCode',
'expiryMonth',
'expiryYear',
'setStoreCc', 'setStoreCc',
'installment' 'installment',
'creditCardDetailsValid'
]); ]);
return this; return this;
}, },
getInstallments: installments.getInstallments(), getInstallments: installments.getInstallments(),
initialize: function () { /**
* Renders the secure fields,
* creates the card component,
* sets up the callbacks for card components and
* set up the installments
*/
renderSecureFields: function() {
var self = this; var self = this;
this._super();
installments.setInstallments(0); self.creditCardOwner.subscribe(function () {
self.updateButton();
});
// include dynamic cse javascript
var dfScriptTag = document.createElement('script');
dfScriptTag.src = this.getLibrarySource();
dfScriptTag.type = "text/javascript";
document.body.appendChild(dfScriptTag);
//Set credit card number to credit card data object installments.setInstallments(0);
this.creditCardNumber.subscribe(function (value) {
// installments enabled ?? // installments enabled ??
var allInstallments = self.getAllInstallments(); var allInstallments = self.getAllInstallments();
var cardNode = document.getElementById('cardContainer');
// what card is this ?? var checkout = new Adyen.Checkout({
locale: window.checkoutConfig.payment.adyenCc.locale
});
if (creditCardData.creditCard) { var card = checkout.create('card', {
var creditcardType = creditCardData.creditCard.type; originKey: window.checkoutConfig.payment.adyenCc.originKey,
loadingContext: window.checkoutConfig.payment.adyenCc.checkoutUrl,
type: 'card',
groupTypes: self.getAvailableCardTypeAltCodes(),
cvcLength(4); onChange: function(state) {
if (creditcardType != "AE") { // what card is this ??
cvcLength(3); // translate adyen card type to magento card type
} var creditCardType = self.getCcCodeByAltCode(state.brand);
if (creditcardType in allInstallments) {
if (creditCardType) {
/* If the credit card type is already set, check if it changed or not */
if (!self.creditCardType() || self.creditCardType() && self.creditCardType() != creditCardType) {
if (creditCardType in allInstallments) {
// get for the creditcard the installments // get for the creditcard the installments
var installmentCreditcard = allInstallments[creditcardType]; var installmentCreditcard = allInstallments[creditCardType];
var grandTotal = quote.totals().grand_total; var grandTotal = quote.totals().grand_total;
var numberOfInstallments = []; var numberOfInstallments = [];
...@@ -123,36 +129,54 @@ define( ...@@ -123,36 +129,54 @@ define(
installments.setInstallments(0); installments.setInstallments(0);
} }
} }
});
}, // Color the image of the credit card
setPlaceOrderHandler: function (handler) { self.creditCardType(creditCardType);
this.placeOrderHandler = handler; }else{
}, self.creditCardType("")
setValidateHandler: function (handler) { }
this.validateHandler = handler;
if (state.isValid) {
// Here we enable the button if the component is now valid
self.creditCardNumber(state.data.encryptedCardNumber);
self.expiryMonth(state.data.encryptedExpiryMonth);
self.expiryYear(state.data.encryptedExpiryYear);
self.securityCode(state.data.encryptedSecurityCode);
self.creditCardDetailsValid(true);
}else{
self.creditCardDetailsValid(false);
}
self.updateButton();
}, },
getCode: function () { onError: function() {}
return 'adyen_cc'; });
card.mount(cardNode);
self.isPlaceOrderActionAllowed(false);
}, },
/**
* Builds the payment details part of the payment information reqeust
*
* @returns {{method: *, additional_data: {cc_type: *, number: *, cvc, expiryMonth: *, expiryYear: *, holderName: *, generationtime: *, store_cc: *, number_of_installments: *}}}
*/
getData: function () { getData: function () {
return { return {
'method': this.item.method, 'method': this.item.method,
additional_data: { additional_data: {
'cc_type': this.creditCardType(), 'cc_type': this.creditCardType(),
'encrypted_data': this.encryptedData(), 'number': this.creditCardNumber(),
'generationtime': this.generationtime(), 'cvc': this.securityCode(),
'expiryMonth': this.expiryMonth(),
'expiryYear': this.expiryYear(),
'holderName': this.creditCardOwner(),
'generationtime': this.getGenerationTime(),
'store_cc': this.setStoreCc(), 'store_cc': this.setStoreCc(),
'number_of_installments': this.installment() 'number_of_installments': this.installment()
} }
}; };
}, },
getCvcLength: function () {
return cvcLength();
},
isActive: function () {
return true;
},
/** /**
* Returns state of place order button * Returns state of place order button
* @returns {boolean} * @returns {boolean}
...@@ -160,9 +184,26 @@ define( ...@@ -160,9 +184,26 @@ define(
isButtonActive: function() { isButtonActive: function() {
return this.isActive() && this.getCode() == this.isChecked() && this.isPlaceOrderActionAllowed(); 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);
}
},
/** /**
* Custom place order function
*
* @override * @override
*
* @param data
* @param event
* @returns {boolean}
*/ */
placeOrder: function (data, event) { placeOrder: function (data, event) {
var self = this; var self = this;
...@@ -171,22 +212,6 @@ define( ...@@ -171,22 +212,6 @@ define(
event.preventDefault(); event.preventDefault();
} }
var options = {};
var cseInstance = adyen.createEncryption(options);
var generationtime = this.getGenerationTime();
var cardData = {
number: this.creditCardNumber(),
cvc: this.creditCardVerificationNumber(),
holderName: this.creditCardOwner(),
expiryMonth: this.creditCardExpMonth(),
expiryYear: this.creditCardExpYear(),
generationtime: generationtime
};
var data = cseInstance.encrypt(cardData);
this.encryptedData(data);
if (this.validate() && additionalValidators.validate()) { if (this.validate() && additionalValidators.validate()) {
this.isPlaceOrderActionAllowed(false); this.isPlaceOrderActionAllowed(false);
...@@ -211,25 +236,88 @@ define( ...@@ -211,25 +236,88 @@ define(
return false; return false;
}, },
getControllerName: function () { /**
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()]; * Validates the payment date when clicking the pay button
*
* @returns {boolean}
*/
validate: function () {
var self = this;
var form = 'form[data-role=adyen-cc-form]';
var validate = $(form).validation() && $(form).validation('isValid');
var owner = Boolean($(form + ' #creditCardHolderName').valid());
if (!validate || !owner) {
return false;
}
return true;
}, },
getPlaceOrderUrl: function () { /**
return window.checkoutConfig.payment.iframe.placeOrderUrl[this.getCode()]; * Validates if the typed in card holder is valid
* - length validation, can not be empty
*
* @returns {boolean}
*/
isCardOwnerValid: function() {
if (this.creditCardOwner().length == 0) {
return false;
}
return true;
}, },
context: function () { /**
return this; * The card component send the card details validity in a callback which is saved in the
* creditCardDetailsValid observable
*
* @returns {*}
*/
isCreditCardDetailsValid: function() {
return this.creditCardDetailsValid();
}, },
/**
* Translates the card type alt code (used in Adyen) to card type code (used in Magento) if it's available
*
* @param altCode
* @returns {*}
*/
getCcCodeByAltCode: function(altCode) {
var ccTypes = window.checkoutConfig.payment.ccform.availableTypesByAlt[this.getCode()];
if (ccTypes.hasOwnProperty(altCode)) {
return ccTypes[altCode];
}
isCseEnabled: function () { return "";
return window.checkoutConfig.payment.adyenCc.cseEnabled;
}, },
getCSEKey: function () { /**
return window.checkoutConfig.payment.adyenCc.cseKey; * Get available card types translated to the Adyen card type codes
* (The card type alt code is the Adyen card type code)
*
* @returns {string[]}
*/
getAvailableCardTypeAltCodes: function() {
var ccTypes = window.checkoutConfig.payment.ccform.availableTypesByAlt[this.getCode()];
return Object.keys(ccTypes);
}, },
getLibrarySource: function () { /**
return window.checkoutConfig.payment.adyenCc.librarySource; * Return Payment method code
*
* @returns {*}
*/
getCode: function () {
return window.checkoutConfig.payment.adyenCc.methodCode;
},
isActive: function () {
return true;
},
getControllerName: function () {
return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];
},
getPlaceOrderUrl: function () {
return window.checkoutConfig.payment.iframe.placeOrderUrl[this.getCode()];
}, },
getGenerationTime: function () { getGenerationTime: function () {
return window.checkoutConfig.payment.adyenCc.generationTime; return window.checkoutConfig.payment.adyenCc.generationTime;
...@@ -238,30 +326,12 @@ define( ...@@ -238,30 +326,12 @@ define(
if (customer.isLoggedIn()) { if (customer.isLoggedIn()) {
return window.checkoutConfig.payment.adyenCc.canCreateBillingAgreement; return window.checkoutConfig.payment.adyenCc.canCreateBillingAgreement;
} }
return false; return false;
}, },
isShowLegend: function () { isShowLegend: function () {
return true; return true;
}, },
validate: function () {
var form = 'form[data-role=adyen-cc-form]';
var validate = $(form).validation() && $(form).validation('isValid');
// add extra validation because jquery validation will not work on non name attributes
var ccNumber = Boolean($(form + ' #creditCardNumber').valid());
var owner = Boolean($(form + ' #creditCardHolderName').valid());
var expiration = Boolean($(form + ' #adyen_cc_expiration').valid());
var expiration_yr = Boolean($(form + ' #adyen_cc_expiration_yr').valid());
var cid = Boolean($(form + ' #adyen_cc_cc_cid').valid());
if (!validate || !ccNumber || !owner || !expiration || !expiration_yr || !cid) {
return false;
}
return true;
},
showLogo: function () { showLogo: function () {
return window.checkoutConfig.payment.adyen.showLogo; return window.checkoutConfig.payment.adyen.showLogo;
}, },
...@@ -275,9 +345,16 @@ define( ...@@ -275,9 +345,16 @@ define(
}, },
getAllInstallments: function () { getAllInstallments: function () {
return window.checkoutConfig.payment.adyenCc.installments; return window.checkoutConfig.payment.adyenCc.installments;
},
setPlaceOrderHandler: function (handler) {
this.placeOrderHandler = handler;
},
setValidateHandler: function (handler) {
this.validateHandler = handler;
},
context: function () {
return this;
} }
}); });
} }
); );
...@@ -68,14 +68,14 @@ ...@@ -68,14 +68,14 @@
<br/> <br/>
<!-- /ko --> <!-- /ko -->
<div class="field type required"> <div class="field type">
<label data-bind="attr: {for: getCode() + '_cc_type'}" class="label"> <label data-bind="attr: {for: getCode() + '_cc_type'}" class="label">
<span><!-- ko text: $t('Credit Card Type')--><!-- /ko --></span> <span><!-- ko text: $t('Credit Card Type')--><!-- /ko --></span>
</label> </label>
<div class="control"> <div class="control">
<ul class="credit-card-types"> <ul class="credit-card-types">
<!-- ko foreach: {data: getCcAvailableTypesValues(), as: 'item'} --> <!-- ko foreach: {data: getCcAvailableTypesValues(), as: 'item'} -->
<li class="item" data-bind="css: {_active: $parent.selectedCardType() == item.value} "> <li class="item" data-bind="css: {_active: $parent.creditCardType() == item.value} ">
<!--ko if: $parent.getIcons(item.value) --> <!--ko if: $parent.getIcons(item.value) -->
<img data-bind="attr: { <img data-bind="attr: {
'src': $parent.getIcons(item.value).url, 'src': $parent.getIcons(item.value).url,
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
</li> </li>
<!--/ko--> <!--/ko-->
</ul> </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>
<input type="hidden" <input type="hidden"
name="payment[cc_type]" name="payment[cc_type]"
class="input-text" class="input-text"
...@@ -96,25 +97,8 @@ ...@@ -96,25 +97,8 @@
"> ">
</div> </div>
</div> </div>
<div class="field number required">
<label data-bind="attr: {for: 'creditCardNumber'}" class="label"> <div class="field holdername type">
<span><!-- ko text: $t('Credit Card Number')--><!-- /ko --></span>
</label>
<div class="control">
<input type="number" class="input-text" value=""
data-encrypted-name="number"
data-bind="attr: {
autocomplete: off,
id: 'creditCardNumber',
title: $t('Credit Card Number'),
'data-container': getCode() + '-cc-number',
'data-validate': JSON.stringify({'required-number':true, 'validate-card-type':getCcAvailableTypesValues(), 'validate-card-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})},
enable: isActive($parents),
value: creditCardNumber,
valueUpdate: 'keyup' "/>
</div>
</div>
<div class="field holdername type required">
<label data-bind="attr: {for: 'creditCardHolderName'}" class="label"> <label data-bind="attr: {for: 'creditCardHolderName'}" class="label">
<span><!-- ko text: $t('Credit Card Owner')--><!-- /ko --></span> <span><!-- ko text: $t('Credit Card Owner')--><!-- /ko --></span>
</label> </label>
...@@ -126,6 +110,7 @@ ...@@ -126,6 +110,7 @@
data-bind="attr: { data-bind="attr: {
id: 'creditCardHolderName', id: 'creditCardHolderName',
title: $t('Credit Card Owner'), title: $t('Credit Card Owner'),
placeholder: $t('Credit Card Owner'),
'data-container': getCode() + '-cc-owner' 'data-container': getCode() + '-cc-owner'
}, },
enable: isActive($parents), enable: isActive($parents),
...@@ -135,82 +120,12 @@ ...@@ -135,82 +120,12 @@
/> />
</div> </div>
</div> </div>
<div class="field date required" data-bind="attr: {id: getCode() + '_cc_type_exp_div'}">
<label data-bind="attr: {for: 'cardExpirationMonth'}" class="label"> <div class="field number cardContainerField">
<span><!-- ko text: $t('Expiration Date')--><!-- /ko --></span> <div afterRender="renderSecureFields()" data-bind="attr: { id: 'cardContainer'}" ></div>
</label>
<div class="control">
<div class="fields group group-2">
<div class="field no-label month">
<div class="control">
<select class="select select-month"
data-encrypted-name="expiryMonth"
data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-cc-exp':'#' + getCode() + '_expiration_yr'})},
enable: isActive($parents),
options: getCcMonthsValues(),
optionsValue: 'value',
optionsText: 'month',
optionsCaption: $t('Month'),
value: creditCardExpMonth"
data-validate="{required:true}">
</select>
</div>
</div>
<div class="field no-label year">
<div class="control">
<select class="select select-year"
data-encrypted-name="expiryYear"
data-bind="attr: {id: getCode() + '_expiration_yr', 'data-container': getCode() + '-cc-year', 'data-validate': JSON.stringify({required:true})},
enable: isActive($parents),
options: getCcYearsValues(),
optionsValue: 'value',
optionsText: 'year',
optionsCaption: $t('Year'),
value: creditCardExpYear"
data-validate="{required:true}">
</select>
</div>
</div>
</div>
</div>
</div>
<!-- ko if: (hasVerification())-->
<div class="field cvv required" data-bind="attr: {id: getCode() + '_cc_type_cvv_div'}">
<label data-bind="attr: {for: getCode() + '_cc_cid'}" class="label">
<span><!-- ko text: $t('Card Verification Number')--><!-- /ko --></span>
</label>
<div class="control _with-tooltip">
<input type="number"
autocomplete="off"
class="input-text cvv"
data-encrypted-name="cvc"
value=""
data-bind="attr: {
id: getCode() + '_cc_cid',
title: $t('Card Verification Number'),
'data-container': getCode() + '-cc-cvv',
'data-validate': JSON.stringify({'required-number':true, 'validate-card-cvv':'#' + getCode() + '_cc_type'}),
maxLength : getCvcLength(),
oninput:'javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);'
},
enable: isActive($parents),
value: creditCardVerificationNumber" ,
data-validate="{required:true}"
/>
<div class="field-tooltip toggle">
<span class="field-tooltip-action action-cvv"
tabindex="0"
data-toggle="dropdown"
data-bind="attr: {title: $t('What is this?')}, mageInit: {'dropdown':{'activeClass': '_active'}}">
<span><!-- ko text: $t('What is this?')--><!-- /ko --></span>
</span>
<div class="field-tooltip-content"
data-target="dropdown"
data-bind="html: getCvvImageHtml()"></div>
</div>
</div>
</div> </div>
<!-- /ko -->
<!-- ko if: (hasInstallments())--> <!-- ko if: (hasInstallments())-->
......
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