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

Commit 48811d7c authored by cyattilakiss's avatar cyattilakiss Committed by GitHub

Merge pull request #343 from Adyen/PW-635

PW-635 Secure Fields integration for backend orders
parents 002899f9 b1532469
...@@ -30,27 +30,20 @@ class Cc extends \Magento\Payment\Block\Form\Cc ...@@ -30,27 +30,20 @@ class Cc extends \Magento\Payment\Block\Form\Cc
*/ */
protected $_template = 'Adyen_Payment::form/cc.phtml'; protected $_template = 'Adyen_Payment::form/cc.phtml';
/**
* Payment config model
*
* @var \Magento\Payment\Model\Config
*/
protected $_paymentConfig;
/** /**
* @var \Adyen\Payment\Helper\Data * @var \Adyen\Payment\Helper\Data
*/ */
protected $_adyenHelper; protected $adyenHelper;
/** /**
* @var \Magento\Framework\App\State * @var \Magento\Framework\App\State
*/ */
protected $_appState; protected $appState;
/** /**
* @var \Magento\Checkout\Model\Session * @var \Magento\Checkout\Model\Session
*/ */
protected $_checkoutSession; protected $checkoutSession;
/** /**
* Cc constructor. * Cc constructor.
...@@ -59,6 +52,7 @@ class Cc extends \Magento\Payment\Block\Form\Cc ...@@ -59,6 +52,7 @@ class Cc extends \Magento\Payment\Block\Form\Cc
* @param \Magento\Payment\Model\Config $paymentConfig * @param \Magento\Payment\Model\Config $paymentConfig
* @param \Adyen\Payment\Helper\Data $adyenHelper * @param \Adyen\Payment\Helper\Data $adyenHelper
* @param \Magento\Checkout\Model\Session $checkoutSession * @param \Magento\Checkout\Model\Session $checkoutSession
* @param \Adyen\Payment\Logger\AdyenLogger $adyenLogger
* @param array $data * @param array $data
*/ */
public function __construct( public function __construct(
...@@ -70,26 +64,34 @@ class Cc extends \Magento\Payment\Block\Form\Cc ...@@ -70,26 +64,34 @@ class Cc extends \Magento\Payment\Block\Form\Cc
) )
{ {
parent::__construct($context, $paymentConfig); parent::__construct($context, $paymentConfig);
$this->_adyenHelper = $adyenHelper; $this->adyenHelper = $adyenHelper;
$this->_appState = $context->getAppState(); $this->appState = $context->getAppState();
$this->_checkoutSession = $checkoutSession; $this->checkoutSession = $checkoutSession;
} }
/**
* @return string
*/
public function getCheckoutCardComponentJs()
{
return $this->adyenHelper->getCheckoutCardComponentJs($this->checkoutSession->getQuote()->getStore()->getId());
}
/** /**
* @return mixed * @return string
* @throws \Magento\Framework\Exception\LocalizedException * @throws \Adyen\AdyenException
*/ */
public function getLibrarySource() public function getCheckoutOriginKeys()
{ {
// get storeId for admin return $this->adyenHelper->getOriginKeyForBaseUrl();
if (!$this->_appState->getAreaCode() === \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) {
$storeId = $this->_storeManager->getStore()->getId();
} else {
$storeId = null;
} }
return $this->_adyenHelper->getLibrarySource($storeId); /**
* @return string
*/
public function getCheckoutContextUrl()
{
return $this->adyenHelper->getCheckoutContextUrl($this->checkoutSession->getQuote()->getStore()->getId());
} }
/** /**
...@@ -100,14 +102,45 @@ class Cc extends \Magento\Payment\Block\Form\Cc ...@@ -100,14 +102,45 @@ class Cc extends \Magento\Payment\Block\Form\Cc
public function hasVerification() public function hasVerification()
{ {
// if backend order and moto payments is turned on don't show cvc // if backend order and moto payments is turned on don't show cvc
if ($this->_appState->getAreaCode() === \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) { if ($this->appState->getAreaCode() === \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE) {
$this->getCheckoutSession(); $this->getCheckoutSession();
$store = $this->_checkoutSession->getQuote()->getStore(); $store = $this->checkoutSession->getQuote()->getStore();
$enableMoto = $this->_adyenHelper->getAdyenCcConfigDataFlag('enable_moto', $store->getId()); $enableMoto = $this->adyenHelper->getAdyenCcConfigDataFlag('enable_moto', $store->getId());
if ($enableMoto) { if ($enableMoto) {
return false; return false;
} }
} }
return true; return true;
} }
/**
* @return string
*/
public function getLocale()
{
return $this->adyenHelper->getStoreLocale($this->checkoutSession->getQuote()->getStore()->getId());
}
/**
* Retrieve availables credit card type codes by alt code
*
* @return array
*/
public function getCcAvailableTypesByAlt()
{
$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;
}
} }
...@@ -68,10 +68,8 @@ class Oneclick extends \Adyen\Payment\Block\Form\Cc ...@@ -68,10 +68,8 @@ class Oneclick extends \Adyen\Payment\Block\Form\Cc
// For backend only allow recurring payments // For backend only allow recurring payments
$recurringType = \Adyen\Payment\Model\RecurringType::RECURRING; $recurringType = \Adyen\Payment\Model\RecurringType::RECURRING;
$cards = $this->_adyenHelper->getOneClickPaymentMethods($customerId, $storeId, $grandTotal, $recurringType); $cards = $this->adyenHelper->getOneClickPaymentMethods($customerId, $storeId, $grandTotal, $recurringType);
return $cards; return $cards;
} }
} }
...@@ -95,8 +95,6 @@ class CcAuthorizationDataBuilder implements BuilderInterface ...@@ -95,8 +95,6 @@ class CcAuthorizationDataBuilder implements BuilderInterface
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SECURITY_CODE); $payment->unsAdditionalInformation(AdyenCcDataAssignObserver::SECURITY_CODE);
$payment->unsAdditionalInformation(AdyenCcDataAssignObserver::HOLDER_NAME); $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
*/ */
......
...@@ -1229,7 +1229,8 @@ class Data extends AbstractHelper ...@@ -1229,7 +1229,8 @@ class Data extends AbstractHelper
if (!$originKey = $this->cache->load("Adyen_origin_key_for_" . $domain)) { if (!$originKey = $this->cache->load("Adyen_origin_key_for_" . $domain)) {
$originKey = ""; $originKey = "";
if ($originKey = $this->getOriginKeyForUrl($domain)) { $storeId = $this->storeManager->getStore()->getId();
if ($originKey = $this->getOriginKeyForUrl($domain, $storeId)) {
$this->cache->save($originKey, "Adyen_origin_key_for_" . $domain, array(), 60 * 60 * 24); $this->cache->save($originKey, "Adyen_origin_key_for_" . $domain, array(), 60 * 60 * 24);
} }
} }
...@@ -1241,10 +1242,11 @@ class Data extends AbstractHelper ...@@ -1241,10 +1242,11 @@ class Data extends AbstractHelper
* Get origin key for a specific url using the adyen api library client * Get origin key for a specific url using the adyen api library client
* *
* @param $url * @param $url
* @return mixed * @param int|null $storeId
* @return string
* @throws \Adyen\AdyenException * @throws \Adyen\AdyenException
*/ */
private function getOriginKeyForUrl($url) private function getOriginKeyForUrl($url, $storeId = null)
{ {
$params = array( $params = array(
"originDomains" => array( "originDomains" => array(
...@@ -1252,7 +1254,7 @@ class Data extends AbstractHelper ...@@ -1252,7 +1254,7 @@ class Data extends AbstractHelper
) )
); );
$client = $this->initializeAdyenClient(); $client = $this->initializeAdyenClient($storeId);
$service = $this->createAdyenCheckoutUtilityService($client); $service = $this->createAdyenCheckoutUtilityService($client);
$respone = $service->originKeys($params); $respone = $service->originKeys($params);
......
...@@ -40,8 +40,6 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver ...@@ -40,8 +40,6 @@ class AdyenCcDataAssignObserver extends AbstractDataAssignObserver
const EXPIRY_YEAR = 'expiryYear'; const EXPIRY_YEAR = 'expiryYear';
const HOLDER_NAME = 'holderName'; const HOLDER_NAME = 'holderName';
const ENCRYPTED_DATA = 'encrypted_data';
/** /**
* @var array * @var array
*/ */
......
<?xml version="1.0"?>
<!--
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* 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>
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="Adyen_Payment::css/order_create_styles.css"/>
</head>
</page>
...@@ -32,105 +32,40 @@ $ccExpYear = $block->getInfoData('cc_exp_year'); ...@@ -32,105 +32,40 @@ $ccExpYear = $block->getInfoData('cc_exp_year');
?> ?>
<fieldset class="admin__fieldset payment-method" id="payment_form_<?php /* @noEscape */ <fieldset class="admin__fieldset payment-method" id="payment_form_<?php /* @noEscape */
echo $code; ?>" echo $code; ?>" style="display:none">
style="display:none"> <div class="field admin__field">
<label for="<?php /* @noEscape */
<div class="field admin__field _required">
<label class="admin__field-label" for="<?php /* @noEscape */
echo $code; ?>_cc_owner"> echo $code; ?>_cc_owner">
<span><?php echo $block->escapeHtml(__('Name on Card')); ?></span> <span><?php echo $block->escapeHtml(__('Name on Card')); ?></span>
</label> </label>
<div class="admin__field-control"> <div>
<input type="text" id="<?php /* @noEscape */ <input type="text" id="<?php /* @noEscape */
echo $code; ?>_cc_owner" data-encrypted-name="holderName" echo $code; ?>_cc_owner" name="payment[holderName]"
title="<?php echo $block->escapeHtml(__('Name on Card')); ?>" class="admin__control-text" title="<?php echo $block->escapeHtml(__('Name on Card')); ?>" class="admin__control-text"
value="<?php /* @noEscape */ value="<?php /* @noEscape */
echo $block->getInfoData('cc_owner'); ?>"/> echo $block->getInfoData('cc_owner'); ?>"
placeholder="<?php echo $block->escapeHtml(__('Name on Card')); ?>"/>
</div> </div>
</div> </div>
<div>
<div class="field-type admin__field _required"> <div>Available card types:</div>
<label class="admin__field-label" for="<?php /* @noEscape */ <div>
echo $code; ?>_cc_type">
<span><?php echo $block->escapeHtml(__('Credit Card Type')); ?></span>
</label>
<div class="admin__field-control">
<select id="<?php /* @noEscape */
echo $code; ?>_cc_type" name="payment[cc_type]"
class="required-entry validate-cc-type-select admin__control-select">
<option value=""></option>
<?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?> <?php foreach ($block->getCcAvailableTypes() as $typeCode => $typeName): ?>
<option value="<?php echo $block->escapeHtml($typeCode); ?>" <span class="cc-type-<?php echo $block->escapeHtml($typeCode); ?>">
<?php if ($typeCode == $ccType): ?>selected="selected"<?php endif ?>>
<?php echo $block->escapeHtml($typeName); ?> <?php echo $block->escapeHtml($typeName); ?>
</option> </span>
<?php endforeach ?>
</select>
</div>
</div>
<div class="field-number admin__field _required">
<label class="admin__field-label" for="<?php /* @noEscape */
echo $code; ?>_cc_number">
<span><?php echo $block->escapeHtml(__('Credit Card Number')); ?></span>
</label>
<div class="admin__field-control">
<input type="text" id="<?php /* @noEscape */
echo $code; ?>_cc_number" data-encrypted-name="number"
title="<?php echo $block->escapeHtml(__('Credit Card Number')); ?>"
class="admin__control-text validate-cc-number"
value="<?php /* @noEscape */
echo $block->getInfoData('cc_number'); ?>"/>
</div>
</div>
<div class="field-date admin__field _required">
<label class="admin__field-label" for="<?php /* @noEscape */
echo $code; ?>_expiration">
<span><?php echo $block->escapeHtml(__('Expiration Date')); ?></span>
</label>
<div class="admin__field-control">
<select id="<?php /* @noEscape */
echo $code ?>_expiration" data-encrypted-name="expiryMonth"
class="admin__control-select admin__control-select-month validate-cc-exp required-entry">
<?php foreach ($block->getCcMonths() as $k => $v): ?>
<option value="<?php echo $block->escapeHtml($k); ?>"
<?php if ($k == $ccExpMonth): ?>selected="selected"<?php endif ?>>
<?php echo $block->escapeHtml($v); ?>
</option>
<?php endforeach; ?>
</select>
<select id="<?php /* @noEscape */
echo $code ?>_expiration_yr" data-encrypted-name="expiryYear"
class="admin__control-select admin__control-select-year required-entry">
<?php foreach ($block->getCcYears() as $k => $v): ?>
<option value="<?php /* @noEscape */
echo $k ? $block->escapeHtml($k) : '' ?>"
<?php if ($k == $ccExpYear): ?>selected="selected"<?php endif ?>>
<?php echo $block->escapeHtml($v); ?>
</option>
<?php endforeach ?> <?php endforeach ?>
</select>
</div> </div>
<p class="helper-text" id="cc-type-helper-text"><?php echo $block->escapeHtml(__('(Please provide a card with the type from the list above)')); ?></p>
</div> </div>
<?php if ($block->hasVerification()): ?> <div id="cardContainer-<?php /* @noEscape */ echo $code; ?>"></div>
<div class="field-number required admin__field _required"> <input id="<?php /* @noEscape */ echo $code; ?>-number" type="hidden" name="payment[number]">
<label class="admin__field-label" for="<?php /* @noEscape */ <input id="<?php /* @noEscape */ echo $code; ?>-cvc" type="hidden" name="payment[cvc]">
echo $code; ?>_cc_cid"> <input id="<?php /* @noEscape */ echo $code; ?>-expiryMonth" type="hidden" name="payment[expiryMonth]">
<span><?php echo $block->escapeHtml(__('Card Verification Number')); ?></span> <input id="<?php /* @noEscape */ echo $code; ?>-expiryYear" type="hidden" name="payment[expiryYear]">
</label> <input id="<?php /* @noEscape */ echo $code; ?>-cc_type" type="hidden" name="payment[cc_type]">
<div class="admin__field-control">
<input type="text" title="<?php echo $block->escapeHtml(__('Card Verification Number')); ?>"
class="required-entry validate-cc-cvn admin__control-cvn admin__control-text"
id="<?php /* @noEscape */
echo $code; ?>_cc_cid"
data-encrypted-name="cvc" value="<?php /* @noEscape */
echo $block->getInfoData('cc_cid') ?>"/>
</div>
</div>
<?php endif; ?>
<script> <script>
require( require(
...@@ -140,58 +75,95 @@ echo $code; ?>" ...@@ -140,58 +75,95 @@ echo $code; ?>"
"Magento_Sales/order/create/form" "Magento_Sales/order/create/form"
], ],
function () { function () {
//<![CDATA[ var ccTypes = <?php echo json_encode($block->getCcAvailableTypesByAlt()); ?>;
var dfScriptTag = document.createElement('script');
dfScriptTag.src = "<?php echo $block->getLibrarySource(); ?>";
dfScriptTag.type = "text/javascript";
document.body.appendChild(dfScriptTag);
var element = $('payment_form_<?php echo $code ?>');
var cse_form = $(element).closest('form');
var cse_options = {
name: 'payment[encrypted_data]'
};
var cse = function () { //<![CDATA[
if (order.paymentMethod && order.paymentMethod == '<?php echo $code ?>') { // Append checkout card components script
try { var scriptTag = document.createElement('script');
scriptTag.src = "<?php echo $block->getCheckoutCardComponentJs(); ?>";
scriptTag.type = "text/javascript";
document.body.appendChild(scriptTag);
// do not validate because it could be that CVC field does not exists (because MOTO this is not needed) // Get cc type by adyen cc type
cse_options.enableValidations = false; var getCcCodeByAltCode = function(altCode) {
var cseForm = adyen.createEncryptedForm(cse_form, cse_options); if (ccTypes.hasOwnProperty(altCode)) {
// encrypt data directly because submit button is not always on the page return ccTypes[altCode];
var test = cseForm.encrypt();
cseForm.createEncryptedField(test);
} catch (e) {
var encryptionFailed = true;
} }
var encryptedForm = document.getElementById(cse_options.name);
if (encryptionFailed || !encryptedForm || encryptedForm.value.length == 0) { return "";
alert("Warning: Adyen Client Side Encryption cannot succeed.");
} }
/*
* Initialize secure fields and set up the onChange callback to
* - fill the input fields with the encrypted data
* - show the heklper text when necessary
*/
var secureFieldsInitialize = function () {
var cardNode = document.getElementById("cardContainer-<?php /* @noEscape */ echo $code; ?>");
var checkout = new AdyenCheckout({
locale: "<?php echo $block->getLocale(); ?>"
});
var card = checkout.create('card', {
originKey: "<?php echo $block->getCheckoutOriginKeys(); ?>",
loadingContext: "<?php echo $block->getCheckoutContextUrl(); ?>",
type: 'card',
groupTypes: ccTypes,
onChange: function(state) {
if (state.isCardValid) {
jQuery("#cc-type-helper-text").hide();
} else {
jQuery("#cc-type-helper-text").show();
} }
// When the state is valid update the input fields
if (state.isValid) {
// Here we enable the button if the component is now valid
jQuery("#<?php /* @noEscape */ echo $code; ?>-number").val(state.data.encryptedCardNumber);
jQuery("#<?php /* @noEscape */ echo $code; ?>-expiryMonth").val(state.data.encryptedExpiryMonth);
jQuery("#<?php /* @noEscape */ echo $code; ?>-expiryYear").val(state.data.encryptedExpiryYear);
jQuery("#<?php /* @noEscape */ echo $code; ?>-cvc").val(state.data.encryptedSecurityCode);
jQuery("#<?php /* @noEscape */ echo $code; ?>-cc_type").val(getCcCodeByAltCode(state.brand));
} }
},
onError: function() {}
});
var cse_initialize = function () { card.mount(cardNode);
order.submit = order.submit.wrap(function (originalSaveMethod) { /*order.submit = order.submit.wrap(function (originalSaveMethod) {
cse.call(this); attachSecureFieldsData.call(this);
originalSaveMethod(); originalSaveMethod();
}); });*/
} }
if (document.readyState === "complete") { // Load card components and force wait until the external script is loaded
cse_initialize(); if (scriptTag.readyState) {
scriptTag.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
secureFieldsInitialize();
}
};
} }
else { else {
Event.observe(window, 'load', cse_initialize); scriptTag.onload = function(){
secureFieldsInitialize();
};
} }
//]]> //]]>
}); });
</script>
// TODO Oneclick
// cvc is not required so cvchide: true or hidecvc
</script>
</fieldset> </fieldset>
/**
* ######
* ######
* ############ ####( ###### #####. ###### ############ ############
* ############# #####( ###### #####. ###### ############# #############
* ###### #####( ###### #####. ###### ##### ###### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ##### ######
* ###### ###### #####( ###### #####. ###### ##### ##### ######
* ############# ############# ############# ############# ##### ######
* ############ ############ ############# ############ ##### ######
* ######
* #############
* ############
*
* 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>
*/
#payment_form_adyen_cc {
padding-left: 30px;
}
.adyen-checkout-card__form .adyen-checkout__input iframe{
max-height: 40px;
}
#payment_form_adyen_cc .admin__field{
margin-bottom: 10px;
}
#payment_form_adyen_cc .helper-text{
font-size: 11px;
color: rgb(144, 162, 189);
font-weight: 100;
}
#payment_form_adyen_cc #adyen_cc_cc_owner {
width: 225px;
border: none;
padding: 0;
color: rgb(0, 27, 43);
font-size: 16px;
font-weight: 400;
margin-top: 10px;
}
#payment_form_adyen_cc #adyen_cc_cc_owner .input-text:focus {
border: none;
box-shadow: none;
}
#payment_form_adyen_cc #adyen_cc_cc_owner::placeholder,
#payment_form_adyen_cc #adyen_cc_cc_owner:placeholder-shown
{
color: rgb(144, 162, 189);
font-weight: 200;
}
#payment_form_adyen_cc .cc-type-VI {
margin: 10px;
display: inline-block;
font-weight: bold;
}
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